Merge mozilla-central to autoland. a=merge CLOSED TREE
|
@ -1,9 +1,9 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 123
|
||||
Version 124
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-122...release-123
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-123...release-124
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
|
|
|
@ -1075,6 +1075,10 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
background: var(--theme-icon-color);
|
||||
mask-size: 100%;
|
||||
}
|
||||
|
||||
.img.arrow.arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
@ -2331,10 +2335,6 @@ menuseparator {
|
|||
color: inherit;
|
||||
}
|
||||
|
||||
.sources-list .tree .img.arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.theme-dark .source-list .tree .node.focused {
|
||||
background-color: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
|
@ -3761,8 +3761,8 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.frames [role="list"] .frames-group .group,
|
||||
.frames [role="list"] .frames-group .group .location {
|
||||
.frames ul .frames-group .group,
|
||||
.frames ul .frames-group .group .location {
|
||||
font-weight: 500;
|
||||
cursor: default;
|
||||
/*
|
||||
|
@ -3773,30 +3773,25 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
|||
direction: ltr;
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group.expanded .group,
|
||||
.frames [role="list"] .frames-group.expanded .group .location {
|
||||
.frames ul .frames-group.expanded .group,
|
||||
.frames ul .frames-group.expanded .group .location {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group.expanded .react path {
|
||||
.frames ul .frames-group.expanded .react path {
|
||||
fill: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group .frames-list [role="listitem"] {
|
||||
.frames ul .frames-group .frames-list li {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group .frames-list {
|
||||
.frames ul .frames-group .frames-list {
|
||||
border-top: 1px solid var(--theme-splitter-color);
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
/* We don't want to display those as flex since only the name is displayed */
|
||||
.frames [role="list"] .frames-group .frames-list [role="listitem"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group.expanded .badge {
|
||||
.frames ul .frames-group.expanded .badge {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
|
@ -3862,7 +3857,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
|||
|
||||
.frames [role="list"] {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin-top: 4px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -3964,7 +3959,6 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
|||
mask-size: 100%;
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-inline-start: 4px;
|
||||
}
|
||||
|
||||
:root.theme-dark .annotation-logo:not(.angular) svg path {
|
||||
|
@ -4624,6 +4618,13 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.source-header .command-bar {
|
||||
flex: initial;
|
||||
flex-shrink: 0;
|
||||
border-bottom: 0;
|
||||
border-inline-start: 1px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
.source-tabs {
|
||||
max-width: calc(100% - 80px);
|
||||
align-self: flex-start;
|
||||
|
@ -4652,7 +4653,8 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: var(--tab-line-color, transparent);
|
||||
transition: transform 250ms var(--animation-curve), opacity 250ms var(--animation-curve);
|
||||
transition: transform 250ms var(--animation-curve),
|
||||
opacity 250ms var(--animation-curve);
|
||||
opacity: 0;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
|
|
@ -20759,8 +20759,6 @@ var _types = __webpack_require__(2268);
|
|||
|
||||
var t = _interopRequireWildcard(_types);
|
||||
|
||||
var _devtoolsSourceMap = __webpack_require__(3646);
|
||||
|
||||
var _getFunctionName = __webpack_require__(1621);
|
||||
|
||||
var _getFunctionName2 = _interopRequireDefault(_getFunctionName);
|
||||
|
@ -20795,6 +20793,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|||
|
||||
// Location information about the expression immediartely surrounding a
|
||||
// given binding reference.
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
function isGeneratedId(id) {
|
||||
return !/\/originalSource/.test(id);
|
||||
}
|
||||
|
||||
function parseSourceScopes(sourceId) {
|
||||
const ast = (0, _ast.getAst)(sourceId);
|
||||
if ((0, _isEmpty2.default)(ast)) {
|
||||
|
@ -20802,9 +20808,7 @@ function parseSourceScopes(sourceId) {
|
|||
}
|
||||
|
||||
return buildScopeList(ast, sourceId);
|
||||
} /* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
}
|
||||
|
||||
function buildScopeList(ast, sourceId) {
|
||||
const { global, lexical } = createGlobalScope(ast, sourceId);
|
||||
|
@ -20836,7 +20840,7 @@ function buildScopeList(ast, sourceId) {
|
|||
// TODO: This should probably check for ".mjs" extension on the
|
||||
// original file, and should also be skipped if the the generated
|
||||
// code is an ES6 module rather than a script.
|
||||
if ((0, _devtoolsSourceMap.isGeneratedId)(sourceId) || ast.program.sourceType === "script" && !looksLikeCommonJS(global)) {
|
||||
if (isGeneratedId(sourceId) || ast.program.sourceType === "script" && !looksLikeCommonJS(global)) {
|
||||
stripModuleScope(global);
|
||||
}
|
||||
|
||||
|
@ -21479,344 +21483,6 @@ function stripModuleScope(rootScope) {
|
|||
});
|
||||
}
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 248:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
(function(){
|
||||
var crypt = __webpack_require__(249),
|
||||
utf8 = __webpack_require__(250).utf8,
|
||||
isBuffer = __webpack_require__(251),
|
||||
bin = __webpack_require__(250).bin,
|
||||
|
||||
// The core
|
||||
md5 = function (message, options) {
|
||||
// Convert to byte array
|
||||
if (message.constructor == String)
|
||||
if (options && options.encoding === 'binary')
|
||||
message = bin.stringToBytes(message);
|
||||
else
|
||||
message = utf8.stringToBytes(message);
|
||||
else if (isBuffer(message))
|
||||
message = Array.prototype.slice.call(message, 0);
|
||||
else if (!Array.isArray(message))
|
||||
message = message.toString();
|
||||
// else, assume byte array already
|
||||
|
||||
var m = crypt.bytesToWords(message),
|
||||
l = message.length * 8,
|
||||
a = 1732584193,
|
||||
b = -271733879,
|
||||
c = -1732584194,
|
||||
d = 271733878;
|
||||
|
||||
// Swap endian
|
||||
for (var i = 0; i < m.length; i++) {
|
||||
m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
|
||||
((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
|
||||
}
|
||||
|
||||
// Padding
|
||||
m[l >>> 5] |= 0x80 << (l % 32);
|
||||
m[(((l + 64) >>> 9) << 4) + 14] = l;
|
||||
|
||||
// Method shortcuts
|
||||
var FF = md5._ff,
|
||||
GG = md5._gg,
|
||||
HH = md5._hh,
|
||||
II = md5._ii;
|
||||
|
||||
for (var i = 0; i < m.length; i += 16) {
|
||||
|
||||
var aa = a,
|
||||
bb = b,
|
||||
cc = c,
|
||||
dd = d;
|
||||
|
||||
a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
|
||||
d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
|
||||
c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
|
||||
b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
|
||||
a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
|
||||
d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
|
||||
c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
|
||||
b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
|
||||
a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
|
||||
d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
|
||||
c = FF(c, d, a, b, m[i+10], 17, -42063);
|
||||
b = FF(b, c, d, a, m[i+11], 22, -1990404162);
|
||||
a = FF(a, b, c, d, m[i+12], 7, 1804603682);
|
||||
d = FF(d, a, b, c, m[i+13], 12, -40341101);
|
||||
c = FF(c, d, a, b, m[i+14], 17, -1502002290);
|
||||
b = FF(b, c, d, a, m[i+15], 22, 1236535329);
|
||||
|
||||
a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
|
||||
d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
|
||||
c = GG(c, d, a, b, m[i+11], 14, 643717713);
|
||||
b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
|
||||
a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
|
||||
d = GG(d, a, b, c, m[i+10], 9, 38016083);
|
||||
c = GG(c, d, a, b, m[i+15], 14, -660478335);
|
||||
b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
|
||||
a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
|
||||
d = GG(d, a, b, c, m[i+14], 9, -1019803690);
|
||||
c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
|
||||
b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
|
||||
a = GG(a, b, c, d, m[i+13], 5, -1444681467);
|
||||
d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
|
||||
c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
|
||||
b = GG(b, c, d, a, m[i+12], 20, -1926607734);
|
||||
|
||||
a = HH(a, b, c, d, m[i+ 5], 4, -378558);
|
||||
d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
|
||||
c = HH(c, d, a, b, m[i+11], 16, 1839030562);
|
||||
b = HH(b, c, d, a, m[i+14], 23, -35309556);
|
||||
a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
|
||||
d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
|
||||
c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
|
||||
b = HH(b, c, d, a, m[i+10], 23, -1094730640);
|
||||
a = HH(a, b, c, d, m[i+13], 4, 681279174);
|
||||
d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
|
||||
c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
|
||||
b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
|
||||
a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
|
||||
d = HH(d, a, b, c, m[i+12], 11, -421815835);
|
||||
c = HH(c, d, a, b, m[i+15], 16, 530742520);
|
||||
b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
|
||||
|
||||
a = II(a, b, c, d, m[i+ 0], 6, -198630844);
|
||||
d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
|
||||
c = II(c, d, a, b, m[i+14], 15, -1416354905);
|
||||
b = II(b, c, d, a, m[i+ 5], 21, -57434055);
|
||||
a = II(a, b, c, d, m[i+12], 6, 1700485571);
|
||||
d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
|
||||
c = II(c, d, a, b, m[i+10], 15, -1051523);
|
||||
b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
|
||||
a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
|
||||
d = II(d, a, b, c, m[i+15], 10, -30611744);
|
||||
c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
|
||||
b = II(b, c, d, a, m[i+13], 21, 1309151649);
|
||||
a = II(a, b, c, d, m[i+ 4], 6, -145523070);
|
||||
d = II(d, a, b, c, m[i+11], 10, -1120210379);
|
||||
c = II(c, d, a, b, m[i+ 2], 15, 718787259);
|
||||
b = II(b, c, d, a, m[i+ 9], 21, -343485551);
|
||||
|
||||
a = (a + aa) >>> 0;
|
||||
b = (b + bb) >>> 0;
|
||||
c = (c + cc) >>> 0;
|
||||
d = (d + dd) >>> 0;
|
||||
}
|
||||
|
||||
return crypt.endian([a, b, c, d]);
|
||||
};
|
||||
|
||||
// Auxiliary functions
|
||||
md5._ff = function (a, b, c, d, x, s, t) {
|
||||
var n = a + (b & c | ~b & d) + (x >>> 0) + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
md5._gg = function (a, b, c, d, x, s, t) {
|
||||
var n = a + (b & d | c & ~d) + (x >>> 0) + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
md5._hh = function (a, b, c, d, x, s, t) {
|
||||
var n = a + (b ^ c ^ d) + (x >>> 0) + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
md5._ii = function (a, b, c, d, x, s, t) {
|
||||
var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
|
||||
return ((n << s) | (n >>> (32 - s))) + b;
|
||||
};
|
||||
|
||||
// Package private blocksize
|
||||
md5._blocksize = 16;
|
||||
md5._digestsize = 16;
|
||||
|
||||
module.exports = function (message, options) {
|
||||
if (message === undefined || message === null)
|
||||
throw new Error('Illegal argument ' + message);
|
||||
|
||||
var digestbytes = crypt.wordsToBytes(md5(message, options));
|
||||
return options && options.asBytes ? digestbytes :
|
||||
options && options.asString ? bin.bytesToString(digestbytes) :
|
||||
crypt.bytesToHex(digestbytes);
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 249:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
(function() {
|
||||
var base64map
|
||||
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
|
||||
|
||||
crypt = {
|
||||
// Bit-wise rotation left
|
||||
rotl: function(n, b) {
|
||||
return (n << b) | (n >>> (32 - b));
|
||||
},
|
||||
|
||||
// Bit-wise rotation right
|
||||
rotr: function(n, b) {
|
||||
return (n << (32 - b)) | (n >>> b);
|
||||
},
|
||||
|
||||
// Swap big-endian to little-endian and vice versa
|
||||
endian: function(n) {
|
||||
// If number given, swap endian
|
||||
if (n.constructor == Number) {
|
||||
return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
|
||||
}
|
||||
|
||||
// Else, assume array and swap all items
|
||||
for (var i = 0; i < n.length; i++)
|
||||
n[i] = crypt.endian(n[i]);
|
||||
return n;
|
||||
},
|
||||
|
||||
// Generate an array of any length of random bytes
|
||||
randomBytes: function(n) {
|
||||
for (var bytes = []; n > 0; n--)
|
||||
bytes.push(Math.floor(Math.random() * 256));
|
||||
return bytes;
|
||||
},
|
||||
|
||||
// Convert a byte array to big-endian 32-bit words
|
||||
bytesToWords: function(bytes) {
|
||||
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
|
||||
words[b >>> 5] |= bytes[i] << (24 - b % 32);
|
||||
return words;
|
||||
},
|
||||
|
||||
// Convert big-endian 32-bit words to a byte array
|
||||
wordsToBytes: function(words) {
|
||||
for (var bytes = [], b = 0; b < words.length * 32; b += 8)
|
||||
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
|
||||
return bytes;
|
||||
},
|
||||
|
||||
// Convert a byte array to a hex string
|
||||
bytesToHex: function(bytes) {
|
||||
for (var hex = [], i = 0; i < bytes.length; i++) {
|
||||
hex.push((bytes[i] >>> 4).toString(16));
|
||||
hex.push((bytes[i] & 0xF).toString(16));
|
||||
}
|
||||
return hex.join('');
|
||||
},
|
||||
|
||||
// Convert a hex string to a byte array
|
||||
hexToBytes: function(hex) {
|
||||
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||||
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||||
return bytes;
|
||||
},
|
||||
|
||||
// Convert a byte array to a base-64 string
|
||||
bytesToBase64: function(bytes) {
|
||||
for (var base64 = [], i = 0; i < bytes.length; i += 3) {
|
||||
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
||||
for (var j = 0; j < 4; j++)
|
||||
if (i * 8 + j * 6 <= bytes.length * 8)
|
||||
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
|
||||
else
|
||||
base64.push('=');
|
||||
}
|
||||
return base64.join('');
|
||||
},
|
||||
|
||||
// Convert a base-64 string to a byte array
|
||||
base64ToBytes: function(base64) {
|
||||
// Remove non-base-64 characters
|
||||
base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
|
||||
|
||||
for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
|
||||
imod4 = ++i % 4) {
|
||||
if (imod4 == 0) continue;
|
||||
bytes.push(((base64map.indexOf(base64.charAt(i - 1))
|
||||
& (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
|
||||
| (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = crypt;
|
||||
})();
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 250:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var charenc = {
|
||||
// UTF-8 encoding
|
||||
utf8: {
|
||||
// Convert a string to a byte array
|
||||
stringToBytes: function(str) {
|
||||
return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
|
||||
},
|
||||
|
||||
// Convert a byte array to a string
|
||||
bytesToString: function(bytes) {
|
||||
return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
|
||||
}
|
||||
},
|
||||
|
||||
// Binary encoding
|
||||
bin: {
|
||||
// Convert a string to a byte array
|
||||
stringToBytes: function(str) {
|
||||
for (var bytes = [], i = 0; i < str.length; i++)
|
||||
bytes.push(str.charCodeAt(i) & 0xFF);
|
||||
return bytes;
|
||||
},
|
||||
|
||||
// Convert a byte array to a string
|
||||
bytesToString: function(bytes) {
|
||||
for (var str = [], i = 0; i < bytes.length; i++)
|
||||
str.push(String.fromCharCode(bytes[i]));
|
||||
return str.join('');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = charenc;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 251:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 262:
|
||||
|
@ -23124,79 +22790,6 @@ function mapOriginalExpression(expression, ast, mappings) {
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3646:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId
|
||||
} = __webpack_require__(3652);
|
||||
|
||||
const {
|
||||
workerUtils: { WorkerDispatcher }
|
||||
} = __webpack_require__(3651);
|
||||
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
|
||||
const setAssetRootURL = dispatcher.task("setAssetRootURL");
|
||||
const getOriginalURLs = dispatcher.task("getOriginalURLs");
|
||||
const hasOriginalURL = dispatcher.task("hasOriginalURL");
|
||||
const getOriginalRanges = dispatcher.task("getOriginalRanges");
|
||||
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
queue: true
|
||||
});
|
||||
const getGeneratedLocation = dispatcher.task("getGeneratedLocation", {
|
||||
queue: true
|
||||
});
|
||||
const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", {
|
||||
queue: true
|
||||
});
|
||||
const getOriginalLocation = dispatcher.task("getOriginalLocation");
|
||||
const getFileGeneratedRange = dispatcher.task("getFileGeneratedRange");
|
||||
const getLocationScopes = dispatcher.task("getLocationScopes");
|
||||
const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
|
||||
const applySourceMap = dispatcher.task("applySourceMap");
|
||||
const clearSourceMaps = dispatcher.task("clearSourceMaps");
|
||||
const hasMappedSource = dispatcher.task("hasMappedSource");
|
||||
const getOriginalStackFrames = dispatcher.task("getOriginalStackFrames");
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId,
|
||||
hasMappedSource,
|
||||
getOriginalURLs,
|
||||
hasOriginalURL,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
getOriginalLocation,
|
||||
getFileGeneratedRange,
|
||||
getLocationScopes,
|
||||
getOriginalSourceText,
|
||||
applySourceMap,
|
||||
clearSourceMaps,
|
||||
getOriginalStackFrames,
|
||||
startSourceMapWorker(url, assetRoot) {
|
||||
dispatcher.start(url);
|
||||
setAssetRootURL(assetRoot);
|
||||
},
|
||||
stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3651:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
|
@ -23214,94 +22807,6 @@ module.exports = {
|
|||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3652:
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const md5 = __webpack_require__(248);
|
||||
|
||||
function originalToGeneratedId(originalId) {
|
||||
const match = originalId.match(/(.*)\/originalSource/);
|
||||
return match ? match[1] : "";
|
||||
}
|
||||
|
||||
function generatedToOriginalId(generatedId, url) {
|
||||
return `${generatedId}/originalSource-${md5(url)}`;
|
||||
}
|
||||
|
||||
function isOriginalId(id) {
|
||||
return (/\/originalSource/.test(id)
|
||||
);
|
||||
}
|
||||
|
||||
function isGeneratedId(id) {
|
||||
return !isOriginalId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the query part or reference identifier of a URL string, if necessary.
|
||||
*/
|
||||
function trimUrlQuery(url) {
|
||||
const length = url.length;
|
||||
const q1 = url.indexOf("?");
|
||||
const q2 = url.indexOf("&");
|
||||
const q3 = url.indexOf("#");
|
||||
const q = Math.min(q1 != -1 ? q1 : length, q2 != -1 ? q2 : length, q3 != -1 ? q3 : length);
|
||||
|
||||
return url.slice(0, q);
|
||||
}
|
||||
|
||||
// Map suffix to content type.
|
||||
const contentMap = {
|
||||
js: "text/javascript",
|
||||
jsm: "text/javascript",
|
||||
mjs: "text/javascript",
|
||||
ts: "text/typescript",
|
||||
tsx: "text/typescript-jsx",
|
||||
jsx: "text/jsx",
|
||||
vue: "text/vue",
|
||||
coffee: "text/coffeescript",
|
||||
elm: "text/elm",
|
||||
cljc: "text/x-clojure",
|
||||
cljs: "text/x-clojurescript"
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the content type for the specified URL. If no specific
|
||||
* content type can be determined, "text/plain" is returned.
|
||||
*
|
||||
* @return String
|
||||
* The content type.
|
||||
*/
|
||||
function getContentType(url) {
|
||||
url = trimUrlQuery(url);
|
||||
const dot = url.lastIndexOf(".");
|
||||
if (dot >= 0) {
|
||||
const name = url.substring(dot + 1);
|
||||
if (name in contentMap) {
|
||||
return contentMap[name];
|
||||
}
|
||||
}
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isOriginalId,
|
||||
isGeneratedId,
|
||||
getContentType,
|
||||
contentMapForTesting: contentMap
|
||||
};
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 3653:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"eslint": "^5.0.0",
|
||||
"eslint-plugin-mozilla": "1.0.4",
|
||||
"eslint-plugin-mozilla": "1.1.1",
|
||||
"fs-extra": "^7.0.0",
|
||||
"lodash": "^4.17.2"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="context-fill #9B9B9B">
|
||||
<path d="M8 13.4c-.5 0-.9-.2-1.2-.6L.4 5.2C0 4.7-.1 4.3.2 3.7S1 3 1.6 3h12.8c.6 0 1.2.1 1.4.7.3.6.2 1.1-.2 1.6l-6.4 7.6c-.3.4-.7.5-1.2.5z"/>
|
||||
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 8c-.25 0-.35-.1-.65-.4l-3.1-3.35C.75 3.7 1.1 3 1.75 3h6.5c.65 0 1 .7.5 1.25L5.65 7.6c-.3.3-.4.4-.65.4z"/>
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 474 B После Ширина: | Высота: | Размер: 400 B |
|
@ -58,8 +58,8 @@
|
|||
background:url(/images/arrow.svg) no-repeat;
|
||||
background-size:contain;
|
||||
background-position:center center;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border:0;
|
||||
padding:0;
|
||||
margin-inline-start: 1px;
|
||||
|
|
|
@ -798,7 +798,7 @@ class Tree extends Component {
|
|||
// it should be scrolled into view.
|
||||
this._focus(item, { preventAutoScroll: true });
|
||||
if (this.props.isExpanded(item)) {
|
||||
this.props.onCollapse(item);
|
||||
this.props.onCollapse(item, e.altKey);
|
||||
} else {
|
||||
this.props.onExpand(item, e.altKey);
|
||||
}
|
||||
|
@ -806,10 +806,7 @@ class Tree extends Component {
|
|||
});
|
||||
});
|
||||
|
||||
const style = Object.assign({}, this.props.style || {}, {
|
||||
padding: 0,
|
||||
margin: 0
|
||||
});
|
||||
const style = Object.assign({}, this.props.style || {});
|
||||
|
||||
return dom.div(
|
||||
{
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const { toolboxConfig } = require("devtools-launchpad/index");
|
||||
const {isDevelopment} = require("devtools-config");
|
||||
|
||||
const path = require("path");
|
||||
const projectPath = path.join(__dirname);
|
||||
|
||||
const webpackConfig = {
|
||||
entry: {
|
||||
"devtools-components": path.join(projectPath, "index.js"),
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.join(__dirname, "assets/build"),
|
||||
filename: "[name].js",
|
||||
publicPath: "/assets/build",
|
||||
libraryTarget: "umd",
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"devtools/client/shared/vendor/react": "react",
|
||||
"devtools/client/shared/vendor/react-dom": "react-dom",
|
||||
"devtools/client/shared/vendor/react-dom-factories": "react-dom-factories",
|
||||
"devtools/client/shared/vendor/react-prop-types": "prop-types",
|
||||
"Services": path.join(__dirname,
|
||||
"node_modules/devtools-modules/client/shared/shim/Services"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const extra = {
|
||||
disablePostCSS: true,
|
||||
};
|
||||
webpackConfig.plugins = [];
|
||||
if (!isDevelopment()) {
|
||||
extra.excludeMap = {
|
||||
react: "devtools/client/shared/vendor/react",
|
||||
"react-dom": "devtools/client/shared/vendor/react-dom",
|
||||
"react-dom-factories": "devtools/client/shared/vendor/react-dom-factories",
|
||||
"prop-types": "devtools/client/shared/vendor/react-prop-types",
|
||||
lodash: "devtools/client/shared/vendor/lodash",
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = toolboxConfig(webpackConfig, {}, extra);
|
|
@ -63,17 +63,17 @@ and navigate to `http://localhost:8000` to access the dashboard.
|
|||
|
||||
Navigating to the above address will have landed you on an empty launchpad UI:
|
||||
|
||||
![Image of empty launchpad](./assets/images/empty-launchpad.png)
|
||||
![Image of empty launchpad](./images/empty-launchpad.png)
|
||||
|
||||
Click on the _Launch Firefox_ button. This should launch Firefox with a dedicated profile, listening for connections on port 6080.
|
||||
|
||||
The UI should update automatically and show you at least one tab for the new Firefox instance. If it doesn't, reload the dashboard.
|
||||
|
||||
![Image of launchpad](./assets/images/launchpad-app.png)
|
||||
![Image of launchpad](./images/launchpad-app.png)
|
||||
|
||||
Click on any of the tabs. This should open the demo app:
|
||||
|
||||
![Image of demo app](./assets/images/demo-app.png)
|
||||
![Image of demo app](./images/demo-app.png)
|
||||
|
||||
Then you can type any expression in the input field. They will be evaluated against the target tab selected in the previous steps (so if there specific objects on window on this webpage, you can check how they are represented with reps etc, ...).
|
||||
|
||||
|
|
До Ширина: | Высота: | Размер: 85 KiB После Ширина: | Высота: | Размер: 142 KiB |
До Ширина: | Высота: | Размер: 70 KiB После Ширина: | Высота: | Размер: 116 KiB |
До Ширина: | Высота: | Размер: 97 KiB После Ширина: | Высота: | Размер: 164 KiB |
|
@ -38,7 +38,7 @@
|
|||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"devtools-config": "^0.0.16",
|
||||
"devtools-launchpad": "^0.0.141",
|
||||
"devtools-launchpad": "^0.0.145",
|
||||
"devtools-license-check": "^0.7.0",
|
||||
"devtools-modules": "~1.1.0",
|
||||
"devtools-services": "^0.0.1",
|
||||
|
@ -46,7 +46,7 @@
|
|||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"enzyme-to-json": "^3.3.1",
|
||||
"eslint": "^5.0.0",
|
||||
"eslint-plugin-mozilla": "1.0.4",
|
||||
"eslint-plugin-mozilla": "1.1.1",
|
||||
"fs-extra": "^7.0.0",
|
||||
"immutable": "^3.8.2",
|
||||
"postcss-url-mapper": "^1.2.0",
|
||||
|
|
|
@ -104,11 +104,19 @@ function releaseActors(state, client) {
|
|||
}
|
||||
}
|
||||
|
||||
function invokeGetter(node: Node, grip: object, getterName: string) {
|
||||
function invokeGetter(
|
||||
node: Node,
|
||||
targetGrip: object,
|
||||
receiverId: string | null,
|
||||
getterName: string
|
||||
) {
|
||||
return async ({ dispatch, client, getState }: ThunkArg) => {
|
||||
try {
|
||||
const objectClient = client.createObjectClient(grip);
|
||||
const result = await objectClient.getPropertyValue(getterName);
|
||||
const objectClient = client.createObjectClient(targetGrip);
|
||||
const result = await objectClient.getPropertyValue(
|
||||
getterName,
|
||||
receiverId
|
||||
);
|
||||
dispatch({
|
||||
type: "GETTER_INVOKED",
|
||||
data: {
|
||||
|
|
|
@ -37,7 +37,8 @@ const {
|
|||
nodeIsLongString,
|
||||
nodeHasFullText,
|
||||
nodeHasGetter,
|
||||
getNonPrototypeParentGripValue
|
||||
getNonPrototypeParentGripValue,
|
||||
getParentGripValue
|
||||
} = Utils.node;
|
||||
|
||||
type Props = {
|
||||
|
@ -167,11 +168,17 @@ class ObjectInspectorItem extends Component<Props> {
|
|||
}
|
||||
|
||||
if (nodeHasGetter(item)) {
|
||||
const parentGrip = getNonPrototypeParentGripValue(item);
|
||||
if (parentGrip) {
|
||||
const targetGrip = getParentGripValue(item);
|
||||
const receiverGrip = getNonPrototypeParentGripValue(item);
|
||||
if (targetGrip && receiverGrip) {
|
||||
Object.assign(repProps, {
|
||||
onInvokeGetterButtonClick: () =>
|
||||
this.props.invokeGetter(item, parentGrip, item.name)
|
||||
this.props.invokeGetter(
|
||||
item,
|
||||
targetGrip,
|
||||
receiverGrip.actor,
|
||||
item.name
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,7 @@ exports[`ObjectInspector - classnames has the expected class 1`] = `
|
|||
onKeyPress={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="tree"
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
tabIndex="0"
|
||||
>
|
||||
<div
|
||||
|
@ -58,12 +53,7 @@ exports[`ObjectInspector - classnames has the inline class when inline prop is t
|
|||
onKeyPress={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="tree"
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
tabIndex="0"
|
||||
>
|
||||
<div
|
||||
|
@ -107,12 +97,7 @@ exports[`ObjectInspector - classnames has the nowrap class when disableWrap prop
|
|||
onKeyPress={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="tree"
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
tabIndex="0"
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -9,12 +9,7 @@ exports[`ObjectInspector - dimTopLevelWindow renders collapsed top-level window
|
|||
onKeyPress={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="tree"
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
tabIndex="0"
|
||||
>
|
||||
<div
|
||||
|
@ -68,12 +63,7 @@ exports[`ObjectInspector - dimTopLevelWindow renders sub-level window 1`] = `
|
|||
onKeyPress={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="tree"
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
tabIndex="0"
|
||||
>
|
||||
<div
|
||||
|
@ -154,12 +144,7 @@ exports[`ObjectInspector - dimTopLevelWindow renders window as expected when dim
|
|||
onKeyPress={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="tree"
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
tabIndex="0"
|
||||
>
|
||||
<div
|
||||
|
@ -213,12 +198,7 @@ exports[`ObjectInspector - dimTopLevelWindow renders window as expected when dim
|
|||
onKeyPress={[Function]}
|
||||
onKeyUp={[Function]}
|
||||
role="tree"
|
||||
style={
|
||||
Object {
|
||||
"margin": 0,
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
style={Object {}}
|
||||
tabIndex="0"
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -877,13 +877,26 @@ function getClosestNonBucketNode(item: Node): Node | null {
|
|||
return getClosestNonBucketNode(parent);
|
||||
}
|
||||
|
||||
function getNonPrototypeParentGripValue(item: Node | null): Node | null {
|
||||
function getParentGripNode(item: Node | null): Node | null {
|
||||
const parentNode = getParent(item);
|
||||
if (!parentNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parentGripNode = getClosestGripNode(parentNode);
|
||||
return getClosestGripNode(parentNode);
|
||||
}
|
||||
|
||||
function getParentGripValue(item: Node | null): any {
|
||||
const parentGripNode = getParentGripNode(item);
|
||||
if (!parentGripNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getValue(parentGripNode);
|
||||
}
|
||||
|
||||
function getNonPrototypeParentGripValue(item: Node | null): Node | null {
|
||||
const parentGripNode = getParentGripNode(item);
|
||||
if (!parentGripNode) {
|
||||
return null;
|
||||
}
|
||||
|
@ -905,6 +918,7 @@ module.exports = {
|
|||
getClosestGripNode,
|
||||
getClosestNonBucketNode,
|
||||
getParent,
|
||||
getParentGripValue,
|
||||
getNonPrototypeParentGripValue,
|
||||
getNumericalPropertiesCount,
|
||||
getValue,
|
||||
|
|
|
@ -57,7 +57,7 @@ function ErrorRep(props) {
|
|||
const stacktrace = props.renderStacktrace
|
||||
? props.renderStacktrace(parseStackString(preview.stack))
|
||||
: getStacktraceElements(props, preview);
|
||||
content.push("\n", stacktrace);
|
||||
content.push(stacktrace);
|
||||
}
|
||||
|
||||
return span(
|
||||
|
|
|
@ -14,4 +14,15 @@ stubs.set("SymbolWithoutIdentifier", {
|
|||
actor: "server1.conn1.child1/symbol2"
|
||||
});
|
||||
|
||||
stubs.set("SymbolWithLongString", {
|
||||
type: "symbol",
|
||||
actor: "server1.conn1.child1/symbol1",
|
||||
name: {
|
||||
type: "longString",
|
||||
initial: "aa".repeat(10000),
|
||||
length: 20000,
|
||||
actor: "server1.conn1.child1/longString58"
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = stubs;
|
||||
|
|
|
@ -8,8 +8,11 @@ const PropTypes = require("prop-types");
|
|||
const { getGripType, wrapRender } = require("./rep-utils");
|
||||
|
||||
const dom = require("react-dom-factories");
|
||||
const { rep: StringRep } = require("./string");
|
||||
const { span } = dom;
|
||||
|
||||
const MAX_STRING_LENGTH = 50;
|
||||
|
||||
/**
|
||||
* Renders a symbol.
|
||||
*/
|
||||
|
@ -21,12 +24,24 @@ function SymbolRep(props) {
|
|||
const { className = "objectBox objectBox-symbol", object } = props;
|
||||
const { name } = object;
|
||||
|
||||
let symbolText = name || "";
|
||||
if (name && name.type && name.type === "longString") {
|
||||
symbolText = StringRep({
|
||||
object: symbolText,
|
||||
shouldCrop: true,
|
||||
cropLimit: MAX_STRING_LENGTH,
|
||||
useQuotes: false
|
||||
});
|
||||
}
|
||||
|
||||
return span(
|
||||
{
|
||||
className,
|
||||
"data-link-actor-id": object.actor
|
||||
},
|
||||
`Symbol(${name || ""})`
|
||||
"Symbol(",
|
||||
symbolText,
|
||||
")"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ exports[`Error - Eval error renders with expected text for an EvalError 1`] = `
|
|||
data-link-actor-id="server1.conn1.child1/obj1022"
|
||||
>
|
||||
EvalError: "EvalError message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -38,8 +36,6 @@ exports[`Error - Internal error renders with expected text for an InternalError
|
|||
data-link-actor-id="server1.conn1.child1/obj1023"
|
||||
>
|
||||
InternalError: "InternalError message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -70,8 +66,6 @@ exports[`Error - Multi line stack error renders with expected text for Error obj
|
|||
data-link-actor-id="server1.conn1.child1/obj1021"
|
||||
>
|
||||
Error: "bar"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -134,8 +128,6 @@ exports[`Error - Range error renders with expected text for RangeError 1`] = `
|
|||
data-link-actor-id="server1.conn1.child1/obj1024"
|
||||
>
|
||||
RangeError: "RangeError message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -166,8 +158,6 @@ exports[`Error - Reference error renders with expected text for ReferenceError 1
|
|||
data-link-actor-id="server1.conn1.child1/obj1025"
|
||||
>
|
||||
ReferenceError: "ReferenceError message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -198,8 +188,6 @@ exports[`Error - Simple error renders with expected text for simple error 1`] =
|
|||
data-link-actor-id="server1.conn1.child1/obj1020"
|
||||
>
|
||||
Error: "Error message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -230,8 +218,6 @@ exports[`Error - Syntax error renders with expected text for SyntaxError 1`] = `
|
|||
data-link-actor-id="server1.conn1.child1/obj1026"
|
||||
>
|
||||
SyntaxError: "SyntaxError message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -262,8 +248,6 @@ exports[`Error - Type error renders with expected text for TypeError 1`] = `
|
|||
data-link-actor-id="server1.conn1.child1/obj1027"
|
||||
>
|
||||
TypeError: "TypeError message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -294,8 +278,6 @@ exports[`Error - URI error renders with expected text for URIError 1`] = `
|
|||
data-link-actor-id="server1.conn1.child1/obj1028"
|
||||
>
|
||||
URIError: "URIError message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -335,8 +317,6 @@ exports[`Error - base-loader.js renders as expected without mode 1`] = `
|
|||
data-link-actor-id="server1.conn1.child1/obj1020"
|
||||
>
|
||||
Error: "Error message"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -415,8 +395,6 @@ exports[`Error - longString stacktrace - cut-off location renders as expected 1`
|
|||
data-link-actor-id="server1.conn1.child1/obj33"
|
||||
>
|
||||
InternalError: "too much recursion"
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -543,8 +521,6 @@ exports[`Error - longString stacktrace renders as expected 1`] = `
|
|||
data-link-actor-id="server1.conn2.child1/obj33"
|
||||
>
|
||||
Error: ""
|
||||
|
||||
|
||||
<span
|
||||
className="objectBox-stackTrace-grid"
|
||||
key="stack"
|
||||
|
@ -719,8 +695,6 @@ exports[`Error - renderStacktrace prop uses renderStacktrace prop when provided
|
|||
data-link-actor-id="server1.conn1.child1/obj1021"
|
||||
>
|
||||
Error: "bar"
|
||||
|
||||
|
||||
<li
|
||||
className="frame"
|
||||
>
|
||||
|
@ -748,8 +722,6 @@ exports[`Error - renderStacktrace prop uses renderStacktrace with longString err
|
|||
data-link-actor-id="server1.conn1.child1/obj33"
|
||||
>
|
||||
InternalError: "too much recursion"
|
||||
|
||||
|
||||
<li
|
||||
className="frame"
|
||||
>
|
||||
|
|
|
@ -37,3 +37,20 @@ describe("test Symbol without identifier", () => {
|
|||
expectActorAttribute(renderedComponent, stub.actor);
|
||||
});
|
||||
});
|
||||
|
||||
describe("test Symbol with long string", () => {
|
||||
const stub = stubs.get("SymbolWithLongString");
|
||||
|
||||
it("renders the expected content", () => {
|
||||
const renderedComponent = shallow(
|
||||
Rep({
|
||||
object: stub
|
||||
})
|
||||
);
|
||||
|
||||
expect(renderedComponent.text()).toEqual(
|
||||
"Symbol(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa…)"
|
||||
);
|
||||
expectActorAttribute(renderedComponent, stub.actor);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const { toolboxConfig } = require("devtools-launchpad/index");
|
||||
const config = require("./config");
|
||||
const ObjectRestSpreadPlugin = require("@sucrase/webpack-object-rest-spread-plugin");
|
||||
|
||||
const path = require("path");
|
||||
const projectPath = path.join(__dirname, "src");
|
||||
|
||||
let webpackConfig = {
|
||||
entry: {
|
||||
reps: [path.join(projectPath, "launchpad/index.js")],
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.join(__dirname, "assets/build"),
|
||||
filename: "[name].js",
|
||||
publicPath: "/assets/build"
|
||||
},
|
||||
|
||||
plugins: [new ObjectRestSpreadPlugin()],
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
"devtools/client/shared/vendor/react": "react",
|
||||
"devtools/client/shared/vendor/react-dom": "react-dom",
|
||||
"devtools/client/shared/vendor/react-dom-factories": "react-dom-factories",
|
||||
"devtools/client/shared/vendor/react-prop-types": "prop-types",
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = toolboxConfig(webpackConfig, config);
|
|
@ -5,60 +5,123 @@
|
|||
// @flow
|
||||
|
||||
const {
|
||||
workerUtils: { WorkerDispatcher }
|
||||
} = require("devtools-utils");
|
||||
|
||||
import type { SourceLocation, Source, SourceId } from "debugger-html";
|
||||
import type { SourceMapConsumer } from "source-map";
|
||||
import type { locationOptions } from "./source-map";
|
||||
|
||||
export const dispatcher = new WorkerDispatcher();
|
||||
|
||||
const _getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
queue: true
|
||||
});
|
||||
|
||||
const _getGeneratedLocation = dispatcher.task("getGeneratedLocation", { queue: true });
|
||||
const _getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", { queue: true });
|
||||
|
||||
|
||||
export const setAssetRootURL = async (assetRoot: string): Promise<void> =>
|
||||
dispatcher.invoke("setAssetRootURL", assetRoot);
|
||||
|
||||
export const getOriginalURLs = async (
|
||||
generatedSource: Source
|
||||
): Promise<SourceMapConsumer> =>
|
||||
dispatcher.invoke("getOriginalURLs", generatedSource);
|
||||
|
||||
export const hasOriginalURL = async (url: string): Promise<boolean> =>
|
||||
dispatcher.invoke("hasOriginalURL", url);
|
||||
|
||||
export const getOriginalRanges = async (
|
||||
sourceId: SourceId,
|
||||
url: string
|
||||
): Promise<
|
||||
Array<{
|
||||
line: number,
|
||||
columnStart: number,
|
||||
columnEnd: number
|
||||
}>
|
||||
> => dispatcher.invoke("getOriginalRanges", sourceId, url);
|
||||
export const getGeneratedRanges = async (
|
||||
location: SourceLocation,
|
||||
originalSource: Source
|
||||
): Promise<
|
||||
Array<{
|
||||
line: number,
|
||||
columnStart: number,
|
||||
columnEnd: number
|
||||
}>
|
||||
> =>
|
||||
_getGeneratedRanges(location, originalSource);
|
||||
|
||||
export const getGeneratedLocation = async (
|
||||
location: SourceLocation,
|
||||
originalSource: Source
|
||||
): Promise<SourceLocation> => _getGeneratedLocation(location,originalSource);
|
||||
|
||||
export const getAllGeneratedLocations = async (
|
||||
location: SourceLocation,
|
||||
originalSource: Source
|
||||
): Promise<Array<SourceLocation>> => _getAllGeneratedLocations(
|
||||
location,
|
||||
originalSource
|
||||
);
|
||||
|
||||
export const getOriginalLocation = async (
|
||||
location: SourceLocation,
|
||||
options: locationOptions = {}
|
||||
): Promise<SourceLocation> =>
|
||||
dispatcher.invoke("getOriginalLocation", location, options);
|
||||
|
||||
export const getFileGeneratedRange = async (
|
||||
originalSource: Source
|
||||
): Promise<?{ start: any, end: any }> =>
|
||||
dispatcher.invoke("getFileGeneratedRange", originalSource);
|
||||
|
||||
export const getLocationScopes = dispatcher.task("getLocationScopes");
|
||||
|
||||
export const getOriginalSourceText = async (
|
||||
originalSource: Source
|
||||
): Promise<?{
|
||||
text: string,
|
||||
contentType: string
|
||||
}> => dispatcher.invoke("getOriginalSourceText", originalSource);
|
||||
|
||||
export const applySourceMap = async (
|
||||
generatedId: string,
|
||||
url: string,
|
||||
code: string,
|
||||
mappings: Object
|
||||
): Promise<void> =>
|
||||
dispatcher.invoke("applySourceMap", generatedId, url, code, mappings);
|
||||
|
||||
export const clearSourceMaps = async (): Promise<void> =>
|
||||
dispatcher.invoke("clearSourceMaps");
|
||||
|
||||
export const hasMappedSource = async (
|
||||
location: SourceLocation
|
||||
): Promise<boolean> => dispatcher.invoke("hasMappedSource", location);
|
||||
|
||||
export const getOriginalStackFrames = async (
|
||||
generatedLocation: SourceLocation
|
||||
): Promise<?Array<{
|
||||
displayName: string,
|
||||
location?: SourceLocation
|
||||
}>> => dispatcher.invoke("getOriginalStackFrames", generatedLocation);
|
||||
|
||||
export {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId
|
||||
} = require("./utils");
|
||||
} from "./utils";
|
||||
|
||||
const {
|
||||
workerUtils: { WorkerDispatcher }
|
||||
} = require("devtools-utils");
|
||||
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
|
||||
const setAssetRootURL = dispatcher.task("setAssetRootURL");
|
||||
const getOriginalURLs = dispatcher.task("getOriginalURLs");
|
||||
const getOriginalRanges = dispatcher.task("getOriginalRanges");
|
||||
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
queue: true
|
||||
});
|
||||
const getGeneratedLocation = dispatcher.task("getGeneratedLocation", {
|
||||
queue: true
|
||||
});
|
||||
const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", {
|
||||
queue: true
|
||||
});
|
||||
const getOriginalLocation = dispatcher.task("getOriginalLocation");
|
||||
const getFileGeneratedRange = dispatcher.task("getFileGeneratedRange");
|
||||
const getLocationScopes = dispatcher.task("getLocationScopes");
|
||||
const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
|
||||
const applySourceMap = dispatcher.task("applySourceMap");
|
||||
const clearSourceMaps = dispatcher.task("clearSourceMaps");
|
||||
const hasMappedSource = dispatcher.task("hasMappedSource");
|
||||
const getOriginalStackFrames = dispatcher.task("getOriginalStackFrames");
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId,
|
||||
hasMappedSource,
|
||||
getOriginalURLs,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
getOriginalLocation,
|
||||
getFileGeneratedRange,
|
||||
getLocationScopes,
|
||||
getOriginalSourceText,
|
||||
applySourceMap,
|
||||
clearSourceMaps,
|
||||
getOriginalStackFrames,
|
||||
startSourceMapWorker(url: string, assetRoot: string) {
|
||||
dispatcher.start(url);
|
||||
setAssetRootURL(assetRoot);
|
||||
},
|
||||
stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
|
||||
export const startSourceMapWorker = (url: string, assetRoot: string) => {
|
||||
dispatcher.start(url);
|
||||
setAssetRootURL(assetRoot);
|
||||
};
|
||||
export const stopSourceMapWorker = dispatcher.stop.bind(dispatcher);
|
||||
|
||||
import * as self from "devtools-source-map";
|
||||
export default self;
|
||||
|
|
|
@ -14,7 +14,11 @@ const { SourceMapConsumer, SourceMapGenerator } = require("source-map");
|
|||
|
||||
const { createConsumer } = require("./utils/createConsumer");
|
||||
const assert = require("./utils/assert");
|
||||
const { fetchSourceMap } = require("./utils/fetchSourceMap");
|
||||
const {
|
||||
fetchSourceMap,
|
||||
hasOriginalURL,
|
||||
clearOriginalURLs
|
||||
} = require("./utils/fetchSourceMap");
|
||||
const {
|
||||
getSourceMap,
|
||||
setSourceMap,
|
||||
|
@ -31,7 +35,9 @@ const { clearWasmXScopes } = require("./utils/wasmXScopes");
|
|||
|
||||
import type { SourceLocation, Source, SourceId } from "debugger-html";
|
||||
|
||||
async function getOriginalURLs(generatedSource: Source) {
|
||||
async function getOriginalURLs(
|
||||
generatedSource: Source
|
||||
): Promise<SourceMapConsumer> {
|
||||
const map = await fetchSourceMap(generatedSource);
|
||||
return map && map.sources;
|
||||
}
|
||||
|
@ -39,7 +45,16 @@ async function getOriginalURLs(generatedSource: Source) {
|
|||
const COMPUTED_SPANS = new WeakSet();
|
||||
|
||||
const SOURCE_MAPPINGS = new WeakMap();
|
||||
async function getOriginalRanges(sourceId: SourceId, url: string) {
|
||||
async function getOriginalRanges(
|
||||
sourceId: SourceId,
|
||||
url: string
|
||||
): Promise<
|
||||
Array<{
|
||||
line: number,
|
||||
columnStart: number,
|
||||
columnEnd: number
|
||||
}>
|
||||
> {
|
||||
if (!isOriginalId(sourceId)) {
|
||||
return [];
|
||||
}
|
||||
|
@ -231,7 +246,7 @@ async function getAllGeneratedLocations(
|
|||
}));
|
||||
}
|
||||
|
||||
type locationOptions = {
|
||||
export type locationOptions = {
|
||||
search?: "LEAST_UPPER_BOUND" | "GREATEST_LOWER_BOUND"
|
||||
};
|
||||
async function getOriginalLocation(
|
||||
|
@ -285,7 +300,12 @@ async function getOriginalLocation(
|
|||
};
|
||||
}
|
||||
|
||||
async function getOriginalSourceText(originalSource: Source) {
|
||||
async function getOriginalSourceText(
|
||||
originalSource: Source
|
||||
): Promise<?{
|
||||
text: string,
|
||||
contentType: string
|
||||
}> {
|
||||
assert(isOriginalId(originalSource.id), "Source is not an original source");
|
||||
|
||||
const generatedSourceId = originalToGeneratedId(originalSource.id);
|
||||
|
@ -306,7 +326,9 @@ async function getOriginalSourceText(originalSource: Source) {
|
|||
};
|
||||
}
|
||||
|
||||
async function getFileGeneratedRange(originalSource: Source) {
|
||||
async function getFileGeneratedRange(
|
||||
originalSource: Source
|
||||
): Promise<?{ start: any, end: any }> {
|
||||
assert(isOriginalId(originalSource.id), "Source is not an original source");
|
||||
|
||||
const map = await getSourceMap(originalToGeneratedId(originalSource.id));
|
||||
|
@ -360,10 +382,12 @@ function applySourceMap(
|
|||
function clearSourceMaps() {
|
||||
clearSourceMapsRequests();
|
||||
clearWasmXScopes();
|
||||
clearOriginalURLs();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getOriginalURLs,
|
||||
hasOriginalURL,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
|
|
|
@ -17,7 +17,7 @@ function convertDwarf(wasm, instance) {
|
|||
);
|
||||
const resultPtr = alloc_mem(12);
|
||||
const enableXScopes = true;
|
||||
convert_dwarf(
|
||||
const success = convert_dwarf(
|
||||
wasmPtr,
|
||||
wasm.byteLength,
|
||||
resultPtr,
|
||||
|
@ -29,6 +29,9 @@ function convertDwarf(wasm, instance) {
|
|||
const outputPtr = resultView.getUint32(0, true),
|
||||
outputLen = resultView.getUint32(4, true);
|
||||
free_mem(resultPtr);
|
||||
if (!success) {
|
||||
throw new Error("Unable to convert from DWARF sections");
|
||||
}
|
||||
if (!utf8Decoder) {
|
||||
utf8Decoder = new TextDecoder("utf-8");
|
||||
}
|
||||
|
|
|
@ -13,6 +13,17 @@ const { createConsumer } = require("./createConsumer");
|
|||
|
||||
import type { Source } from "debugger-html";
|
||||
|
||||
// URLs which have been seen in a completed source map request.
|
||||
const originalURLs = new Set();
|
||||
|
||||
function clearOriginalURLs() {
|
||||
originalURLs.clear();
|
||||
}
|
||||
|
||||
function hasOriginalURL(url: string): boolean {
|
||||
return originalURLs.has(url);
|
||||
}
|
||||
|
||||
function _resolveSourceMapURL(source: Source) {
|
||||
const { url = "", sourceMapURL = "" } = source;
|
||||
|
||||
|
@ -55,10 +66,14 @@ async function _resolveAndFetch(generatedSource: Source): SourceMapConsumer {
|
|||
}
|
||||
}
|
||||
|
||||
if (map && map.sources) {
|
||||
map.sources.forEach(url => originalURLs.add(url));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
function fetchSourceMap(generatedSource: Source) {
|
||||
function fetchSourceMap(generatedSource: Source): SourceMapConsumer {
|
||||
const existingRequest = getSourceMap(generatedSource.id);
|
||||
|
||||
// If it has already been requested, return the request. Make sure
|
||||
|
@ -84,4 +99,4 @@ function fetchSourceMap(generatedSource: Source) {
|
|||
return req;
|
||||
}
|
||||
|
||||
module.exports = { fetchSourceMap };
|
||||
module.exports = { fetchSourceMap, hasOriginalURL, clearOriginalURLs };
|
||||
|
|
|
@ -16,7 +16,7 @@ function generatedToOriginalId(generatedId: string, url: string) {
|
|||
}
|
||||
|
||||
function isOriginalId(id: string) {
|
||||
return !!id.match(/\/originalSource/);
|
||||
return /\/originalSource/.test(id);
|
||||
}
|
||||
|
||||
function isGeneratedId(id: string) {
|
||||
|
@ -62,7 +62,7 @@ const contentMap = {
|
|||
* @return String
|
||||
* The content type.
|
||||
*/
|
||||
function getContentType(url: string) {
|
||||
function getContentType(url: string): string {
|
||||
url = trimUrlQuery(url);
|
||||
const dot = url.lastIndexOf(".");
|
||||
if (dot >= 0) {
|
||||
|
|
|
@ -13,14 +13,18 @@ const { generatedToOriginalId } = require("./index");
|
|||
const xScopes = new Map();
|
||||
|
||||
type XScopeItem = any;
|
||||
type XScopeItemsIndex = Map<string, XScopeItem>;
|
||||
type XScopeItemsIndex = Map<string | number, XScopeItem>;
|
||||
|
||||
function indexLinkingNames(items: XScopeItem[]): XScopeItemsIndex {
|
||||
const result = new Map();
|
||||
let queue = [...items];
|
||||
while (queue.length > 0) {
|
||||
const item = queue.shift();
|
||||
if ("linkage_name" in item) {
|
||||
if ("uid" in item) {
|
||||
result.set(item.uid, item);
|
||||
} else if ("linkage_name" in item) {
|
||||
// TODO the linkage_name string value is used for compatibility
|
||||
// with old format. Remove in favour of the uid referencing.
|
||||
result.set(item.linkage_name, item);
|
||||
}
|
||||
if ("children" in item) {
|
||||
|
@ -30,6 +34,19 @@ function indexLinkingNames(items: XScopeItem[]): XScopeItemsIndex {
|
|||
return result;
|
||||
}
|
||||
|
||||
function getIndexedItem(
|
||||
index: XScopeItemsIndex,
|
||||
key: string | { uid: number }
|
||||
): XScopeItem {
|
||||
if (typeof key === "object" && key != null) {
|
||||
return index.get(key.uid);
|
||||
}
|
||||
if (typeof key === "string") {
|
||||
return index.get(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
type XScopeData = {
|
||||
code_section_offset: number,
|
||||
debug_info: Array<XScopeItem>,
|
||||
|
@ -112,7 +129,7 @@ function filterScopes(
|
|||
break;
|
||||
case "inlined_subroutine":
|
||||
if (isInRange(item, pc)) {
|
||||
const linkedItem = index.get(item.abstract_origin);
|
||||
const linkedItem = getIndexedItem(index, item.abstract_origin);
|
||||
const s: FoundScope = {
|
||||
id: item.abstract_origin,
|
||||
name: linkedItem ? linkedItem.name : void 0
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
const {
|
||||
getOriginalURLs,
|
||||
hasOriginalURL,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
|
@ -29,6 +30,7 @@ const {
|
|||
self.onmessage = workerHandler({
|
||||
setAssetRootURL,
|
||||
getOriginalURLs,
|
||||
hasOriginalURL,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
// @flow
|
||||
|
||||
import { isOriginalId } from "devtools-source-map";
|
||||
import {
|
||||
locationMoved,
|
||||
breakpointExists,
|
||||
assertBreakpoint,
|
||||
createBreakpoint,
|
||||
|
@ -20,10 +18,13 @@ import {
|
|||
getSource,
|
||||
getSourceActors,
|
||||
getSymbols,
|
||||
getFirstVisibleBreakpointPosition
|
||||
} from "../../selectors";
|
||||
import { getGeneratedLocation } from "../../utils/source-maps";
|
||||
import { getTextAtPosition } from "../../utils/source";
|
||||
import { recordEvent } from "../../utils/telemetry";
|
||||
import { features } from "../../utils/prefs";
|
||||
import { setBreakpointPositions } from "./breakpointPositions";
|
||||
|
||||
import type {
|
||||
BreakpointOptions,
|
||||
|
@ -67,58 +68,40 @@ async function addBreakpointPromise(getState, client, sourceMaps, breakpoint) {
|
|||
if (breakpointExists(state, location)) {
|
||||
const newBreakpoint = { ...breakpoint, location, generatedLocation };
|
||||
assertBreakpoint(newBreakpoint);
|
||||
return { breakpoint: newBreakpoint };
|
||||
return newBreakpoint;
|
||||
}
|
||||
|
||||
const sourceActors = getSourceActors(state, generatedSource.id);
|
||||
const newGeneratedLocation = { ...generatedLocation };
|
||||
|
||||
for (const sourceActor of sourceActors) {
|
||||
const sourceActorLocation = makeSourceActorLocation(
|
||||
sourceActor,
|
||||
generatedLocation
|
||||
);
|
||||
const { actualLocation } = await client.setBreakpoint(
|
||||
sourceActorLocation,
|
||||
breakpoint.options,
|
||||
isOriginalId(location.sourceId)
|
||||
);
|
||||
newGeneratedLocation.line = actualLocation.line;
|
||||
newGeneratedLocation.column = actualLocation.column;
|
||||
await client.setBreakpoint(sourceActorLocation, breakpoint.options);
|
||||
}
|
||||
|
||||
const newLocation = await sourceMaps.getOriginalLocation(
|
||||
newGeneratedLocation
|
||||
);
|
||||
|
||||
const symbols = getSymbols(getState(), source);
|
||||
const astLocation = await getASTLocation(source, symbols, newLocation);
|
||||
const astLocation = await getASTLocation(source, symbols, location);
|
||||
|
||||
const originalText = getTextAtPosition(source, location);
|
||||
const text = getTextAtPosition(generatedSource, newGeneratedLocation);
|
||||
const text = getTextAtPosition(generatedSource, generatedLocation);
|
||||
|
||||
const newBreakpoint = {
|
||||
id: makeBreakpointId(generatedLocation),
|
||||
disabled: false,
|
||||
loading: false,
|
||||
options: breakpoint.options,
|
||||
location: newLocation,
|
||||
location,
|
||||
astLocation,
|
||||
generatedLocation: newGeneratedLocation,
|
||||
generatedLocation,
|
||||
text,
|
||||
originalText
|
||||
};
|
||||
|
||||
assertBreakpoint(newBreakpoint);
|
||||
|
||||
const previousLocation = locationMoved(location, newLocation)
|
||||
? location
|
||||
: null;
|
||||
|
||||
return {
|
||||
breakpoint: newBreakpoint,
|
||||
previousLocation
|
||||
};
|
||||
return newBreakpoint;
|
||||
}
|
||||
|
||||
export function addHiddenBreakpoint(location: SourceLocation) {
|
||||
|
@ -144,22 +127,26 @@ export function enableBreakpoint(breakpoint: Breakpoint) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new breakpoint
|
||||
*
|
||||
* @memberof actions/breakpoints
|
||||
* @static
|
||||
* @param {BreakpointOptions} options Any options for the new breakpoint.
|
||||
*/
|
||||
|
||||
export function addBreakpoint(
|
||||
location: SourceLocation,
|
||||
options: BreakpointOptions = {}
|
||||
) {
|
||||
return ({ dispatch, getState, sourceMaps, client }: ThunkArgs) => {
|
||||
return async ({ dispatch, getState, sourceMaps, client }: ThunkArgs) => {
|
||||
recordEvent("add_breakpoint");
|
||||
let breakpointPosition = location;
|
||||
if (features.columnBreakpoints && location.column === undefined) {
|
||||
await dispatch(setBreakpointPositions(location));
|
||||
breakpointPosition = getFirstVisibleBreakpointPosition(
|
||||
getState(),
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
const breakpoint = createBreakpoint(location, options);
|
||||
if (!breakpointPosition) {
|
||||
return;
|
||||
}
|
||||
|
||||
const breakpoint = createBreakpoint(breakpointPosition, options);
|
||||
|
||||
return dispatch({
|
||||
type: "ADD_BREAKPOINT",
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import {
|
||||
getSourceActors,
|
||||
getBreakpointPositionsForLine
|
||||
} from "../../selectors";
|
||||
|
||||
import { makeSourceActorLocation } from "../../utils/breakpoint";
|
||||
|
||||
import type { SourceLocation } from "../../types";
|
||||
import type { ThunkArgs } from "../../actions/types";
|
||||
|
||||
export function setBreakpointPositions(location: SourceLocation) {
|
||||
return async ({ getState, dispatch, client }: ThunkArgs) => {
|
||||
if (
|
||||
getBreakpointPositionsForLine(
|
||||
getState(),
|
||||
location.sourceId,
|
||||
location.line
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceActors = getSourceActors(getState(), location.sourceId);
|
||||
const sourceActor = sourceActors[0];
|
||||
|
||||
const sourceActorLocation = makeSourceActorLocation(sourceActor, location);
|
||||
const positions = await client.getBreakpointPositions(sourceActorLocation);
|
||||
|
||||
return dispatch({ type: "ADD_BREAKPOINT_POSITIONS", positions, location });
|
||||
};
|
||||
}
|
|
@ -9,6 +9,7 @@ DIRS += [
|
|||
|
||||
DebuggerModules(
|
||||
'addBreakpoint.js',
|
||||
'breakpointPositions.js',
|
||||
'index.js',
|
||||
'remapLocations.js',
|
||||
'syncBreakpoint.js',
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import { setBreakpointPositions } from "./breakpointPositions";
|
||||
import {
|
||||
locationMoved,
|
||||
createBreakpoint,
|
||||
|
@ -16,6 +18,8 @@ import { getGeneratedLocation } from "../../utils/source-maps";
|
|||
import { getTextAtPosition } from "../../utils/source";
|
||||
import { originalToGeneratedId, isOriginalId } from "devtools-source-map";
|
||||
import { getSource, getSourceActors } from "../../selectors";
|
||||
import { features } from "../../utils/prefs";
|
||||
|
||||
import type { ThunkArgs, Action } from "../types";
|
||||
|
||||
import type {
|
||||
|
@ -75,6 +79,7 @@ export async function syncBreakpointPromise(
|
|||
getState: Function,
|
||||
client: Object,
|
||||
sourceMaps: Object,
|
||||
dispatch: Function,
|
||||
sourceId: SourceId,
|
||||
pendingBreakpoint: PendingBreakpoint
|
||||
): Promise<BreakpointSyncData | null> {
|
||||
|
@ -121,10 +126,19 @@ export async function syncBreakpointPromise(
|
|||
);
|
||||
|
||||
const sourceActors = getSourceActors(getState(), sourceId);
|
||||
let possiblePosition = true;
|
||||
if (features.columnBreakpoints && generatedLocation.column != undefined) {
|
||||
const { positions } = await dispatch(
|
||||
setBreakpointPositions(generatedLocation)
|
||||
);
|
||||
if (!positions.includes(generatedLocation.column)) {
|
||||
possiblePosition = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** ******* CASE 1: No server change ***********/
|
||||
// early return if breakpoint is disabled or we are in the sameLocation
|
||||
if (pendingBreakpoint.disabled || isSameLocation) {
|
||||
if (possiblePosition && (pendingBreakpoint.disabled || isSameLocation)) {
|
||||
// Make sure the breakpoint is installed on all source actors.
|
||||
if (!pendingBreakpoint.disabled) {
|
||||
for (const sourceActor of sourceActors) {
|
||||
|
@ -166,42 +180,33 @@ export async function syncBreakpointPromise(
|
|||
}
|
||||
}
|
||||
|
||||
if (!possiblePosition || !scopedGeneratedLocation.line) {
|
||||
return { previousLocation, breakpoint: null };
|
||||
}
|
||||
|
||||
/** ******* Case 2: Add New Breakpoint ***********/
|
||||
// If we are not disabled, set the breakpoint on the server and get
|
||||
// that info so we can set it on our breakpoints.
|
||||
|
||||
if (!scopedGeneratedLocation.line) {
|
||||
return { previousLocation, breakpoint: null };
|
||||
}
|
||||
|
||||
const newGeneratedLocation = { ...scopedGeneratedLocation };
|
||||
for (const sourceActor of sourceActors) {
|
||||
const sourceActorLocation = makeSourceActorLocation(
|
||||
sourceActor,
|
||||
scopedGeneratedLocation
|
||||
);
|
||||
const { actualLocation } = await client.setBreakpoint(
|
||||
await client.setBreakpoint(
|
||||
sourceActorLocation,
|
||||
pendingBreakpoint.options,
|
||||
isOriginalId(sourceId)
|
||||
);
|
||||
newGeneratedLocation.line = actualLocation.line;
|
||||
newGeneratedLocation.column = actualLocation.column;
|
||||
}
|
||||
|
||||
// the breakpoint might have slid server side, so we want to get the location
|
||||
// based on the server's return value
|
||||
const newLocation = await sourceMaps.getOriginalLocation(
|
||||
newGeneratedLocation
|
||||
);
|
||||
|
||||
const originalText = getTextAtPosition(source, newLocation);
|
||||
const text = getTextAtPosition(generatedSource, newGeneratedLocation);
|
||||
const originalText = getTextAtPosition(source, scopedLocation);
|
||||
const text = getTextAtPosition(generatedSource, scopedGeneratedLocation);
|
||||
|
||||
return createSyncData(
|
||||
pendingBreakpoint,
|
||||
newLocation,
|
||||
newGeneratedLocation,
|
||||
scopedLocation,
|
||||
scopedGeneratedLocation,
|
||||
previousLocation,
|
||||
text,
|
||||
originalText
|
||||
|
@ -226,6 +231,7 @@ export function syncBreakpoint(
|
|||
getState,
|
||||
client,
|
||||
sourceMaps,
|
||||
dispatch,
|
||||
sourceId,
|
||||
pendingBreakpoint
|
||||
);
|
||||
|
|
|
@ -1,40 +1,5 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`breakpoints adding a breakpoint to an invalid location adds only one breakpoint with a corrected location 1`] = `
|
||||
Object {
|
||||
"astLocation": Object {
|
||||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"line": 7,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
},
|
||||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"line": 7,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
},
|
||||
"id": "a:5:",
|
||||
"loading": false,
|
||||
"location": Object {
|
||||
"line": 7,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
},
|
||||
"options": Object {
|
||||
"condition": null,
|
||||
"hidden": false,
|
||||
"logValue": null,
|
||||
},
|
||||
"originalText": "",
|
||||
"text": "",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`breakpoints should add a breakpoint 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
|
@ -51,7 +16,6 @@ Array [
|
|||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"line": 2,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
|
@ -106,7 +70,6 @@ Object {
|
|||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"line": 1,
|
||||
"sourceId": "a.js",
|
||||
"sourceUrl": "http://localhost:8000/examples/a.js",
|
||||
|
@ -145,7 +108,6 @@ Array [
|
|||
},
|
||||
"disabled": true,
|
||||
"generatedLocation": Object {
|
||||
"column": undefined,
|
||||
"line": 5,
|
||||
"sourceId": "a",
|
||||
"sourceUrl": "http://localhost:8000/examples/a",
|
||||
|
|
|
@ -179,7 +179,7 @@ Object {
|
|||
"column": undefined,
|
||||
"line": 3,
|
||||
"sourceId": "magic.js",
|
||||
"sourceUrl": "http://localhost:8000/magic.js",
|
||||
"sourceUrl": "http://localhost:8000/examples/magic.js",
|
||||
},
|
||||
"options": Object {
|
||||
"condition": null,
|
||||
|
|
|
@ -12,10 +12,7 @@ import {
|
|||
getTelemetryEvents
|
||||
} from "../../../utils/test-head";
|
||||
|
||||
import {
|
||||
simulateCorrectThreadClient,
|
||||
simpleMockThreadClient
|
||||
} from "../../tests/helpers/threadClient.js";
|
||||
import { simpleMockThreadClient } from "../../tests/helpers/threadClient.js";
|
||||
|
||||
describe("breakpoints", () => {
|
||||
it("should add a breakpoint", async () => {
|
||||
|
@ -68,7 +65,7 @@ describe("breakpoints", () => {
|
|||
const csr = makeSource("a");
|
||||
await dispatch(actions.newSource(csr));
|
||||
await dispatch(actions.loadSourceText(csr.source));
|
||||
const { breakpoint } = await dispatch(actions.addBreakpoint(loc1));
|
||||
const breakpoint = await dispatch(actions.addBreakpoint(loc1));
|
||||
await dispatch(actions.disableBreakpoint(breakpoint));
|
||||
|
||||
expect(selectors.getBreakpointCount(getState())).toEqual(1);
|
||||
|
@ -98,31 +95,6 @@ describe("breakpoints", () => {
|
|||
expect(selectors.getBreakpointCount(getState())).toEqual(1);
|
||||
});
|
||||
|
||||
describe("adding a breakpoint to an invalid location", () => {
|
||||
it("adds only one breakpoint with a corrected location", async () => {
|
||||
const invalidLocation = {
|
||||
sourceId: "a",
|
||||
line: 5,
|
||||
sourceUrl: "http://localhost:8000/examples/a"
|
||||
};
|
||||
const {
|
||||
correctedThreadClient,
|
||||
correctedLocation
|
||||
} = simulateCorrectThreadClient(2, invalidLocation);
|
||||
const { dispatch, getState } = createStore(correctedThreadClient);
|
||||
|
||||
const csr = makeSource("a");
|
||||
await dispatch(actions.newSource(csr));
|
||||
await dispatch(actions.loadSourceText(csr.source));
|
||||
|
||||
await dispatch(actions.addBreakpoint(invalidLocation));
|
||||
const state = getState();
|
||||
expect(selectors.getBreakpointCount(state)).toEqual(1);
|
||||
const bp = selectors.getBreakpoint(state, correctedLocation);
|
||||
expect(bp).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
it("should remove a breakpoint", async () => {
|
||||
const { dispatch, getState } = createStore(simpleMockThreadClient);
|
||||
|
||||
|
@ -181,7 +153,7 @@ describe("breakpoints", () => {
|
|||
await dispatch(actions.newSource(bCSR));
|
||||
await dispatch(actions.loadSourceText(bCSR.source));
|
||||
|
||||
const { breakpoint } = await dispatch(actions.addBreakpoint(loc1));
|
||||
const breakpoint = await dispatch(actions.addBreakpoint(loc1));
|
||||
await dispatch(actions.addBreakpoint(loc2));
|
||||
|
||||
await dispatch(actions.disableBreakpoint(breakpoint));
|
||||
|
@ -202,7 +174,7 @@ describe("breakpoints", () => {
|
|||
await dispatch(actions.newSource(aCSR));
|
||||
await dispatch(actions.loadSourceText(aCSR.source));
|
||||
|
||||
const { breakpoint } = await dispatch(actions.addBreakpoint(loc));
|
||||
const breakpoint = await dispatch(actions.addBreakpoint(loc));
|
||||
await dispatch(actions.disableBreakpoint(breakpoint));
|
||||
|
||||
let bp = selectors.getBreakpoint(getState(), loc);
|
||||
|
@ -338,7 +310,7 @@ describe("breakpoints", () => {
|
|||
};
|
||||
|
||||
await dispatch(actions.newSource(makeSource("a")));
|
||||
const { breakpoint } = await dispatch(actions.addBreakpoint(loc));
|
||||
const breakpoint = await dispatch(actions.addBreakpoint(loc));
|
||||
await dispatch(actions.disableBreakpoint(breakpoint));
|
||||
|
||||
const bp = selectors.getBreakpoint(getState(), loc);
|
||||
|
|
|
@ -135,6 +135,7 @@ describe("loading the debugger", () => {
|
|||
getState,
|
||||
threadClient,
|
||||
sourceMaps,
|
||||
dispatch,
|
||||
reloadedSource.source.id,
|
||||
pendingBreakpoint()
|
||||
);
|
||||
|
@ -165,6 +166,7 @@ describe("loading the debugger", () => {
|
|||
getState,
|
||||
threadClient,
|
||||
sourceMaps,
|
||||
dispatch,
|
||||
reloadedSource.source.id,
|
||||
pendingBreakpoint()
|
||||
);
|
||||
|
@ -209,6 +211,7 @@ describe("reloading debuggee", () => {
|
|||
getState,
|
||||
threadClient,
|
||||
sourceMaps,
|
||||
dispatch,
|
||||
reloadedSource.source.id,
|
||||
pendingBreakpoint({ location: loc1 })
|
||||
);
|
||||
|
@ -252,6 +255,7 @@ describe("reloading debuggee", () => {
|
|||
getState,
|
||||
threadClient,
|
||||
sourceMaps,
|
||||
dispatch,
|
||||
reloadedSource.source.id,
|
||||
pendingBreakpoint()
|
||||
);
|
||||
|
@ -279,7 +283,7 @@ describe("reloading debuggee", () => {
|
|||
column: undefined
|
||||
};
|
||||
|
||||
const { breakpoint } = await dispatch(actions.addBreakpoint(location));
|
||||
const breakpoint = await dispatch(actions.addBreakpoint(location));
|
||||
await dispatch(actions.disableBreakpoint(breakpoint));
|
||||
|
||||
(getGeneratedLocation: any).mockImplementationOnce(() =>
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import {
|
||||
createStore,
|
||||
selectors,
|
||||
actions,
|
||||
makeSource,
|
||||
waitForState
|
||||
} from "../../../utils/test-head";
|
||||
|
||||
import { generateBreakpoint } from "../../tests/helpers/breakpoints.js";
|
||||
|
||||
import { simpleMockThreadClient } from "../../tests/helpers/threadClient.js";
|
||||
|
||||
describe("toggleBreakpointsAtLine", () => {
|
||||
it("removes all breakpoints on a given line", async () => {
|
||||
const store = createStore(simpleMockThreadClient);
|
||||
const { dispatch } = store;
|
||||
|
||||
const source = makeSource("foo.js");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(source));
|
||||
|
||||
await Promise.all([
|
||||
dispatch(
|
||||
actions.addBreakpoint(generateBreakpoint("foo.js", 5, 1).location)
|
||||
),
|
||||
dispatch(
|
||||
actions.addBreakpoint(generateBreakpoint("foo.js", 5, 2).location)
|
||||
),
|
||||
dispatch(
|
||||
actions.addBreakpoint(generateBreakpoint("foo.js", 5, 3).location)
|
||||
)
|
||||
]);
|
||||
|
||||
await dispatch(actions.selectLocation({ sourceId: "foo.js" }));
|
||||
|
||||
await waitForState(store, state => selectors.hasSymbols(state, source));
|
||||
|
||||
await dispatch(actions.toggleBreakpointsAtLine(5));
|
||||
await waitForState(
|
||||
store,
|
||||
state => selectors.getBreakpointCount(state) === 0
|
||||
);
|
||||
});
|
||||
|
||||
it("removes all breakpoints on an empty line", async () => {
|
||||
const store = createStore(simpleMockThreadClient);
|
||||
const { dispatch } = store;
|
||||
|
||||
const source = makeSource("foo.js");
|
||||
await dispatch(actions.newSource(source));
|
||||
await dispatch(actions.loadSourceText(makeSource("foo.js")));
|
||||
|
||||
await dispatch(actions.addBreakpoint({ sourceId: source.id, line: 3 }));
|
||||
await dispatch(actions.selectLocation({ sourceId: "foo.js" }));
|
||||
|
||||
await waitForState(store, state =>
|
||||
selectors.hasPausePoints(state, source.id)
|
||||
);
|
||||
|
||||
await dispatch(actions.toggleBreakpointsAtLine(3));
|
||||
|
||||
await waitForState(
|
||||
store,
|
||||
state => selectors.getBreakpointCount(state) === 0
|
||||
);
|
||||
});
|
||||
});
|
|
@ -8,7 +8,8 @@ import {
|
|||
isEvaluatingExpression,
|
||||
getSelectedFrame,
|
||||
getSources,
|
||||
getLastCommand
|
||||
getLastCommand,
|
||||
wasStepping
|
||||
} from "../../selectors";
|
||||
|
||||
import { mapFrames } from ".";
|
||||
|
@ -81,7 +82,10 @@ export function paused(pauseInfo: Pause) {
|
|||
await dispatch(selectLocation(selectedFrame.location));
|
||||
}
|
||||
|
||||
dispatch(togglePaneCollapse("end", false));
|
||||
if (!wasStepping(getState())) {
|
||||
dispatch(togglePaneCollapse("end", false));
|
||||
}
|
||||
|
||||
await dispatch(fetchScopes());
|
||||
|
||||
// Run after fetching scoping data so that it may make use of the sourcemap
|
||||
|
|
|
@ -23,7 +23,7 @@ export function resumed(packet: ResumedPacket) {
|
|||
const wasPausedInEval = inDebuggerEval(why);
|
||||
const wasStepping = isStepping(getState());
|
||||
|
||||
dispatch({ type: "RESUME", thread: packet.from });
|
||||
dispatch({ type: "RESUME", thread: packet.from, wasStepping });
|
||||
|
||||
if (!wasStepping && !wasPausedInEval) {
|
||||
await dispatch(evaluateExpressions());
|
||||
|
|
|
@ -28,43 +28,13 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`invalid breakpoint location a corrected corresponding pending breakpoint is added 1`] = `
|
||||
Object {
|
||||
"astLocation": Object {
|
||||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 7,
|
||||
"sourceId": "foo.js",
|
||||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
},
|
||||
},
|
||||
"disabled": false,
|
||||
"generatedLocation": Object {
|
||||
"column": 0,
|
||||
"line": 7,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
},
|
||||
"location": Object {
|
||||
"column": 0,
|
||||
"line": 7,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
},
|
||||
"options": Object {
|
||||
"condition": null,
|
||||
"hidden": false,
|
||||
"logValue": null,
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`when adding breakpoints a corresponding pending breakpoint should be added 1`] = `
|
||||
Object {
|
||||
"astLocation": Object {
|
||||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceId": "foo.js/originalSource",
|
||||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
|
@ -77,7 +47,7 @@ Object {
|
|||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
},
|
||||
"location": Object {
|
||||
"column": undefined,
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo.js",
|
||||
},
|
||||
|
@ -95,6 +65,7 @@ Object {
|
|||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceId": "foo/originalSource",
|
||||
"sourceUrl": "http://localhost:8000/examples/foo",
|
||||
|
@ -107,7 +78,7 @@ Object {
|
|||
"sourceUrl": "http://localhost:8000/examples/foo",
|
||||
},
|
||||
"location": Object {
|
||||
"column": undefined,
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo",
|
||||
},
|
||||
|
@ -125,6 +96,7 @@ Object {
|
|||
"index": 0,
|
||||
"name": undefined,
|
||||
"offset": Object {
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceId": "foo2/originalSource",
|
||||
"sourceUrl": "http://localhost:8000/examples/foo2",
|
||||
|
@ -137,7 +109,7 @@ Object {
|
|||
"sourceUrl": "http://localhost:8000/examples/foo2",
|
||||
},
|
||||
"location": Object {
|
||||
"column": undefined,
|
||||
"column": 0,
|
||||
"line": 5,
|
||||
"sourceUrl": "http://localhost:8000/examples/foo2",
|
||||
},
|
||||
|
|
|
@ -4,10 +4,7 @@
|
|||
|
||||
// @flow
|
||||
|
||||
import { makeBreakpointActorId } from "../../../utils/breakpoint";
|
||||
|
||||
import type {
|
||||
SourceLocation,
|
||||
SourceActor,
|
||||
SourceActorLocation,
|
||||
BreakpointOptions
|
||||
|
@ -65,39 +62,6 @@ export const simpleMockThreadClient = {
|
|||
})
|
||||
};
|
||||
|
||||
// Breakpoint Sliding
|
||||
function generateCorrectingThreadClient(offset = 0) {
|
||||
return {
|
||||
getBreakpointByLocation: (jest.fn(): any),
|
||||
setBreakpoint: (location: SourceActorLocation, condition: string) => {
|
||||
const actualLocation = { ...location, line: location.line + offset };
|
||||
|
||||
return Promise.resolve({
|
||||
id: makeBreakpointActorId(location),
|
||||
actualLocation,
|
||||
condition
|
||||
});
|
||||
},
|
||||
sourceContents: ({ source }: SourceActor) =>
|
||||
Promise.resolve(createSource(source))
|
||||
};
|
||||
}
|
||||
|
||||
/* in some cases, a breakpoint may be added, but the source will respond
|
||||
* with a different breakpoint location. This is due to the breakpoint being
|
||||
* added between functions, or somewhere that doesnt make sense. This function
|
||||
* simulates that behavior.
|
||||
* */
|
||||
export function simulateCorrectThreadClient(
|
||||
offset: number,
|
||||
location: SourceLocation
|
||||
) {
|
||||
const correctedThreadClient = generateCorrectingThreadClient(offset);
|
||||
const offsetLine = { line: location.line + offset };
|
||||
const correctedLocation = { ...location, ...offsetLine };
|
||||
return { correctedThreadClient, correctedLocation };
|
||||
}
|
||||
|
||||
// sources and tabs
|
||||
export const sourceThreadClient = {
|
||||
sourceContents: function({
|
||||
|
|
|
@ -10,10 +10,7 @@ import {
|
|||
mockPendingBreakpoint
|
||||
} from "./helpers/breakpoints.js";
|
||||
|
||||
import {
|
||||
simulateCorrectThreadClient,
|
||||
simpleMockThreadClient
|
||||
} from "./helpers/threadClient.js";
|
||||
import { simpleMockThreadClient } from "./helpers/threadClient.js";
|
||||
|
||||
import { asyncStore } from "../../utils/prefs";
|
||||
|
||||
|
@ -45,8 +42,7 @@ import {
|
|||
selectors,
|
||||
actions,
|
||||
makeOriginalSource,
|
||||
waitForState,
|
||||
makeSource
|
||||
waitForState
|
||||
} from "../../utils/test-head";
|
||||
|
||||
import { makePendingLocationId } from "../../utils/breakpoint";
|
||||
|
@ -350,31 +346,3 @@ describe("adding sources", () => {
|
|||
expect(selectors.getBreakpointCount(getState())).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("invalid breakpoint location", () => {
|
||||
it("a corrected corresponding pending breakpoint is added", async () => {
|
||||
// setup
|
||||
const bp = generateBreakpoint("foo.js");
|
||||
const {
|
||||
correctedThreadClient,
|
||||
correctedLocation
|
||||
} = simulateCorrectThreadClient(2, bp.location);
|
||||
const { dispatch, getState } = createStore(correctedThreadClient);
|
||||
const correctedPendingId = makePendingLocationId(correctedLocation);
|
||||
|
||||
// test
|
||||
const csr = makeSource("foo.js");
|
||||
await dispatch(actions.newSource(csr));
|
||||
await dispatch(actions.loadSourceText(csr.source));
|
||||
|
||||
// Fixup the breakpoint so that its location can be loaded.
|
||||
bp.location.sourceId = "foo.js";
|
||||
bp.generatedLocation = { ...bp.location };
|
||||
|
||||
await dispatch(actions.addBreakpoint(bp.location));
|
||||
const pendingBps = selectors.getPendingBreakpoints(getState());
|
||||
|
||||
const pendingBp = pendingBps[correctedPendingId];
|
||||
expect(pendingBp).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { actions, createStore } from "../../utils/test-head";
|
||||
const threadClient = {
|
||||
evaluate: jest.fn()
|
||||
};
|
||||
|
||||
describe("toolbox", () => {
|
||||
describe("evaluate in console", () => {
|
||||
it("variable", () => {
|
||||
const { dispatch } = createStore(threadClient);
|
||||
dispatch(actions.evaluateInConsole("foo"));
|
||||
|
||||
expect(threadClient.evaluate).toBeCalledWith(
|
||||
'console.log("foo"); console.log(foo)',
|
||||
{ frameId: null, thread: "UnknownThread" }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,15 +4,15 @@
|
|||
|
||||
// @flow
|
||||
|
||||
import type { Breakpoint, SourceLocation, XHRBreakpoint } from "../../types";
|
||||
import type {
|
||||
Breakpoint,
|
||||
SourceLocation,
|
||||
XHRBreakpoint,
|
||||
BreakpointLinePositions
|
||||
} from "../../types";
|
||||
|
||||
import type { PromiseAction } from "../utils/middleware/promise";
|
||||
|
||||
type AddBreakpointResult = {
|
||||
previousLocation: SourceLocation,
|
||||
breakpoint: Breakpoint
|
||||
};
|
||||
|
||||
export type BreakpointAction =
|
||||
| PromiseAction<
|
||||
{|
|
||||
|
@ -20,7 +20,7 @@ export type BreakpointAction =
|
|||
+breakpoint: Breakpoint,
|
||||
+condition?: string
|
||||
|},
|
||||
AddBreakpointResult
|
||||
Breakpoint
|
||||
>
|
||||
| PromiseAction<{|
|
||||
+type: "REMOVE_BREAKPOINT",
|
||||
|
@ -74,7 +74,7 @@ export type BreakpointAction =
|
|||
+type: "ENABLE_BREAKPOINT",
|
||||
+breakpoint: Breakpoint
|
||||
|},
|
||||
AddBreakpointResult
|
||||
Breakpoint
|
||||
>
|
||||
| {|
|
||||
+type: "DISABLE_BREAKPOINT",
|
||||
|
@ -91,4 +91,9 @@ export type BreakpointAction =
|
|||
| {|
|
||||
+type: "REMAP_BREAKPOINTS",
|
||||
+breakpoints: Breakpoint[]
|
||||
|}
|
||||
| {|
|
||||
type: "ADD_BREAKPOINT_POSITIONS",
|
||||
positions: BreakpointLinePositions,
|
||||
location: SourceLocation
|
||||
|};
|
||||
|
|
|
@ -18,7 +18,8 @@ export type PauseAction =
|
|||
| {|
|
||||
+type: "RESUME",
|
||||
+thread: string,
|
||||
+value: void
|
||||
+value: void,
|
||||
+wasStepping: boolean
|
||||
|}
|
||||
| {|
|
||||
+type: "PAUSED",
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
// @flow
|
||||
|
||||
import {
|
||||
type SymbolDeclaration,
|
||||
type SymbolDeclarations
|
||||
} from "../../workers/parser";
|
||||
|
||||
import type { Source } from "../../types";
|
||||
|
||||
function updateSymbolLocation(
|
||||
site: SymbolDeclaration,
|
||||
source: Source,
|
||||
sourceMaps: any
|
||||
) {
|
||||
return sourceMaps
|
||||
.getGeneratedLocation(
|
||||
{ ...site.location.start, sourceId: source.id },
|
||||
source
|
||||
)
|
||||
.then(loc => {
|
||||
return {
|
||||
...site,
|
||||
generatedLocation: { line: loc.line, column: loc.column }
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateSymbolLocations(
|
||||
symbols: SymbolDeclarations,
|
||||
source: Source,
|
||||
sourceMaps: any
|
||||
): Promise<SymbolDeclarations> {
|
||||
if (!symbols || !symbols.callExpressions) {
|
||||
return Promise.resolve(symbols);
|
||||
}
|
||||
|
||||
const mappedCallExpressions = await Promise.all(
|
||||
symbols.callExpressions.map(site =>
|
||||
updateSymbolLocation(site, source, sourceMaps)
|
||||
)
|
||||
);
|
||||
|
||||
const newSymbols = { ...symbols, callExpressions: mappedCallExpressions };
|
||||
|
||||
return Promise.resolve(newSymbols);
|
||||
}
|
|
@ -32,7 +32,7 @@ import type { PausePointsMap } from "../../workers/parser";
|
|||
|
||||
import { makeBreakpointActorId } from "../../utils/breakpoint";
|
||||
|
||||
import { createSource, createBreakpointLocation, createWorker } from "./create";
|
||||
import { createSource, createWorker } from "./create";
|
||||
import { supportsWorkers, updateWorkerClients } from "./workers";
|
||||
|
||||
import { features } from "../../utils/prefs";
|
||||
|
@ -189,9 +189,8 @@ function removeXHRBreakpoint(path: string, method: string) {
|
|||
|
||||
function setBreakpoint(
|
||||
location: SourceActorLocation,
|
||||
options: BreakpointOptions,
|
||||
noSliding: boolean
|
||||
): Promise<BreakpointResult> {
|
||||
options: BreakpointOptions
|
||||
) {
|
||||
const sourceThreadClient = lookupThreadClient(location.sourceActor.thread);
|
||||
const sourceClient = sourceThreadClient.source({
|
||||
actor: location.sourceActor.actor
|
||||
|
@ -202,17 +201,10 @@ function setBreakpoint(
|
|||
line: location.line,
|
||||
column: location.column,
|
||||
options,
|
||||
noSliding
|
||||
})
|
||||
.then(([{ actualLocation }, bpClient]) => {
|
||||
actualLocation = createBreakpointLocation(location, actualLocation);
|
||||
|
||||
const id = makeBreakpointActorId(actualLocation);
|
||||
.then(([, bpClient]) => {
|
||||
const id = makeBreakpointActorId(location);
|
||||
bpClients[id] = bpClient;
|
||||
bpClient.location.line = actualLocation.line;
|
||||
bpClient.location.column = actualLocation.column;
|
||||
|
||||
return { id, actualLocation };
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -456,6 +448,23 @@ function getMainThread() {
|
|||
return threadClient.actor;
|
||||
}
|
||||
|
||||
async function getBreakpointPositions(
|
||||
location: SourceActorLocation
|
||||
): Promise<Array<Number>> {
|
||||
const {
|
||||
sourceActor: { thread, actor },
|
||||
line
|
||||
} = location;
|
||||
const sourceThreadClient = lookupThreadClient(thread);
|
||||
const sourceClient = sourceThreadClient.source({ actor });
|
||||
const { positions } = await sourceClient.getBreakpointPositionsCompressed({
|
||||
start: { line },
|
||||
end: { line }
|
||||
});
|
||||
|
||||
return positions ? positions[line] : [];
|
||||
}
|
||||
|
||||
const clientCommands = {
|
||||
autocomplete,
|
||||
blackBox,
|
||||
|
@ -476,6 +485,7 @@ const clientCommands = {
|
|||
sourceContents,
|
||||
getSourceForActor,
|
||||
getBreakpointByLocation,
|
||||
getBreakpointPositions,
|
||||
setBreakpoint,
|
||||
setXHRBreakpoint,
|
||||
removeXHRBreakpoint,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// @flow
|
||||
// This module converts Firefox specific types to the generic types
|
||||
|
||||
import type { Frame, Source, SourceActorLocation, ThreadId } from "../../types";
|
||||
import type { Frame, Source, ThreadId } from "../../types";
|
||||
import type {
|
||||
PausedPacket,
|
||||
FramesResponse,
|
||||
|
@ -96,25 +96,6 @@ export function createPause(
|
|||
};
|
||||
}
|
||||
|
||||
// Firefox only returns `actualLocation` if it actually changed,
|
||||
// but we want it always to exist. Format `actualLocation` if it
|
||||
// exists, otherwise use `location`.
|
||||
|
||||
export function createBreakpointLocation(
|
||||
location: SourceActorLocation,
|
||||
actualLocation?: Object
|
||||
): SourceActorLocation {
|
||||
if (!actualLocation) {
|
||||
return location;
|
||||
}
|
||||
|
||||
return {
|
||||
...location,
|
||||
line: actualLocation.line,
|
||||
column: actualLocation.column
|
||||
};
|
||||
}
|
||||
|
||||
export function createWorker(actor: string, url: string) {
|
||||
return {
|
||||
actor,
|
||||
|
|
|
@ -330,9 +330,12 @@ export type SourceClient = {
|
|||
setBreakpoint: ({
|
||||
line: number,
|
||||
column: ?number,
|
||||
condition: ?string,
|
||||
noSliding: boolean
|
||||
condition: ?string
|
||||
}) => Promise<BreakpointResponse>,
|
||||
getBreakpointPositionsCompressed: (range: {
|
||||
start: { line: number },
|
||||
end: { line: number }
|
||||
}) => Promise<any>,
|
||||
prettyPrint: number => Promise<*>,
|
||||
disablePrettyPrint: () => Promise<*>,
|
||||
blackBox: (range?: Range) => Promise<*>,
|
||||
|
@ -398,7 +401,7 @@ export type BreakpointClient = {
|
|||
line: number,
|
||||
column: ?number
|
||||
},
|
||||
setOptions: (BreakpointOptions) => Promise<BreakpointClient>,
|
||||
setOptions: BreakpointOptions => Promise<BreakpointClient>,
|
||||
// request: any,
|
||||
source: SourceClient,
|
||||
options: BreakpointOptions
|
||||
|
|
|
@ -1,238 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { range, keyBy, isEqualWith, uniqBy, groupBy, flatten } from "lodash";
|
||||
|
||||
import CallSite from "./CallSite";
|
||||
|
||||
import {
|
||||
getSelectedSource,
|
||||
getSymbols,
|
||||
getSelectedLocation,
|
||||
getBreakpointsForSource
|
||||
} from "../../selectors";
|
||||
|
||||
import { getTokenLocation } from "../../utils/editor";
|
||||
import { isWasm } from "../../utils/wasm";
|
||||
|
||||
import actions from "../../actions";
|
||||
|
||||
function getCallSiteAtLocation(callSites, location) {
|
||||
return callSites.find(callSite =>
|
||||
isEqualWith(callSite.location, location, (cloc, loc) => {
|
||||
return (
|
||||
loc.line === cloc.start.line &&
|
||||
(loc.column >= cloc.start.column && loc.column <= cloc.end.column)
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
class CallSites extends Component {
|
||||
props: {
|
||||
symbols: Array<Symbol>,
|
||||
callSites: Array<Symbol>,
|
||||
editor: Object,
|
||||
breakpoints: Map,
|
||||
addBreakpoint: Function,
|
||||
removeBreakpoint: Function,
|
||||
selectedSource: Object,
|
||||
selectedLocation: Object
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { editor } = this.props;
|
||||
const codeMirrorWrapper = editor.codeMirror.getWrapperElement();
|
||||
|
||||
codeMirrorWrapper.addEventListener("click", e => this.onTokenClick(e));
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { editor } = this.props;
|
||||
const codeMirrorWrapper = editor.codeMirror.getWrapperElement();
|
||||
|
||||
codeMirrorWrapper.removeEventListener("click", e => this.onTokenClick(e));
|
||||
}
|
||||
|
||||
onTokenClick(e) {
|
||||
const { target } = e;
|
||||
const { editor, selectedLocation } = this.props;
|
||||
|
||||
if (
|
||||
!target.classList.contains("call-site") &&
|
||||
!target.classList.contains("call-site-bp")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { sourceId } = selectedLocation;
|
||||
const { line, column } = getTokenLocation(editor.codeMirror, target);
|
||||
|
||||
this.toggleBreakpoint(line, isWasm(sourceId) ? undefined : column);
|
||||
}
|
||||
|
||||
toggleBreakpoint(line, column = undefined) {
|
||||
const {
|
||||
selectedSource,
|
||||
selectedLocation,
|
||||
addBreakpoint,
|
||||
removeBreakpoint,
|
||||
callSites
|
||||
} = this.props;
|
||||
|
||||
const callSite = getCallSiteAtLocation(callSites, { line, column });
|
||||
|
||||
if (!callSite) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bp = callSite.breakpoint;
|
||||
|
||||
if ((bp && bp.loading) || !selectedLocation || !selectedSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { sourceId } = selectedLocation;
|
||||
|
||||
if (bp) {
|
||||
// NOTE: it's possible the breakpoint has slid to a column
|
||||
column = column || bp.location.column;
|
||||
removeBreakpoint({
|
||||
sourceId: sourceId,
|
||||
line: line,
|
||||
column
|
||||
});
|
||||
} else {
|
||||
addBreakpoint({
|
||||
sourceId: sourceId,
|
||||
sourceUrl: selectedSource.url,
|
||||
line: line,
|
||||
column: column
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Return the call sites that are on the same line as an
|
||||
// existing line breakpoint
|
||||
filterCallSitesByLineNumber() {
|
||||
const { callSites, breakpoints } = this.props;
|
||||
|
||||
// Get unique lines from breakpoints so we can filter out unwated call sites
|
||||
const uniqueBreakpointLines = new Set(
|
||||
breakpoints.map(bp => bp.location.line)
|
||||
);
|
||||
|
||||
// Get call sites based on activated breakpoint lines
|
||||
const callSitesInRange = callSites.filter(({ location }) =>
|
||||
uniqueBreakpointLines.has(location.start.line)
|
||||
);
|
||||
|
||||
// Group call sites by line
|
||||
const callSitesByLineObj = groupBy(callSitesInRange, "location.start.line");
|
||||
|
||||
// Per group, ensure all call sites are unique
|
||||
return flatten(
|
||||
Object.values(callSitesByLineObj).map(arr => {
|
||||
const uniques = uniqBy(
|
||||
arr,
|
||||
site =>
|
||||
`${site.generatedLocation.line}:${site.generatedLocation.column}`
|
||||
);
|
||||
// Only return call sites for a line when more than 1 is found
|
||||
return uniques.length > 1 ? uniques : [];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { editor, callSites, selectedSource, breakpoints } = this.props;
|
||||
|
||||
if (!callSites || breakpoints.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const callSitesFiltered = this.filterCallSitesByLineNumber();
|
||||
|
||||
let sites;
|
||||
editor.codeMirror.operation(() => {
|
||||
const childCallSites = callSitesFiltered.map((callSite, index) => {
|
||||
const props = {
|
||||
key: index,
|
||||
callSite,
|
||||
editor,
|
||||
source: selectedSource,
|
||||
breakpoint: callSite.breakpoint,
|
||||
showCallSite: true
|
||||
};
|
||||
return <CallSite {...props} />;
|
||||
});
|
||||
sites = <div>{childCallSites}</div>;
|
||||
});
|
||||
return sites;
|
||||
}
|
||||
}
|
||||
|
||||
function getCallSites(symbols, breakpoints) {
|
||||
if (!symbols || !symbols.callExpressions) {
|
||||
return;
|
||||
}
|
||||
|
||||
const callSites = symbols.callExpressions;
|
||||
|
||||
// NOTE: we create a breakpoint map keyed on location
|
||||
// to speed up the lookups. Hopefully we'll fix the
|
||||
// inconsistency with column offsets so that we can expect
|
||||
// a breakpoint to be added at the beginning of a call expression.
|
||||
const bpLocationMap = keyBy(breakpoints, ({ location }) =>
|
||||
locationKey(location)
|
||||
);
|
||||
|
||||
function locationKey({ line, column }) {
|
||||
return `${line}/${column}`;
|
||||
}
|
||||
|
||||
function findBreakpoint(callSite) {
|
||||
const {
|
||||
location: { start, end }
|
||||
} = callSite;
|
||||
|
||||
const breakpointId = range(start.column - 1, end.column)
|
||||
.map(column => locationKey({ line: start.line, column }))
|
||||
.find(key => bpLocationMap[key]);
|
||||
|
||||
if (breakpointId) {
|
||||
return bpLocationMap[breakpointId];
|
||||
}
|
||||
}
|
||||
|
||||
return callSites
|
||||
.filter(({ location }) => location.start.line === location.end.line)
|
||||
.map(callSite => ({ ...callSite, breakpoint: findBreakpoint(callSite) }));
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedLocation = getSelectedLocation(state);
|
||||
const selectedSource = getSelectedSource(state);
|
||||
const sourceId = selectedLocation && selectedLocation.sourceId;
|
||||
const symbols = getSymbols(state, selectedSource);
|
||||
const breakpoints = getBreakpointsForSource(state, sourceId);
|
||||
|
||||
return {
|
||||
selectedLocation,
|
||||
selectedSource,
|
||||
callSites: getCallSites(symbols, breakpoints),
|
||||
breakpoints: breakpoints
|
||||
};
|
||||
};
|
||||
|
||||
const { addBreakpoint, removeBreakpoint } = actions;
|
||||
const mapDispatchToProps = { addBreakpoint, removeBreakpoint };
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(CallSites);
|
|
@ -1,216 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { Component } from "react";
|
||||
import { showMenu } from "devtools-contextmenu";
|
||||
import { connect } from "../../utils/connect";
|
||||
import { lineAtHeight } from "../../utils/editor";
|
||||
import { features } from "../../utils/prefs";
|
||||
import {
|
||||
getContextMenu,
|
||||
getEmptyLines,
|
||||
getSelectedLocation,
|
||||
getSelectedSource,
|
||||
getVisibleBreakpoints,
|
||||
isPaused as getIsPaused
|
||||
} from "../../selectors";
|
||||
|
||||
import actions from "../../actions";
|
||||
|
||||
type Props = {
|
||||
setContextMenu: Function,
|
||||
contextMenu: Object
|
||||
};
|
||||
|
||||
export function gutterMenu({
|
||||
breakpoint,
|
||||
line,
|
||||
column,
|
||||
event,
|
||||
isPaused,
|
||||
toggleBreakpoint,
|
||||
openConditionalPanel,
|
||||
toggleDisabledBreakpoint,
|
||||
isCbPanelOpen,
|
||||
closeConditionalPanel,
|
||||
continueToHere,
|
||||
sourceId
|
||||
}) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
const gutterItems = {
|
||||
addBreakpoint: {
|
||||
id: "node-menu-add-breakpoint",
|
||||
label: L10N.getStr("editor.addBreakpoint")
|
||||
},
|
||||
addLogPoint: {
|
||||
id: "node-menu-add-log-point",
|
||||
label: L10N.getStr("editor.addLogPoint")
|
||||
},
|
||||
addConditional: {
|
||||
id: "node-menu-add-conditional-breakpoint",
|
||||
label: L10N.getStr("editor.addConditionBreakpoint")
|
||||
},
|
||||
removeBreakpoint: {
|
||||
id: "node-menu-remove-breakpoint",
|
||||
label: L10N.getStr("editor.removeBreakpoint")
|
||||
},
|
||||
editLogPoint: {
|
||||
id: "node-menu-edit-log-point",
|
||||
label: L10N.getStr("editor.editLogPoint")
|
||||
},
|
||||
editConditional: {
|
||||
id: "node-menu-edit-conditional-breakpoint",
|
||||
label: L10N.getStr("editor.editConditionBreakpoint")
|
||||
},
|
||||
enableBreakpoint: {
|
||||
id: "node-menu-enable-breakpoint",
|
||||
label: L10N.getStr("editor.enableBreakpoint")
|
||||
},
|
||||
disableBreakpoint: {
|
||||
id: "node-menu-disable-breakpoint",
|
||||
label: L10N.getStr("editor.disableBreakpoint")
|
||||
},
|
||||
continueToHere: {
|
||||
id: "node-menu-continue-to-here",
|
||||
label: L10N.getStr("editor.continueToHere.label")
|
||||
}
|
||||
};
|
||||
|
||||
const toggleBreakpointItem = {
|
||||
accesskey: L10N.getStr("shortcuts.toggleBreakpoint.accesskey"),
|
||||
disabled: false,
|
||||
click: () => {
|
||||
toggleBreakpoint(line, column);
|
||||
if (isCbPanelOpen) {
|
||||
closeConditionalPanel();
|
||||
}
|
||||
},
|
||||
accelerator: L10N.getStr("toggleBreakpoint.key"),
|
||||
...(breakpoint ? gutterItems.removeBreakpoint : gutterItems.addBreakpoint)
|
||||
};
|
||||
|
||||
const logPoint = {
|
||||
accesskey: L10N.getStr("editor.addLogPoint.accesskey"),
|
||||
disabled: false,
|
||||
click: () =>
|
||||
openConditionalPanel(
|
||||
breakpoint ? breakpoint.location : { line, column, sourceId },
|
||||
true
|
||||
),
|
||||
accelerator: L10N.getStr("toggleCondPanel.key"),
|
||||
...(breakpoint && breakpoint.condition
|
||||
? gutterItems.editLogPoint
|
||||
: gutterItems.addLogPoint)
|
||||
};
|
||||
|
||||
const conditionalBreakpoint = {
|
||||
accesskey: L10N.getStr("editor.addConditionBreakpoint.accesskey"),
|
||||
disabled: false,
|
||||
// Leaving column undefined so pause points can be detected
|
||||
click: () =>
|
||||
openConditionalPanel(
|
||||
breakpoint ? breakpoint.location : { line, column, sourceId }
|
||||
),
|
||||
accelerator: L10N.getStr("toggleCondPanel.key"),
|
||||
...(breakpoint && breakpoint.condition
|
||||
? gutterItems.editConditional
|
||||
: gutterItems.addConditional)
|
||||
};
|
||||
|
||||
let items = [toggleBreakpointItem, conditionalBreakpoint];
|
||||
|
||||
if (features.logPoints) {
|
||||
items.push(logPoint)
|
||||
}
|
||||
|
||||
if (breakpoint && breakpoint.condition) {
|
||||
const remove = breakpoint.log ? conditionalBreakpoint : logPoint;
|
||||
items = items.filter(item => item !== remove);
|
||||
}
|
||||
|
||||
if (isPaused) {
|
||||
const continueToHereItem = {
|
||||
accesskey: L10N.getStr("editor.continueToHere.accesskey"),
|
||||
disabled: false,
|
||||
click: () => continueToHere(line, column),
|
||||
...gutterItems.continueToHere
|
||||
};
|
||||
items.push(continueToHereItem);
|
||||
}
|
||||
|
||||
if (breakpoint) {
|
||||
const disableBreakpoint = {
|
||||
accesskey: L10N.getStr("editor.disableBreakpoint.accesskey"),
|
||||
disabled: false,
|
||||
click: () => toggleDisabledBreakpoint(line, column),
|
||||
...(breakpoint.disabled
|
||||
? gutterItems.enableBreakpoint
|
||||
: gutterItems.disableBreakpoint)
|
||||
};
|
||||
items.push(disableBreakpoint);
|
||||
}
|
||||
|
||||
showMenu(event, items);
|
||||
}
|
||||
|
||||
class GutterContextMenuComponent extends Component {
|
||||
props: Props;
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return nextProps.contextMenu.type === "Gutter";
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
// clear the context menu since it is open
|
||||
this.props.setContextMenu("", null);
|
||||
return this.showMenu(nextProps);
|
||||
}
|
||||
|
||||
showMenu(nextProps) {
|
||||
const { contextMenu, ...props } = nextProps;
|
||||
const { event } = contextMenu;
|
||||
|
||||
const sourceId = props.selectedSource ? props.selectedSource.id : "";
|
||||
const line = lineAtHeight(props.editor, sourceId, event);
|
||||
const column = props.editor.codeMirror.coordsChar({
|
||||
left: event.x,
|
||||
top: event.y
|
||||
}).ch;
|
||||
const breakpoint = nextProps.breakpoints.find(
|
||||
bp => bp.location.line === line && bp.location.column === column
|
||||
);
|
||||
|
||||
// Allow getFirstVisiblePausePoint to find the best first breakpoint
|
||||
// position by not providing an explicit column number
|
||||
if (features.columnBreakpoints && !breakpoint && column === 0) {
|
||||
column = undefined;
|
||||
}
|
||||
|
||||
gutterMenu({ event, sourceId, line, column, breakpoint, ...props });
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = getSelectedSource(state);
|
||||
|
||||
return {
|
||||
selectedLocation: getSelectedLocation(state),
|
||||
selectedSource: selectedSource,
|
||||
breakpoints: getVisibleBreakpoints(state),
|
||||
isPaused: getIsPaused(state),
|
||||
contextMenu: getContextMenu(state),
|
||||
emptyLines: getEmptyLines(state, selectedSource.id)
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
actions
|
||||
)(GutterContextMenuComponent);
|
|
@ -1,59 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
// @flow
|
||||
import { Component } from "react";
|
||||
|
||||
const markerEl = document.createElement("div");
|
||||
|
||||
function makeMarker() {
|
||||
const marker = markerEl.cloneNode(true);
|
||||
marker.className = "editor hit-marker";
|
||||
return marker;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
hitData: { [string]: any },
|
||||
editor: any
|
||||
};
|
||||
|
||||
class HitMarker extends Component<Props> {
|
||||
addMarker() {
|
||||
const hitData = this.props.hitData;
|
||||
const line = hitData.line - 1;
|
||||
|
||||
this.props.editor.setGutterMarker(line, "hit-markers", makeMarker());
|
||||
|
||||
this.props.editor.addLineClass(line, "line", "hit-marker");
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps: any) {
|
||||
return (
|
||||
this.props.editor !== nextProps.editor ||
|
||||
this.props.hitData !== nextProps.hitData
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.addMarker();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.addMarker();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const hitData = this.props.hitData;
|
||||
const line = hitData.line - 1;
|
||||
|
||||
this.props.editor.setGutterMarker(line, "hit-markers", null);
|
||||
this.props.editor.removeLineClass(line, "line", "hit-marker");
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default HitMarker;
|
|
@ -15,6 +15,13 @@
|
|||
user-select: none;
|
||||
}
|
||||
|
||||
.source-header .command-bar {
|
||||
flex: initial;
|
||||
flex-shrink: 0;
|
||||
border-bottom: 0;
|
||||
border-inline-start: 1px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
.source-tabs {
|
||||
max-width: calc(100% - 80px);
|
||||
align-self: flex-start;
|
||||
|
@ -43,7 +50,8 @@
|
|||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: var(--tab-line-color, transparent);
|
||||
transition: transform 250ms var(--animation-curve), opacity 250ms var(--animation-curve);
|
||||
transition: transform 250ms var(--animation-curve),
|
||||
opacity 250ms var(--animation-curve);
|
||||
opacity: 0;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
import React, { PureComponent } from "react";
|
||||
import { connect } from "../../utils/connect";
|
||||
|
||||
import { getSelectedSource, getSourcesForTabs } from "../../selectors";
|
||||
import {
|
||||
getSelectedSource,
|
||||
getSourcesForTabs,
|
||||
getIsPaused
|
||||
} from "../../selectors";
|
||||
import { isVisible } from "../../utils/ui";
|
||||
|
||||
import { getHiddenTabs } from "../../utils/tabs";
|
||||
|
@ -21,6 +25,7 @@ import Tab from "./Tab";
|
|||
import { PaneToggleButton } from "../shared/Button";
|
||||
import Dropdown from "../shared/Dropdown";
|
||||
import AccessibleImage from "../shared/AccessibleImage";
|
||||
import CommandBar from "../SecondaryPanes/CommandBar";
|
||||
|
||||
import type { Source } from "../../types";
|
||||
|
||||
|
@ -36,7 +41,8 @@ type Props = {
|
|||
closeTab: typeof actions.closeTab,
|
||||
togglePaneCollapse: typeof actions.togglePaneCollapse,
|
||||
showSource: typeof actions.showSource,
|
||||
selectSource: typeof actions.selectSource
|
||||
selectSource: typeof actions.selectSource,
|
||||
isPaused: boolean
|
||||
};
|
||||
|
||||
type State = {
|
||||
|
@ -170,6 +176,15 @@ class Tabs extends PureComponent<Props, State> {
|
|||
return <Dropdown panel={Panel} icon={icon} />;
|
||||
}
|
||||
|
||||
renderCommandBar() {
|
||||
const { horizontal, endPanelCollapsed, isPaused } = this.props;
|
||||
if (!endPanelCollapsed || !isPaused) {
|
||||
return;
|
||||
}
|
||||
|
||||
return <CommandBar horizontal={horizontal} />;
|
||||
}
|
||||
|
||||
renderStartPanelToggleButton() {
|
||||
return (
|
||||
<PaneToggleButton
|
||||
|
@ -203,6 +218,7 @@ class Tabs extends PureComponent<Props, State> {
|
|||
{this.renderTabs()}
|
||||
{this.renderDropdown()}
|
||||
{this.renderEndPanelToggleButton()}
|
||||
{this.renderCommandBar()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -210,7 +226,8 @@ class Tabs extends PureComponent<Props, State> {
|
|||
|
||||
const mapStateToProps = state => ({
|
||||
selectedSource: getSelectedSource(state),
|
||||
tabSources: getSourcesForTabs(state)
|
||||
tabSources: getSourcesForTabs(state),
|
||||
isPaused: getIsPaused(state)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -99,10 +99,6 @@
|
|||
color: inherit;
|
||||
}
|
||||
|
||||
.sources-list .tree .img.arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.theme-dark .source-list .tree .node.focused {
|
||||
background-color: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,6 @@ class SourcesTree extends Component<Props, State> {
|
|||
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
const {
|
||||
thread,
|
||||
projectRoot,
|
||||
debuggeeUrl,
|
||||
sources,
|
||||
|
|
|
@ -196,7 +196,7 @@ describe("SourcesTree", () => {
|
|||
await component
|
||||
.find(".sources-list")
|
||||
.simulate("keydown", { keyCode: 13 });
|
||||
// expect(props.selectSource).toHaveBeenCalledWith(item.contents.id);
|
||||
expect(props.selectSource).toHaveBeenCalledWith(item.contents.id);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -370,7 +370,7 @@ function generateDefaults(overrides: Object) {
|
|||
autoExpandAll: true,
|
||||
selectSource: jest.fn(),
|
||||
setExpandedState: jest.fn(),
|
||||
sources: { FakeThread: defaultSources },
|
||||
sources: defaultSources,
|
||||
debuggeeUrl: "http://mdn.com",
|
||||
clearProjectDirectoryRoot: jest.fn(),
|
||||
setProjectDirectoryRoot: jest.fn(),
|
||||
|
|
|
@ -6,10 +6,32 @@ exports[`SourcesTree After changing expanded nodes Shows the tree with four.js,
|
|||
key="pane"
|
||||
>
|
||||
<div
|
||||
className="no-sources-message"
|
||||
key="empty"
|
||||
className="sources-list"
|
||||
key="tree"
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
This page has no sources
|
||||
<ManagedTree
|
||||
autoExpandAll={false}
|
||||
autoExpandDepth={0}
|
||||
expanded={
|
||||
Array [
|
||||
"four.js",
|
||||
"five.js",
|
||||
"six.js",
|
||||
]
|
||||
}
|
||||
getChildren={[Function]}
|
||||
getParent={[Function]}
|
||||
getPath={[Function]}
|
||||
getRoots={[Function]}
|
||||
itemHeight={21}
|
||||
key="full"
|
||||
onCollapse={[Function]}
|
||||
onExpand={[Function]}
|
||||
onFocus={[Function]}
|
||||
preventBlur={true}
|
||||
renderItem={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -20,10 +42,25 @@ exports[`SourcesTree Should show the tree with nothing expanded 1`] = `
|
|||
key="pane"
|
||||
>
|
||||
<div
|
||||
className="no-sources-message"
|
||||
key="empty"
|
||||
className="sources-list"
|
||||
key="tree"
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
This page has no sources
|
||||
<ManagedTree
|
||||
autoExpandAll={false}
|
||||
autoExpandDepth={1}
|
||||
getChildren={[Function]}
|
||||
getParent={[Function]}
|
||||
getPath={[Function]}
|
||||
getRoots={[Function]}
|
||||
itemHeight={21}
|
||||
key="full"
|
||||
onCollapse={[Function]}
|
||||
onExpand={[Function]}
|
||||
onFocus={[Function]}
|
||||
preventBlur={true}
|
||||
renderItem={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -34,10 +71,32 @@ exports[`SourcesTree When loading initial source Shows the tree with one.js, two
|
|||
key="pane"
|
||||
>
|
||||
<div
|
||||
className="no-sources-message"
|
||||
key="empty"
|
||||
className="sources-list"
|
||||
key="tree"
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
This page has no sources
|
||||
<ManagedTree
|
||||
autoExpandAll={false}
|
||||
autoExpandDepth={0}
|
||||
expanded={
|
||||
Array [
|
||||
"one.js",
|
||||
"two.js",
|
||||
"three.js",
|
||||
]
|
||||
}
|
||||
getChildren={[Function]}
|
||||
getParent={[Function]}
|
||||
getPath={[Function]}
|
||||
getRoots={[Function]}
|
||||
itemHeight={21}
|
||||
key="full"
|
||||
onCollapse={[Function]}
|
||||
onExpand={[Function]}
|
||||
onFocus={[Function]}
|
||||
preventBlur={true}
|
||||
renderItem={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -48,8 +107,9 @@ exports[`SourcesTree on receiving new props updates highlighted items updates hi
|
|||
key="pane"
|
||||
>
|
||||
<div
|
||||
className="no-sources-message"
|
||||
key="empty"
|
||||
className="sources-list"
|
||||
key="tree"
|
||||
onKeyDown={[Function]}
|
||||
>
|
||||
<ManagedTree
|
||||
autoExpandAll={false}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
.frames [role="list"] {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin-top: 4px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,6 @@
|
|||
mask-size: 100%;
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-inline-start: 4px;
|
||||
}
|
||||
|
||||
:root.theme-dark .annotation-logo:not(.angular) svg path {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
.frames [role="list"] .frames-group .group,
|
||||
.frames [role="list"] .frames-group .group .location {
|
||||
.frames ul .frames-group .group,
|
||||
.frames ul .frames-group .group .location {
|
||||
font-weight: 500;
|
||||
cursor: default;
|
||||
/*
|
||||
|
@ -14,30 +14,25 @@
|
|||
direction: ltr;
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group.expanded .group,
|
||||
.frames [role="list"] .frames-group.expanded .group .location {
|
||||
.frames ul .frames-group.expanded .group,
|
||||
.frames ul .frames-group.expanded .group .location {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group.expanded .react path {
|
||||
.frames ul .frames-group.expanded .react path {
|
||||
fill: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group .frames-list [role="listitem"] {
|
||||
.frames ul .frames-group .frames-list li {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group .frames-list {
|
||||
.frames ul .frames-group .frames-list {
|
||||
border-top: 1px solid var(--theme-splitter-color);
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
}
|
||||
|
||||
/* We don't want to display those as flex since only the name is displayed */
|
||||
.frames [role="list"] .frames-group .frames-list [role="listitem"] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.frames [role="list"] .frames-group.expanded .badge {
|
||||
.frames ul .frames-group.expanded .badge {
|
||||
color: var(--theme-highlight-blue);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ describe("Frame", () => {
|
|||
|
||||
const props = frameProperties(frame, null);
|
||||
const component = mount(<Frame {...props} />);
|
||||
expect(component.text()).toBe("\trenderFoo foo-view.js:10\n");
|
||||
expect(component.text()).toBe(" renderFoo foo-view.js:10");
|
||||
});
|
||||
|
||||
it("full URL", () => {
|
||||
|
@ -80,7 +80,7 @@ describe("Frame", () => {
|
|||
|
||||
const props = frameProperties(frame, null, { displayFullUrl: true });
|
||||
const component = mount(<Frame {...props} />);
|
||||
expect(component.text()).toBe(`renderFoo ${url}:10`);
|
||||
expect(component.text()).toBe(` renderFoo ${url}:10`);
|
||||
});
|
||||
|
||||
it("getFrameTitle", () => {
|
||||
|
|
|
@ -65,6 +65,9 @@ exports[`Group displays a group 1`] = `
|
|||
<Badge>
|
||||
1
|
||||
</Badge>
|
||||
<br
|
||||
className="clipboard-only"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -134,11 +137,16 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
<Badge>
|
||||
3
|
||||
</Badge>
|
||||
<br
|
||||
className="clipboard-only"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="frames-list"
|
||||
>
|
||||
<FrameIndent />
|
||||
<FrameIndent
|
||||
key="frame-indent-0"
|
||||
/>
|
||||
<Frame
|
||||
copyStackTrace={[MockFunction]}
|
||||
disableContextMenu={false}
|
||||
|
@ -233,7 +241,9 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
toggleBlackBox={[MockFunction]}
|
||||
toggleFrameworkGrouping={[MockFunction]}
|
||||
/>
|
||||
<FrameIndent />
|
||||
<FrameIndent
|
||||
key="frame-indent-1"
|
||||
/>
|
||||
<Frame
|
||||
copyStackTrace={[MockFunction]}
|
||||
disableContextMenu={false}
|
||||
|
@ -328,7 +338,9 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
toggleBlackBox={[MockFunction]}
|
||||
toggleFrameworkGrouping={[MockFunction]}
|
||||
/>
|
||||
<FrameIndent />
|
||||
<FrameIndent
|
||||
key="frame-indent-2"
|
||||
/>
|
||||
<Frame
|
||||
copyStackTrace={[MockFunction]}
|
||||
disableContextMenu={false}
|
||||
|
@ -492,6 +504,9 @@ exports[`Group renders group with anonymous functions 1`] = `
|
|||
<Badge>
|
||||
3
|
||||
</Badge>
|
||||
<br
|
||||
className="clipboard-only"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -561,11 +576,16 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
<Badge>
|
||||
3
|
||||
</Badge>
|
||||
<br
|
||||
className="clipboard-only"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="frames-list"
|
||||
>
|
||||
<FrameIndent />
|
||||
<FrameIndent
|
||||
key="frame-indent-0"
|
||||
/>
|
||||
<Frame
|
||||
copyStackTrace={[MockFunction]}
|
||||
disableContextMenu={false}
|
||||
|
@ -659,7 +679,9 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
toggleBlackBox={[MockFunction]}
|
||||
toggleFrameworkGrouping={[MockFunction]}
|
||||
/>
|
||||
<FrameIndent />
|
||||
<FrameIndent
|
||||
key="frame-indent-1"
|
||||
/>
|
||||
<Frame
|
||||
copyStackTrace={[MockFunction]}
|
||||
disableContextMenu={false}
|
||||
|
@ -753,7 +775,9 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
toggleBlackBox={[MockFunction]}
|
||||
toggleFrameworkGrouping={[MockFunction]}
|
||||
/>
|
||||
<FrameIndent />
|
||||
<FrameIndent
|
||||
key="frame-indent-2"
|
||||
/>
|
||||
<Frame
|
||||
copyStackTrace={[MockFunction]}
|
||||
disableContextMenu={false}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import type { Frame } from "../../../types";
|
||||
|
||||
export type LocalFrame = Frame & {
|
||||
library: string,
|
||||
source: Source
|
||||
};
|
|
@ -1,110 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import React, { PureComponent } from "react";
|
||||
import { connect } from "../../utils/connect";
|
||||
import actions from "../../actions";
|
||||
|
||||
import { createObjectClient } from "../../client/firefox";
|
||||
import { getSelectedFrame, getAllPopupObjectProperties } from "../../selectors";
|
||||
|
||||
import { objectInspector } from "devtools-reps";
|
||||
import { isReactComponent } from "../../utils/preview";
|
||||
|
||||
import type { Frame } from "../../types";
|
||||
|
||||
const {
|
||||
component: ObjectInspector,
|
||||
utils: {
|
||||
createNode,
|
||||
getChildren,
|
||||
loadProperties: { loadItemProperties }
|
||||
}
|
||||
} = objectInspector;
|
||||
|
||||
type Props = {
|
||||
selectedFrame: Frame,
|
||||
popupObjectProperties: Object,
|
||||
setPopupObjectProperties: typeof actions.setPopupObjectProperties,
|
||||
openElementInInspector: typeof actions.setPopupObjectProperties
|
||||
};
|
||||
|
||||
class FrameworkComponent extends PureComponent<Props> {
|
||||
async componentWillMount() {
|
||||
const expression = "this;";
|
||||
const { selectedFrame, setPopupObjectProperties } = this.props;
|
||||
const value = selectedFrame.this;
|
||||
|
||||
const root = createNode({ name: expression, contents: { value } });
|
||||
const properties = await loadItemProperties(root, createObjectClient);
|
||||
if (properties) {
|
||||
setPopupObjectProperties(value, properties);
|
||||
}
|
||||
}
|
||||
|
||||
renderReactComponent() {
|
||||
const {
|
||||
selectedFrame,
|
||||
popupObjectProperties,
|
||||
openElementInInspector
|
||||
} = this.props;
|
||||
const expression = "this;";
|
||||
const value = selectedFrame.this;
|
||||
const root = {
|
||||
name: expression,
|
||||
path: expression,
|
||||
contents: { value }
|
||||
};
|
||||
|
||||
const loadedRootProperties = popupObjectProperties[value.actor];
|
||||
if (!loadedRootProperties) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let roots = getChildren({
|
||||
item: root,
|
||||
loadedProperties: new Map([[root.path, loadedRootProperties]])
|
||||
});
|
||||
|
||||
roots = roots.filter(r => ["state", "props"].includes(r.name));
|
||||
|
||||
return (
|
||||
<div className="pane framework-component">
|
||||
<ObjectInspector
|
||||
roots={roots}
|
||||
autoExpandAll={false}
|
||||
autoExpandDepth={0}
|
||||
disableWrap={true}
|
||||
focusable={false}
|
||||
dimTopLevelWindow={true}
|
||||
createObjectClient={grip => createObjectClient(grip)}
|
||||
onDOMNodeClick={grip => openElementInInspector(grip)}
|
||||
onInspectIconClick={grip => openElementInInspector(grip)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { selectedFrame } = this.props;
|
||||
if (selectedFrame && isReactComponent(selectedFrame.this)) {
|
||||
return this.renderReactComponent();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
selectedFrame: getSelectedFrame(state),
|
||||
popupObjectProperties: getAllPopupObjectProperties(state)
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
{
|
||||
setPopupObjectProperties: actions.setPopupObjectProperties,
|
||||
openElementInInspector: actions.openElementInInspectorCommand
|
||||
}
|
||||
)(FrameworkComponent);
|
|
@ -7,3 +7,7 @@
|
|||
background: var(--theme-icon-color);
|
||||
mask-size: 100%;
|
||||
}
|
||||
|
||||
.img.arrow.arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { shallow } from "enzyme";
|
||||
import Svg from "../Svg";
|
||||
|
||||
describe("Svg", () => {
|
||||
it("renders with props", () => {
|
||||
const wrapper = shallow(
|
||||
Svg({
|
||||
name: "webpack",
|
||||
className: "class",
|
||||
onClick: () => {},
|
||||
"aria-label": "label"
|
||||
})
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("render nothing if invalid svg name", () => {
|
||||
const svg = Svg({ name: "reallyRandomNameHere" });
|
||||
expect(svg).toBe(null);
|
||||
});
|
||||
|
||||
it("calls onClick method on click", () => {
|
||||
const onClick = jest.fn();
|
||||
const wrapper = shallow(
|
||||
Svg({
|
||||
name: "webpack",
|
||||
className: "class",
|
||||
onClick,
|
||||
"aria-label": "label"
|
||||
})
|
||||
);
|
||||
wrapper.simulate("click");
|
||||
expect(onClick).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
|
@ -1,15 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Svg renders with props 1`] = `
|
||||
<i
|
||||
aria-label="label"
|
||||
className="webpack class"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<svg></svg>",
|
||||
}
|
||||
}
|
||||
onClick={[Function]}
|
||||
src={null}
|
||||
/>
|
||||
`;
|
|
@ -232,30 +232,6 @@ export function getPausePoint(
|
|||
}
|
||||
}
|
||||
|
||||
export function getFirstPausePointLocation(
|
||||
state: OuterState,
|
||||
location: SourceLocation
|
||||
): SourceLocation {
|
||||
const { sourceId } = location;
|
||||
const pausePoints = getPausePoints(state, location.sourceId);
|
||||
if (!pausePoints) {
|
||||
return location;
|
||||
}
|
||||
|
||||
const pausesAtLine = pausePoints.filter(
|
||||
point => point.location.line == location.line
|
||||
);
|
||||
|
||||
if (pausesAtLine) {
|
||||
const values: PausePoint[] = (Object.values(pausesAtLine): any);
|
||||
const firstPausePoint = values.find(pausePoint => pausePoint.types.break);
|
||||
if (firstPausePoint) {
|
||||
return { ...firstPausePoint.location, sourceId };
|
||||
}
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
export function hasPausePoints(state: OuterState, sourceId: string): boolean {
|
||||
const pausePoints = getPausePoints(state, sourceId);
|
||||
return !!pausePoints;
|
||||
|
|
|
@ -18,7 +18,10 @@ import type {
|
|||
XHRBreakpoint,
|
||||
Breakpoint,
|
||||
BreakpointId,
|
||||
SourceLocation
|
||||
SourceLocation,
|
||||
BreakpointPositions,
|
||||
BreakpointLinePositions,
|
||||
BreakpointSourcePositions
|
||||
} from "../types";
|
||||
import type { Action, DonePromiseAction } from "../actions/types";
|
||||
|
||||
|
@ -27,7 +30,9 @@ export type XHRBreakpointsList = $ReadOnlyArray<XHRBreakpoint>;
|
|||
|
||||
export type BreakpointsState = {
|
||||
breakpoints: BreakpointsMap,
|
||||
xhrBreakpoints: XHRBreakpointsList
|
||||
breakpointPositions: BreakpointPositions,
|
||||
xhrBreakpoints: XHRBreakpointsList,
|
||||
breakpointsDisabled: boolean
|
||||
};
|
||||
|
||||
export function initialBreakpointsState(
|
||||
|
@ -36,6 +41,7 @@ export function initialBreakpointsState(
|
|||
return {
|
||||
breakpoints: {},
|
||||
xhrBreakpoints: xhrBreakpoints,
|
||||
breakpointPositions: {},
|
||||
breakpointsDisabled: false
|
||||
};
|
||||
}
|
||||
|
@ -104,6 +110,21 @@ function update(
|
|||
case "DISABLE_XHR_BREAKPOINT": {
|
||||
return updateXHRBreakpoint(state, action);
|
||||
}
|
||||
|
||||
case "ADD_BREAKPOINT_POSITIONS": {
|
||||
const {
|
||||
location: { sourceId, line },
|
||||
positions
|
||||
} = action;
|
||||
const sourcePositions = state.breakpointPositions[sourceId] || {};
|
||||
return {
|
||||
...state,
|
||||
breakpointPositions: {
|
||||
...state.breakpointPositions,
|
||||
[sourceId]: { ...sourcePositions, [line]: positions }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -186,7 +207,7 @@ function addBreakpoint(state, action): BreakpointsState {
|
|||
// when the action completes, we can commit the breakpoint
|
||||
if (action.status === "done") {
|
||||
const { value } = ((action: any): DonePromiseAction);
|
||||
return syncBreakpoint(state, value);
|
||||
return syncBreakpoint(state, { breakpoint: value, previousLocation: null });
|
||||
}
|
||||
|
||||
// Remove the optimistic update
|
||||
|
@ -331,4 +352,27 @@ export function getHiddenBreakpoint(state: OuterState): ?Breakpoint {
|
|||
return breakpoints.find(bp => bp.options.hidden);
|
||||
}
|
||||
|
||||
export function getBreakpointPositions(
|
||||
state: OuterState
|
||||
): ?BreakpointPositions {
|
||||
return state.breakpoints.breakpointPositions;
|
||||
}
|
||||
|
||||
export function getBreakpointPositionsForSource(
|
||||
state: OuterState,
|
||||
sourceId: string
|
||||
): ?BreakpointSourcePositions {
|
||||
const positions = getBreakpointPositions(state);
|
||||
return positions && positions[sourceId];
|
||||
}
|
||||
|
||||
export function getBreakpointPositionsForLine(
|
||||
state: OuterState,
|
||||
sourceId: string,
|
||||
line: number
|
||||
): ?BreakpointLinePositions {
|
||||
const positions = getBreakpointPositionsForSource(state, sourceId);
|
||||
return positions ? positions[line] : null;
|
||||
}
|
||||
|
||||
export default update;
|
||||
|
|
|
@ -69,6 +69,7 @@ type ThreadPauseState = {
|
|||
shouldPauseOnCaughtExceptions: boolean,
|
||||
command: Command,
|
||||
lastCommand: Command,
|
||||
wasStepping: boolean,
|
||||
previousLocation: ?MappedLocation,
|
||||
skipPausing: boolean
|
||||
};
|
||||
|
@ -277,7 +278,10 @@ function update(
|
|||
if (!action.thread && !state.currentThread) {
|
||||
return state;
|
||||
}
|
||||
return updateThreadState(resumedPauseState);
|
||||
return updateThreadState({
|
||||
...resumedPauseState,
|
||||
wasStepping: !!action.wasStepping
|
||||
});
|
||||
|
||||
case "EVALUATE_EXPRESSION":
|
||||
return updateThreadState({
|
||||
|
@ -359,6 +363,10 @@ export function getLastCommand(state: OuterState, thread: string) {
|
|||
return getThreadPauseState(state.pause, thread).lastCommand;
|
||||
}
|
||||
|
||||
export function wasStepping(state: OuterState): boolean {
|
||||
return getCurrentPauseState(state).wasStepping;
|
||||
}
|
||||
|
||||
export function isStepping(state: OuterState) {
|
||||
return ["stepIn", "stepOver", "stepOut"].includes(getPauseCommand(state));
|
||||
}
|
||||
|
|
|
@ -69,15 +69,7 @@ function addBreakpoint(state, action) {
|
|||
return state;
|
||||
}
|
||||
// when the action completes, we can commit the breakpoint
|
||||
const {
|
||||
breakpoint,
|
||||
previousLocation
|
||||
} = ((action: any): DonePromiseAction).value;
|
||||
|
||||
if (previousLocation) {
|
||||
const previousLocationId = makePendingLocationId(previousLocation);
|
||||
state = deleteBreakpoint(state, previousLocationId);
|
||||
}
|
||||
const breakpoint = ((action: any): DonePromiseAction).value;
|
||||
|
||||
const locationId = makePendingLocationId(breakpoint.location);
|
||||
const pendingBreakpoint = createPendingBreakpoint(breakpoint);
|
||||
|
|
|
@ -30,7 +30,8 @@ export {
|
|||
} from "./breakpointAtLocation";
|
||||
export {
|
||||
getVisibleBreakpoints,
|
||||
getFirstVisibleBreakpoints
|
||||
getFirstVisibleBreakpoints,
|
||||
getFirstVisibleBreakpointPosition
|
||||
} from "./visibleBreakpoints";
|
||||
export { inComponent } from "./inComponent";
|
||||
export { isSelectedFrameVisible } from "./isSelectedFrameVisible";
|
||||
|
|
|
@ -7,14 +7,24 @@
|
|||
import { createSelector } from "reselect";
|
||||
import { uniqBy } from "lodash";
|
||||
|
||||
import { getBreakpointsList } from "../reducers/breakpoints";
|
||||
import {
|
||||
getBreakpointsList,
|
||||
getBreakpointPositionsForLine,
|
||||
getBreakpointPositions
|
||||
} from "../reducers/breakpoints";
|
||||
import { getPausePoints } from "../reducers/ast";
|
||||
import { getSelectedSource } from "../reducers/sources";
|
||||
|
||||
import { sortBreakpoints } from "../utils/breakpoint";
|
||||
import { getSelectedLocation } from "../utils/source-maps";
|
||||
|
||||
import type { Breakpoint, Source } from "../types";
|
||||
import type { Selector } from "../reducers/types";
|
||||
import type {
|
||||
Breakpoint,
|
||||
Source,
|
||||
SourceLocation,
|
||||
BreakpointPositions
|
||||
} from "../types";
|
||||
import type { Selector, State } from "../reducers/types";
|
||||
|
||||
function isVisible(breakpoint: Breakpoint, selectedSource: Source) {
|
||||
const location = getSelectedLocation(breakpoint, selectedSource);
|
||||
|
@ -27,7 +37,12 @@ function isVisible(breakpoint: Breakpoint, selectedSource: Source) {
|
|||
export const getVisibleBreakpoints: Selector<?(Breakpoint[])> = createSelector(
|
||||
getSelectedSource,
|
||||
getBreakpointsList,
|
||||
(selectedSource: ?Source, breakpoints: Breakpoint[]) => {
|
||||
getBreakpointPositions,
|
||||
(
|
||||
selectedSource: ?Source,
|
||||
breakpoints: Breakpoint[],
|
||||
positions: ?BreakpointPositions
|
||||
) => {
|
||||
if (selectedSource == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -39,6 +54,33 @@ export const getVisibleBreakpoints: Selector<?(Breakpoint[])> = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
export function getFirstVisibleBreakpointPosition(
|
||||
state: State,
|
||||
location: SourceLocation
|
||||
): ?SourceLocation {
|
||||
const { sourceId, line } = location;
|
||||
const pausePoints = getPausePoints(state, location.sourceId);
|
||||
const positions = getBreakpointPositionsForLine(state, sourceId, line);
|
||||
|
||||
if (!pausePoints || !positions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const pausesAtLine = pausePoints.filter(
|
||||
p => p.location.line == line && positions.includes(p.location.column)
|
||||
);
|
||||
|
||||
if (pausesAtLine.length > 0) {
|
||||
const firstPausePoint = pausesAtLine.find(
|
||||
pausePoint => pausePoint.types.break
|
||||
);
|
||||
if (firstPausePoint) {
|
||||
return { ...firstPausePoint.location, sourceId };
|
||||
}
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the first breakpoint per line, which appear in the selected source.
|
||||
*/
|
||||
|
|
|
@ -441,3 +441,8 @@ export type Cancellable = {
|
|||
export type EventListenerBreakpoints = string[];
|
||||
|
||||
export type SourceDocuments = { [string]: Object };
|
||||
|
||||
export type BreakpointPosition = { line: number, string: number };
|
||||
export type BreakpointLinePositions = Array<BreakpointPosition>;
|
||||
export type BreakpointSourcePositions = { [number]: BreakpointLinePositions };
|
||||
export type BreakpointPositions = { [string]: BreakpointSourcePositions };
|
||||
|
|
|
@ -22,6 +22,7 @@ import App from "../components/App";
|
|||
import { asyncStore, prefs } from "./prefs";
|
||||
|
||||
import type { Panel } from "../client/firefox/types";
|
||||
import typeof SourceMaps from "../../packages/devtools-source-map/src";
|
||||
|
||||
function renderPanel(component, store) {
|
||||
const root = document.createElement("div");
|
||||
|
@ -41,7 +42,7 @@ function renderPanel(component, store) {
|
|||
|
||||
export function bootstrapStore(
|
||||
client: any,
|
||||
sourceMaps: Object,
|
||||
sourceMaps: SourceMaps,
|
||||
panel: Panel,
|
||||
initialState: Object
|
||||
) {
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import { createSelector as reselectCreateSelector } from "reselect";
|
||||
|
||||
function createSelector(...args) {
|
||||
// $FlowFixMe
|
||||
return reselectCreateSelector(...args);
|
||||
}
|
||||
|
||||
export { createSelector };
|
|
@ -16,15 +16,12 @@ import type { Location as BabelLocation } from "@babel/types";
|
|||
import type { Symbols } from "../reducers/ast";
|
||||
import type { QuickOpenType } from "../reducers/quick-open";
|
||||
import type { TabList } from "../reducers/tabs";
|
||||
import type { SourcesMapByThread } from "../reducers/types";
|
||||
import type { Source } from "../types";
|
||||
import type {
|
||||
SymbolDeclaration,
|
||||
IdentifierDeclaration
|
||||
} from "../workers/parser";
|
||||
|
||||
import { flatten } from "lodash";
|
||||
|
||||
export const MODIFIERS = {
|
||||
"@": "functions",
|
||||
"#": "variables",
|
||||
|
|
|
@ -13,7 +13,6 @@ import type {
|
|||
Location as BabelLocation
|
||||
} from "@babel/types";
|
||||
|
||||
import { isGeneratedId } from "devtools-source-map";
|
||||
import getFunctionName from "../utils/getFunctionName";
|
||||
import { getAst } from "../utils/ast";
|
||||
|
||||
|
@ -153,6 +152,10 @@ type ScopeCollectionVisitorState = {
|
|||
declarationBindingIds: Set<Node>
|
||||
};
|
||||
|
||||
function isGeneratedId(id: string) {
|
||||
return !/\/originalSource/.test(id);
|
||||
}
|
||||
|
||||
export function parseSourceScopes(sourceId: SourceId): ?Array<ParsedScope> {
|
||||
const ast = getAst(sourceId);
|
||||
if (isEmpty(ast)) {
|
||||
|
|
|
@ -35,15 +35,6 @@ function enableBreakpoints(dbg, count) {
|
|||
return enabled;
|
||||
}
|
||||
|
||||
function findBreakpoint(dbg, url, line) {
|
||||
const {
|
||||
selectors: { getBreakpoint },
|
||||
getState
|
||||
} = dbg;
|
||||
const source = findSource(dbg, url);
|
||||
return getBreakpoint(getState(), { sourceId: source.id, line });
|
||||
}
|
||||
|
||||
// Test enabling and disabling a breakpoint using the check boxes
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-scripts.html", "simple2");
|
||||
|
|
|
@ -31,15 +31,6 @@ async function enableBreakpoint(dbg, index) {
|
|||
await enabled;
|
||||
}
|
||||
|
||||
function findBreakpoint(dbg, url, line) {
|
||||
const {
|
||||
selectors: { getBreakpoint },
|
||||
getState
|
||||
} = dbg;
|
||||
const source = findSource(dbg, url);
|
||||
return getBreakpoint(getState(), { sourceId: source.id, line });
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
clearDebuggerPreferences();
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ add_task(async function() {
|
|||
await selectSource(dbg, mainSrc);
|
||||
|
||||
// Test that breakpoint is not off by a line.
|
||||
await addBreakpoint(dbg, mainSrc, 4);
|
||||
await addBreakpoint(dbg, mainSrc, 4, 2);
|
||||
is(getBreakpointCount(getState()), 1, "One breakpoint exists");
|
||||
ok(
|
||||
getBreakpoint(getState(), { sourceId: mainSrc.id, line: 4, column: 2 }),
|
||||
|
|
|
@ -22,7 +22,7 @@ add_task(async function() {
|
|||
await selectSource(dbg, sortedSrc);
|
||||
|
||||
// Test that breakpoint is not off by a line.
|
||||
await addBreakpoint(dbg, sortedSrc, 9);
|
||||
await addBreakpoint(dbg, sortedSrc, 9, 4);
|
||||
is(getBreakpointCount(getState()), 1, "One breakpoint exists");
|
||||
ok(
|
||||
getBreakpoint(getState(), { sourceId: sortedSrc.id, line: 9, column: 4 }),
|
||||
|
|
|
@ -767,10 +767,13 @@ function findBreakpoint(dbg, url, line) {
|
|||
if (
|
||||
Services.prefs.getBoolPref("devtools.debugger.features.column-breakpoints")
|
||||
) {
|
||||
column = dbg.selectors.getFirstPausePointLocation(dbg.store.getState(), {
|
||||
sourceId: source.id,
|
||||
line
|
||||
}).column;
|
||||
({ column } = dbg.selectors.getFirstVisibleBreakpointPosition(
|
||||
dbg.store.getState(),
|
||||
{
|
||||
sourceId: source.id,
|
||||
line
|
||||
}
|
||||
));
|
||||
}
|
||||
return getBreakpoint(getState(), { sourceId: source.id, line, column });
|
||||
}
|
||||
|
@ -789,7 +792,7 @@ async function loadAndAddBreakpoint(dbg, filename, line, column) {
|
|||
await selectSource(dbg, source);
|
||||
|
||||
// Test that breakpoint is not off by a line.
|
||||
await addBreakpoint(dbg, source, line);
|
||||
await addBreakpoint(dbg, source, line, column);
|
||||
|
||||
is(getBreakpointCount(getState()), 1, "One breakpoint exists");
|
||||
if (!getBreakpoint(getState(), { sourceId: source.id, line, column })) {
|
||||
|
@ -1103,7 +1106,7 @@ const selectors = {
|
|||
scopeValue: i =>
|
||||
`.scopes-list .tree-node:nth-child(${i}) .object-delimiter + *`,
|
||||
frame: i => `.frames [role="list"] [role="listitem"]:nth-child(${i})`,
|
||||
frames: '.frames [role="list"] [role="listitem"]',
|
||||
frames: `.frames [role="list"] [role="listitem"]`,
|
||||
gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`,
|
||||
// These work for bobth the breakpoint listing and gutter marker
|
||||
gutterContextMenu: {
|
||||
|
|
|
@ -419,70 +419,97 @@ function isSlowBuffer (obj) {
|
|||
"use strict";
|
||||
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.stopSourceMapWorker = exports.startSourceMapWorker = exports.isOriginalId = exports.isGeneratedId = exports.generatedToOriginalId = exports.originalToGeneratedId = exports.getOriginalStackFrames = exports.hasMappedSource = exports.clearSourceMaps = exports.applySourceMap = exports.getOriginalSourceText = exports.getLocationScopes = exports.getFileGeneratedRange = exports.getOriginalLocation = exports.getAllGeneratedLocations = exports.getGeneratedLocation = exports.getGeneratedRanges = exports.getOriginalRanges = exports.hasOriginalURL = exports.getOriginalURLs = exports.setAssetRootURL = exports.dispatcher = undefined;
|
||||
|
||||
var _utils = __webpack_require__(3652);
|
||||
|
||||
Object.defineProperty(exports, "originalToGeneratedId", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _utils.originalToGeneratedId;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "generatedToOriginalId", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _utils.generatedToOriginalId;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isGeneratedId", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _utils.isGeneratedId;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "isOriginalId", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _utils.isOriginalId;
|
||||
}
|
||||
});
|
||||
|
||||
var _devtoolsSourceMap = __webpack_require__(3646);
|
||||
|
||||
var self = _interopRequireWildcard(_devtoolsSourceMap);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
const {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId
|
||||
} = __webpack_require__(3652);
|
||||
|
||||
const {
|
||||
workerUtils: { WorkerDispatcher }
|
||||
} = __webpack_require__(3651);
|
||||
|
||||
const dispatcher = new WorkerDispatcher();
|
||||
const dispatcher = exports.dispatcher = new WorkerDispatcher();
|
||||
|
||||
const setAssetRootURL = dispatcher.task("setAssetRootURL");
|
||||
const getOriginalURLs = dispatcher.task("getOriginalURLs");
|
||||
const hasOriginalURL = dispatcher.task("hasOriginalURL");
|
||||
const getOriginalRanges = dispatcher.task("getOriginalRanges");
|
||||
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
const _getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
queue: true
|
||||
});
|
||||
const getGeneratedLocation = dispatcher.task("getGeneratedLocation", {
|
||||
queue: true
|
||||
});
|
||||
const getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", {
|
||||
queue: true
|
||||
});
|
||||
const getOriginalLocation = dispatcher.task("getOriginalLocation");
|
||||
const getFileGeneratedRange = dispatcher.task("getFileGeneratedRange");
|
||||
const getLocationScopes = dispatcher.task("getLocationScopes");
|
||||
const getOriginalSourceText = dispatcher.task("getOriginalSourceText");
|
||||
const applySourceMap = dispatcher.task("applySourceMap");
|
||||
const clearSourceMaps = dispatcher.task("clearSourceMaps");
|
||||
const hasMappedSource = dispatcher.task("hasMappedSource");
|
||||
const getOriginalStackFrames = dispatcher.task("getOriginalStackFrames");
|
||||
|
||||
module.exports = {
|
||||
originalToGeneratedId,
|
||||
generatedToOriginalId,
|
||||
isGeneratedId,
|
||||
isOriginalId,
|
||||
hasMappedSource,
|
||||
getOriginalURLs,
|
||||
hasOriginalURL,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
getOriginalLocation,
|
||||
getFileGeneratedRange,
|
||||
getLocationScopes,
|
||||
getOriginalSourceText,
|
||||
applySourceMap,
|
||||
clearSourceMaps,
|
||||
getOriginalStackFrames,
|
||||
startSourceMapWorker(url, assetRoot) {
|
||||
dispatcher.start(url);
|
||||
setAssetRootURL(assetRoot);
|
||||
},
|
||||
stopSourceMapWorker: dispatcher.stop.bind(dispatcher)
|
||||
const _getGeneratedLocation = dispatcher.task("getGeneratedLocation", { queue: true });
|
||||
const _getAllGeneratedLocations = dispatcher.task("getAllGeneratedLocations", { queue: true });
|
||||
|
||||
const setAssetRootURL = exports.setAssetRootURL = async assetRoot => dispatcher.invoke("setAssetRootURL", assetRoot);
|
||||
|
||||
const getOriginalURLs = exports.getOriginalURLs = async generatedSource => dispatcher.invoke("getOriginalURLs", generatedSource);
|
||||
|
||||
const hasOriginalURL = exports.hasOriginalURL = async url => dispatcher.invoke("hasOriginalURL", url);
|
||||
|
||||
const getOriginalRanges = exports.getOriginalRanges = async (sourceId, url) => dispatcher.invoke("getOriginalRanges", sourceId, url);
|
||||
const getGeneratedRanges = exports.getGeneratedRanges = async (location, originalSource) => _getGeneratedRanges(location, originalSource);
|
||||
|
||||
const getGeneratedLocation = exports.getGeneratedLocation = async (location, originalSource) => _getGeneratedLocation(location, originalSource);
|
||||
|
||||
const getAllGeneratedLocations = exports.getAllGeneratedLocations = async (location, originalSource) => _getAllGeneratedLocations(location, originalSource);
|
||||
|
||||
const getOriginalLocation = exports.getOriginalLocation = async (location, options = {}) => dispatcher.invoke("getOriginalLocation", location, options);
|
||||
|
||||
const getFileGeneratedRange = exports.getFileGeneratedRange = async originalSource => dispatcher.invoke("getFileGeneratedRange", originalSource);
|
||||
|
||||
const getLocationScopes = exports.getLocationScopes = dispatcher.task("getLocationScopes");
|
||||
|
||||
const getOriginalSourceText = exports.getOriginalSourceText = async originalSource => dispatcher.invoke("getOriginalSourceText", originalSource);
|
||||
|
||||
const applySourceMap = exports.applySourceMap = async (generatedId, url, code, mappings) => dispatcher.invoke("applySourceMap", generatedId, url, code, mappings);
|
||||
|
||||
const clearSourceMaps = exports.clearSourceMaps = async () => dispatcher.invoke("clearSourceMaps");
|
||||
|
||||
const hasMappedSource = exports.hasMappedSource = async location => dispatcher.invoke("hasMappedSource", location);
|
||||
|
||||
const getOriginalStackFrames = exports.getOriginalStackFrames = async generatedLocation => dispatcher.invoke("getOriginalStackFrames", generatedLocation);
|
||||
|
||||
const startSourceMapWorker = exports.startSourceMapWorker = (url, assetRoot) => {
|
||||
dispatcher.start(url);
|
||||
setAssetRootURL(assetRoot);
|
||||
};
|
||||
const stopSourceMapWorker = exports.stopSourceMapWorker = dispatcher.stop.bind(dispatcher);
|
||||
|
||||
exports.default = self;
|
||||
|
||||
/***/ }),
|
||||
|
||||
|
|
|
@ -457,7 +457,7 @@ void ShadowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
|
|||
if (!aVisitor.mEvent->mFlags.mComposed) {
|
||||
nsCOMPtr<nsIContent> originalTarget =
|
||||
do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
|
||||
if (originalTarget->GetContainingShadow() == this) {
|
||||
if (originalTarget && originalTarget->GetContainingShadow() == this) {
|
||||
// If we do stop propagation, we still want to propagate
|
||||
// the event to chrome (nsPIDOMWindow::GetParentTarget()).
|
||||
// The load event is special in that we don't ever propagate it
|
||||
|
|
|
@ -145,8 +145,10 @@ bool WebGLContext::InitWebGL2(FailureReason* const out_failReason) {
|
|||
gl->GetUIntegerv(LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS,
|
||||
&mGLMaxUniformBufferBindings);
|
||||
|
||||
mGLMinProgramTexelOffset = gl->GetIntAs<uint32_t>(LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET);
|
||||
mGLMaxProgramTexelOffset = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET);
|
||||
mGLMinProgramTexelOffset =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET);
|
||||
mGLMaxProgramTexelOffset =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET);
|
||||
|
||||
mIndexedUniformBufferBindings.resize(mGLMaxUniformBufferBindings);
|
||||
|
||||
|
|
|
@ -428,25 +428,35 @@ bool WebGLContext::InitAndValidateGL(FailureReason* const out_failReason) {
|
|||
////////////////
|
||||
|
||||
if (gl->IsGLES()) {
|
||||
mGLMaxFragmentUniformVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
|
||||
mGLMaxVertexUniformVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS);
|
||||
mGLMaxFragmentUniformVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS);
|
||||
mGLMaxVertexUniformVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS);
|
||||
if (gl->Version() >= 300) {
|
||||
mGLMaxVertexOutputVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS) / 4;
|
||||
mGLMaxFragmentInputVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4;
|
||||
mGLMaxVertexOutputVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS) / 4;
|
||||
mGLMaxFragmentInputVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4;
|
||||
} else {
|
||||
mGLMaxFragmentInputVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VARYING_VECTORS);
|
||||
mGLMaxFragmentInputVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VARYING_VECTORS);
|
||||
mGLMaxVertexOutputVectors = mGLMaxFragmentInputVectors;
|
||||
}
|
||||
} else {
|
||||
mGLMaxFragmentUniformVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS) / 4;
|
||||
mGLMaxVertexUniformVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4;
|
||||
mGLMaxFragmentUniformVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS) / 4;
|
||||
mGLMaxVertexUniformVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4;
|
||||
|
||||
if (gl->Version() >= 320) {
|
||||
mGLMaxVertexOutputVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS) / 4;
|
||||
mGLMaxFragmentInputVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4;
|
||||
mGLMaxVertexOutputVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS) / 4;
|
||||
mGLMaxFragmentInputVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS) / 4;
|
||||
} else {
|
||||
// Same enum val as GL2's GL_MAX_VARYING_FLOATS.
|
||||
mGLMaxFragmentInputVectors = gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VARYING_COMPONENTS) / 4;
|
||||
mGLMaxFragmentInputVectors =
|
||||
gl->GetIntAs<uint32_t>(LOCAL_GL_MAX_VARYING_COMPONENTS) / 4;
|
||||
mGLMaxVertexOutputVectors = mGLMaxFragmentInputVectors;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1819,7 +1819,7 @@ void RuntimeService::CrashIfHanging() {
|
|||
}
|
||||
|
||||
// This string will be leaked.
|
||||
MOZ_CRASH_UNSAFE_OOL(strdup(msg.BeginReading()));
|
||||
MOZ_CRASH_UNSAFE(strdup(msg.BeginReading()));
|
||||
}
|
||||
|
||||
// This spins the event loop until all workers are finished and their threads
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace {
|
|||
|
||||
void AssertOnOwningThread(void* aThread) {
|
||||
if (MOZ_UNLIKELY(aThread != GetCurrentVirtualThread())) {
|
||||
MOZ_CRASH_UNSAFE_OOL("WorkerHolder on the wrong thread.");
|
||||
MOZ_CRASH_UNSAFE("WorkerHolder on the wrong thread.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ void GLBlitTextureImageHelper::SetBlitFramebufferForDestTexture(
|
|||
// your texture is not texture complete -- that is, you
|
||||
// allocated a texture name, but didn't actually define its
|
||||
// size via a call to TexImage2D.
|
||||
MOZ_CRASH_UNSAFE_OOL(msg.get());
|
||||
MOZ_CRASH_UNSAFE(msg.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1957,7 +1957,7 @@ gfxFont* gfxFontGroup::GetDefaultFont() {
|
|||
mFamilyList.ToString(familiesString);
|
||||
SprintfLiteral(msg, "unable to find a usable font (%.220s)",
|
||||
familiesString.get());
|
||||
MOZ_CRASH_UNSAFE_OOL(msg);
|
||||
MOZ_CRASH_UNSAFE(msg);
|
||||
}
|
||||
|
||||
return mDefaultFont.get();
|
||||
|
|
|
@ -102,11 +102,15 @@ VertexInfo write_vertex(RectWithSize instance_rect,
|
|||
// Clamp to the two local clip rects.
|
||||
vec2 clamped_local_pos = clamp_rect(local_pos, local_clip_rect);
|
||||
|
||||
// Compute the visible rect to snap against. This ensures segments along the
|
||||
// edges are snapped consistently with other nearby primitives.
|
||||
RectWithSize visible_rect = intersect_rects(local_clip_rect, snap_rect);
|
||||
|
||||
/// Compute the snapping offset.
|
||||
vec2 snap_offset = compute_snap_offset(
|
||||
clamped_local_pos,
|
||||
transform.m,
|
||||
snap_rect,
|
||||
visible_rect,
|
||||
task.common_data.device_pixel_scale
|
||||
);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
|||
use storage;
|
||||
use util::{ScaleOffset, MatrixHelpers, MaxRect, Recycler, TransformedRectKind};
|
||||
use util::{pack_as_float, project_rect, raster_rect_to_device_pixels};
|
||||
use util::{scale_factors, clamp_to_scale_factor, RectHelpers};
|
||||
use util::{scale_factors, clamp_to_scale_factor};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
pub mod borders;
|
||||
|
@ -3536,9 +3536,9 @@ fn compute_snap_offset_impl(
|
|||
)
|
||||
}
|
||||
|
||||
/// Retrieve the exact device space rectangle for a primitive, taking
|
||||
/// into account the snapping that the shaders will apply if the transform
|
||||
/// is axis-aligned.
|
||||
/// Retrieve the exact unsnapped device space rectangle for a primitive.
|
||||
/// If the transform is axis-aligned, compute the snapping offsets that
|
||||
/// the shaders will apply.
|
||||
fn get_unclipped_device_rect(
|
||||
prim_spatial_node_index: SpatialNodeIndex,
|
||||
root_spatial_node_index: SpatialNodeIndex,
|
||||
|
@ -3583,11 +3583,7 @@ fn get_unclipped_device_rect(
|
|||
bottom_right,
|
||||
};
|
||||
|
||||
let p0 = unclipped_device_rect.origin + top_left;
|
||||
let p1 = unclipped_device_rect.bottom_right() + bottom_right;
|
||||
let unclipped = DeviceRect::from_floats(p0.x, p0.y, p1.x, p1.y);
|
||||
|
||||
Some((unclipped, snap_offsets))
|
||||
Some((unclipped_device_rect, snap_offsets))
|
||||
}
|
||||
TransformedRectKind::Complex => {
|
||||
Some((unclipped_device_rect, SnapOffsets::empty()))
|
||||
|
|
|
@ -14,7 +14,7 @@ platform(linux,mac) == border-suite-3.yaml border-suite-3.png
|
|||
== border-double-simple-2.yaml border-double-simple-2-ref.yaml
|
||||
fuzzy(64,24) == border-groove-simple.yaml border-groove-simple-ref.yaml
|
||||
fuzzy(64,24) == border-ridge-simple.yaml border-ridge-simple-ref.yaml
|
||||
platform(linux,mac) fuzzy(1,2) == degenerate-curve.yaml degenerate-curve.png
|
||||
platform(linux,mac) fuzzy(1,3) == degenerate-curve.yaml degenerate-curve.png
|
||||
platform(linux,mac) == border-image.yaml border-image-ref.png
|
||||
== border-image-crash.yaml border-image-crash-ref.yaml
|
||||
== border-image-fill.yaml border-image-fill-ref.png
|
||||
|
|
|
@ -34,4 +34,4 @@ fuzzy(1,5) platform(linux,mac) == box-shadow-huge-radius.yaml box-shadow-huge-ra
|
|||
|
||||
platform(linux,mac) == box-shadow-large-blur-radius-2.yaml box-shadow-large-blur-radius-2.png
|
||||
platform(linux,mac) == box-shadow-large-blur-radius-3.yaml box-shadow-large-blur-radius-3.png
|
||||
platform(linux,mac) == scale.yaml scale.png
|
||||
platform(linux,mac) fuzzy(1,79) == scale.yaml scale.png
|
||||
|
|
|
@ -25,7 +25,7 @@ platform(linux,mac) == perspective-mask.yaml perspective-mask.png
|
|||
rotate-clip.yaml rotate-clip-ref.yaml
|
||||
clip-translate.yaml clip-translate-ref.yaml
|
||||
platform(linux,mac) == perspective-clip.yaml perspective-clip.png
|
||||
platform(linux,mac) == perspective-clip-1.yaml perspective-clip-1.png
|
||||
platform(linux,mac) fuzzy(1,2) == perspective-clip-1.yaml perspective-clip-1.png
|
||||
platform(linux,mac) fuzzy(1,2) == perspective-shadow.yaml perspective-shadow.png
|
||||
== complex-preserve-3d.yaml blank.yaml
|
||||
platform(linux,mac) fuzzy(9,348) == perspective-border-radius.yaml perspective-border-radius.png
|
||||
|
|