Merge inbound to central, a=merge

MozReview-Commit-ID: 4FEkd1x2GD
This commit is contained in:
Wes Kocher 2017-09-08 13:36:31 -07:00
commit 2a30786cad
136 changed files with 3349 additions and 2025 deletions

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s && os == 'win' && release_or_beta
support-files =
head.js
!/accessible/tests/browser/events.js

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s && os == 'win' && release_or_beta
support-files =
head.js
doc_treeupdate_ariadialog.html

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s && os == 'win' && release_or_beta
support-files =
head.js
!/accessible/tests/browser/events.js

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s && os == 'win' && release_or_beta
support-files =
head.js
!/accessible/tests/browser/events.js

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s && os == 'win' && release_or_beta
support-files =
head.js
!/accessible/tests/browser/events.js

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = e10s && os == 'win' && release_or_beta
support-files =
head.js
!/accessible/tests/browser/events.js

View File

@ -667,9 +667,6 @@ pref("accessibility.typeaheadfind.timeout", 5000);
pref("accessibility.typeaheadfind.linksonly", false);
pref("accessibility.typeaheadfind.flashBar", 1);
// Tracks when accessibility is loaded into the previous session.
pref("accessibility.loadedInLastSession", false);
pref("plugins.click_to_play", true);
pref("plugins.testmode", false);
@ -980,9 +977,6 @@ pref("toolkit.crashreporter.infoURL",
// base URL for web-based support pages
pref("app.support.baseURL", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/");
// a11y conflicts with e10s support page
pref("app.support.e10sAccessibilityUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/accessibility-ppt");
// base url for web-based feedback pages
#ifdef MOZ_DEV_EDITION
pref("app.feedback.baseURL", "https://input.mozilla.org/%LOCALE%/feedback/firefoxdev/%VERSION%/");

View File

@ -528,13 +528,6 @@ BrowserGlue.prototype = {
this._flashHangCount = 0;
this._firstWindowReady = new Promise(resolve => this._firstWindowLoaded = resolve);
if (AppConstants.platform == "macosx" ||
(AppConstants.platform == "win" && AppConstants.RELEASE_OR_BETA)) {
// Handles prompting to inform about incompatibilites when accessibility
// and e10s are active together.
E10SAccessibilityCheck.init();
}
},
// cleanup (called on application shutdown)
@ -1009,10 +1002,7 @@ BrowserGlue.prototype = {
}
this._sanitizer.onStartup();
E10SAccessibilityCheck.onWindowsRestored();
this._scheduleStartupIdleTasks();
this._lateTasksIdleObserver = (idleService, topic, data) => {
if (topic == "idle") {
idleService.removeIdleObserver(this._lateTasksIdleObserver,
@ -2800,132 +2790,9 @@ var DefaultBrowserCheck = {
},
};
var E10SAccessibilityCheck = {
// tracks when an a11y init observer fires prior to the
// first window being opening.
_wantsPrompt: false,
init() {
Services.obs.addObserver(this, "a11y-init-or-shutdown", true);
Services.obs.addObserver(this, "quit-application-granted", true);
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
get forcedOn() {
try {
return Services.prefs.getBoolPref("browser.tabs.remote.force-enable");
} catch (e) {}
return false;
},
observe(subject, topic, data) {
switch (topic) {
case "quit-application-granted":
// Tag the profile with a11y load state. We use this in nsAppRunner
// checks on the next start.
Services.prefs.setBoolPref("accessibility.loadedInLastSession",
Services.appinfo.accessibilityEnabled);
break;
case "a11y-init-or-shutdown":
if (data == "1") {
// Update this so users can check this while still running
Services.prefs.setBoolPref("accessibility.loadedInLastSession", true);
this._showE10sAccessibilityWarning();
}
break;
}
},
onWindowsRestored() {
if (this._wantsPrompt) {
this._wantsPrompt = false;
this._showE10sAccessibilityWarning();
}
},
_warnedAboutAccessibility: false,
_showE10sAccessibilityWarning() {
// We don't prompt about a11y incompat if e10s is off.
if (!Services.appinfo.browserTabsRemoteAutostart) {
return;
}
// If the user set the forced pref and it's true, ignore a11y init.
// If the pref doesn't exist or if it's false, prompt.
if (this.forcedOn) {
return;
}
// Only prompt once per session
if (this._warnedAboutAccessibility) {
return;
}
this._warnedAboutAccessibility = true;
let win = RecentWindow.getMostRecentBrowserWindow();
if (!win || !win.gBrowser || !win.gBrowser.selectedBrowser) {
Services.console.logStringMessage(
"Accessibility support is partially disabled due to compatibility issues with new features.");
this._wantsPrompt = true;
this._warnedAboutAccessibility = false;
return;
}
let browser = win.gBrowser.selectedBrowser;
// We disable a11y for content and prompt on the chrome side letting
// a11y users know they need to disable e10s and restart.
let promptMessage = win.gNavigatorBundle.getFormattedString(
"e10s.accessibilityNotice.mainMessage2",
[gBrandBundle.GetStringFromName("brandShortName")]
);
let notification;
let restartCallback = function() {
let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
if (cancelQuit.data) {
return; // somebody canceled our quit request
}
// Restart the browser
Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
};
// main option: an Ok button, keeps running with content accessibility disabled
let mainAction = {
label: win.gNavigatorBundle.getString("e10s.accessibilityNotice.acceptButton.label"),
accessKey: win.gNavigatorBundle.getString("e10s.accessibilityNotice.acceptButton.accesskey"),
callback() {
// If the user invoked the button option remove the notification,
// otherwise keep the alert icon around in the address bar.
notification.remove();
},
dismiss: true
};
// secondary option: a restart now button. When we restart e10s will be disabled due to
// accessibility having been loaded in the previous session.
let secondaryActions = [{
label: win.gNavigatorBundle.getString("e10s.accessibilityNotice.enableAndRestart.label"),
accessKey: win.gNavigatorBundle.getString("e10s.accessibilityNotice.enableAndRestart.accesskey"),
callback: restartCallback,
}];
let options = {
popupIconURL: "chrome://browser/skin/e10s-64@2x.png",
learnMoreURL: Services.urlFormatter.formatURLPref("app.support.e10sAccessibilityUrl"),
persistent: true,
persistWhileVisible: true,
};
notification =
win.PopupNotifications.show(browser, "a11y_enabled_with_e10s",
promptMessage, null, mainAction,
secondaryActions, options);
},
};
var components = [BrowserGlue, ContentPermissionPrompt];
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
// Listen for UITour messages.
// Do it here instead of the UITour module itself so that the UITour module is lazy loaded
// when the first message is received.

View File

@ -63,9 +63,6 @@ browser.jar:
skin/classic/browser/sync-desktopIcon.svg (../shared/sync-desktopIcon.svg)
skin/classic/browser/sync-mobileIcon.svg (../shared/sync-mobileIcon.svg)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png

View File

@ -87,9 +87,6 @@ browser.jar:
skin/classic/browser/yosemite/menuPanel-exit@2x.png (menuPanel-exit-yosemite@2x.png)
skin/classic/browser/yosemite/menuPanel-help.png (menuPanel-help-yosemite.png)
skin/classic/browser/yosemite/menuPanel-help@2x.png (menuPanel-help-yosemite@2x.png)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png

View File

@ -57,14 +57,13 @@
.customizationmode-button {
border: 1px solid #b1b1b1;
margin: 6px 10px;
padding: 2px 5px;
background-color: #fcfcfd;
color: rgb(71,71,71);
-moz-appearance: none;
}
.customizationmode-checkbox {
.customizationmode-checkbox,
.customizationmode-button {
color: rgb(71, 71, 71);
margin: 6px 10px;
padding: 2px 5px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -83,10 +83,6 @@ browser.jar:
skin/classic/browser/window-controls/restore-highcontrast.svg (window-controls/restore-highcontrast.svg)
skin/classic/browser/window-controls/restore-themes.svg (window-controls/restore-themes.svg)
#ifdef E10S_TESTING_ONLY
skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
#endif
[extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
% override chrome://browser/skin/page-livemarks.png chrome://browser/skin/feeds/feedIcon16.png
% override chrome://browser/skin/feeds/audioFeedIcon.png chrome://browser/skin/feeds/feedIcon.png

View File

@ -420,6 +420,10 @@ body {
--search-overlays-semitransparent: rgba(42, 46, 56, 0.66);
--popup-shadow-color: #5c667b;
}
* {
box-sizing: border-box;
}
.debugger {
display: flex;
flex: 1;
@ -877,12 +881,6 @@ html .arrow.expanded svg {
.managed-tree .tree .node.focused {
color: white;
background-color: var(--theme-selection-background);
padding-bottom: 2px;
}
.theme-dark .managed-tree .tree .node.focused {
background-color: var(--theme-selection-background-hover);
padding-bottom: 2px;
}
html:not([dir="rtl"]) .managed-tree .tree .node > div {
@ -907,7 +905,7 @@ html[dir="rtl"] .managed-tree .tree .node > div {
.close-btn .close {
width: 14px;
height: 14px;
transition: all 0.25s ease-in-out;
transition: all 0.15s ease-in-out;
border: 1px solid transparent;
border-radius: 2px;
padding: 0;
@ -1267,15 +1265,16 @@ html[dir="rtl"] .managed-tree .tree .node > div {
.toggle-search .text {
margin-left: 1em;
cursor: default;
}
.toggle-search .active {
color: var(--theme-selection-background);
cursor: default;
}
.sources-panel {
flex: 1;
background-color: var(--theme-sidebar-background);
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
position: relative;
@ -1287,7 +1286,8 @@ html[dir="rtl"] .managed-tree .tree .node > div {
}
.sources-header {
height: 30px;
height: 29px;
background-color: var(--theme-toolbar-background);
border-bottom: 1px solid var(--theme-splitter-color);
padding-top: 0px;
padding-bottom: 0px;
@ -2236,7 +2236,7 @@ html[dir="rtl"] .arrow svg,
width: calc(100% - 1.5px);
top: 30px;
left: 0px;
--editor-footer-height: 27px;
--editor-footer-height: 24px;
}
html[dir="rtl"] .editor-mount {
@ -2440,24 +2440,8 @@ html[dir="rtl"] .editor-mount {
.cm-highlight-full::before {
border: 1px solid var(--theme-comment-alt);
}
.cm-highlight-start::before {
border-left-width: 1px;
border-left-style: solid;
border-left-color: var(--theme-comment-alt);
margin: 0 0 -1px -1px;
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
}
.cm-highlight-end::before {
border-right-width: 1px;
border-right-style: solid;
border-right-color: var(--theme-comment-alt);
margin: 0 -1px -1px 0;
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
border-radius: 2px;
margin: 0 -1px -1px -1px;
}
.breakpoints-toggle {
margin: 2px 3px;
@ -2566,7 +2550,7 @@ html .breakpoints-list .breakpoint.paused {
width: 100%;
margin: 0px;
border: 1px;
background-color: var(--theme-body-background);
background-color: var(--theme-sidebar-background);
font-size: 12px;
padding: 0px 20px;
color: var(--theme-body-color);
@ -2587,7 +2571,7 @@ html .breakpoints-list .breakpoint.paused {
.expressions-list {
/* TODO: add normalize */
margin: 0;
padding: 0.5em 0;
padding: 0;
}
.expression-input-container {
padding: 0.5em;
@ -2851,18 +2835,29 @@ html .breakpoints-list .breakpoint.paused {
.event-listeners .listener:hover .close {
display: block;
}
:root {
--accordion-header-background: var(--theme-toolbar-background);
}
:root.theme-dark {
--accordion-header-background: #141416;
}
.accordion {
background-color: var(--theme-body-background);
background-color: var(--theme-sidebar-background);
width: 100%;
}
.accordion ._header {
background-color: var(--theme-toolbar-background);
background-color: var(--accordion-header-background);
border-bottom: 1px solid var(--theme-splitter-color);
display: flex;
font-size: 12px;
padding: 5px;
padding: 4px;
transition: all 0.25s ease;
width: 100%;
height: 24px;
align-items: center;
-webkit-user-select: none;
@ -2872,10 +2867,6 @@ html .breakpoints-list .breakpoint.paused {
user-select: none;
}
.accordion ._header {
display: flex;
}
.accordion ._header:hover {
background-color: var(--theme-toolbar-background-hover);
}
@ -2921,15 +2912,15 @@ html .breakpoints-list .breakpoint.paused {
border: none;
}
.command-bar {
flex: 0 0 30px;
flex: 0 0 29px;
border-bottom: 1px solid var(--theme-splitter-color);
display: flex;
height: 30px;
height: 29px;
overflow: hidden;
position: sticky;
top: 0;
z-index: 1;
background-color: var(--theme-body-background);
background-color: var(--theme-toolbar-background);
}
.command-bar.vertical {
@ -3083,14 +3074,17 @@ html .command-bar > button:disabled {
text-align: center;
font-size: 1.25em;
color: var(--theme-comment-alt);
background-color: var(--theme-tab-toolbar-background);
background-color: var(--theme-toolbar-background);
font-weight: lighter;
z-index: 100;
}
.theme-dark .welcomebox {
background-color: var(--theme-body-background);
}
.alignlabel {
display: inline-block;
text-align: left;
}
.welcomebox .toggle-button-end {
@ -3101,13 +3095,25 @@ html .command-bar > button:disabled {
offset-inline-start: auto;
}
.shortcutKeys {
text-align: right;
float: left;
font-family: Courier;
}
.shortcutFunction {
text-align: left;
float: left;
margin-left: 25px;
}
html .welcomebox .toggle-button-end.collapsed {
bottom: 1px;
}
.source-header {
border-bottom: 1px solid var(--theme-splitter-color);
width: 100%;
height: 30px;
height: 29px;
display: flex;
align-items: flex-end;
}
@ -3147,7 +3153,7 @@ html .welcomebox .toggle-button-end.collapsed {
display: inline-flex;
align-items: flex-end;
position: relative;
transition: all 0.25s ease;
transition: all 0.15s ease;
min-width: 40px;
overflow: hidden;
padding: 5px;

File diff suppressed because one or more lines are too long

View File

@ -4126,45 +4126,7 @@ module.exports = baseCreate;
/***/ }),
/* 404 */
/***/ (function(module, exports, __webpack_require__) {
var isArrayLike = __webpack_require__(220),
isObjectLike = __webpack_require__(14);
/**
* This method is like `_.isArrayLike` except that it also checks if `value`
* is an object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array-like object,
* else `false`.
* @example
*
* _.isArrayLikeObject([1, 2, 3]);
* // => true
*
* _.isArrayLikeObject(document.body.children);
* // => true
*
* _.isArrayLikeObject('abc');
* // => false
*
* _.isArrayLikeObject(_.noop);
* // => false
*/
function isArrayLikeObject(value) {
return isObjectLike(value) && isArrayLike(value);
}
module.exports = isArrayLikeObject;
/***/ }),
/* 404 */,
/* 405 */,
/* 406 */
/***/ (function(module, exports, __webpack_require__) {
@ -28517,6 +28479,9 @@ module.exports = basePropertyDeep;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports.getNextStep = getNextStep;
var _debuggerHtml = __webpack_require__(843);
@ -28525,45 +28490,40 @@ var _types = __webpack_require__(844);
var _closest = __webpack_require__(1055);
var _contains = __webpack_require__(1127);
var _helpers = __webpack_require__(1052);
function getNextStep(source, stepType, pausedPosition) {
function getNextStep(source, pausedPosition) {
var awaitExpression = getAwaitExpression(source, pausedPosition);
if (!awaitExpression) {
return null;
}
var awaitStatement = awaitExpression.getStatementParent();
return getLocationAfterAwaitExpression(awaitStatement, pausedPosition);
}
function getAwaitExpression(source, pausedPosition) {
var closestPath = (0, _closest.getClosestPath)(source, pausedPosition);
if (!closestPath) {
return { nextStepType: stepType };
return null;
}
if ((0, _helpers.isAwaitExpression)(closestPath, pausedPosition)) {
var nextHiddenBreakpointLocation = getLocationAfterAwaitExpression(closestPath, pausedPosition);
return { nextStepType: "resume", nextHiddenBreakpointLocation };
if ((0, _helpers.isAwaitExpression)(closestPath)) {
return closestPath;
}
return { nextStepType: stepType };
return closestPath.find(p => p.isAwaitExpression());
}
function getLocationAfterAwaitExpression(path, position) {
var children = getFunctionBodyChildren(path);
if (!children) {
return;
function getLocationAfterAwaitExpression(statement, position) {
var nextStatement = statement.getSibling(statement.key + 1);
if (nextStatement.node) {
return _extends({}, nextStatement.node.loc.start, {
sourceId: position.sourceId
});
}
for (var i = 0; i !== children.length; i++) {
var child = children[i];
if ((0, _contains.containsPosition)(child.loc, position)) {
var nextChild = children[++i];
var nextLocation = nextChild.loc.start;
nextLocation.sourceId = position.sourceId;
return nextLocation;
}
}
}
function getFunctionBodyChildren(path) {
var blockScope = path.scope.block;
if (!blockScope) {
return;
}
var children = blockScope.body.body;
return children;
return null;
}
/***/ }),
@ -28937,6 +28897,8 @@ var _getSymbols = __webpack_require__(1050);
var _getSymbols2 = _interopRequireDefault(_getSymbols);
var _ast = __webpack_require__(1051);
var _getOutOfScopeLocations = __webpack_require__(1072);
var _getOutOfScopeLocations2 = _interopRequireDefault(_getOutOfScopeLocations);
@ -28959,6 +28921,7 @@ self.onmessage = workerHandler({
getOutOfScopeLocations: _getOutOfScopeLocations2.default,
getSymbols: _getSymbols2.default,
clearSymbols: _getSymbols.clearSymbols,
clearASTs: _ast.clearASTs,
getVariablesInScope: _scopes.getVariablesInScope,
getNextStep: _steps.getNextStep,
getEmptyLines: _getEmptyLines2.default
@ -29745,6 +29708,7 @@ Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getAst = getAst;
exports.clearASTs = clearASTs;
exports.traverseAst = traverseAst;
var _parseScriptTags = __webpack_require__(1023);
@ -29822,6 +29786,10 @@ function getAst(source) {
return ast;
}
function clearASTs() {
ASTs = new Map();
}
function traverseAst(source, visitor) {
var ast = getAst(source);
if ((0, _isEmpty2.default)(ast)) {
@ -32842,6 +32810,7 @@ function containsPosition(a, b) {
return startsBefore && endsAfter;
}
function containsLocation(a, b) {
return containsPosition(a, b.start) && containsPosition(a, b.end);
}
@ -32858,7 +32827,7 @@ function nodeContainsPosition(node, position) {
var baseDifference = __webpack_require__(1131),
baseFlatten = __webpack_require__(707),
baseRest = __webpack_require__(411),
isArrayLikeObject = __webpack_require__(404);
isArrayLikeObject = __webpack_require__(1155);
/**
* Creates an array of `array` values not included in the other given arrays
@ -32964,6 +32933,68 @@ function baseDifference(array, values, iteratee, comparator) {
module.exports = baseDifference;
/***/ }),
/* 1132 */,
/* 1133 */,
/* 1134 */,
/* 1135 */,
/* 1136 */,
/* 1137 */,
/* 1138 */,
/* 1139 */,
/* 1140 */,
/* 1141 */,
/* 1142 */,
/* 1143 */,
/* 1144 */,
/* 1145 */,
/* 1146 */,
/* 1147 */,
/* 1148 */,
/* 1149 */,
/* 1150 */,
/* 1151 */,
/* 1152 */,
/* 1153 */,
/* 1154 */,
/* 1155 */
/***/ (function(module, exports, __webpack_require__) {
var isArrayLike = __webpack_require__(220),
isObjectLike = __webpack_require__(14);
/**
* This method is like `_.isArrayLike` except that it also checks if `value`
* is an object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array-like object,
* else `false`.
* @example
*
* _.isArrayLikeObject([1, 2, 3]);
* // => true
*
* _.isArrayLikeObject(document.body.children);
* // => true
*
* _.isArrayLikeObject('abc');
* // => false
*
* _.isArrayLikeObject(_.noop);
* // => false
*/
function isArrayLikeObject(value) {
return isObjectLike(value) && isArrayLike(value);
}
module.exports = isArrayLikeObject;
/***/ })
/******/ ]);
});

View File

@ -317,7 +317,7 @@ function ignoreWhiteSpace(str) {
function wholeMatch(query, wholeWord) {
if (query == "" || !wholeWord) {
if (query === "" || !wholeWord) {
return query;
}
@ -350,7 +350,7 @@ function buildQuery(originalQuery, modifiers, _ref) {
wholeWord = modifiers.wholeWord;
if (originalQuery == "") {
if (originalQuery === "") {
return new RegExp(originalQuery);
}
@ -443,8 +443,6 @@ var _buildQuery2 = _interopRequireDefault(_buildQuery);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var MAX_LENGTH = 100000;
function getMatches(query, text, modifiers) {
if (!query || !text || !modifiers) {
return [];
@ -457,12 +455,8 @@ function getMatches(query, text, modifiers) {
for (var i = 0; i < lines.length; i++) {
var singleMatch = void 0;
var line = lines[i];
if (line.length <= MAX_LENGTH) {
while ((singleMatch = regexQuery.exec(line)) !== null) {
matchedLocations.push({ line: i, ch: singleMatch.index });
}
} else {
return [];
while ((singleMatch = regexQuery.exec(line)) !== null) {
matchedLocations.push({ line: i, ch: singleMatch.index });
}
}
return matchedLocations;
@ -873,13 +867,20 @@ function getSourceLineCount(source) {
function getMode(source) {
var contentType = source.contentType,
text = source.text,
isWasm = source.isWasm;
isWasm = source.isWasm,
url = source.url;
if (!text || isWasm) {
return { name: "text" };
}
// if the url ends with .marko we set the name to Javascript so
// syntax highlighting works for marko too
if (url && url.match(/\.marko$/i)) {
return { name: "javascript" };
}
// Use HTML mode for files in which the first non whitespace
// character is `<` regardless of extension.
var isHTMLLike = text.match(/^\s*</);

View File

@ -48,6 +48,7 @@ support-files =
[browser_dbg-breaking.js]
[browser_dbg-breaking-from-console.js]
[browser_dbg-breakpoints.js]
[browser_dbg-breakpoints-toggle.js]
[browser_dbg-breakpoints-reloading.js]
skip-if = true # Bug 1383576
[browser_dbg-breakpoints-cond.js]

View File

@ -1,10 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests async stepping will:
// 1. step over await statements
// 2. step into async functions
// 3. step out of async functions
// Tests async stepping will step over await statements
add_task(async function test() {
Services.prefs.setBoolPref("devtools.debugger.features.async-stepping", true);
const dbg = await initDebugger("doc-async.html", "async");

View File

@ -9,16 +9,16 @@ async function waitOnToolbox(toolbox, event) {
return new Promise(resolve => toolbox.on(event, resolve));
}
add_task(function*() {
add_task(async function() {
const url = EXAMPLE_URL + "doc-script-switching.html";
const toolbox = yield openNewTabAndToolbox(url, "webconsole");
const toolbox = await openNewTabAndToolbox(url, "webconsole");
// Type "debugger" into console
let jsterm = toolbox.getPanel("webconsole").hud.jsterm;
jsterm.execute("debugger");
// Wait for the debugger to be selected and make sure it's paused
yield waitOnToolbox(toolbox, "jsdebugger-selected");
await waitOnToolbox(toolbox, "jsdebugger-selected");
is(toolbox.threadClient.state, "paused");
// Create a dbg context
@ -26,7 +26,7 @@ add_task(function*() {
const { selectors: { getSelectedSource }, getState } = dbg;
// Make sure the thread is paused in the right source and location
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
is(dbg.win.cm.getValue(), "debugger");
const source = getSelectedSource(getState()).toJS();
assertPausedLocation(dbg);

View File

@ -3,30 +3,30 @@
// Tests the breakpoints are hit in various situations.
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
const { selectors: { getSelectedSource }, getState } = dbg;
// Make sure we can set a top-level breakpoint and it will be hit on
// reload.
yield addBreakpoint(dbg, "scripts.html", 18);
await addBreakpoint(dbg, "scripts.html", 18);
reload(dbg);
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
yield resume(dbg);
await resume(dbg);
const paused = waitForPaused(dbg);
// Create an eval script that pauses itself.
invokeInTab("doEval");
yield paused;
yield resume(dbg);
await paused;
await resume(dbg);
const source = getSelectedSource(getState()).toJS();
ok(!source.url, "It is an eval source");
yield addBreakpoint(dbg, source, 5);
await addBreakpoint(dbg, source, 5);
invokeInTab("evaledFunc");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
});

View File

@ -24,49 +24,47 @@ function assertEditorBreakpoint(dbg, line, shouldExist) {
);
}
function setConditionalBreakpoint(dbg, index, condition) {
return Task.spawn(function*() {
rightClickElement(dbg, "gutter", index);
selectMenuItem(dbg, 2);
yield waitForElement(dbg, ".conditional-breakpoint-panel input");
findElementWithSelector(dbg, ".conditional-breakpoint-panel input").focus();
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, condition);
pressKey(dbg, "Enter");
});
async function setConditionalBreakpoint(dbg, index, condition) {
rightClickElement(dbg, "gutter", index);
selectMenuItem(dbg, 2);
await waitForElement(dbg, ".conditional-breakpoint-panel input");
findElementWithSelector(dbg, ".conditional-breakpoint-panel input").focus();
// Position cursor reliably at the end of the text.
pressKey(dbg, "End");
type(dbg, condition);
pressKey(dbg, "Enter");
}
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
yield selectSource(dbg, "simple2");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
await selectSource(dbg, "simple2");
// Adding a conditional Breakpoint
yield setConditionalBreakpoint(dbg, 5, "1");
yield waitForDispatch(dbg, "ADD_BREAKPOINT");
await setConditionalBreakpoint(dbg, 5, "1");
await waitForDispatch(dbg, "ADD_BREAKPOINT");
let bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "1", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true);
// Editing a conditional Breakpoint
yield setConditionalBreakpoint(dbg, 5, "2");
yield waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
await setConditionalBreakpoint(dbg, 5, "2");
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "12", "breakpoint is created with the condition");
assertEditorBreakpoint(dbg, 5, true);
// Removing a conditional breakpoint
clickElement(dbg, "gutter", 5);
yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
bp = findBreakpoint(dbg, "simple2", 5);
is(bp, null, "breakpoint was removed");
assertEditorBreakpoint(dbg, 5, false);
// Adding a condition to a breakpoint
clickElement(dbg, "gutter", 5);
yield waitForDispatch(dbg, "ADD_BREAKPOINT");
yield setConditionalBreakpoint(dbg, 5, "1");
yield waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
await waitForDispatch(dbg, "ADD_BREAKPOINT");
await setConditionalBreakpoint(dbg, 5, "1");
await waitForDispatch(dbg, "SET_BREAKPOINT_CONDITION");
bp = findBreakpoint(dbg, "simple2", 5);
is(bp.condition, "1", "breakpoint is created with the condition");

View File

@ -23,21 +23,21 @@ function assertEditorBreakpoint(dbg, line) {
ok(exists, `Breakpoint exists on line ${line}`);
}
add_task(function*() {
add_task(async function() {
requestLongerTimeout(3);
const dbg = yield initDebugger("doc-scripts.html");
const dbg = await initDebugger("doc-scripts.html");
const { selectors: { getBreakpoints, getBreakpoint }, getState } = dbg;
const source = findSource(dbg, "simple1.js");
yield selectSource(dbg, source.url);
yield addBreakpoint(dbg, 5);
yield addBreakpoint(dbg, 4);
await selectSource(dbg, source.url);
await addBreakpoint(dbg, 5);
await addBreakpoint(dbg, 4);
const syncedBps = waitForDispatch(dbg, "SYNC_BREAKPOINT", 2);
yield reload(dbg, "simple1");
yield waitForSelectedSource(dbg);
yield syncedBps;
await reload(dbg, "simple1");
await waitForSelectedSource(dbg);
await syncedBps;
assertEditorBreakpoint(dbg, 4);
assertEditorBreakpoint(dbg, 5);

View File

@ -0,0 +1,87 @@
function toggleBreakpoint(dbg, index) {
const bp = findElement(dbg, "breakpointItem", index);
const input = bp.querySelector("input");
input.click();
}
async function removeBreakpoint(dbg, index) {
const removed = waitForDispatch(dbg, "REMOVE_BREAKPOINT");
const bp = findElement(dbg, "breakpointItem", index);
bp.querySelector(".close-btn").click();
await removed;
}
async function disableBreakpoint(dbg, index) {
const disabled = waitForDispatch(dbg, "DISABLE_BREAKPOINT");
toggleBreakpoint(dbg, index);
await disabled;
}
async function enableBreakpoint(dbg, index) {
const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT");
toggleBreakpoint(dbg, index);
await enabled;
}
function toggleBreakpoints(dbg, count) {
clickElement(dbg, "toggleBreakpoints");
}
function disableBreakpoints(dbg, count) {
const toggled = waitForDispatch(dbg, "DISABLE_BREAKPOINT", count);
toggleBreakpoints(dbg);
return toggled;
}
function enableBreakpoints(dbg, count) {
const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT", count);
toggleBreakpoints(dbg);
return enabled;
}
function findBreakpoint(dbg, url, line) {
const { selectors: { getBreakpoint }, getState } = dbg;
const source = findSource(dbg, url);
return getBreakpoint(getState(), { sourceId: source.id, line });
}
function findBreakpoints(dbg) {
const { selectors: { getBreakpoints }, getState } = dbg;
return getBreakpoints(getState());
}
// toggle all breakpoints
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html", "simple2");
// Create two breakpoints
await selectSource(dbg, "simple2");
await addBreakpoint(dbg, "simple2", 3);
await addBreakpoint(dbg, "simple2", 5);
// Disable all of the breakpoints
await disableBreakpoints(dbg, 2);
let bp1 = findBreakpoint(dbg, "simple2", 3);
let bp2 = findBreakpoint(dbg, "simple2", 5);
if (!bp2) {
debugger;
}
is(bp1.disabled, true, "first breakpoint is disabled");
is(bp2.disabled, true, "second breakpoint is disabled");
// Enable all of the breakpoints
await enableBreakpoints(dbg, 2);
bp1 = findBreakpoint(dbg, "simple2", 3);
bp2 = findBreakpoint(dbg, "simple2", 5);
is(bp1.disabled, false, "first breakpoint is enabled");
is(bp2.disabled, false, "second breakpoint is enabled");
// Remove the breakpoints
await removeBreakpoint(dbg, 1);
await removeBreakpoint(dbg, 1);
const bps = findBreakpoints(dbg);
is(bps.size, 0, "breakpoints are removed");
});

View File

@ -7,26 +7,23 @@ function toggleBreakpoint(dbg, index) {
input.click();
}
function removeBreakpoint(dbg, index) {
return Task.spawn(function*() {
const bp = findElement(dbg, "breakpointItem", index);
bp.querySelector(".close-btn").click();
yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
});
async function removeBreakpoint(dbg, index) {
const removed = waitForDispatch(dbg, "REMOVE_BREAKPOINT");
const bp = findElement(dbg, "breakpointItem", index);
bp.querySelector(".close-btn").click();
await removed;
}
function disableBreakpoint(dbg, index) {
return Task.spawn(function*() {
toggleBreakpoint(dbg, index);
yield waitForDispatch(dbg, "DISABLE_BREAKPOINT");
});
async function disableBreakpoint(dbg, index) {
const disabled = waitForDispatch(dbg, "DISABLE_BREAKPOINT");
toggleBreakpoint(dbg, index);
await disabled;
}
function enableBreakpoint(dbg, index) {
return Task.spawn(function*() {
toggleBreakpoint(dbg, index);
yield waitForDispatch(dbg, "ENABLE_BREAKPOINT");
});
async function enableBreakpoint(dbg, index) {
const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT");
toggleBreakpoint(dbg, index);
await enabled;
}
function toggleBreakpoints(dbg, count) {
@ -34,13 +31,15 @@ function toggleBreakpoints(dbg, count) {
}
function disableBreakpoints(dbg, count) {
const toggled = waitForDispatch(dbg, "DISABLE_BREAKPOINT", count);
toggleBreakpoints(dbg);
return waitForDispatch(dbg, "DISABLE_BREAKPOINT", count);
return toggled;
}
function enableBreakpoints(dbg, count) {
const enabled = waitForDispatch(dbg, "ENABLE_BREAKPOINT", count);
toggleBreakpoints(dbg);
return waitForDispatch(dbg, "ENABLE_BREAKPOINT", count);
return enabled;
}
function findBreakpoint(dbg, url, line) {
@ -54,54 +53,24 @@ function findBreakpoints(dbg) {
return getBreakpoints(getState());
}
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
// Create two breakpoints
yield selectSource(dbg, "simple2");
yield addBreakpoint(dbg, "simple2", 3);
yield addBreakpoint(dbg, "simple2", 5);
await selectSource(dbg, "simple2");
await addBreakpoint(dbg, "simple2", 3);
await addBreakpoint(dbg, "simple2", 5);
// Disable the first one
yield disableBreakpoint(dbg, 1);
await disableBreakpoint(dbg, 1);
let bp1 = findBreakpoint(dbg, "simple2", 3);
let bp2 = findBreakpoint(dbg, "simple2", 5);
is(bp1.disabled, true, "first breakpoint is disabled");
is(bp2.disabled, false, "second breakpoint is enabled");
// Disable and Re-Enable the second one
yield disableBreakpoint(dbg, 2);
yield enableBreakpoint(dbg, 2);
await disableBreakpoint(dbg, 2);
await enableBreakpoint(dbg, 2);
bp2 = findBreakpoint(dbg, "simple2", 5);
is(bp2.disabled, false, "second breakpoint is enabled");
});
// toggle all
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
// Create two breakpoints
yield selectSource(dbg, "simple2");
yield addBreakpoint(dbg, "simple2", 3);
yield addBreakpoint(dbg, "simple2", 5);
// Disable all of the breakpoints
yield disableBreakpoints(dbg, 2);
let bp1 = findBreakpoint(dbg, "simple2", 3);
let bp2 = findBreakpoint(dbg, "simple2", 5);
is(bp1.disabled, true, "first breakpoint is disabled");
is(bp2.disabled, true, "second breakpoint is disabled");
// Enable all of the breakpoints
yield enableBreakpoints(dbg, 2);
bp1 = findBreakpoint(dbg, "simple2", 3);
bp2 = findBreakpoint(dbg, "simple2", 5);
is(bp1.disabled, false, "first breakpoint is enabled");
is(bp2.disabled, false, "second breakpoint is enabled");
// Remove the breakpoints
yield removeBreakpoint(dbg, 1);
yield removeBreakpoint(dbg, 1);
const bps = findBreakpoints(dbg);
is(bps.size, 0, "breakpoints are removed");
});

View File

@ -17,8 +17,8 @@ function toggleButton(dbg) {
return callStackBody.querySelector(".show-more");
}
add_task(function* () {
const dbg = yield initDebugger("doc-script-switching.html");
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");
toggleCallStack(dbg);
@ -26,7 +26,7 @@ add_task(function* () {
is(notPaused, "Not Paused", "Not paused message is shown");
invokeInTab("firstCall");
yield waitForPaused(dbg);
await waitForPaused(dbg);
ok(isFrameSelected(dbg, 1, "secondCall"), "the first frame is selected");
@ -34,13 +34,13 @@ add_task(function* () {
ok(!button, "toggle button shouldn't be there");
});
add_task(function* () {
const dbg = yield initDebugger("doc-frames.html");
add_task(async function() {
const dbg = await initDebugger("doc-frames.html");
toggleCallStack(dbg);
invokeInTab("startRecursion");
yield waitForPaused(dbg);
await waitForPaused(dbg);
ok(isFrameSelected(dbg, 1, "recurseA"), "the first frame is selected");

View File

@ -42,12 +42,12 @@ registerCleanupFunction(function() {
gProcess = null;
});
add_task(function*() {
add_task(async function() {
// Windows XP and 8.1 test slaves are terribly slow at this test.
requestLongerTimeout(5);
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
gProcess = yield initChromeDebugger();
gProcess = await initChromeDebugger();
ok(
gProcess._dbgProcess,
@ -81,5 +81,5 @@ add_task(function*() {
info("profile path: " + gProcess._dbgProfilePath);
yield gProcess.close();
await gProcess.close();
});

View File

@ -68,21 +68,21 @@ registerCleanupFunction(function() {
DebuggerServer = null;
});
add_task(function*() {
add_task(async function() {
gClient = initDebuggerClient();
const [type] = yield gClient.connect();
const [type] = await gClient.connect();
is(type, "browser", "Root actor should identify itself as a browser.");
const response = yield gClient.getProcess();
const response = await gClient.getProcess();
let actor = response.form.actor;
gThreadClient = yield attachThread(gClient, actor);
gThreadClient = await attachThread(gClient, actor);
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, "about:mozilla");
// listen for a new source and global
gThreadClient.addListener("newSource", onNewSource);
gClient.addListener("newGlobal", onNewGlobal);
yield promise.all([gNewGlobal.promise, gNewChromeSource.promise]);
await promise.all([gNewGlobal.promise, gNewChromeSource.promise]);
yield resumeAndCloseConnection();
await resumeAndCloseConnection();
});

View File

@ -25,20 +25,21 @@ function getSplitConsole(dbg) {
});
}
add_task(function* () {
add_task(async function() {
Services.prefs.setBoolPref("devtools.toolbox.splitconsoleEnabled", true);
const dbg = yield initDebugger("doc-script-switching.html");
const dbg = await initDebugger("doc-script-switching.html");
yield selectSource(dbg, "switching-01");
await selectSource(dbg, "switching-01");
// open the console
yield getSplitConsole(dbg);
await getSplitConsole(dbg);
ok(dbg.toolbox.splitConsole, "Split console is shown.");
// close the console
clickElement(dbg, "codeMirror");
await clickElement(dbg, "codeMirror");
// First time to focus out of text area
pressKey(dbg, "Escape");
// Second time to hide console
pressKey(dbg, "Escape");
ok(!dbg.toolbox.splitConsole, "Split console is hidden.");

View File

@ -24,31 +24,31 @@ function clickStepOut(dbg) {
* 4. stepOver to the end of a function
* 5. stepUp at the end of a function
*/
add_task(function*() {
const dbg = yield initDebugger("doc-debugger-statements.html");
add_task(async function() {
const dbg = await initDebugger("doc-debugger-statements.html");
yield reload(dbg);
yield waitForPaused(dbg);
await reload(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
// resume
clickElement(dbg, "resume");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
// step over
yield clickStepOver(dbg);
await clickStepOver(dbg);
assertPausedLocation(dbg);
// step into
yield clickStepIn(dbg);
await clickStepIn(dbg);
assertPausedLocation(dbg);
// step over
yield clickStepOver(dbg);
await clickStepOver(dbg);
assertPausedLocation(dbg);
// step out
yield clickStepOut(dbg);
await clickStepOut(dbg);
assertPausedLocation(dbg);
});

View File

@ -25,22 +25,22 @@ function assertEditorBreakpoint(dbg, line, shouldExist) {
);
}
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
const { selectors: { getBreakpoints, getBreakpoint }, getState } = dbg;
const source = findSource(dbg, "simple1.js");
yield selectSource(dbg, source.url);
await selectSource(dbg, source.url);
// Make sure that clicking the gutter creates a breakpoint icon.
clickGutter(dbg, 4);
yield waitForDispatch(dbg, "ADD_BREAKPOINT");
await waitForDispatch(dbg, "ADD_BREAKPOINT");
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
assertEditorBreakpoint(dbg, 4, true);
// Make sure clicking at the same place removes the icon.
clickGutter(dbg, 4);
yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
is(getBreakpoints(getState()).size, 0, "No breakpoints exist");
assertEditorBreakpoint(dbg, 4, false);
});

View File

@ -5,8 +5,8 @@
// matter if the source text doesn't exist yet or even if the source
// doesn't exist.
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
const { selectors: { getSource }, getState } = dbg;
const sourceUrl = EXAMPLE_URL + "long.js";
@ -17,19 +17,19 @@ add_task(function*() {
// Wait for the source text to load and make sure we're in the right
// place.
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
// TODO: revisit highlighting lines when the debugger opens
//assertHighlightLocation(dbg, "long.js", 66);
// Jump to line 16 and make sure the editor scrolled.
yield selectSource(dbg, "long.js", 16);
await selectSource(dbg, "long.js", 16);
assertHighlightLocation(dbg, "long.js", 16);
// Make sure only one line is ever highlighted and the flash
// animation is cancelled on old lines.
yield selectSource(dbg, "long.js", 17);
yield selectSource(dbg, "long.js", 18);
await selectSource(dbg, "long.js", 17);
await selectSource(dbg, "long.js", 18);
assertHighlightLocation(dbg, "long.js", 18);
is(
findAllElements(dbg, "highlightLine").length,
@ -45,7 +45,7 @@ add_task(function*() {
// fully loaded, and check the highlighted line.
const simple1 = findSource(dbg, "simple1.js");
ok(getSource(getState(), simple1.id).get("loadedState"));
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
ok(getSource(getState(), simple1.id).get("text"));
assertHighlightLocation(dbg, "simple1.js", 6);
});

View File

@ -3,12 +3,12 @@
// Tests that the editor sets the correct mode for different file
// types
add_task(function* () {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
yield selectSource(dbg, "simple1.js");
await selectSource(dbg, "simple1.js");
is(dbg.win.cm.getOption("mode").name, "javascript", "Mode is correct");
yield selectSource(dbg, "doc-scripts.html");
await selectSource(dbg, "doc-scripts.html");
is(dbg.win.cm.getOption("mode").name, "htmlmixed", "Mode is correct");
});

View File

@ -11,44 +11,44 @@ function isElementVisible(dbg, elementName) {
return bpLine && isVisibleWithin(cm, bpLine);
}
add_task(function*() {
add_task(async function() {
// This test runs too slowly on linux debug. I'd like to figure out
// which is the slowest part of this and make it run faster, but to
// fix a frequent failure allow a longer timeout.
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-scripts.html");
const dbg = await initDebugger("doc-scripts.html");
const { selectors: { getSelectedSource }, getState } = dbg;
const simple1 = findSource(dbg, "simple1.js");
const simple2 = findSource(dbg, "simple2.js");
// Set the initial breakpoint.
yield addBreakpoint(dbg, simple1, 4);
await addBreakpoint(dbg, simple1, 4);
ok(!getSelectedSource(getState()), "No selected source");
// Call the function that we set a breakpoint in.
invokeInTab("main");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
// Step through to another file and make sure it's paused in the
// right place.
yield stepIn(dbg);
await stepIn(dbg);
assertPausedLocation(dbg);
// Step back out to the initial file.
yield stepOut(dbg);
yield stepOut(dbg);
await stepOut(dbg);
await stepOut(dbg);
assertPausedLocation(dbg);
yield resume(dbg);
await resume(dbg);
// Make sure that we can set a breakpoint on a line out of the
// viewport, and that pausing there scrolls the editor to it.
let longSrc = findSource(dbg, "long.js");
yield addBreakpoint(dbg, longSrc, 66);
await addBreakpoint(dbg, longSrc, 66);
invokeInTab("testModel");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
ok(isElementVisible(dbg, "breakpoint"), "Breakpoint is visible");
});

View File

@ -53,32 +53,32 @@ async function editExpression(dbg, input) {
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
}
add_task(function*() {
const dbg = yield initDebugger("doc-script-switching.html");
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");
invokeInTab("firstCall");
yield waitForPaused(dbg);
await waitForPaused(dbg);
yield addExpression(dbg, "f");
await addExpression(dbg, "f");
is(getLabel(dbg, 1), "f");
is(getValue(dbg, 1), "(unavailable)");
yield editExpression(dbg, "oo");
await editExpression(dbg, "oo");
is(getLabel(dbg, 1), "foo()");
// There is no "value" element for functions.
assertEmptyValue(dbg, 1);
yield addExpression(dbg, "location");
await addExpression(dbg, "location");
is(getLabel(dbg, 2), "location");
ok(getValue(dbg, 2).includes("Location"), "has a value");
// can expand an expression
toggleExpression(dbg, 2);
yield waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
await waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
yield deleteExpression(dbg, "foo");
yield deleteExpression(dbg, "location");
await deleteExpression(dbg, "foo");
await deleteExpression(dbg, "location");
is(findAllElements(dbg, "expressionNodes").length, 0);
});

View File

@ -6,21 +6,21 @@
* 1. pause in the main thread
* 2. pause in the iframe
*/
add_task(function*() {
const dbg = yield initDebugger("doc-iframes.html");
add_task(async function() {
const dbg = await initDebugger("doc-iframes.html");
// test pausing in the main thread
yield reload(dbg);
yield waitForPaused(dbg);
await reload(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
// test pausing in the iframe
yield resume(dbg);
yield waitForPaused(dbg);
await resume(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
// test pausing in the iframe
yield resume(dbg);
yield waitForPaused(dbg);
await resume(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
});

View File

@ -10,26 +10,26 @@ function countSources(dbg) {
* Test navigating
* navigating while paused will reset the pause state and sources
*/
add_task(function*() {
const dbg = yield initDebugger("doc-script-switching.html");
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");
const { selectors: { getSelectedSource, getPause }, getState } = dbg;
invokeInTab("firstCall");
yield waitForPaused(dbg);
await waitForPaused(dbg);
yield navigate(dbg, "doc-scripts.html", "simple1.js");
yield addBreakpoint(dbg, "simple1.js", 4);
await navigate(dbg, "doc-scripts.html", "simple1.js");
await addBreakpoint(dbg, "simple1.js", 4);
invokeInTab("main");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
is(countSources(dbg), 4, "4 sources are loaded.");
yield navigate(dbg, "about:blank");
yield waitForDispatch(dbg, "NAVIGATE");
await navigate(dbg, "about:blank");
await waitForDispatch(dbg, "NAVIGATE");
is(countSources(dbg), 0, "0 sources are loaded.");
ok(!getPause(getState()), "No pause state exists");
yield navigate(
await navigate(
dbg,
"doc-scripts.html",
"simple1.js",
@ -41,10 +41,12 @@ add_task(function*() {
is(countSources(dbg), 4, "4 sources are loaded.");
// Test that the current select source persists across reloads
yield selectSource(dbg, "long.js");
yield reload(dbg, "long.js");
await selectSource(dbg, "long.js");
await reload(dbg, "long.js");
ok(
getSelectedSource(getState()).get("url").includes("long.js"),
getSelectedSource(getState())
.get("url")
.includes("long.js"),
"Selected source is long.js"
);
});

View File

@ -16,30 +16,30 @@ function caughtException() {
3. pause on a caught error
4. skip a caught error
*/
add_task(function*() {
const dbg = yield initDebugger("doc-exceptions.html");
add_task(async function() {
const dbg = await initDebugger("doc-exceptions.html");
// test skipping an uncaught exception
yield uncaughtException();
await uncaughtException();
ok(!isPaused(dbg));
// Test pausing on an uncaught exception
yield togglePauseOnExceptions(dbg, true, false);
await togglePauseOnExceptions(dbg, true, false);
uncaughtException();
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
yield resume(dbg);
await resume(dbg);
// Test pausing on a caught Error
caughtException();
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
yield resume(dbg);
await resume(dbg);
// Test skipping a caught error
yield togglePauseOnExceptions(dbg, true, true);
await togglePauseOnExceptions(dbg, true, true);
caughtException();
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
yield resume(dbg);
await resume(dbg);
});

View File

@ -3,21 +3,21 @@
// Tests pretty-printing a source that is currently paused.
add_task(function*() {
const dbg = yield initDebugger("doc-minified.html");
add_task(async function() {
const dbg = await initDebugger("doc-minified.html");
yield selectSource(dbg, "math.min.js");
yield addBreakpoint(dbg, "math.min.js", 2);
await selectSource(dbg, "math.min.js");
await addBreakpoint(dbg, "math.min.js", 2);
invokeInTab("arithmetic");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
clickElement(dbg, "prettyPrintButton");
yield waitForDispatch(dbg, "SELECT_SOURCE");
await waitForDispatch(dbg, "SELECT_SOURCE");
// this doesnt work yet
// assertPausedLocation(dbg);
yield resume(dbg);
await resume(dbg);
});

View File

@ -3,13 +3,13 @@
// Tests basic pretty-printing functionality.
add_task(function*() {
const dbg = yield initDebugger("doc-minified.html");
add_task(async function() {
const dbg = await initDebugger("doc-minified.html");
yield selectSource(dbg, "math.min.js", 2);
await selectSource(dbg, "math.min.js", 2);
clickElement(dbg, "prettyPrintButton");
yield waitForSource(dbg, "math.min.js:formatted");
await waitForSource(dbg, "math.min.js:formatted");
const ppSrc = findSource(dbg, "math.min.js:formatted");
ok(ppSrc, "Pretty-printed source exists");
@ -17,19 +17,19 @@ add_task(function*() {
// this is not implemented yet
// assertHighlightLocation(dbg, "math.min.js:formatted", 18);
yield addBreakpoint(dbg, ppSrc, 18);
await addBreakpoint(dbg, ppSrc, 18);
invokeInTab("arithmetic");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
yield stepOver(dbg);
await stepOver(dbg);
assertPausedLocation(dbg);
yield resume(dbg);
await resume(dbg);
// The pretty-print button should go away in the pretty-printed
// source.
ok(!findElement(dbg, "editorFooter"), "Footer is hidden");
yield selectSource(dbg, "math.min.js");
await selectSource(dbg, "math.min.js");
ok(findElement(dbg, "editorFooter"), "Footer is hidden");
});

View File

@ -23,14 +23,14 @@ function onLoadObjectProperties(dbg) {
return waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
}
add_task(function*() {
const dbg = yield initDebugger("doc-script-mutate.html");
add_task(async function() {
const dbg = await initDebugger("doc-script-mutate.html");
toggleScopes(dbg);
let onPaused = waitForPaused(dbg);
invokeInTab("mutate");
yield onPaused;
await onPaused;
is(
getScopeNodeLabel(dbg, 2),
@ -44,7 +44,7 @@ add_task(function*() {
);
info("Expand `phonebook`");
yield expandNode(dbg, 3);
await expandNode(dbg, 3);
is(
getScopeNodeLabel(dbg, 4),
"S",
@ -52,7 +52,7 @@ add_task(function*() {
);
info("Expand `S`");
yield expandNode(dbg, 4);
await expandNode(dbg, 4);
is(
getScopeNodeLabel(dbg, 5),
"sarah",
@ -65,7 +65,7 @@ add_task(function*() {
);
info("Expand `sarah`");
yield expandNode(dbg, 5);
await expandNode(dbg, 5);
is(
getScopeNodeLabel(dbg, 6),
"lastName",
@ -79,8 +79,8 @@ add_task(function*() {
info("Resuming");
onPaused = waitForPaused(dbg);
yield resume(dbg);
yield onPaused;
await resume(dbg);
await onPaused;
is(
getScopeNodeLabel(dbg, 2),

View File

@ -9,23 +9,23 @@ function getLabel(dbg, index) {
return findElement(dbg, "scopeNode", index).innerText;
}
add_task(function*() {
const dbg = yield initDebugger("doc-script-switching.html");
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");
toggleScopes(dbg);
invokeInTab("firstCall");
yield waitForPaused(dbg);
await waitForPaused(dbg);
is(getLabel(dbg, 1), "secondCall");
is(getLabel(dbg, 2), "<this>");
is(getLabel(dbg, 4), "foo()");
toggleNode(dbg, 4);
yield waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
await waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
is(getLabel(dbg, 5), "arguments");
yield stepOver(dbg);
await stepOver(dbg);
is(getLabel(dbg, 4), "foo()");
is(getLabel(dbg, 5), "Window");
});

View File

@ -12,30 +12,30 @@ function getFocusedEl(dbg) {
return doc.activeElement;
}
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
const {
selectors: { getBreakpoints, getBreakpoint, getActiveSearch },
getState
} = dbg;
const source = findSource(dbg, "simple1.js");
yield selectSource(dbg, source.url);
await selectSource(dbg, source.url);
const cm = getCM(dbg);
pressKey(dbg, "fileSearch");
is(dbg.selectors.getActiveSearchState(dbg.getState()), "file");
is(dbg.selectors.getActiveSearch(dbg.getState()), "file");
// test closing and re-opening
pressKey(dbg, "Escape");
is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
is(dbg.selectors.getActiveSearch(dbg.getState()), null);
pressKey(dbg, "fileSearch");
const el = getFocusedEl(dbg);
type(dbg, "con");
yield waitForSearchState(dbg);
await waitForSearchState(dbg);
const state = cm.state.search;
@ -55,7 +55,7 @@ add_task(function*() {
is(state.posFrom.line, 4);
// selecting another source keeps search open
yield selectSource(dbg, "simple2");
await selectSource(dbg, "simple2");
pressKey(dbg, "Enter");
is(state.posFrom.line, 0);
});

View File

@ -5,23 +5,21 @@ function openProjectSearch(dbg) {
synthesizeKeyShortcut("CmdOrCtrl+Shift+F");
return waitForState(
dbg,
state => dbg.selectors.getActiveSearchState(state) === "project"
state => dbg.selectors.getActiveSearch(state) === "project"
);
}
function closeProjectSearch(dbg) {
pressKey(dbg, "Escape");
return waitForState(dbg, state => !dbg.selectors.getActiveSearchState(state));
}
function getResult(dbg) {
return findElementWithSelector(dbg, ".managed-tree .result");
return waitForState(dbg, state => !dbg.selectors.getActiveSearch(state));
}
async function selectResult(dbg) {
const item = getResult(dbg);
const select = waitForDispatch(dbg, "SELECT_SOURCE");
item.click();
const select = waitForState(
dbg,
() => !dbg.selectors.getActiveSearch(dbg.getState())
);
await clickElement(dbg, "fileMatch");
return select;
}
@ -36,28 +34,29 @@ function getResultsCount(dbg) {
}
// Testing project search
add_task(function*() {
add_task(async function() {
Services.prefs.setBoolPref(
"devtools.debugger.project-text-search-enabled",
true
);
const dbg = yield initDebugger("doc-script-switching.html", "switching-01");
const dbg = await initDebugger("doc-script-switching.html", "switching-01");
yield selectSource(dbg, "switching-01");
await selectSource(dbg, "switching-01");
// test opening and closing
yield openProjectSearch(dbg);
yield closeProjectSearch(dbg);
await openProjectSearch(dbg);
await closeProjectSearch(dbg);
yield openProjectSearch(dbg);
await openProjectSearch(dbg);
type(dbg, "first");
pressKey(dbg, "Enter");
yield waitForState(dbg, () => getResultsCount(dbg) === 1);
await waitForState(dbg, () => getResultsCount(dbg) === 1);
yield selectResult(dbg);
is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
await selectResult(dbg);
is(dbg.selectors.getActiveSearch(dbg.getState()), null);
const selectedSource = dbg.selectors.getSelectedSource(dbg.getState());
ok(selectedSource.get("url").includes("switching-01"));

View File

@ -2,22 +2,22 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Testing source search
add_task(function*() {
const dbg = yield initDebugger("doc-script-switching.html");
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html");
// test opening and closing
pressKey(dbg, "sourceSearch");
is(dbg.selectors.getActiveSearchState(dbg.getState()), "source");
is(dbg.selectors.getActiveSearch(dbg.getState()), "source");
pressKey(dbg, "Escape");
is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
is(dbg.selectors.getActiveSearch(dbg.getState()), null);
pressKey(dbg, "sourceSearch");
yield waitForElement(dbg, "input");
await waitForElement(dbg, "input");
findElementWithSelector(dbg, "input").focus();
type(dbg, "sw");
pressKey(dbg, "Enter");
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
let source = dbg.selectors.getSelectedSource(dbg.getState());
ok(source.get("url").match(/switching-01/), "first source is selected");
@ -28,7 +28,7 @@ add_task(function*() {
pressKey(dbg, "Down");
pressKey(dbg, "Enter");
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
source = dbg.selectors.getSelectedSource(dbg.getState());
ok(source.get("url").match(/switching-02/), "second source is selected");
});

View File

@ -11,18 +11,18 @@ function resultCount(dbg) {
}
// Testing function search
add_task(function*() {
const dbg = yield initDebugger("doc-script-switching.html", "switching-01");
add_task(async function() {
const dbg = await initDebugger("doc-script-switching.html", "switching-01");
yield selectSource(dbg, "switching-01");
await selectSource(dbg, "switching-01");
// test opening and closing
yield openFunctionSearch(dbg);
is(dbg.selectors.getActiveSearchState(dbg.getState()), "symbol");
await openFunctionSearch(dbg);
is(dbg.selectors.getActiveSearch(dbg.getState()), "symbol");
pressKey(dbg, "Escape");
is(dbg.selectors.getActiveSearchState(dbg.getState()), null);
is(dbg.selectors.getActiveSearch(dbg.getState()), null);
yield openFunctionSearch(dbg);
await openFunctionSearch(dbg);
is(resultCount(dbg), 1);
type(dbg, "x");

View File

@ -4,20 +4,20 @@
// Test that an error while loading a sourcemap does not break
// debugging.
add_task(function*() {
add_task(async function() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemap-bogus.html");
const dbg = await initDebugger("doc-sourcemap-bogus.html");
const { selectors: { getSources }, getState } = dbg;
yield selectSource(dbg, "bogus-map.js");
await selectSource(dbg, "bogus-map.js");
// We should still be able to set breakpoints and pause in the
// generated source.
yield addBreakpoint(dbg, "bogus-map.js", 4);
await addBreakpoint(dbg, "bogus-map.js", 4);
invokeInTab("runCode");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
// Make sure that only the single generated source exists. The

View File

@ -1,18 +1,18 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
add_task(function*() {
add_task(async function() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemaps.html");
const dbg = await initDebugger("doc-sourcemaps.html");
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
yield waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
await waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
ok(true, "Original sources exist");
const entrySrc = findSource(dbg, "entry.js");
yield selectSource(dbg, entrySrc);
await selectSource(dbg, entrySrc);
ok(
dbg.win.cm.getValue().includes("window.keepMeAlive"),
"Original source text loaded correctly"
@ -20,19 +20,19 @@ add_task(function*() {
// Test that breakpoint sliding is not attempted. The breakpoint
// should not move anywhere.
yield addBreakpoint(dbg, entrySrc, 13);
await addBreakpoint(dbg, entrySrc, 13);
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
ok(
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
"Breakpoint has correct line"
);
yield addBreakpoint(dbg, entrySrc, 15);
yield disableBreakpoint(dbg, entrySrc, 15);
await addBreakpoint(dbg, entrySrc, 15);
await disableBreakpoint(dbg, entrySrc, 15);
// Test reloading the debugger
yield reload(dbg, "opts.js");
yield waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
await reload(dbg, "opts.js");
await waitForDispatch(dbg, "LOAD_SOURCE_TEXT");
is(getBreakpoints(getState()).size, 2, "One breakpoint exists");

View File

@ -33,30 +33,30 @@ function clickGutter(dbg, line) {
clickElement(dbg, "gutter", line);
}
add_task(function*() {
add_task(async function() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemaps.html");
const dbg = await initDebugger("doc-sourcemaps.html");
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
yield waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
await waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js");
ok(true, "Original sources exist");
const bundleSrc = findSource(dbg, "bundle.js");
yield selectSource(dbg, bundleSrc);
await selectSource(dbg, bundleSrc);
yield clickGutter(dbg, 13);
yield waitForDispatch(dbg, "ADD_BREAKPOINT");
await clickGutter(dbg, 13);
await waitForDispatch(dbg, "ADD_BREAKPOINT");
assertEditorBreakpoint(dbg, 13, true);
yield clickGutter(dbg, 13);
yield waitForDispatch(dbg, "REMOVE_BREAKPOINT");
await clickGutter(dbg, 13);
await waitForDispatch(dbg, "REMOVE_BREAKPOINT");
is(getBreakpoints(getState()).size, 0, "No breakpoints exists");
const entrySrc = findSource(dbg, "entry.js");
yield selectSource(dbg, entrySrc);
await selectSource(dbg, entrySrc);
ok(
dbg.win.cm.getValue().includes("window.keepMeAlive"),
"Original source text loaded correctly"
@ -64,25 +64,25 @@ add_task(function*() {
// Test that breakpoint sliding is not attempted. The breakpoint
// should not move anywhere.
yield addBreakpoint(dbg, entrySrc, 13);
await addBreakpoint(dbg, entrySrc, 13);
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
assertBreakpointExists(dbg, entrySrc, 13);
// Test breaking on a breakpoint
yield addBreakpoint(dbg, "entry.js", 15);
await addBreakpoint(dbg, "entry.js", 15);
is(getBreakpoints(getState()).size, 2, "Two breakpoints exist");
assertBreakpointExists(dbg, entrySrc, 15);
invokeInTab("keepMeAlive");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
yield stepIn(dbg);
await stepIn(dbg);
assertPausedLocation(dbg);
yield stepOver(dbg);
await stepOver(dbg);
assertPausedLocation(dbg);
yield stepOut(dbg);
yield stepOut(dbg);
await stepOut(dbg);
await stepOut(dbg);
assertPausedLocation(dbg);
});

View File

@ -6,22 +6,22 @@
// This source map does not have source contents, so it's fetched separately
add_task(function*() {
add_task(async function() {
// NOTE: the CORS call makes the test run times inconsistent
requestLongerTimeout(2);
const dbg = yield initDebugger("doc-sourcemaps2.html");
const dbg = await initDebugger("doc-sourcemaps2.html");
const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg;
yield waitForSources(dbg, "main.js", "main.min.js");
await waitForSources(dbg, "main.js", "main.min.js");
ok(true, "Original sources exist");
const mainSrc = findSource(dbg, "main.js");
yield selectSource(dbg, mainSrc);
await selectSource(dbg, mainSrc);
// Test that breakpoint is not off by a line.
yield addBreakpoint(dbg, mainSrc, 4);
await addBreakpoint(dbg, mainSrc, 4);
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
ok(
getBreakpoint(getState(), { sourceId: mainSrc.id, line: 4, column: 2 }),
@ -30,6 +30,6 @@ add_task(function*() {
invokeInTab("logMessage");
yield waitForPaused(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
});

View File

@ -3,27 +3,27 @@
// Tests that the source tree works.
function* waitForSourceCount(dbg, i) {
async function waitForSourceCount(dbg, i) {
// We are forced to wait until the DOM nodes appear because the
// source tree batches its rendering.
yield waitUntil(() => {
await waitUntil(() => {
return findAllElements(dbg, "sourceNodes").length === i;
});
}
add_task(function*() {
const dbg = yield initDebugger("doc-sources.html");
add_task(async function() {
const dbg = await initDebugger("doc-sources.html");
const { selectors: { getSelectedSource }, getState } = dbg;
yield waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
// Expand nodes and make sure more sources appear.
is(findAllElements(dbg, "sourceNodes").length, 2);
clickElement(dbg, "sourceArrow", 2);
await clickElement(dbg, "sourceArrow", 2);
is(findAllElements(dbg, "sourceNodes").length, 7);
clickElement(dbg, "sourceArrow", 3);
await clickElement(dbg, "sourceArrow", 3);
is(findAllElements(dbg, "sourceNodes").length, 8);
// Select a source.
@ -32,14 +32,16 @@ add_task(function*() {
"Source is not focused"
);
const selected = waitForDispatch(dbg, "SELECT_SOURCE");
clickElement(dbg, "sourceNode", 4);
yield selected;
await clickElement(dbg, "sourceNode", 4);
await selected;
ok(
findElementWithSelector(dbg, ".sources-list .focused"),
"Source is focused"
);
ok(
getSelectedSource(getState()).get("url").includes("nested-source.js"),
getSelectedSource(getState())
.get("url")
.includes("nested-source.js"),
"The right source is selected"
);
@ -50,7 +52,7 @@ add_task(function*() {
content.document.body.appendChild(script);
});
yield waitForSourceCount(dbg, 9);
await waitForSourceCount(dbg, 9);
is(
findElement(dbg, "sourceNode", 7).textContent,
"math.min.js",
@ -60,16 +62,16 @@ add_task(function*() {
// Make sure named eval sources appear in the list.
});
add_task(function*() {
const dbg = yield initDebugger("doc-sources.html");
add_task(async function() {
const dbg = await initDebugger("doc-sources.html");
const { selectors: { getSelectedSource }, getState } = dbg;
yield waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js");
ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
content.eval("window.evaledFunc = function() {} //# sourceURL=evaled.js");
});
yield waitForSourceCount(dbg, 3);
await waitForSourceCount(dbg, 3);
is(
findElement(dbg, "sourceNode", 3).textContent,
"(no domain)",
@ -78,8 +80,8 @@ add_task(function*() {
// work around: the folder is rendered at the bottom, so we close the
// root folder and open the (no domain) folder
clickElement(dbg, "sourceArrow", 3);
yield waitForSourceCount(dbg, 4);
await clickElement(dbg, "sourceArrow", 3);
await waitForSourceCount(dbg, 4);
is(
findElement(dbg, "sourceNode", 4).textContent,

View File

@ -7,33 +7,33 @@ function countTabs(dbg) {
return findElement(dbg, "sourceTabs").children.length;
}
add_task(function*() {
let dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
let dbg = await initDebugger("doc-scripts.html");
yield selectSource(dbg, "simple1");
yield selectSource(dbg, "simple2");
await selectSource(dbg, "simple1");
await selectSource(dbg, "simple2");
is(countTabs(dbg), 2);
// Test reloading the debugger
yield reload(dbg, "simple1", "simple2");
await reload(dbg, "simple1", "simple2");
is(countTabs(dbg), 2);
yield waitForSelectedSource(dbg);
await waitForSelectedSource(dbg);
// Test reloading the debuggee a second time
yield reload(dbg, "simple1", "simple2");
await reload(dbg, "simple1", "simple2");
is(countTabs(dbg), 2);
yield waitForSelectedSource(dbg);
await waitForSelectedSource(dbg);
});
add_task(function*() {
let dbg = yield initDebugger("doc-scripts.html", "simple1", "simple2");
add_task(async function() {
let dbg = await initDebugger("doc-scripts.html", "simple1", "simple2");
yield selectSource(dbg, "simple1");
yield selectSource(dbg, "simple2");
await selectSource(dbg, "simple1");
await selectSource(dbg, "simple2");
closeTab(dbg, "simple1");
closeTab(dbg, "simple2");
// Test reloading the debugger
yield reload(dbg, "simple1", "simple2");
await reload(dbg, "simple1", "simple2");
is(countTabs(dbg), 0);
});

View File

@ -25,10 +25,10 @@ function getSplitConsole(dbg) {
});
}
add_task(function*() {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
yield selectSource(dbg, "long");
await selectSource(dbg, "long");
dbg.win.cm.scrollTo(0, 284);
pressKey(dbg, "inspector");

View File

@ -25,22 +25,22 @@ function pressStepOut(dbg) {
return waitForPaused(dbg);
}
add_task(function*() {
const dbg = yield initDebugger("doc-debugger-statements.html");
add_task(async function() {
const dbg = await initDebugger("doc-debugger-statements.html");
yield reload(dbg);
yield waitForPaused(dbg);
await reload(dbg);
await waitForPaused(dbg);
assertPausedLocation(dbg);
yield pressResume(dbg);
await pressResume(dbg);
assertPausedLocation(dbg);
yield pressStepIn(dbg);
await pressStepIn(dbg);
assertPausedLocation(dbg);
yield pressStepOut(dbg);
await pressStepOut(dbg);
assertPausedLocation(dbg);
yield pressStepOver(dbg);
await pressStepOver(dbg);
assertPausedLocation(dbg);
});

View File

@ -3,27 +3,36 @@
// Tests that keyboard navigation into and out of debugger code editor
add_task(function* () {
const dbg = yield initDebugger("doc-scripts.html");
add_task(async function() {
const dbg = await initDebugger("doc-scripts.html");
let doc = dbg.win.document;
yield selectSource(dbg, "simple2");
await selectSource(dbg, "simple2");
yield waitForElement(dbg, ".CodeMirror");
await waitForElement(dbg, ".CodeMirror");
findElementWithSelector(dbg, ".CodeMirror").focus();
// Enter code editor
pressKey(dbg, "Enter");
is(findElementWithSelector(dbg, "textarea"), doc.activeElement,
"Editor is enabled");
is(
findElementWithSelector(dbg, "textarea"),
doc.activeElement,
"Editor is enabled"
);
// Exit code editor and focus on container
pressKey(dbg, "Escape");
is(findElementWithSelector(dbg, ".CodeMirror"), doc.activeElement,
"Focused on container");
is(
findElementWithSelector(dbg, ".CodeMirror"),
doc.activeElement,
"Focused on container"
);
// Enter code editor
pressKey(dbg, "Tab");
is(findElementWithSelector(dbg, "textarea"), doc.activeElement,
"Editor is enabled");
is(
findElementWithSelector(dbg, "textarea"),
doc.activeElement,
"Editor is enabled"
);
});

View File

@ -9,5 +9,7 @@
</head>
<body>
<button onclick="main()">Main</button>
</body>
</html>

View File

@ -211,8 +211,9 @@ function waitForSource(dbg, url) {
});
}
function waitForElement(dbg, selector) {
return waitUntil(() => findElementWithSelector(dbg, selector));
async function waitForElement(dbg, selector) {
await waitUntil(() => findElementWithSelector(dbg, selector));
return findElementWithSelector(dbg, selector);
}
function waitForSelectedSource(dbg, sourceId) {
@ -290,7 +291,9 @@ function assertHighlightLocation(dbg, source, line) {
"Highlighted line is visible"
);
ok(
getCM(dbg).lineInfo(line - 1).wrapClass.includes("highlight-line"),
getCM(dbg)
.lineInfo(line - 1)
.wrapClass.includes("highlight-line"),
"Line is highlighted"
);
}
@ -730,7 +733,8 @@ const selectors = {
sourceNode: i => `.sources-list .tree-node:nth-child(${i})`,
sourceNodes: ".sources-list .tree-node",
sourceArrow: i => `.sources-list .tree-node:nth-child(${i}) .arrow`,
resultItems: `.result-list .result-item`
resultItems: `.result-list .result-item`,
fileMatch: `.managed-tree .result`
};
function getSelector(elementName, ...args) {
@ -770,12 +774,17 @@ function findAllElements(dbg, elementName, ...args) {
* @return {Promise}
* @static
*/
function clickElement(dbg, elementName, ...args) {
async function clickElement(dbg, elementName, ...args) {
const selector = getSelector(elementName, ...args);
const el = findElement(dbg, elementName, ...args);
const el = await waitForElement(dbg, selector);
el.scrollIntoView();
return EventUtils.synthesizeMouseAtCenter(
return clickElementWithSelector(dbg, selector);
}
function clickElementWithSelector(dbg, selector) {
EventUtils.synthesizeMouseAtCenter(
findElementWithSelector(dbg, selector),
{},
dbg.win

View File

@ -26,6 +26,7 @@
.accordion ._header {
background-color: var(--accordion-header-background);
border-bottom: 1px solid var(--theme-splitter-color);
color: var(--theme-toolbar-color);
cursor: pointer;
font-size: 12px;
padding: 4px;

View File

@ -143,6 +143,10 @@ sources.search.alt.key=CmdOrCtrl+O
# full project text search for searching all the files the debugger has seen.
projectTextSearch.key=CmdOrCtrl+Shift+F
# LOCALIZATION NOTE (functionSearch.key): A key shortcut to open the
# modal for searching functions in a file.
functionSearch.key=CmdOrCtrl+Shift+O
# LOCALIZATION NOTE (projectTextSearch.placeholder): A placeholder shown
# when searching across all of the files in a project.
projectTextSearch.placeholder=Find in files…
@ -395,6 +399,10 @@ sourceFooter.unblackbox.accesskey=b
# with a blackboxed source
sourceFooter.blackboxed=Blackboxed Source
# LOCALIZATION NOTE (sourceFooter.codeCoverage): Text associated
# with a code coverage button
sourceFooter.codeCoverage=Code Coverage
# LOCALIZATION NOTE (sourceTabs.closeTabButtonTooltip): The tooltip that is displayed
# for close tab button in source tabs.
sourceTabs.closeTabButtonTooltip=Close tab
@ -421,6 +429,9 @@ scopes.block=Block
# LOCALIZATION NOTE (sources.header): Sources left sidebar header
sources.header=Sources
# LOCALIZATION NOTE (outline.header): Outline left sidebar header
outline.header=Outline
# LOCALIZATION NOTE (sources.search): Sources left sidebar prompt
# e.g. Cmd+P to search. On a mac, we use the command unicode character.
# On windows, it's ctrl.
@ -444,9 +455,13 @@ welcome.search=%S to search for sources
# a mac we use the unicode character.
welcome.findInFiles=%S to find in files
# LOCALIZATION NOTE (welcome.searchFunction): Label displayed in the welcome
# panel. %S is replaced by the keyboard shortcut to search for functions.
welcome.searchFunction=%S to search for functions in file
# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search
# prompt for searching for files.
sourceSearch.search=Search Sources…
sourceSearch.search=Search sources…
# LOCALIZATION NOTE (sourceSearch.noResults): The center pane Source Search
# message when the query did not match any of the sources.

View File

@ -38,5 +38,5 @@ pref("devtools.debugger.expressions", "[]");
pref("devtools.debugger.file-search-case-sensitive", false);
pref("devtools.debugger.file-search-whole-word", false);
pref("devtools.debugger.file-search-regex-match", false);
pref("devtools.debugger.features.async-stepping", false);
pref("devtools.debugger.features.async-stepping", true);
pref("devtools.debugger.project-text-search-enabled", true);

View File

@ -81,7 +81,7 @@
.theme-light .tabs .tabs-menu-item {
margin: 0;
padding: 0;
color: var(--theme-content-color1);
color: var(--theme-toolbar-color);
}
.theme-dark .tabs .tabs-menu-item:last-child,

View File

@ -109,7 +109,6 @@ body {
flex-direction: column;
height: 100%;
overflow: hidden;
color: var(--theme-content-color3);
}
/* The top toolbar, containing the toggle-all button. And the timeline toolbar,

View File

@ -222,8 +222,9 @@
}
.ruleview-header {
background-color: var(--rule-header-background-color);
background: var(--rule-header-background-color);
border-bottom: 1px solid var(--theme-splitter-color);
color: var(--theme-toolbar-color);
font-size: 12px;
padding: 4px;
width: 100%;

View File

@ -140,12 +140,8 @@
-moz-box-flex: initial;
}
.theme-dark .devtools-tab {
color: var(--theme-body-color-alt);
}
.theme-light .devtools-tab {
color: var(--theme-body-color);
.devtools-tab {
color: var(--theme-toolbar-color);
}
.theme-dark .devtools-tab:hover {

View File

@ -24,6 +24,7 @@
/* Toolbar */
--theme-tab-toolbar-background: var(--grey-10);
--theme-toolbar-background: var(--grey-10);
--theme-toolbar-color: var(--grey-90);
--theme-toolbar-background-hover: rgba(221, 225, 228, 0.66);
--theme-toolbar-background-alt: #f5f5f5;
--theme-toolbar-hover: rgba(170, 170, 170, .2);
@ -41,7 +42,7 @@
--theme-comment: #696969;
--theme-comment-alt: #ccd1d5;
--theme-body-color: #393f4c;
--theme-body-color: var(--grey-60);
--theme-body-color-alt: #585959;
--theme-body-color-inactive: #999797;
--theme-content-color1: #292e33;
@ -99,6 +100,7 @@
/* Toolbar */
--theme-tab-toolbar-background: var(--grey-90);
--theme-toolbar-background: var(--grey-90);
--theme-toolbar-color: var(--grey-40);
--theme-toolbar-background-hover: #20232B;
--theme-toolbar-background-alt: #2F343E;
--theme-toolbar-hover: rgba(110, 120, 130, 0.1);
@ -116,11 +118,11 @@
--theme-comment: #757873;
--theme-comment-alt: #5a6375;
--theme-body-color: #8fa1b2;
--theme-body-color: var(--grey-40);
--theme-body-color-alt: #b6babf;
--theme-body-color-inactive: #8fa1b2;
--theme-body-color-inactive: var(--grey-40);
--theme-content-color1: #a9bacb;
--theme-content-color2: #8fa1b2;
--theme-content-color2: var(--grey-40);
--theme-content-color3: #5f7387;
--theme-highlight-green: #00ff7f;

View File

@ -840,17 +840,20 @@ nsCopySupport::FireClipboardEvent(EventMessage aEventMessage,
doDefault = (status != nsEventStatus_eConsumeNoDefault);
}
// When this function exits, the event dispatch is over. We want to disconnect
// our DataTransfer, which means setting its mode to `Protected` and clearing
// all stored data, before we return.
auto clearAfter = MakeScopeExit([&] {
if (clipboardData) {
clipboardData->SetMode(DataTransfer::Mode::Protected);
clipboardData->ClearAll();
}
});
// No need to do anything special during a paste. Either an event listener
// took care of it and cancelled the event, or the caller will handle it.
// Return true to indicate that the event wasn't cancelled.
if (originalEventMessage == ePaste) {
// Clear and mark the clipboardData as readonly. This prevents someone
// from reading the clipboard contents after the paste event has fired.
if (clipboardData) {
clipboardData->ClearAll();
clipboardData->SetReadOnly();
}
if (aActionTaken) {
*aActionTaken = true;
}

View File

@ -4534,7 +4534,7 @@ nsPIDOMWindowInner::UpdateWebSocketCount(int32_t aDelta)
return;
}
if (!IsTopInnerWindow()) {
if (mTopInnerWindow && !IsTopInnerWindow()) {
mTopInnerWindow->UpdateWebSocketCount(aDelta);
}
@ -4562,7 +4562,7 @@ nsPIDOMWindowInner::UpdateUserMediaCount(int32_t aDelta)
return;
}
if (!IsTopInnerWindow()) {
if (mTopInnerWindow && !IsTopInnerWindow()) {
mTopInnerWindow->UpdateUserMediaCount(aDelta);
}

View File

@ -21,6 +21,7 @@ class nsAttrName;
class nsTextFragment;
class nsIFrame;
class nsXBLBinding;
class nsITextControlElement;
namespace mozilla {
class EventChainPreVisitor;
@ -980,6 +981,11 @@ public:
virtual bool OwnedOnlyByTheDOMTree() { return false; }
virtual already_AddRefed<nsITextControlElement> GetAsTextControlElement()
{
return nullptr;
}
protected:
/**
* Hook for implementing GetID. This is guaranteed to only be

View File

@ -599,8 +599,14 @@ protected:
template<typename A, typename B>
RangeBoundaryBase& operator=(const RangeBoundaryBase<A,B>& aOther)
{
mParent = aOther.mParent;
mRef = aOther.mRef;
// Since the member variables may be nsCOMPtrs, better to try to avoid
// extra Release/AddRef calls.
if (mParent != aOther.mParent) {
mParent = aOther.mParent;
}
if (mRef != aOther.mRef) {
mRef = aOther.mRef;
}
mOffset = aOther.mOffset;
return *this;
}

View File

@ -343,7 +343,7 @@ TypeUtils::ToInternalRequest(const CacheRequest& aIn)
nsCOMPtr<nsIInputStream> stream = ReadStream::Create(aIn.body());
internalRequest->SetBody(stream);
internalRequest->SetBody(stream, -1);
return internalRequest.forget();
}

View File

@ -81,6 +81,27 @@ enum CustomClipboardTypeId {
eCustomClipboardTypeId_String
};
static DataTransfer::Mode
ModeForEvent(EventMessage aEventMessage)
{
switch (aEventMessage) {
case eCut:
case eCopy:
case eDragStart:
// For these events, we want to be able to add data to the data transfer,
// Otherwise, the data is already present.
return DataTransfer::Mode::ReadWrite;
case eDrop:
case ePaste:
case ePasteNoFormatting:
// For these events we want to be able to read the data which is stored in
// the DataTransfer, rather than just the type information.
return DataTransfer::Mode::ReadOnly;
default:
return DataTransfer::Mode::Protected;
}
}
DataTransfer::DataTransfer(nsISupports* aParent, EventMessage aEventMessage,
bool aIsExternal, int32_t aClipboardType)
: mParent(aParent)
@ -88,7 +109,7 @@ DataTransfer::DataTransfer(nsISupports* aParent, EventMessage aEventMessage,
, mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
, mEventMessage(aEventMessage)
, mCursorState(false)
, mReadOnly(true)
, mMode(ModeForEvent(aEventMessage))
, mIsExternal(aIsExternal)
, mUserCancelled(false)
, mIsCrossDomainSubFrameDrop(false)
@ -97,14 +118,9 @@ DataTransfer::DataTransfer(nsISupports* aParent, EventMessage aEventMessage,
, mDragImageY(0)
{
mItems = new DataTransferItemList(this, aIsExternal);
// For these events, we want to be able to add data to the data transfer, so
// clear the readonly state. Otherwise, the data is already present. For
// external usage, cache the data from the native clipboard or drag.
if (aEventMessage == eCut ||
aEventMessage == eCopy ||
aEventMessage == eDragStart) {
mReadOnly = false;
} else if (mIsExternal) {
// For external usage, cache the data from the native clipboard or drag.
if (mIsExternal && mMode != Mode::ReadWrite) {
if (aEventMessage == ePasteNoFormatting) {
mEventMessage = ePaste;
CacheExternalClipboardFormats(true);
@ -134,7 +150,7 @@ DataTransfer::DataTransfer(nsISupports* aParent,
, mEffectAllowed(aEffectAllowed)
, mEventMessage(aEventMessage)
, mCursorState(aCursorState)
, mReadOnly(true)
, mMode(ModeForEvent(aEventMessage))
, mIsExternal(aIsExternal)
, mUserCancelled(aUserCancelled)
, mIsCrossDomainSubFrameDrop(aIsCrossDomainSubFrameDrop)
@ -429,7 +445,7 @@ DataTransfer::ClearData(const Optional<nsAString>& aFormat,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
if (mReadOnly) {
if (IsReadOnly()) {
aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
}
@ -659,6 +675,25 @@ DataTransfer::TypesListMayHaveChanged()
DataTransferBinding::ClearCachedTypesValue(this);
}
already_AddRefed<DataTransfer>
DataTransfer::MozCloneForEvent(const nsAString& aEvent, ErrorResult& aRv)
{
nsCOMPtr<nsIAtom> atomEvt = NS_Atomize(aEvent);
if (!atomEvt) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
EventMessage eventMessage = nsContentUtils::GetEventMessage(atomEvt);
RefPtr<DataTransfer> dt;
nsresult rv = Clone(mParent, eventMessage, false, false, getter_AddRefs(dt));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
return dt.forget();
}
nsresult
DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
uint32_t aIndex,
@ -668,7 +703,7 @@ DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
return NS_OK;
}
if (mReadOnly) {
if (IsReadOnly()) {
return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
}
@ -716,7 +751,7 @@ DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
if (mReadOnly) {
if (IsReadOnly()) {
aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
}
@ -753,7 +788,7 @@ DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv)
{
MOZ_ASSERT(!mReadOnly);
MOZ_ASSERT(!IsReadOnly());
MOZ_ASSERT(aIndex < MozItemCount());
MOZ_ASSERT(aIndex == 0 ||
(mEventMessage != eCut && mEventMessage != eCopy &&
@ -768,7 +803,7 @@ DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
void
DataTransfer::SetDragImage(Element& aImage, int32_t aX, int32_t aY)
{
if (!mReadOnly) {
if (!IsReadOnly()) {
mDragImage = &aImage;
mDragImageX = aX;
mDragImageY = aY;
@ -848,7 +883,7 @@ DataTransfer::GetFiles(bool aRecursiveFlag,
void
DataTransfer::AddElement(Element& aElement, ErrorResult& aRv)
{
if (mReadOnly) {
if (IsReadOnly()) {
aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
return;
}

View File

@ -61,6 +61,14 @@ public:
return static_cast<DataTransfer*>(aArg);
}
/// An enum which represents which "Drag Data Store Mode" the DataTransfer is
/// in according to the spec.
enum class Mode : uint8_t {
ReadWrite,
ReadOnly,
Protected,
};
protected:
// hide the default constructor
@ -68,6 +76,7 @@ protected:
// this constructor is used only by the Clone method to copy the fields as
// needed to a new data transfer.
// NOTE: Do not call this method directly.
DataTransfer(nsISupports* aParent,
EventMessage aEventMessage,
const uint32_t aEffectAllowed,
@ -214,13 +223,25 @@ public:
return mItems;
}
// a readonly dataTransfer cannot have new data added or existing data
// removed. Only the dropEffect and effectAllowed may be modified.
bool IsReadOnly() const {
return mReadOnly;
// Returns the current "Drag Data Store Mode" of the DataTransfer. This
// determines what modifications may be performed on the DataTransfer, and
// what data may be read from it.
Mode GetMode() const {
return mMode;
}
void SetReadOnly() {
mReadOnly = true;
void SetMode(Mode aMode) {
mMode = aMode;
}
// Helper method. Is true if the DataTransfer's mode is ReadOnly or Protected,
// which means that the DataTransfer cannot be modified.
bool IsReadOnly() const {
return mMode != Mode::ReadWrite;
}
// Helper method. Is true if the DataTransfer's mode is Protected, which means
// that DataTransfer type information may be read, but data may not be.
bool IsProtected() const {
return mMode == Mode::Protected;
}
int32_t ClipboardType() const {
@ -278,6 +299,12 @@ public:
return mDragImage;
}
// This method makes a copy of the DataTransfer object, with a few properties
// changed, and the mode updated to reflect the correct mode for the given
// event. This method is used during the drag operation to generate the
// DataTransfer objects for each event after `dragstart`. Event objects will
// lazily clone the DataTransfer stored in the DragSession (which is a clone
// of the DataTransfer used in the `dragstart` event) when requested.
nsresult Clone(nsISupports* aParent, EventMessage aEventMessage,
bool aUserCancelled, bool aIsCrossDomainSubFrameDrop,
DataTransfer** aResult);
@ -295,6 +322,11 @@ public:
// GetTypes being added or removed or changing item kinds.
void TypesListMayHaveChanged();
// Testing method used to emulate internal DataTransfer management.
// NOTE: Please don't use this. See the comments in the webidl for more.
already_AddRefed<DataTransfer> MozCloneForEvent(const nsAString& aEvent,
ErrorResult& aRv);
protected:
// caches text and uri-list data formats that exist in the drag service or
@ -343,9 +375,8 @@ protected:
// Indicates the behavior of the cursor during drag operations
bool mCursorState;
// readonly data transfers may not be modified except the drop effect and
// effect allowed.
bool mReadOnly;
// The current "Drag Data Store Mode" which the DataTransfer is in.
Mode mMode;
// true for drags started without a data transfer, for example, those from
// another application.

View File

@ -503,14 +503,20 @@ DataTransferItem::Data(nsIPrincipal* aPrincipal, ErrorResult& aRv)
{
MOZ_ASSERT(aPrincipal);
nsCOMPtr<nsIVariant> variant = DataNoSecurityCheck();
// If the inbound principal is system, we can skip the below checks, as
// they will trivially succeed.
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
return variant.forget();
return DataNoSecurityCheck();
}
// We should not allow raw data to be accessed from a Protected DataTransfer.
// We don't prevent this access if the accessing document is Chrome.
if (mDataTransfer->IsProtected()) {
return nullptr;
}
nsCOMPtr<nsIVariant> variant = DataNoSecurityCheck();
MOZ_ASSERT(!ChromeOnly(), "Non-chrome code shouldn't see a ChromeOnly DataTransferItem");
if (ChromeOnly()) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);

View File

@ -562,6 +562,14 @@ DataTransferItemList::GenerateFiles(FileList* aFiles,
{
MOZ_ASSERT(aFiles);
MOZ_ASSERT(aFilesPrincipal);
// For non-system principals, the Files list should be empty if the
// DataTransfer is protected.
if (!nsContentUtils::IsSystemPrincipal(aFilesPrincipal) &&
mDataTransfer->IsProtected()) {
return;
}
uint32_t count = Length();
for (uint32_t i = 0; i < count; i++) {
bool found;

View File

@ -1772,6 +1772,12 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
RefPtr<DataTransfer> dataTransfer =
new DataTransfer(window, eDragStart, false, -1);
auto protectDataTransfer = MakeScopeExit([&] {
if (dataTransfer) {
dataTransfer->SetMode(DataTransfer::Mode::Protected);
dataTransfer->ClearAll();
}
});
nsCOMPtr<nsISelection> selection;
nsCOMPtr<nsIContent> eventContent, targetContent;
@ -1839,11 +1845,6 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
nullptr);
}
// now that the dataTransfer has been updated in the dragstart and
// draggesture events, make it read only so that the data doesn't
// change during the drag.
dataTransfer->SetReadOnly();
if (status != nsEventStatus_eConsumeNoDefault) {
bool dragStarted = DoDefaultDragStart(aPresContext, event, dataTransfer,
targetContent, selection);
@ -2006,6 +2007,18 @@ EventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
if (!transArray)
return false;
// After this function returns, the DataTransfer will be cleared so it appears
// empty to content. We need to pass a DataTransfer into the Drag Session, so
// we need to make a copy.
RefPtr<DataTransfer> dataTransfer;
aDataTransfer->Clone(aDragTarget, eDrop, aDataTransfer->MozUserCancelled(),
false, getter_AddRefs(dataTransfer));
// Copy over the drop effect, as Clone doesn't copy it for us.
uint32_t dropEffect;
aDataTransfer->GetDropEffectInt(&dropEffect);
dataTransfer->SetDropEffectInt(dropEffect);
// XXXndeakin don't really want to create a new drag DOM event
// here, but we need something to pass to the InvokeDragSession
// methods.
@ -2018,7 +2031,7 @@ EventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
// other than a selection is being dragged.
if (!dragImage && aSelection) {
dragService->InvokeDragSessionWithSelection(aSelection, transArray,
action, event, aDataTransfer);
action, event, dataTransfer);
}
else {
// if dragging within a XUL tree and no custom drag image was
@ -2045,7 +2058,7 @@ EventStateManager::DoDefaultDragStart(nsPresContext* aPresContext,
dragImage ? dragImage->AsDOMNode() :
nullptr,
imageX, imageY, event,
aDataTransfer);
dataTransfer);
}
return true;

View File

@ -130,6 +130,9 @@
var dt = e.dataTransfer;
dragenterFired++;
// NOTE: This test is run with chrome privileges.
// For back-compat reasons, protected mode acts like readonly mode for
// chrome documents.
readOnly(e);
}

View File

@ -34,8 +34,8 @@ SimpleTest.waitForFocus(() => {
"clipboard contains html text");
window.addEventListener("paste", (e) => {
ok(e.clipboardData.types.indexOf('text/html'), -1, "clipboardData shouldn't have text/html");
ok(e.clipboardData.getData('text/plain'), "Formatted Text", "getData(text/plain) should return plain text");
is(e.clipboardData.types.indexOf('text/html'), -1, "clipboardData shouldn't have text/html");
is(e.clipboardData.getData('text/plain'), "Formatted Text", "getData(text/plain) should return plain text");
SimpleTest.finish();
});

View File

@ -74,7 +74,7 @@ function runTests()
SpecialPowers.addChromeEventListener("drop", chromeListener, true, false);
var targetNotHandling = document.getElementById("nothandling_target");
fireDrop(targetNotHandling, true, true);
fireDrop(targetNotHandling, false, true);
SpecialPowers.removeChromeEventListener("drop", chromeListener, true);
ok(chromeGotEvent, "Chrome should have got drop event!");
is(gGotHandlingDrop, false, "Didn't get drop on accepting element (2)");

View File

@ -369,12 +369,15 @@ FetchDriver::HttpFetch()
MOZ_ASSERT_IF(!hasContentTypeHeader, contentType.IsVoid());
#endif // DEBUG
int64_t bodyLength;
nsCOMPtr<nsIInputStream> bodyStream;
mRequest->GetBody(getter_AddRefs(bodyStream));
mRequest->GetBody(getter_AddRefs(bodyStream), &bodyLength);
if (bodyStream) {
nsAutoCString method;
mRequest->GetMethod(method);
rv = uploadChan->ExplicitSetUploadStream(bodyStream, contentType, -1, method, false /* aStreamHasHeaders */);
rv = uploadChan->ExplicitSetUploadStream(bodyStream, contentType,
bodyLength, method,
false /* aStreamHasHeaders */);
NS_ENSURE_SUCCESS(rv, rv);
}
}

View File

@ -30,6 +30,7 @@ InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult
copy->mHeaders = new InternalHeaders(*mHeaders);
copy->SetUnsafeRequest();
copy->mBodyStream = mBodyStream;
copy->mBodyLength = mBodyLength;
copy->mForceOriginHeader = true;
// The "client" is not stored in our implementation. Fetch API users should
// use the appropriate window/document/principal and other Gecko security
@ -79,6 +80,7 @@ InternalRequest::InternalRequest(const nsACString& aURL,
const nsACString& aFragment)
: mMethod("GET")
, mHeaders(new InternalHeaders(HeadersGuardEnum::None))
, mBodyLength(InternalResponse::UNKNOWN_BODY_SIZE)
, mContentPolicyType(nsIContentPolicy::TYPE_FETCH)
, mReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR))
, mReferrerPolicy(ReferrerPolicy::_empty)

View File

@ -462,20 +462,25 @@ public:
}
void
SetBody(nsIInputStream* aStream)
SetBody(nsIInputStream* aStream, int64_t aBodyLength)
{
// A request's body may not be reset once set.
MOZ_ASSERT_IF(aStream, !mBodyStream);
mBodyStream = aStream;
mBodyLength = aBodyLength;
}
// Will return the original stream!
// Use a tee or copy if you don't want to erase the original.
void
GetBody(nsIInputStream** aStream)
GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr)
{
nsCOMPtr<nsIInputStream> s = mBodyStream;
s.forget(aStream);
if (aBodyLength) {
*aBodyLength = mBodyLength;
}
}
// The global is used as the client for the new object.
@ -554,6 +559,7 @@ private:
nsTArray<nsCString> mURLList;
RefPtr<InternalHeaders> mHeaders;
nsCOMPtr<nsIInputStream> mBodyStream;
int64_t mBodyLength;
nsContentPolicyType mContentPolicyType;

View File

@ -212,7 +212,7 @@ public:
return;
}
return GetUnfilteredBody(aStream, aBodySize);
GetUnfilteredBody(aStream, aBodySize);
}
void

View File

@ -580,11 +580,11 @@ Request::Constructor(const GlobalObject& aGlobal,
const fetch::OwningBodyInit& bodyInit = bodyInitNullable.Value();
nsCOMPtr<nsIInputStream> stream;
nsAutoCString contentTypeWithCharset;
uint64_t contentLengthUnused;
uint64_t contentLength = 0;
aRv = ExtractByteStreamFromBody(bodyInit,
getter_AddRefs(stream),
contentTypeWithCharset,
contentLengthUnused);
contentLength);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
@ -604,10 +604,10 @@ Request::Constructor(const GlobalObject& aGlobal,
request->ClearCreatedByFetchEvent();
if (hasCopiedBody) {
request->SetBody(nullptr);
request->SetBody(nullptr, 0);
}
request->SetBody(temporaryBody);
request->SetBody(temporaryBody, contentLength);
}
}
@ -619,7 +619,7 @@ Request::Constructor(const GlobalObject& aGlobal,
nsCOMPtr<nsIInputStream> body;
inputReq->GetBody(getter_AddRefs(body));
if (body) {
inputReq->SetBody(nullptr);
inputReq->SetBody(nullptr, 0);
inputReq->SetBodyUsed(aGlobal.Context(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;

View File

@ -126,13 +126,19 @@ public:
Headers* Headers_();
void
GetBody(nsIInputStream** aStream) { return mRequest->GetBody(aStream); }
using FetchBody::GetBody;
void
SetBody(nsIInputStream* aStream) { return mRequest->SetBody(aStream); }
GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr)
{
mRequest->GetBody(aStream, aBodyLength);
}
void
SetBody(nsIInputStream* aStream, int64_t aBodyLength)
{
mRequest->SetBody(aStream, aBodyLength);
}
static already_AddRefed<Request>
Constructor(const GlobalObject& aGlobal, const RequestOrUSVString& aInput,

View File

@ -105,7 +105,10 @@ public:
Headers* Headers_();
void
GetBody(nsIInputStream** aStream) { return mInternalResponse->GetBody(aStream); }
GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr)
{
mInternalResponse->GetBody(aStream, aBodyLength);
}
using FetchBody::GetBody;

View File

@ -9,13 +9,18 @@
#include "IPCBlobInputStreamStorage.h"
#include "mozilla/ipc/InputStreamParams.h"
#include "nsIAsyncInputStream.h"
#include "nsIStreamTransportService.h"
#include "nsITransport.h"
#include "nsNetCID.h"
namespace mozilla {
namespace dom {
namespace {
class CallbackRunnable final : public CancelableRunnable
static NS_DEFINE_CID(kStreamTransportServiceCID, NS_STREAMTRANSPORTSERVICE_CID);
class InputStreamCallbackRunnable final : public CancelableRunnable
{
public:
static void
@ -23,8 +28,8 @@ public:
nsIEventTarget* aEventTarget,
IPCBlobInputStream* aStream)
{
RefPtr<CallbackRunnable> runnable =
new CallbackRunnable(aCallback, aStream);
RefPtr<InputStreamCallbackRunnable> runnable =
new InputStreamCallbackRunnable(aCallback, aStream);
nsCOMPtr<nsIEventTarget> target = aEventTarget;
if (!target) {
@ -44,9 +49,9 @@ public:
}
private:
CallbackRunnable(nsIInputStreamCallback* aCallback,
IPCBlobInputStream* aStream)
: CancelableRunnable("dom::CallbackRunnable")
InputStreamCallbackRunnable(nsIInputStreamCallback* aCallback,
IPCBlobInputStream* aStream)
: CancelableRunnable("dom::InputStreamCallbackRunnable")
, mCallback(aCallback)
, mStream(aStream)
{
@ -58,6 +63,49 @@ private:
RefPtr<IPCBlobInputStream> mStream;
};
class FileMetadataCallbackRunnable final : public CancelableRunnable
{
public:
static void
Execute(nsIFileMetadataCallback* aCallback,
nsIEventTarget* aEventTarget,
IPCBlobInputStream* aStream)
{
RefPtr<FileMetadataCallbackRunnable> runnable =
new FileMetadataCallbackRunnable(aCallback, aStream);
nsCOMPtr<nsIEventTarget> target = aEventTarget;
if (!target) {
target = NS_GetCurrentThread();
}
target->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
NS_IMETHOD
Run() override
{
mCallback->OnFileMetadataReady(mStream);
mCallback = nullptr;
mStream = nullptr;
return NS_OK;
}
private:
FileMetadataCallbackRunnable(nsIFileMetadataCallback* aCallback,
IPCBlobInputStream* aStream)
: CancelableRunnable("dom::FileMetadataCallbackRunnable")
, mCallback(aCallback)
, mStream(aStream)
{
MOZ_ASSERT(mCallback);
MOZ_ASSERT(mStream);
}
nsCOMPtr<nsIFileMetadataCallback> mCallback;
RefPtr<IPCBlobInputStream> mStream;
};
} // anonymous
NS_IMPL_ADDREF(IPCBlobInputStream);
@ -69,8 +117,8 @@ NS_INTERFACE_MAP_BEGIN(IPCBlobInputStream)
NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
NS_INTERFACE_MAP_ENTRY(nsICloneableInputStream)
NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFileMetadata, IsFileMetadata())
NS_INTERFACE_MAP_ENTRY(nsIFileMetadata)
NS_INTERFACE_MAP_ENTRY(nsIAsyncFileMetadata)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END
@ -109,7 +157,22 @@ IPCBlobInputStream::Available(uint64_t* aLength)
if (mState == eRunning) {
MOZ_ASSERT(mRemoteStream);
return mRemoteStream->Available(aLength);
// This will go away eventually: an async input stream can return 0 in
// Available(), but this is not currently fully supported in the rest of
// gecko.
if (!mAsyncRemoteStream) {
*aLength = mActor->Size();
return NS_OK;
}
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->Available(aLength);
}
MOZ_ASSERT(mState == eClosed);
@ -125,7 +188,15 @@ IPCBlobInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aReadCount)
}
if (mState == eRunning) {
return mRemoteStream->Read(aBuffer, aCount, aReadCount);
MOZ_ASSERT(mRemoteStream);
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->Read(aBuffer, aCount, aReadCount);
}
MOZ_ASSERT(mState == eClosed);
@ -142,7 +213,15 @@ IPCBlobInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
}
if (mState == eRunning) {
return mRemoteStream->ReadSegments(aWriter, aClosure, aCount, aResult);
MOZ_ASSERT(mRemoteStream);
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->ReadSegments(aWriter, aClosure, aCount, aResult);
}
MOZ_ASSERT(mState == eClosed);
@ -164,12 +243,21 @@ IPCBlobInputStream::Close()
mActor = nullptr;
}
if (mAsyncRemoteStream) {
mAsyncRemoteStream->Close();
mAsyncRemoteStream = nullptr;
}
if (mRemoteStream) {
mRemoteStream->Close();
mRemoteStream = nullptr;
}
mCallback = nullptr;
mInputStreamCallback = nullptr;
mInputStreamCallbackEventTarget = nullptr;
mFileMetadataCallback = nullptr;
mFileMetadataCallbackEventTarget = nullptr;
mState = eClosed;
return NS_OK;
@ -222,8 +310,8 @@ IPCBlobInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
case eInit:
MOZ_ASSERT(mActor);
mCallback = aCallback;
mCallbackEventTarget = aEventTarget;
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
mState = ePending;
mActor->StreamNeeded(this, aEventTarget);
@ -231,17 +319,17 @@ IPCBlobInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
// We are still waiting for the remote inputStream
case ePending:
if (mCallback && aCallback) {
if (mInputStreamCallback && aCallback) {
return NS_ERROR_FAILURE;
}
mCallback = aCallback;
mCallbackEventTarget = aEventTarget;
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aEventTarget;
return NS_OK;
// We have the remote inputStream, let's check if we can execute the callback.
case eRunning:
return MaybeExecuteCallback(aCallback, aEventTarget);
return MaybeExecuteInputStreamCallback(aCallback, aEventTarget);
// Stream is closed.
default:
@ -265,58 +353,66 @@ IPCBlobInputStream::StreamReady(nsIInputStream* aInputStream)
// stream is not available anymore. We keep the state as pending just to block
// any additional operation.
nsCOMPtr<nsIInputStreamCallback> callback;
callback.swap(mCallback);
if (!aInputStream) {
return;
}
nsCOMPtr<nsIEventTarget> callbackEventTarget;
callbackEventTarget.swap(mCallbackEventTarget);
mRemoteStream = aInputStream;
if (aInputStream && callback) {
MOZ_ASSERT(mState == ePending);
MOZ_ASSERT(mState == ePending);
mState = eRunning;
mRemoteStream = aInputStream;
mState = eRunning;
nsCOMPtr<nsIFileMetadataCallback> fileMetadataCallback;
fileMetadataCallback.swap(mFileMetadataCallback);
MaybeExecuteCallback(callback, callbackEventTarget);
nsCOMPtr<nsIEventTarget> fileMetadataCallbackEventTarget;
fileMetadataCallbackEventTarget.swap(mFileMetadataCallbackEventTarget);
if (fileMetadataCallback) {
FileMetadataCallbackRunnable::Execute(fileMetadataCallback,
fileMetadataCallbackEventTarget,
this);
}
nsCOMPtr<nsIInputStreamCallback> inputStreamCallback;
inputStreamCallback.swap(mInputStreamCallback);
nsCOMPtr<nsIEventTarget> inputStreamCallbackEventTarget;
inputStreamCallbackEventTarget.swap(mInputStreamCallbackEventTarget);
if (inputStreamCallback) {
MaybeExecuteInputStreamCallback(inputStreamCallback,
inputStreamCallbackEventTarget);
}
}
nsresult
IPCBlobInputStream::MaybeExecuteCallback(nsIInputStreamCallback* aCallback,
nsIEventTarget* aCallbackEventTarget)
IPCBlobInputStream::MaybeExecuteInputStreamCallback(nsIInputStreamCallback* aCallback,
nsIEventTarget* aCallbackEventTarget)
{
MOZ_ASSERT(mState == eRunning);
MOZ_ASSERT(mRemoteStream);
// If the stream supports nsIAsyncInputStream, we need to call its AsyncWait
// and wait for OnInputStreamReady.
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
if (asyncStream) {
// If the callback has been already set, we return an error.
if (mCallback && aCallback) {
return NS_ERROR_FAILURE;
}
mCallback = aCallback;
mCallbackEventTarget = aCallbackEventTarget;
if (!mCallback) {
return NS_OK;
}
RefPtr<nsIEventTarget> target = GetCurrentThreadEventTarget();
return asyncStream->AsyncWait(this, 0, 0, target);
// If the callback has been already set, we return an error.
if (mInputStreamCallback && aCallback) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(!mCallback);
MOZ_ASSERT(!mCallbackEventTarget);
mInputStreamCallback = aCallback;
mInputStreamCallbackEventTarget = aCallbackEventTarget;
if (!aCallback) {
if (!mInputStreamCallback) {
return NS_OK;
}
CallbackRunnable::Execute(aCallback, aCallbackEventTarget, this);
return NS_OK;
nsresult rv = EnsureAsyncRemoteStream();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(mAsyncRemoteStream);
return mAsyncRemoteStream->AsyncWait(this, 0, 0, aCallbackEventTarget);
}
// nsIInputStreamCallback
@ -330,18 +426,20 @@ IPCBlobInputStream::OnInputStreamReady(nsIAsyncInputStream* aStream)
}
MOZ_ASSERT(mState == eRunning);
MOZ_ASSERT(mRemoteStream == aStream);
MOZ_ASSERT(mAsyncRemoteStream == aStream);
// The callback has been canceled in the meantime.
if (!mCallback) {
if (!mInputStreamCallback) {
return NS_OK;
}
CallbackRunnable::Execute(mCallback, mCallbackEventTarget, this);
mCallback = nullptr;
mCallbackEventTarget = nullptr;
nsCOMPtr<nsIInputStreamCallback> callback;
callback.swap(mInputStreamCallback);
nsCOMPtr<nsIEventTarget> callbackEventTarget;
callbackEventTarget.swap(mInputStreamCallbackEventTarget);
InputStreamCallbackRunnable::Execute(callback, callbackEventTarget, this);
return NS_OK;
}
@ -371,17 +469,50 @@ IPCBlobInputStream::ExpectedSerializedLength()
return mozilla::Nothing();
}
// nsIFileMetadata
// nsIAsyncFileMetadata
bool
IPCBlobInputStream::IsFileMetadata() const
NS_IMETHODIMP
IPCBlobInputStream::AsyncWait(nsIFileMetadataCallback* aCallback,
nsIEventTarget* aEventTarget)
{
// We are nsIFileMetadata only if we have the remote stream and that is a
// nsIFileMetadata.
nsCOMPtr<nsIFileMetadata> fileMetadata = do_QueryInterface(mRemoteStream);
return !!fileMetadata;
// 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);
mFileMetadataCallback = aCallback;
mFileMetadataCallbackEventTarget = aEventTarget;
mState = ePending;
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:
FileMetadataCallbackRunnable::Execute(aCallback, aEventTarget, this);
return NS_OK;
// Stream is closed.
default:
MOZ_ASSERT(mState == eClosed);
return NS_BASE_STREAM_CLOSED;
}
}
// nsIFileMetadata
NS_IMETHODIMP
IPCBlobInputStream::GetSize(int64_t* aRetval)
{
@ -415,44 +546,60 @@ IPCBlobInputStream::GetFileDescriptor(PRFileDesc** aRetval)
return fileMetadata->GetFileDescriptor(aRetval);
}
// nsISeekableStream
bool
IPCBlobInputStream::IsSeekableStream() const
nsresult
IPCBlobInputStream::EnsureAsyncRemoteStream()
{
// We are nsISeekableStream only if we have the remote stream and that is a
// nsISeekableStream.
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mRemoteStream);
return !!seekableStream;
}
NS_IMETHODIMP
IPCBlobInputStream::Seek(int32_t aWhence, int64_t aOffset)
{
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mRemoteStream);
if (!seekableStream) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
if (!mRemoteStream) {
return NS_ERROR_FAILURE;
}
return seekableStream->Seek(aWhence, aOffset);
}
NS_IMETHODIMP
IPCBlobInputStream::Tell(int64_t *aResult)
{
nsCOMPtr<nsISeekableStream> seekableStream = do_QueryInterface(mRemoteStream);
if (!seekableStream) {
return mState == eClosed ? NS_BASE_STREAM_CLOSED : NS_ERROR_FAILURE;
// We already have an async remote stream.
if (mAsyncRemoteStream) {
return NS_OK;
}
return seekableStream->Tell(aResult);
}
// If the stream is blocking, we want to make it unblocking using a pipe.
bool nonBlocking = false;
nsresult rv = mRemoteStream->IsNonBlocking(&nonBlocking);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mRemoteStream);
if (!asyncStream || !nonBlocking) {
nsCOMPtr<nsIStreamTransportService> sts =
do_GetService(kStreamTransportServiceCID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsITransport> transport;
rv = sts->CreateInputTransport(mRemoteStream,
/* aStartOffset */ 0,
/* aReadLimit */ -1,
/* aCloseWhenDone */ true,
getter_AddRefs(transport));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIInputStream> wrapper;
rv = transport->OpenInputStream(/* aFlags */ 0,
/* aSegmentSize */ 0,
/* aSegmentCount */ 0,
getter_AddRefs(wrapper));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
asyncStream = do_QueryInterface(wrapper);
}
MOZ_ASSERT(asyncStream);
mAsyncRemoteStream = asyncStream;
return NS_OK;
NS_IMETHODIMP
IPCBlobInputStream::SetEOF()
{
// This is a read-only stream.
return NS_ERROR_FAILURE;
}
} // namespace dom

View File

@ -11,7 +11,6 @@
#include "nsICloneableInputStream.h"
#include "nsIFileStreams.h"
#include "nsIIPCSerializableInputStream.h"
#include "nsISeekableStream.h"
#include "nsCOMPtr.h"
namespace mozilla {
@ -23,8 +22,7 @@ class IPCBlobInputStream final : public nsIAsyncInputStream
, public nsIInputStreamCallback
, public nsICloneableInputStream
, public nsIIPCSerializableInputStream
, public nsISeekableStream
, public nsIFileMetadata
, public nsIAsyncFileMetadata
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
@ -33,8 +31,8 @@ public:
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSICLONEABLEINPUTSTREAM
NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
NS_DECL_NSIFILEMETADATA
NS_DECL_NSIASYNCFILEMETADATA
explicit IPCBlobInputStream(IPCBlobInputStreamChild* aActor);
@ -45,14 +43,11 @@ private:
~IPCBlobInputStream();
nsresult
MaybeExecuteCallback(nsIInputStreamCallback* aCallback,
nsIEventTarget* aEventTarget);
MaybeExecuteInputStreamCallback(nsIInputStreamCallback* aCallback,
nsIEventTarget* aEventTarget);
bool
IsSeekableStream() const;
bool
IsFileMetadata() const;
nsresult
EnsureAsyncRemoteStream();
RefPtr<IPCBlobInputStreamChild> mActor;
@ -78,10 +73,15 @@ private:
} mState;
nsCOMPtr<nsIInputStream> mRemoteStream;
nsCOMPtr<nsIAsyncInputStream> mAsyncRemoteStream;
// These 2 values are set only if mState is ePending.
nsCOMPtr<nsIInputStreamCallback> mCallback;
nsCOMPtr<nsIEventTarget> mCallbackEventTarget;
nsCOMPtr<nsIInputStreamCallback> mInputStreamCallback;
nsCOMPtr<nsIEventTarget> mInputStreamCallbackEventTarget;
// These 2 values are set only if mState is ePending.
nsCOMPtr<nsIFileMetadataCallback> mFileMetadataCallback;
nsCOMPtr<nsIEventTarget> mFileMetadataCallbackEventTarget;
};
} // namespace dom

View File

@ -687,7 +687,7 @@ HttpServer::Connection::ConsumeLine(const char* aBuffer,
NS_ENSURE_SUCCESS(rv, rv);
mCurrentRequestBody = do_QueryInterface(output);
mPendingReq->SetBody(input);
mPendingReq->SetBody(input, -1);
} else {
LOG_V("HttpServer::Connection::ConsumeLine(%p) - No body", this);
mState = eRequestLine;

View File

@ -343,6 +343,12 @@ public:
return mHasPatternAttribute;
}
virtual already_AddRefed<nsITextControlElement> GetAsTextControlElement() override
{
nsCOMPtr<nsITextControlElement> txt = this;
return txt.forget();
}
// nsIConstraintValidation
bool IsTooLong();
bool IsTooShort();

View File

@ -168,6 +168,12 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTextAreaElement,
nsGenericHTMLFormElementWithState)
virtual already_AddRefed<nsITextControlElement> GetAsTextControlElement() override
{
nsCOMPtr<nsITextControlElement> txt = this;
return txt.forget();
}
// nsIConstraintValidation
bool IsTooLong();
bool IsTooShort();

View File

@ -1477,6 +1477,7 @@ DispatchFileHandleSuccessEvent(FileHandleResultHelper* aResultHelper)
class BackgroundRequestChild::PreprocessHelper final
: public CancelableRunnable
, public nsIInputStreamCallback
, public nsIFileMetadataCallback
{
typedef std::pair<nsCOMPtr<nsIInputStream>,
nsCOMPtr<nsIInputStream>> StreamPair;
@ -1560,9 +1561,13 @@ private:
void
ContinueWithStatus(nsresult aStatus);
nsresult
DataIsReady(nsIInputStream* aInputStream);
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIRUNNABLE
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIFILEMETADATACALLBACK
virtual nsresult
Cancel() override;
@ -3518,6 +3523,17 @@ PreprocessHelper::WaitForStreamReady(nsIInputStream* aInputStream)
MOZ_ASSERT(!IsOnOwningThread());
MOZ_ASSERT(aInputStream);
nsCOMPtr<nsIAsyncFileMetadata> asyncFileMetadata =
do_QueryInterface(aInputStream);
if (asyncFileMetadata) {
nsresult rv = asyncFileMetadata->AsyncWait(this, mTaskQueueEventTarget);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aInputStream);
if (!asyncStream) {
return NS_ERROR_NO_INTERFACE;
@ -3564,7 +3580,8 @@ PreprocessHelper::ContinueWithStatus(nsresult aStatus)
}
NS_IMPL_ISUPPORTS_INHERITED(BackgroundRequestChild::PreprocessHelper,
CancelableRunnable, nsIInputStreamCallback)
CancelableRunnable, nsIInputStreamCallback,
nsIFileMetadataCallback)
NS_IMETHODIMP
BackgroundRequestChild::
@ -3582,6 +3599,23 @@ PreprocessHelper::Run()
NS_IMETHODIMP
BackgroundRequestChild::
PreprocessHelper::OnInputStreamReady(nsIAsyncInputStream* aStream)
{
return DataIsReady(aStream);
}
NS_IMETHODIMP
BackgroundRequestChild::
PreprocessHelper::OnFileMetadataReady(nsIAsyncFileMetadata* aObject)
{
nsCOMPtr<nsIInputStream> stream = do_QueryInterface(aObject);
MOZ_ASSERT(stream, "It was a stream before!");
return DataIsReady(stream);
}
nsresult
BackgroundRequestChild::
PreprocessHelper::DataIsReady(nsIInputStream* aStream)
{
MOZ_ASSERT(!IsOnOwningThread());
MOZ_ASSERT(aStream);

View File

@ -268,11 +268,6 @@
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
#if defined(XP_WIN)
// e10s forced enable pref, defined in nsAppRunner.cpp
extern const char* kForceEnableE10sPref;
#endif
using base::ChildPrivileges;
using base::KillProcess;
@ -1311,13 +1306,8 @@ ContentParent::Init()
// process.
if (nsIPresShell::IsAccessibilityActive()) {
#if defined(XP_WIN)
#if defined(RELEASE_OR_BETA)
// On Windows we currently only enable a11y in the content process
// for testing purposes.
if (Preferences::GetBool(kForceEnableE10sPref, false))
#endif
Unused << SendActivateA11y(::GetCurrentThreadId(),
a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
Unused << SendActivateA11y(::GetCurrentThreadId(),
a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
#else
Unused << SendActivateA11y(0, 0);
#endif
@ -2851,13 +2841,8 @@ ContentParent::Observe(nsISupports* aSubject,
// Make sure accessibility is running in content process when
// accessibility gets initiated in chrome process.
#if defined(XP_WIN)
#if defined(RELEASE_OR_BETA)
// On Windows we currently only enable a11y in the content process
// for testing purposes.
if (Preferences::GetBool(kForceEnableE10sPref, false))
#endif
Unused << SendActivateA11y(::GetCurrentThreadId(),
a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
Unused << SendActivateA11y(::GetCurrentThreadId(),
a11y::AccessibleWrap::GetContentProcessIdFor(ChildID()));
#else
Unused << SendActivateA11y(0, 0);
#endif

View File

@ -659,22 +659,19 @@ function checkCachedDataTransfer(cd, eventtype)
setClipboardText("Some Clipboard Text");
var oldtext = cd.getData("text/plain");
ok(oldtext != "Some Clipboard Text", "clipboard get using " + testprefix);
ok(!oldtext, "clipboard get using " + testprefix);
var exh = false;
try { cd.mozSetDataAt("text/plain", "Test Cache Data", 0); } catch (ex) { exh = true; }
ok(eventtype == "paste" ? exh : !exh, "exception occured setting " + testprefix);
var newtext = (eventtype == "paste") ? cd.getData("text/plain") :
cd.mozGetDataAt("text/plain", 0);
is(newtext, (eventtype == "paste") ? oldtext : "Test Cache Data",
" clipboardData not changed using " + testprefix);
try {
cd.mozSetDataAt("text/plain", "Test Cache Data", 0);
} catch (ex) {}
ok(!cd.getData("text/plain"), "clipboard set using " + testprefix);
is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix);
var exh = false;
try { cd.mozClearDataAt("text/plain", 0); } catch (ex) { exh = true; }
ok(eventtype == "paste" ? exh : !exh, "exception occured clearing " + testprefix);
try {
cd.mozClearDataAt("text/plain", 0);
} catch (ex) {}
ok(!cd.getData("text/plain"), "clipboard clear using " + testprefix);
is(getClipboardText(), "Some Clipboard Text", "clipboard not changed using " + testprefix);
}

View File

@ -155,4 +155,16 @@ partial interface DataTransfer {
*/
[UseCounter]
readonly attribute Node? mozSourceNode;
/**
* Copy the given DataTransfer for the given event. Used by testing code for
* creating emulated Drag and Drop events in the UI.
*
* NOTE: Don't expose a DataTransfer produced with this method to the web or
* use this for non-testing purposes. It can easily be used to get the
* DataTransfer into an invalid state, and is an unstable implementation
* detail of EventUtils.synthesizeDrag.
*/
[Throws, ChromeOnly]
DataTransfer mozCloneForEvent(DOMString event);
};

View File

@ -209,8 +209,14 @@ FileReaderSync::ReadAsText(Blob& aBlob,
return;
}
uint64_t blobSize = aBlob.GetSize(aRv);
if (NS_WARN_IF(aRv.Failed())){
return;
}
nsCOMPtr<nsIInputStream> syncStream;
aRv = ConvertAsyncToSyncStream(stream, getter_AddRefs(syncStream));
aRv = ConvertAsyncToSyncStream(blobSize - sniffBuf.Length(), stream,
getter_AddRefs(syncStream));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@ -255,8 +261,13 @@ FileReaderSync::ReadAsDataURL(Blob& aBlob, nsAString& aResult,
return;
}
uint64_t blobSize = aBlob.GetSize(aRv);
if (NS_WARN_IF(aRv.Failed())){
return;
}
nsCOMPtr<nsIInputStream> syncStream;
aRv = ConvertAsyncToSyncStream(stream, getter_AddRefs(syncStream));
aRv = ConvertAsyncToSyncStream(blobSize, stream, getter_AddRefs(syncStream));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@ -269,11 +280,6 @@ FileReaderSync::ReadAsDataURL(Blob& aBlob, nsAString& aResult,
return;
}
uint64_t blobSize = aBlob.GetSize(aRv);
if (NS_WARN_IF(aRv.Failed())){
return;
}
// The file is changed in the meantime?
if (blobSize != size) {
return;
@ -466,7 +472,8 @@ FileReaderSync::SyncRead(nsIInputStream* aStream, char* aBuffer,
}
nsresult
FileReaderSync::ConvertAsyncToSyncStream(nsIInputStream* aAsyncStream,
FileReaderSync::ConvertAsyncToSyncStream(uint64_t aStreamSize,
nsIInputStream* aAsyncStream,
nsIInputStream** aSyncStream)
{
// If the stream is not async, we just need it to be bufferable.
@ -475,30 +482,19 @@ FileReaderSync::ConvertAsyncToSyncStream(nsIInputStream* aAsyncStream,
return NS_NewBufferedInputStream(aSyncStream, aAsyncStream, 4096);
}
uint64_t length;
nsresult rv = aAsyncStream->Available(&length);
if (rv == NS_BASE_STREAM_CLOSED) {
// The stream has already been closed. Nothing to do.
*aSyncStream = nullptr;
return NS_OK;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoCString buffer;
if (!buffer.SetLength(length, fallible)) {
if (!buffer.SetLength(aStreamSize, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
uint32_t read;
rv = SyncRead(aAsyncStream, buffer.BeginWriting(), length, &read);
nsresult rv =
SyncRead(aAsyncStream, buffer.BeginWriting(), aStreamSize, &read);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (read != length) {
if (read != aStreamSize) {
return NS_ERROR_FAILURE;
}

View File

@ -32,7 +32,8 @@ private:
nsresult ConvertStream(nsIInputStream *aStream, const char *aCharset,
nsAString &aResult);
nsresult ConvertAsyncToSyncStream(nsIInputStream* aAsyncStream,
nsresult ConvertAsyncToSyncStream(uint64_t aStreamSize,
nsIInputStream* aAsyncStream,
nsIInputStream** aSyncStream);
nsresult SyncRead(nsIInputStream* aStream, char* aBuffer,

View File

@ -1603,7 +1603,7 @@ private:
mReferrerPolicy,
mContentPolicyType,
mIntegrity);
internalReq->SetBody(mUploadStream);
internalReq->SetBody(mUploadStream, -1);
// For Telemetry, note that this Request object was created by a Fetch event.
internalReq->SetCreatedByFetchEvent();

View File

@ -646,6 +646,8 @@ public:
}
aFontEntry->mSkipDefaultFeatureSpaceCheck = mSkipDefaultFeatureSpaceCheck;
mAvailableFonts.AppendElement(aFontEntry);
mIsSimpleFamily = false; // CheckForSimpleFamily may set this later,
// but at this point we're not sure
}
// note that the styles for this family have been added

View File

@ -183,14 +183,17 @@ MacOSFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
// characters it supports, so only check/clear the
// complex-script ranges for non-Graphite fonts
// for layout support, check for the presence of mort/morx and/or
// for layout support, check for the presence of mort/morx/kerx and/or
// opentype layout tables
bool hasAATLayout = HasFontTable(TRUETYPE_TAG('m','o','r','x')) ||
HasFontTable(TRUETYPE_TAG('m','o','r','t'));
bool hasAppleKerning = HasFontTable(TRUETYPE_TAG('k','e','r','x'));
bool hasGSUB = HasFontTable(TRUETYPE_TAG('G','S','U','B'));
bool hasGPOS = HasFontTable(TRUETYPE_TAG('G','P','O','S'));
if (hasAATLayout && !(hasGSUB || hasGPOS)) {
mRequiresAAT = true; // prefer CoreText if font has no OTL tables
if ((hasAATLayout && !(hasGSUB || hasGPOS)) || hasAppleKerning) {
mRequiresAAT = true; // prefer CoreText if font has no OTL tables,
// or if it uses the Apple-specific 'kerx'
// variant of kerning table
}
for (const ScriptRange* sr = gfxPlatformFontList::sComplexScriptRanges;

View File

@ -974,8 +974,13 @@ js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason)
return;
#endif
bool canUsePromotionRate;
const float promotionRate = calcPromotionRate(&canUsePromotionRate);
/*
* This incorrect promotion rate results in better nursery sizing
* decisions, however we should to better tuning based on the real
* promotion rate in the future.
*/
const float promotionRate =
float(previousGC.tenuredBytes) / float(previousGC.nurseryCapacity);
newMaxNurseryChunks = runtime()->gc.tunables.gcMaxNurseryBytes() >> ChunkShift;
if (newMaxNurseryChunks != maxNurseryChunks_) {
@ -986,15 +991,11 @@ js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason)
/* We need to shrink the nursery */
shrinkAllocableSpace(extraChunks);
if (canUsePromotionRate)
previousPromotionRate_ = promotionRate;
previousPromotionRate_ = promotionRate;
return;
}
}
if (!canUsePromotionRate)
return;
if (promotionRate > GrowThreshold)
growAllocableSpace();
else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold)

Some files were not shown because too many files have changed in this diff Show More