зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
846f00f83f
|
@ -115,3 +115,6 @@ jobs:
|
|||
mozilla-central:
|
||||
- {weekday: 'Monday', hour: 10, minute: 0}
|
||||
- {weekday: 'Thursday', hour: 10, minute: 0}
|
||||
mozilla-esr60:
|
||||
- {weekday: 'Monday', hour: 10, minute: 0}
|
||||
- {weekday: 'Thursday', hour: 10, minute: 0}
|
||||
|
|
|
@ -42,7 +42,7 @@ cpp_quote("//")
|
|||
cpp_quote("// computedStyle( ")
|
||||
cpp_quote("// /* [in] */ unsigned short maxStyleProperties,")
|
||||
cpp_quote("// /* [out] */ unsigned short *numStyleProperties, ")
|
||||
cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes")
|
||||
cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes")
|
||||
cpp_quote("// /* [out] */ BSTR *styleProperties, ")
|
||||
cpp_quote("// /* [out] */ BSTR *styleValues);")
|
||||
cpp_quote("// ---------------------------------------------------------------------------------------------------=")
|
||||
|
@ -52,7 +52,7 @@ cpp_quote("// useAlternateView=TRUE: properties for media types set w/ nsIDOMSi
|
|||
cpp_quote("//")
|
||||
cpp_quote("// computedStyleForProperties( ")
|
||||
cpp_quote("// /* [in] */ unsigned short numStyleProperties, ")
|
||||
cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes")
|
||||
cpp_quote("// /* [in] */ boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes")
|
||||
cpp_quote("// /* [in] */ BSTR *styleProperties, ")
|
||||
cpp_quote("// /* [out] */ BSTR *styleValues);")
|
||||
cpp_quote("// ---------------------------------------------------------------------------------------------------=")
|
||||
|
@ -141,7 +141,7 @@ interface ISimpleDOMNode : IUnknown
|
|||
|
||||
[propget] HRESULT computedStyle(
|
||||
[in] unsigned short maxStyleProperties,
|
||||
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
|
||||
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes
|
||||
[out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleProperties,
|
||||
[out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleValues,
|
||||
[out, retval] unsigned short *numStyleProperties
|
||||
|
@ -149,7 +149,7 @@ interface ISimpleDOMNode : IUnknown
|
|||
|
||||
[propget] HRESULT computedStyleForProperties(
|
||||
[in] unsigned short numStyleProperties,
|
||||
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in nsIDOMDocument::set_alternateViewMediaTypes
|
||||
[in] boolean useAlternateView, // If TRUE, returns properites for media as set in Document's set_alternateViewMediaTypes
|
||||
[in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties,
|
||||
[out, retval, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleValues
|
||||
);
|
||||
|
|
|
@ -44,7 +44,6 @@ const nsIAccessibleValue = Ci.nsIAccessibleValue;
|
|||
|
||||
const nsIObserverService = Ci.nsIObserverService;
|
||||
|
||||
const nsIDOMDocument = Ci.nsIDOMDocument;
|
||||
const nsIDOMNode = Ci.nsIDOMNode;
|
||||
const nsIDOMWindow = Ci.nsIDOMWindow;
|
||||
|
||||
|
|
|
@ -1062,7 +1062,7 @@ function synthClick(aNodeOrID, aCheckerOrEventSeq, aArgs) {
|
|||
|
||||
this.invoke = function synthClick_invoke() {
|
||||
var targetNode = this.DOMNode;
|
||||
if (targetNode instanceof nsIDOMDocument) {
|
||||
if (targetNode.nodeType == targetNode.DOCUMENT_NODE) {
|
||||
targetNode =
|
||||
this.DOMNode.body ? this.DOMNode.body : this.DOMNode.documentElement;
|
||||
}
|
||||
|
|
|
@ -56,12 +56,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=441737
|
|||
// is(docAcc.docType, "HTML",
|
||||
// "Wrong type of document!");
|
||||
|
||||
// Test for correct nsIDOMDocument retrieval.
|
||||
// Test for correct Document retrieval.
|
||||
var domDoc = null;
|
||||
try {
|
||||
domDoc = docAcc.DOMDocument.QueryInterface(nsIDOMDocument);
|
||||
domDoc = docAcc.DOMDocument;
|
||||
} catch (e) {}
|
||||
ok(domDoc, "no nsIDOMDocument for this doc accessible!");
|
||||
ok(domDoc, "no Document for this doc accessible!");
|
||||
is(domDoc, document, "Document nodes do not match!");
|
||||
|
||||
// Test for correct nsIDOMWindow retrieval.
|
||||
|
|
|
@ -588,12 +588,8 @@ var AboutNetAndCertErrorListener = {
|
|||
},
|
||||
|
||||
handleEvent(aEvent) {
|
||||
let doc;
|
||||
if (aEvent.originalTarget instanceof Ci.nsIDOMDocument) {
|
||||
doc = aEvent.originalTarget;
|
||||
} else {
|
||||
doc = aEvent.originalTarget.ownerDocument;
|
||||
}
|
||||
// Documents have a null ownerDocument.
|
||||
let doc = aEvent.originalTarget.ownerDocument || aEvent.originalTarget;
|
||||
|
||||
if (!this.isAboutNetError(doc) && !this.isAboutCertError(doc)) {
|
||||
return;
|
||||
|
|
|
@ -74,7 +74,7 @@ function focusInChild() {
|
|||
var id;
|
||||
if (event.target instanceof Ci.nsIDOMWindow)
|
||||
id = getWindowDocId(event.originalTarget) + "-window";
|
||||
else if (event.target instanceof Ci.nsIDOMDocument)
|
||||
else if (event.target.nodeType == event.target.DOCUMENT_NODE)
|
||||
id = getWindowDocId(event.originalTarget) + "-document";
|
||||
else
|
||||
id = event.originalTarget.id;
|
||||
|
|
|
@ -966,8 +966,8 @@ this.tabs = class extends ExtensionAPI {
|
|||
let browser = event.originalTarget;
|
||||
|
||||
// For non-remote browsers, this event is dispatched on the document
|
||||
// rather than on the <browser>.
|
||||
if (browser instanceof Ci.nsIDOMDocument) {
|
||||
// rather than on the <browser>. But either way we have a node here.
|
||||
if (browser.nodeType == browser.DOCUMENT_NODE) {
|
||||
browser = browser.docShell.chromeEventHandler;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.0.506
|
||||
Current extension version is: 2.0.517
|
||||
|
||||
Taken from upstream commit: b7a3a5e7
|
||||
Taken from upstream commit: 7cd6c0fb
|
||||
|
|
|
@ -1650,8 +1650,8 @@ exports.GlobalWorkerOptions = GlobalWorkerOptions;
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.506';
|
||||
var pdfjsBuild = 'b7a3a5e7';
|
||||
var pdfjsVersion = '2.0.517';
|
||||
var pdfjsBuild = '7cd6c0fb';
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(0);
|
||||
var pdfjsDisplayAPI = __w_pdfjs_require__(9);
|
||||
var pdfjsDisplayTextLayer = __w_pdfjs_require__(17);
|
||||
|
@ -4929,7 +4929,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||
}
|
||||
return worker.messageHandler.sendWithPromise('GetDocRequest', {
|
||||
docId,
|
||||
apiVersion: '2.0.506',
|
||||
apiVersion: '2.0.517',
|
||||
source: {
|
||||
data: source.data,
|
||||
url: source.url,
|
||||
|
@ -6252,8 +6252,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
|
|||
}();
|
||||
var version, build;
|
||||
{
|
||||
exports.version = version = '2.0.506';
|
||||
exports.build = build = 'b7a3a5e7';
|
||||
exports.version = version = '2.0.517';
|
||||
exports.build = build = '7cd6c0fb';
|
||||
}
|
||||
exports.getDocument = getDocument;
|
||||
exports.LoopbackPort = LoopbackPort;
|
||||
|
|
|
@ -21103,8 +21103,8 @@ exports.PostScriptCompiler = PostScriptCompiler;
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.0.506';
|
||||
var pdfjsBuild = 'b7a3a5e7';
|
||||
var pdfjsVersion = '2.0.517';
|
||||
var pdfjsBuild = '7cd6c0fb';
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(20);
|
||||
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
||||
|
||||
|
@ -21305,7 +21305,7 @@ var WorkerMessageHandler = {
|
|||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.0.506';
|
||||
let workerVersion = '2.0.517';
|
||||
if (apiVersion !== null && apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
}
|
||||
|
@ -36238,10 +36238,9 @@ var Type1Parser = function Type1ParserClosure() {
|
|||
var glyph = this.getToken();
|
||||
length = this.readInt();
|
||||
this.getToken();
|
||||
data = stream.makeSubStream(stream.pos, length);
|
||||
data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
|
||||
lenIV = program.properties.privateData['lenIV'];
|
||||
encoded = this.readCharStrings(data.getBytes(), lenIV);
|
||||
stream.skip(length);
|
||||
encoded = this.readCharStrings(data, lenIV);
|
||||
this.nextChar();
|
||||
token = this.getToken();
|
||||
if (token === 'noaccess') {
|
||||
|
@ -36260,10 +36259,9 @@ var Type1Parser = function Type1ParserClosure() {
|
|||
var index = this.readInt();
|
||||
length = this.readInt();
|
||||
this.getToken();
|
||||
data = stream.makeSubStream(stream.pos, length);
|
||||
data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
|
||||
lenIV = program.properties.privateData['lenIV'];
|
||||
encoded = this.readCharStrings(data.getBytes(), lenIV);
|
||||
stream.skip(length);
|
||||
encoded = this.readCharStrings(data, lenIV);
|
||||
this.nextChar();
|
||||
token = this.getToken();
|
||||
if (token === 'noaccess') {
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.moveToEndOfArray = exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.backtrackBeforeAllVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isFileSchema = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined;
|
||||
exports.moveToEndOfArray = exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.backtrackBeforeAllVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined;
|
||||
|
||||
var _pdfjsLib = __webpack_require__(1);
|
||||
|
||||
|
@ -397,14 +397,6 @@ function getVisibleElements(scrollEl, views, sortByVisibility = false, horizonta
|
|||
function noContextMenuHandler(evt) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
function isFileSchema(url) {
|
||||
let i = 0,
|
||||
ii = url.length;
|
||||
while (i < ii && url[i].trim() === '') {
|
||||
i++;
|
||||
}
|
||||
return url.substr(i, 7).toLowerCase() === 'file://';
|
||||
}
|
||||
function isDataSchema(url) {
|
||||
let i = 0,
|
||||
ii = url.length;
|
||||
|
@ -614,7 +606,6 @@ exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING;
|
|||
exports.VERTICAL_PADDING = VERTICAL_PADDING;
|
||||
exports.isValidRotation = isValidRotation;
|
||||
exports.isPortraitOrientation = isPortraitOrientation;
|
||||
exports.isFileSchema = isFileSchema;
|
||||
exports.cloneObj = cloneObj;
|
||||
exports.PresentationModeState = PresentationModeState;
|
||||
exports.RendererType = RendererType;
|
||||
|
@ -1438,11 +1429,6 @@ let PDFViewerApplication = {
|
|||
parameters[prop] = args[prop];
|
||||
}
|
||||
}
|
||||
if (this.url && (0, _ui_utils.isFileSchema)(this.url)) {
|
||||
let appConfig = this.appConfig;
|
||||
appConfig.toolbar.download.setAttribute('hidden', 'true');
|
||||
appConfig.secondaryToolbar.downloadButton.setAttribute('hidden', 'true');
|
||||
}
|
||||
let loadingTask = (0, _pdfjsLib.getDocument)(parameters);
|
||||
this.pdfLoadingTask = loadingTask;
|
||||
loadingTask.onPassword = (updateCallback, reason) => {
|
||||
|
|
|
@ -17,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
setTimeout: "resource://gre/modules/Timer.jsm",
|
||||
ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
|
||||
OfflineAppCacheHelper: "resource://gre/modules/offlineAppCache.jsm",
|
||||
ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "sas",
|
||||
|
@ -71,6 +72,12 @@ var Sanitizer = {
|
|||
*/
|
||||
PREF_TIMESPAN: "privacy.sanitize.timeSpan",
|
||||
|
||||
/**
|
||||
* Pref to newTab segregation. If true, on shutdown, the private container
|
||||
* used in about:newtab is cleaned up. Exposed because used in tests.
|
||||
*/
|
||||
PREF_NEWTAB_SEGREGATION: "privacy.usercontext.about_newtab_segregation.enabled",
|
||||
|
||||
/**
|
||||
* Time span constants corresponding to values of the privacy.sanitize.timeSpan
|
||||
* pref. Used to determine how much history to clear, for various items
|
||||
|
@ -91,6 +98,11 @@ var Sanitizer = {
|
|||
*/
|
||||
shouldSanitizeOnShutdown: false,
|
||||
|
||||
/**
|
||||
* Whether we should sanitize the private container for about:newtab.
|
||||
*/
|
||||
shouldSanitizeNewTabContainer: false,
|
||||
|
||||
/**
|
||||
* Shows a sanitization dialog to the user.
|
||||
*
|
||||
|
@ -145,6 +157,17 @@ var Sanitizer = {
|
|||
{fetchState: () => ({ progress })}
|
||||
);
|
||||
|
||||
this.shouldSanitizeNewTabContainer = Services.prefs.getBoolPref(this.PREF_NEWTAB_SEGREGATION, false);
|
||||
if (this.shouldSanitizeNewTabContainer) {
|
||||
addPendingSanitization("newtab-container", [], {});
|
||||
}
|
||||
|
||||
let i = pendingSanitizations.findIndex(s => s.id == "newtab-container");
|
||||
if (i != -1) {
|
||||
pendingSanitizations.splice(i, 1);
|
||||
sanitizeNewTabSegregation();
|
||||
}
|
||||
|
||||
// Finally, run the sanitizations that were left pending, because we crashed
|
||||
// before completing them.
|
||||
for (let {itemsToClear, options} of pendingSanitizations) {
|
||||
|
@ -272,6 +295,12 @@ var Sanitizer = {
|
|||
let itemsToClear = getItemsToClearFromPrefBranch(Sanitizer.PREF_SHUTDOWN_BRANCH);
|
||||
addPendingSanitization("shutdown", itemsToClear, {});
|
||||
}
|
||||
} else if (data == this.PREF_NEWTAB_SEGREGATION) {
|
||||
this.shouldSanitizeNewTabContainer = Services.prefs.getBoolPref(this.PREF_NEWTAB_SEGREGATION, false);
|
||||
removePendingSanitization("newtab-container");
|
||||
if (this.shouldSanitizeNewTabContainer) {
|
||||
addPendingSanitization("newtab-container", [], {});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -990,6 +1019,11 @@ async function sanitizeOnShutdown(progress) {
|
|||
}
|
||||
}
|
||||
|
||||
if (Sanitizer.shouldSanitizeNewTabContainer) {
|
||||
sanitizeNewTabSegregation();
|
||||
removePendingSanitization("newtab-container");
|
||||
}
|
||||
|
||||
if (Sanitizer.shouldSanitizeOnShutdown) {
|
||||
// We didn't crash during shutdown sanitization, so annotate it to avoid
|
||||
// sanitizing again on startup.
|
||||
|
@ -1061,6 +1095,14 @@ async function sanitizeSessionPrincipal(principal) {
|
|||
]);
|
||||
}
|
||||
|
||||
function sanitizeNewTabSegregation() {
|
||||
let identity = ContextualIdentityService.getPrivateIdentity("userContextIdInternal.thumbnail");
|
||||
if (identity) {
|
||||
Services.obs.notifyObservers(null, "clear-origin-attributes-data",
|
||||
JSON.stringify({ userContextId: identity.userContextId }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of items to clear from the given pref branch.
|
||||
* @param branch The pref branch to fetch.
|
||||
|
|
|
@ -11,9 +11,13 @@ do_get_profile();
|
|||
|
||||
add_task(async function() {
|
||||
ChromeUtils.import("resource:///modules/Sanitizer.jsm");
|
||||
|
||||
Services.prefs.setBoolPref(Sanitizer.PREF_NEWTAB_SEGREGATION, false);
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref(Sanitizer.PREF_SANITIZE_ON_SHUTDOWN);
|
||||
Services.prefs.clearUserPref(Sanitizer.PREF_SHUTDOWN_BRANCH + "formdata");
|
||||
Services.prefs.clearUserPref(Sanitizer.PREF_NEWTAB_SEGREGATION);
|
||||
});
|
||||
Services.prefs.setBoolPref(Sanitizer.PREF_SANITIZE_ON_SHUTDOWN, true);
|
||||
Services.prefs.setBoolPref(Sanitizer.PREF_SHUTDOWN_BRANCH + "formdata", true);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version 58
|
||||
Version 60
|
||||
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-57...release-58
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-59...release-60
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.2
|
||||
- babel-preset-react @6.24.1
|
||||
- react @16.2.0
|
||||
- react-dom @16.2.0
|
||||
- webpack @3.12.0
|
||||
- webpack @3.11.0
|
||||
|
|
|
@ -1108,7 +1108,10 @@ html .toggle-button.end.vertical svg {
|
|||
|
||||
.search-field i.magnifying-glass,
|
||||
.search-field i.sad-face {
|
||||
padding: 6px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
padding-inline-end: 10px;
|
||||
padding-inline-start: 5px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
|
@ -1118,6 +1121,11 @@ html .toggle-button.end.vertical svg {
|
|||
width: 40px;
|
||||
}
|
||||
|
||||
.search-field.big i.sad-face {
|
||||
padding-top: 4px;
|
||||
padding-inline-start: 4px;
|
||||
}
|
||||
|
||||
.search-field .magnifying-glass path,
|
||||
.search-field .magnifying-glass ellipse {
|
||||
stroke: var(--theme-comment);
|
||||
|
@ -1134,18 +1142,13 @@ html .toggle-button.end.vertical svg {
|
|||
.search-field .summary {
|
||||
line-height: 27px;
|
||||
text-align: center;
|
||||
padding-right: 10px;
|
||||
padding-inline-end: 10px;
|
||||
color: var(--theme-body-color-inactive);
|
||||
align-self: center;
|
||||
padding-top: 1px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.search-field.big .summary {
|
||||
padding: 5px 0 5px 0;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
.search-field .search-nav-buttons {
|
||||
display: flex;
|
||||
user-select: none;
|
||||
|
@ -1261,7 +1264,7 @@ html .toggle-button.end.vertical svg {
|
|||
}
|
||||
|
||||
.project-text-search .search-field .close-btn.big {
|
||||
margin-top: 6px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.project-text-search .managed-tree {
|
||||
|
@ -3077,7 +3080,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
|||
max-width: calc(100% - var(--breakpoint-expression-right-clear-space));
|
||||
display: inline-block;
|
||||
padding-inline-end: 8px;
|
||||
cursor: default;
|
||||
cursor: pointer;
|
||||
flex-grow: 1;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
@ -3261,7 +3264,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
|
|||
.expression-container__close-btn {
|
||||
position: absolute;
|
||||
offset-inline-end: 0px;
|
||||
top: 0px;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.expression-content {
|
||||
|
@ -4049,6 +4052,7 @@ html .welcomebox .toggle-button-end.collapsed {
|
|||
position: relative;
|
||||
transition: all 0.15s ease;
|
||||
min-width: 40px;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
padding: 5px;
|
||||
margin-inline-start: 3px;
|
||||
|
|
|
@ -22811,7 +22811,7 @@ function toParsedScopes(children, sourceId) {
|
|||
return {
|
||||
start: scope.loc.start,
|
||||
end: scope.loc.end,
|
||||
type: scope.type === "module" ? "block" : scope.type,
|
||||
type: scope.type === "module" || scope.type === "function-body" ? "block" : scope.type,
|
||||
displayName: scope.displayName,
|
||||
bindings: scope.bindings,
|
||||
children: toParsedScopes(scope.children, sourceId)
|
||||
|
@ -22906,9 +22906,18 @@ function isLetOrConst(node) {
|
|||
}
|
||||
|
||||
function hasLexicalDeclaration(node, parent) {
|
||||
const nodes = [];
|
||||
if (t.isSwitchStatement(node)) {
|
||||
for (const caseNode of node.cases) {
|
||||
nodes.push(...caseNode.consequent);
|
||||
}
|
||||
} else {
|
||||
nodes.push(...node.body);
|
||||
}
|
||||
|
||||
const isFunctionBody = t.isFunction(parent, { body: node });
|
||||
|
||||
return node.body.some(child => isLexicalVariable(child) || !isFunctionBody && child.type === "FunctionDeclaration" || child.type === "ClassDeclaration");
|
||||
return nodes.some(child => isLexicalVariable(child) || t.isClassDeclaration(child) || !isFunctionBody && t.isFunctionDeclaration(child));
|
||||
}
|
||||
function isLexicalVariable(node) {
|
||||
return isNode(node, "VariableDeclaration") && isLetOrConst(node);
|
||||
|
@ -22973,19 +22982,27 @@ const scopeCollectionVisitor = {
|
|||
// This ignores Annex B function declaration hoisting, which
|
||||
// is probably a fine assumption.
|
||||
state.declarationBindingIds.add(node.id);
|
||||
const fnScope = getVarScope(scope);
|
||||
scope.bindings[node.id.name] = {
|
||||
type: fnScope === scope ? "var" : "let",
|
||||
refs: [{
|
||||
type: "fn-decl",
|
||||
start: fromBabelLocation(node.id.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.id.loc.end, state.sourceId),
|
||||
declaration: {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
}
|
||||
}]
|
||||
};
|
||||
const refs = [{
|
||||
type: "fn-decl",
|
||||
start: fromBabelLocation(node.id.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.id.loc.end, state.sourceId),
|
||||
declaration: {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
}
|
||||
}];
|
||||
|
||||
if (scope.type === "block") {
|
||||
scope.bindings[node.id.name] = {
|
||||
type: "let",
|
||||
refs
|
||||
};
|
||||
} else {
|
||||
getVarScope(scope).bindings[node.id.name] = {
|
||||
type: "var",
|
||||
refs
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), {
|
||||
|
@ -23007,6 +23024,13 @@ const scopeCollectionVisitor = {
|
|||
refs: []
|
||||
};
|
||||
}
|
||||
|
||||
if (t.isBlockStatement(node.body) && hasLexicalDeclaration(node.body, node)) {
|
||||
scope = pushTempScope(state, "function-body", "Function Body", {
|
||||
start: fromBabelLocation(node.body.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.body.loc.end, state.sourceId)
|
||||
});
|
||||
}
|
||||
} else if (t.isClass(node)) {
|
||||
if (t.isIdentifier(node.id)) {
|
||||
// For decorated classes, the AST considers the first the decorator
|
||||
|
@ -23075,7 +23099,9 @@ const scopeCollectionVisitor = {
|
|||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
});
|
||||
parseDeclarator(node.param, scope, "var", "catch", node, state);
|
||||
} else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) {
|
||||
} else if (t.isBlockStatement(node) &&
|
||||
// Function body's are handled in the function logic above.
|
||||
!t.isFunction(parentNode) && hasLexicalDeclaration(node, parentNode)) {
|
||||
// Debugger will create new lexical environment for the block.
|
||||
pushTempScope(state, "block", "Block", {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
|
@ -23199,7 +23225,7 @@ const scopeCollectionVisitor = {
|
|||
type: "implicit",
|
||||
refs: []
|
||||
};
|
||||
} else if (t.isSwitchStatement(node) && node.cases.some(caseNode => caseNode.consequent.some(child => isLexicalVariable(child)))) {
|
||||
} else if (t.isSwitchStatement(node) && hasLexicalDeclaration(node, parentNode)) {
|
||||
pushTempScope(state, "block", "Switch", {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
|
@ -25012,6 +25038,7 @@ const {
|
|||
const dispatcher = new WorkerDispatcher();
|
||||
|
||||
const getOriginalURLs = dispatcher.task("getOriginalURLs");
|
||||
const getOriginalRanges = dispatcher.task("getOriginalRanges");
|
||||
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
queue: true
|
||||
});
|
||||
|
@ -25035,6 +25062,7 @@ module.exports = {
|
|||
isOriginalId,
|
||||
hasMappedSource,
|
||||
getOriginalURLs,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
|
|
|
@ -417,7 +417,7 @@ function toggleBreakpoint(line, column) {
|
|||
line,
|
||||
column
|
||||
});
|
||||
const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource);
|
||||
const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource.id);
|
||||
|
||||
if (!bp && isEmptyLine || bp && bp.loading) {
|
||||
return;
|
||||
|
@ -434,8 +434,8 @@ function toggleBreakpoint(line, column) {
|
|||
}
|
||||
|
||||
return dispatch(addBreakpoint({
|
||||
sourceId: selectedSource.get("id"),
|
||||
sourceUrl: selectedSource.get("url"),
|
||||
sourceId: selectedSource.id,
|
||||
sourceUrl: selectedSource.url,
|
||||
line: line,
|
||||
column: column
|
||||
}));
|
||||
|
|
|
@ -51,7 +51,6 @@ function willNavigate(event) {
|
|||
await sourceMaps.clearSourceMaps();
|
||||
(0, _wasm.clearWasmStates)();
|
||||
(0, _editor.clearDocuments)();
|
||||
(0, _editor.removeEditor)();
|
||||
(0, _parser.clearSymbols)();
|
||||
(0, _parser.clearASTs)();
|
||||
(0, _parser.clearScopes)();
|
||||
|
|
|
@ -41,7 +41,7 @@ async function loadSource(source, {
|
|||
const id = source.get("id");
|
||||
|
||||
if ((0, _devtoolsSourceMap.isOriginalId)(id)) {
|
||||
return await sourceMaps.getOriginalSourceText(source.toJS());
|
||||
return sourceMaps.getOriginalSourceText(source.toJS());
|
||||
}
|
||||
|
||||
const response = await client.sourceContents(id);
|
||||
|
|
|
@ -211,9 +211,9 @@ const mapStateToProps = state => {
|
|||
return {
|
||||
selectedLocation: (0, _selectors.getSelectedLocation)(state),
|
||||
selectedSource,
|
||||
hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")),
|
||||
hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.id),
|
||||
contextMenu: (0, _selectors.getContextMenu)(state),
|
||||
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), symbols),
|
||||
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource, symbols),
|
||||
getFunctionLocation: line => (0, _ast.findClosestFunction)(symbols, {
|
||||
line,
|
||||
column: Infinity
|
||||
|
|
|
@ -70,7 +70,7 @@ class EmptyLines extends _react.Component {
|
|||
|
||||
const mapStateToProps = state => {
|
||||
const selectedSource = (0, _selectors.getSelectedSource)(state);
|
||||
const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.toJS());
|
||||
const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.id);
|
||||
return {
|
||||
selectedSource,
|
||||
emptyLines: selectedSource ? foundEmptyLines : []
|
||||
|
|
|
@ -169,7 +169,7 @@ const mapStateToProps = state => {
|
|||
breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
|
||||
isPaused: (0, _selectors.isPaused)(state),
|
||||
contextMenu: (0, _selectors.getContextMenu)(state),
|
||||
emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.toJS())
|
||||
emptyLines: (0, _selectors.getEmptyLines)(state, selectedSource.id)
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
|
|||
|
||||
var _Button = require("../shared/Button/index");
|
||||
|
||||
var _text = require("../../utils/text");
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
@ -175,7 +177,7 @@ class Tab extends _react.PureComponent {
|
|||
shouldHide: icon => ["file", "javascript"].includes(icon)
|
||||
}), _react2.default.createElement("div", {
|
||||
className: "filename"
|
||||
}, (0, _devtoolsModules.getUnicodeUrlPath)(filename)), _react2.default.createElement(_Button.CloseButton, {
|
||||
}, (0, _text.truncateMiddleText)((0, _devtoolsModules.getUnicodeUrlPath)(filename), 30)), _react2.default.createElement(_Button.CloseButton, {
|
||||
handleClick: onClickClose,
|
||||
tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip")
|
||||
}));
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactDom = require("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
var _reactDom2 = _interopRequireDefault(_reactDom);
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _Button = require("../shared/Button/index");
|
||||
|
||||
var _breakpoint = require("../../utils/breakpoint/index");
|
||||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* 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 getBreakpointLocation(source, line, column) {
|
||||
const isWasm = source && source.isWasm;
|
||||
const columnVal = _prefs.features.columnBreakpoints && column ? `:${column}` : "";
|
||||
const bpLocation = isWasm ? `0x${line.toString(16).toUpperCase()}` : `${line}${columnVal}`;
|
||||
return bpLocation;
|
||||
}
|
||||
|
||||
function getBreakpointText(selectedSource, breakpoint) {
|
||||
const {
|
||||
condition,
|
||||
text,
|
||||
originalText
|
||||
} = breakpoint;
|
||||
|
||||
if (condition) {
|
||||
return condition;
|
||||
}
|
||||
|
||||
if (!selectedSource || (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) || originalText.length == 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
return originalText;
|
||||
}
|
||||
|
||||
class Breakpoint extends _react.Component {
|
||||
componentDidMount() {
|
||||
this.setupEditor();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (getBreakpointText(this.props.selectedSource, this.props.breakpoint) != getBreakpointText(prevProps.selectedSource, prevProps.breakpoint)) {
|
||||
this.destroyEditor();
|
||||
}
|
||||
|
||||
this.setupEditor();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.destroyEditor();
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
const prevBreakpoint = this.props.breakpoint;
|
||||
const nextBreakpoint = nextProps.breakpoint;
|
||||
return !prevBreakpoint || this.props.selectedSource != nextProps.selectedSource || prevBreakpoint.text != nextBreakpoint.text || prevBreakpoint.disabled != nextBreakpoint.disabled || prevBreakpoint.condition != nextBreakpoint.condition || prevBreakpoint.hidden != nextBreakpoint.hidden || prevBreakpoint.isCurrentlyPaused != nextBreakpoint.isCurrentlyPaused;
|
||||
}
|
||||
|
||||
destroyEditor() {
|
||||
if (this.editor) {
|
||||
this.editor.destroy();
|
||||
this.editor = null;
|
||||
}
|
||||
}
|
||||
|
||||
setupEditor() {
|
||||
if (this.editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
selectedSource,
|
||||
breakpoint
|
||||
} = this.props;
|
||||
this.editor = (0, _breakpoint.createEditor)(getBreakpointText(selectedSource, breakpoint)); // disables the default search shortcuts
|
||||
// $FlowIgnore
|
||||
|
||||
this.editor._initShortcuts = () => {};
|
||||
|
||||
const node = _reactDom2.default.findDOMNode(this);
|
||||
|
||||
if (node instanceof HTMLElement) {
|
||||
const mountNode = node.querySelector(".breakpoint-label");
|
||||
|
||||
if (node instanceof HTMLElement) {
|
||||
// $FlowIgnore
|
||||
mountNode.innerHTML = "";
|
||||
this.editor.appendToLocalElement(mountNode);
|
||||
this.editor.codeMirror.on("mousedown", (_, e) => e.preventDefault());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderCheckbox() {
|
||||
const {
|
||||
onChange,
|
||||
breakpoint
|
||||
} = this.props;
|
||||
const {
|
||||
disabled
|
||||
} = breakpoint;
|
||||
return _react2.default.createElement("input", {
|
||||
type: "checkbox",
|
||||
className: "breakpoint-checkbox",
|
||||
checked: !disabled,
|
||||
onChange: onChange,
|
||||
onClick: ev => ev.stopPropagation()
|
||||
});
|
||||
}
|
||||
|
||||
renderText() {
|
||||
const {
|
||||
selectedSource,
|
||||
breakpoint
|
||||
} = this.props;
|
||||
const text = getBreakpointText(selectedSource, breakpoint);
|
||||
return _react2.default.createElement("label", {
|
||||
className: "breakpoint-label",
|
||||
title: text
|
||||
}, text);
|
||||
}
|
||||
|
||||
renderLineClose() {
|
||||
const {
|
||||
breakpoint,
|
||||
onCloseClick,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const {
|
||||
location
|
||||
} = breakpoint;
|
||||
let {
|
||||
line,
|
||||
column
|
||||
} = location;
|
||||
|
||||
if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) && breakpoint.generatedLocation) {
|
||||
line = breakpoint.generatedLocation.line;
|
||||
column = breakpoint.generatedLocation.column;
|
||||
}
|
||||
|
||||
return _react2.default.createElement("div", {
|
||||
className: "breakpoint-line-close"
|
||||
}, _react2.default.createElement("div", {
|
||||
className: "breakpoint-line"
|
||||
}, getBreakpointLocation(breakpoint.source, line, column)), _react2.default.createElement(_Button.CloseButton, {
|
||||
handleClick: onCloseClick,
|
||||
tooltip: L10N.getStr("breakpoints.removeBreakpointTooltip")
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
breakpoint,
|
||||
onClick,
|
||||
onContextMenu
|
||||
} = this.props;
|
||||
const locationId = breakpoint.locationId;
|
||||
const isCurrentlyPaused = breakpoint.isCurrentlyPaused;
|
||||
const isDisabled = breakpoint.disabled;
|
||||
const isConditional = !!breakpoint.condition;
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)({
|
||||
breakpoint,
|
||||
paused: isCurrentlyPaused,
|
||||
disabled: isDisabled,
|
||||
"is-conditional": isConditional
|
||||
}),
|
||||
key: locationId,
|
||||
onClick: onClick,
|
||||
onContextMenu: onContextMenu
|
||||
}, this.renderCheckbox(), this.renderText(), this.renderLineClose());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exports.default = Breakpoint;
|
|
@ -1,212 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _immutable = require("devtools/client/shared/vendor/immutable");
|
||||
|
||||
var I = _interopRequireWildcard(_immutable);
|
||||
|
||||
var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"];
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _Breakpoint = require("./Breakpoint");
|
||||
|
||||
var _Breakpoint2 = _interopRequireDefault(_Breakpoint);
|
||||
|
||||
var _SourceIcon = require("../shared/SourceIcon");
|
||||
|
||||
var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
|
||||
|
||||
var _actions = require("../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _source = require("../../utils/source");
|
||||
|
||||
var _selectors = require("../../selectors/index");
|
||||
|
||||
var _pause = require("../../utils/pause/index");
|
||||
|
||||
var _breakpoint = require("../../utils/breakpoint/index");
|
||||
|
||||
var _BreakpointsContextMenu = require("./BreakpointsContextMenu");
|
||||
|
||||
var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu);
|
||||
|
||||
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)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
function isCurrentlyPausedAtBreakpoint(frame, why, breakpoint) {
|
||||
if (!frame || !(0, _pause.isInterrupted)(why)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bpId = (0, _breakpoint.makeLocationId)(breakpoint.location);
|
||||
const pausedId = (0, _breakpoint.makeLocationId)(frame.location);
|
||||
return bpId === pausedId;
|
||||
}
|
||||
|
||||
function createExceptionOption(label, value, onChange, className) {
|
||||
return _react2.default.createElement("div", {
|
||||
className: className,
|
||||
onClick: onChange
|
||||
}, _react2.default.createElement("input", {
|
||||
type: "checkbox",
|
||||
checked: value ? "checked" : "",
|
||||
onChange: e => e.stopPropagation() && onChange()
|
||||
}), _react2.default.createElement("div", {
|
||||
className: "breakpoint-exceptions-label"
|
||||
}, label));
|
||||
}
|
||||
|
||||
function sortFilenames(urlA, urlB) {
|
||||
const filenameA = (0, _source.getFilenameFromURL)(urlA);
|
||||
const filenameB = (0, _source.getFilenameFromURL)(urlB);
|
||||
|
||||
if (filenameA > filenameB) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (filenameA < filenameB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Breakpoints extends _react.Component {
|
||||
handleBreakpointCheckbox(breakpoint) {
|
||||
if (breakpoint.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (breakpoint.disabled) {
|
||||
this.props.enableBreakpoint(breakpoint.location);
|
||||
} else {
|
||||
this.props.disableBreakpoint(breakpoint.location);
|
||||
}
|
||||
}
|
||||
|
||||
selectBreakpoint(breakpoint) {
|
||||
this.props.selectLocation(breakpoint.location);
|
||||
}
|
||||
|
||||
removeBreakpoint(event, breakpoint) {
|
||||
event.stopPropagation();
|
||||
this.props.removeBreakpoint(breakpoint.location);
|
||||
}
|
||||
|
||||
renderBreakpoint(breakpoint) {
|
||||
const {
|
||||
selectedSource
|
||||
} = this.props;
|
||||
return _react2.default.createElement(_Breakpoint2.default, {
|
||||
key: breakpoint.locationId,
|
||||
breakpoint: breakpoint,
|
||||
selectedSource: selectedSource,
|
||||
onClick: () => this.selectBreakpoint(breakpoint),
|
||||
onContextMenu: e => (0, _BreakpointsContextMenu2.default)(_objectSpread({}, this.props, {
|
||||
breakpoint,
|
||||
contextMenuEvent: e
|
||||
})),
|
||||
onChange: () => this.handleBreakpointCheckbox(breakpoint),
|
||||
onCloseClick: ev => this.removeBreakpoint(ev, breakpoint)
|
||||
});
|
||||
}
|
||||
|
||||
renderExceptionsOptions() {
|
||||
const {
|
||||
breakpoints,
|
||||
shouldPauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions,
|
||||
pauseOnExceptions
|
||||
} = this.props;
|
||||
const isEmpty = breakpoints.size == 0;
|
||||
const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions");
|
||||
const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught");
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("breakpoints-exceptions-options", {
|
||||
empty: isEmpty
|
||||
})
|
||||
}, exceptionsBox, shouldPauseOnExceptions ? ignoreCaughtBox : null);
|
||||
}
|
||||
|
||||
renderBreakpoints() {
|
||||
const {
|
||||
breakpoints
|
||||
} = this.props;
|
||||
|
||||
if (breakpoints.size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const groupedBreakpoints = (0, _lodash.groupBy)((0, _lodash.sortBy)([...breakpoints.valueSeq()], bp => bp.location.line), bp => (0, _source.getRawSourceURL)(bp.source.url));
|
||||
return [...Object.keys(groupedBreakpoints).sort(sortFilenames).map(url => {
|
||||
const groupBreakpoints = groupedBreakpoints[url].filter(bp => !bp.hidden && (bp.text || bp.originalText));
|
||||
|
||||
if (!groupBreakpoints.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
source
|
||||
} = groupBreakpoints[0];
|
||||
return [_react2.default.createElement("div", {
|
||||
className: "breakpoint-heading",
|
||||
title: url,
|
||||
key: url,
|
||||
onClick: () => this.props.selectSource(source.id)
|
||||
}, _react2.default.createElement(_SourceIcon2.default, {
|
||||
source: source
|
||||
}), (0, _source.getFilename)(source)), ...groupBreakpoints.map(bp => this.renderBreakpoint(bp))];
|
||||
})];
|
||||
}
|
||||
|
||||
render() {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "pane breakpoints-list"
|
||||
}, this.renderExceptionsOptions(), this.renderBreakpoints());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateLocation(sources, frame, why, bp) {
|
||||
const source = (0, _selectors.getSourceInSources)(sources, bp.location.sourceId);
|
||||
const isCurrentlyPaused = isCurrentlyPausedAtBreakpoint(frame, why, bp);
|
||||
const locationId = (0, _breakpoint.makeLocationId)(bp.location);
|
||||
|
||||
const localBP = _objectSpread({}, bp, {
|
||||
locationId,
|
||||
isCurrentlyPaused,
|
||||
source
|
||||
});
|
||||
|
||||
return localBP;
|
||||
}
|
||||
|
||||
const _getBreakpoints = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _selectors.getTopFrame, _selectors.getPauseReason, (breakpoints, sources, frame, why) => breakpoints.map(bp => updateLocation(sources, frame, why, bp)).filter(bp => bp.source && !bp.source.isBlackBoxed));
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
breakpoints: _getBreakpoints(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state)
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints);
|
|
@ -0,0 +1,196 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _actions = require("../../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _BreakpointsContextMenu = require("./BreakpointsContextMenu");
|
||||
|
||||
var _BreakpointsContextMenu2 = _interopRequireDefault(_BreakpointsContextMenu);
|
||||
|
||||
var _Button = require("../../shared/Button/index");
|
||||
|
||||
var _breakpoint = require("../../../utils/breakpoint/index");
|
||||
|
||||
var _prefs = require("../../../utils/prefs");
|
||||
|
||||
var _editor = require("../../../utils/editor/index");
|
||||
|
||||
var _selectors = require("../../../selectors/index");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
function getMappedLocation(mappedLocation, selectedSource) {
|
||||
return selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id) ? mappedLocation.generatedLocation : mappedLocation.location;
|
||||
}
|
||||
|
||||
class Breakpoint extends _react.PureComponent {
|
||||
constructor(...args) {
|
||||
var _temp;
|
||||
|
||||
return _temp = super(...args), this.onContextMenu = e => {
|
||||
(0, _BreakpointsContextMenu2.default)(_objectSpread({}, this.props, {
|
||||
contextMenuEvent: e
|
||||
}));
|
||||
}, this.selectBreakpoint = () => {
|
||||
const {
|
||||
breakpoint,
|
||||
selectSpecificLocation
|
||||
} = this.props;
|
||||
selectSpecificLocation(breakpoint.location);
|
||||
}, this.removeBreakpoint = event => {
|
||||
const {
|
||||
breakpoint,
|
||||
removeBreakpoint
|
||||
} = this.props;
|
||||
event.stopPropagation();
|
||||
removeBreakpoint(breakpoint.location);
|
||||
}, this.handleBreakpointCheckbox = () => {
|
||||
const {
|
||||
breakpoint,
|
||||
enableBreakpoint,
|
||||
disableBreakpoint
|
||||
} = this.props;
|
||||
|
||||
if (breakpoint.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (breakpoint.disabled) {
|
||||
enableBreakpoint(breakpoint.location);
|
||||
} else {
|
||||
disableBreakpoint(breakpoint.location);
|
||||
}
|
||||
}, _temp;
|
||||
}
|
||||
|
||||
isCurrentlyPausedAtBreakpoint() {
|
||||
const {
|
||||
frame,
|
||||
breakpoint,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
|
||||
if (!frame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bpId = (0, _breakpoint.getLocationWithoutColumn)(getMappedLocation(breakpoint, selectedSource));
|
||||
const frameId = (0, _breakpoint.getLocationWithoutColumn)(getMappedLocation(frame, selectedSource));
|
||||
return bpId == frameId;
|
||||
}
|
||||
|
||||
getBreakpointLocation() {
|
||||
const {
|
||||
breakpoint,
|
||||
source,
|
||||
selectedSource
|
||||
} = this.props;
|
||||
const {
|
||||
column,
|
||||
line
|
||||
} = getMappedLocation(breakpoint, selectedSource);
|
||||
const isWasm = source && source.isWasm;
|
||||
const columnVal = _prefs.features.columnBreakpoints && column ? `:${column}` : "";
|
||||
const bpLocation = isWasm ? `0x${line.toString(16).toUpperCase()}` : `${line}${columnVal}`;
|
||||
return bpLocation;
|
||||
}
|
||||
|
||||
getBreakpointText() {
|
||||
const {
|
||||
selectedSource,
|
||||
breakpoint
|
||||
} = this.props;
|
||||
const {
|
||||
condition
|
||||
} = breakpoint;
|
||||
|
||||
if (condition) {
|
||||
return condition;
|
||||
}
|
||||
|
||||
if (selectedSource && (0, _devtoolsSourceMap.isGeneratedId)(selectedSource.id)) {
|
||||
return breakpoint.text;
|
||||
}
|
||||
|
||||
return breakpoint.originalText;
|
||||
}
|
||||
|
||||
highlightText() {
|
||||
const text = this.getBreakpointText();
|
||||
const codeMirror = (0, _editor.getCodeMirror)();
|
||||
|
||||
if (!text || !codeMirror) {
|
||||
return {
|
||||
__html: ""
|
||||
};
|
||||
}
|
||||
|
||||
const node = document.createElement("div");
|
||||
codeMirror.constructor.runMode(text, "application/javascript", node);
|
||||
return {
|
||||
__html: node.innerHTML
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
breakpoint
|
||||
} = this.props;
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)({
|
||||
breakpoint,
|
||||
paused: this.isCurrentlyPausedAtBreakpoint(),
|
||||
disabled: breakpoint.disabled,
|
||||
"is-conditional": !!breakpoint.condition
|
||||
}),
|
||||
onClick: this.selectBreakpoint,
|
||||
onContextMenu: this.onContextMenu
|
||||
}, _react2.default.createElement("input", {
|
||||
type: "checkbox",
|
||||
className: "breakpoint-checkbox",
|
||||
checked: !breakpoint.disabled,
|
||||
onChange: this.handleBreakpointCheckbox,
|
||||
onClick: ev => ev.stopPropagation()
|
||||
}), _react2.default.createElement("label", {
|
||||
className: "breakpoint-label cm-s-mozilla",
|
||||
title: this.getBreakpointText(),
|
||||
dangerouslySetInnerHTML: this.highlightText()
|
||||
}), _react2.default.createElement("div", {
|
||||
className: "breakpoint-line-close"
|
||||
}, _react2.default.createElement("div", {
|
||||
className: "breakpoint-line"
|
||||
}, this.getBreakpointLocation()), _react2.default.createElement(_Button.CloseButton, {
|
||||
handleClick: e => this.removeBreakpoint(e),
|
||||
tooltip: L10N.getStr("breakpoints.removeBreakpointTooltip")
|
||||
})));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
frame: (0, _selectors.getTopFrame)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state)
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoint);
|
|
@ -0,0 +1,105 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _reactRedux = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
var _Breakpoint = require("./Breakpoint");
|
||||
|
||||
var _Breakpoint2 = _interopRequireDefault(_Breakpoint);
|
||||
|
||||
var _SourceIcon = require("../../shared/SourceIcon");
|
||||
|
||||
var _SourceIcon2 = _interopRequireDefault(_SourceIcon);
|
||||
|
||||
var _actions = require("../../../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _source = require("../../../utils/source");
|
||||
|
||||
var _breakpoint = require("../../../utils/breakpoint/index");
|
||||
|
||||
var _selectors = require("../../../selectors/index");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* 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 createExceptionOption(label, value, onChange, className) {
|
||||
return _react2.default.createElement("div", {
|
||||
className: className,
|
||||
onClick: onChange
|
||||
}, _react2.default.createElement("input", {
|
||||
type: "checkbox",
|
||||
checked: value ? "checked" : "",
|
||||
onChange: e => e.stopPropagation() && onChange()
|
||||
}), _react2.default.createElement("div", {
|
||||
className: "breakpoint-exceptions-label"
|
||||
}, label));
|
||||
}
|
||||
|
||||
class Breakpoints extends _react.Component {
|
||||
renderExceptionsOptions() {
|
||||
const {
|
||||
breakpointSources,
|
||||
shouldPauseOnExceptions,
|
||||
shouldPauseOnCaughtExceptions,
|
||||
pauseOnExceptions
|
||||
} = this.props;
|
||||
const isEmpty = breakpointSources.length == 0;
|
||||
const exceptionsBox = createExceptionOption(L10N.getStr("pauseOnExceptionsItem2"), shouldPauseOnExceptions, () => pauseOnExceptions(!shouldPauseOnExceptions, false), "breakpoints-exceptions");
|
||||
const ignoreCaughtBox = createExceptionOption(L10N.getStr("pauseOnCaughtExceptionsItem"), shouldPauseOnCaughtExceptions, () => pauseOnExceptions(true, !shouldPauseOnCaughtExceptions), "breakpoints-exceptions-caught");
|
||||
return _react2.default.createElement("div", {
|
||||
className: (0, _classnames2.default)("breakpoints-exceptions-options", {
|
||||
empty: isEmpty
|
||||
})
|
||||
}, exceptionsBox, shouldPauseOnExceptions ? ignoreCaughtBox : null);
|
||||
}
|
||||
|
||||
renderBreakpoints() {
|
||||
const {
|
||||
breakpointSources
|
||||
} = this.props;
|
||||
return [...breakpointSources.map(({
|
||||
source,
|
||||
breakpoints
|
||||
}) => [_react2.default.createElement("div", {
|
||||
className: "breakpoint-heading",
|
||||
title: source.url,
|
||||
key: source.url,
|
||||
onClick: () => this.props.selectSource(source.id)
|
||||
}, _react2.default.createElement(_SourceIcon2.default, {
|
||||
source: source
|
||||
}), (0, _source.getFilename)(source)), ...breakpoints.map(breakpoint => _react2.default.createElement(_Breakpoint2.default, {
|
||||
breakpoint: breakpoint,
|
||||
source: source,
|
||||
key: (0, _breakpoint.makeLocationId)(breakpoint.location)
|
||||
}))])];
|
||||
}
|
||||
|
||||
render() {
|
||||
return _react2.default.createElement("div", {
|
||||
className: "pane breakpoints-list"
|
||||
}, this.renderExceptionsOptions(), this.renderBreakpoints());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
breakpointSources: (0, _selectors.getBreakpointSources)(state),
|
||||
selectedSource: (0, _selectors.getSelectedSource)(state)
|
||||
});
|
||||
|
||||
exports.default = (0, _reactRedux.connect)(mapStateToProps, _actions2.default)(Breakpoints);
|
15
servo/etc/ci/clean_build_artifacts.sh → devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/moz.build
Executable file → Normal file
15
servo/etc/ci/clean_build_artifacts.sh → devtools/client/debugger/new/src/components/SecondaryPanes/Breakpoints/moz.build
Executable file → Normal file
|
@ -1,11 +1,14 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o pipefail
|
||||
DIRS += [
|
||||
|
||||
rm -rf target/{debug,release,doc,geckolib}
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'Breakpoint.js',
|
||||
'BreakpointsContextMenu.js',
|
||||
'index.js',
|
||||
)
|
|
@ -28,7 +28,7 @@ var _Svg2 = _interopRequireDefault(_Svg);
|
|||
|
||||
var _prefs = require("../../utils/prefs");
|
||||
|
||||
var _Breakpoints = require("./Breakpoints");
|
||||
var _Breakpoints = require("./Breakpoints/index");
|
||||
|
||||
var _Breakpoints2 = _interopRequireDefault(_Breakpoints);
|
||||
|
||||
|
|
|
@ -4,13 +4,11 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'Breakpoints',
|
||||
'Frames',
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'Breakpoint.js',
|
||||
'Breakpoints.js',
|
||||
'BreakpointsContextMenu.js',
|
||||
'CommandBar.js',
|
||||
'EventListeners.js',
|
||||
'Expressions.js',
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* 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 CloseButton({
|
||||
handleClick,
|
||||
buttonClass,
|
||||
tooltip
|
||||
}) {
|
||||
return _react2.default.createElement("button", {
|
||||
className: buttonClass ? `close-btn ${buttonClass}` : "close-btn",
|
||||
onClick: handleClick,
|
||||
title: tooltip
|
||||
}, _react2.default.createElement("img", {
|
||||
className: "close"
|
||||
}));
|
||||
}
|
||||
|
||||
exports.default = CloseButton;
|
|
@ -1,54 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _react = require("devtools/client/shared/vendor/react");
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _classnames = require("devtools/client/debugger/new/dist/vendors").vendored["classnames"];
|
||||
|
||||
var _classnames2 = _interopRequireDefault(_classnames);
|
||||
|
||||
var _Svg = require("devtools/client/debugger/new/dist/vendors").vendored["Svg"];
|
||||
|
||||
var _Svg2 = _interopRequireDefault(_Svg);
|
||||
|
||||
var _CommandBarButton = require("./CommandBarButton");
|
||||
|
||||
var _CommandBarButton2 = _interopRequireDefault(_CommandBarButton);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* 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/>. */
|
||||
class PaneToggleButton extends _react.PureComponent {
|
||||
render() {
|
||||
const {
|
||||
position,
|
||||
collapsed,
|
||||
horizontal,
|
||||
handleClick
|
||||
} = this.props;
|
||||
const title = !collapsed ? L10N.getStr("expandPanes") : L10N.getStr("collapsePanes");
|
||||
return _react2.default.createElement(_CommandBarButton2.default, {
|
||||
className: (0, _classnames2.default)("toggle-button", position, {
|
||||
collapsed,
|
||||
vertical: !horizontal
|
||||
}),
|
||||
onClick: () => handleClick(position, collapsed),
|
||||
title: title
|
||||
}, _react2.default.createElement(_Svg2.default, {
|
||||
name: "togglePanes"
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PaneToggleButton.defaultProps = {
|
||||
horizontal: false
|
||||
};
|
||||
exports.default = PaneToggleButton;
|
|
@ -162,17 +162,17 @@ function isSymbolsLoading(state, source) {
|
|||
return symbols.hasOwnProperty("loading");
|
||||
}
|
||||
|
||||
function isEmptyLineInSource(state, line, selectedSource) {
|
||||
const emptyLines = getEmptyLines(state, selectedSource);
|
||||
function isEmptyLineInSource(state, line, selectedSourceId) {
|
||||
const emptyLines = getEmptyLines(state, selectedSourceId);
|
||||
return emptyLines && emptyLines.includes(line);
|
||||
}
|
||||
|
||||
function getEmptyLines(state, source) {
|
||||
if (!source) {
|
||||
function getEmptyLines(state, sourceId) {
|
||||
if (!sourceId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return state.ast.emptyLines.get(source.id);
|
||||
return state.ast.emptyLines.get(sourceId);
|
||||
}
|
||||
|
||||
function getPausePoints(state, sourceId) {
|
||||
|
|
|
@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|||
});
|
||||
exports.getSelectedSourceText = exports.getSelectedSource = exports.getSelectedLocation = exports.getSourcesForTabs = exports.getSourceTabs = exports.getTabs = exports.getSources = exports.RelativeSourceRecordClass = exports.SourceRecordClass = undefined;
|
||||
exports.initialSourcesState = initialSourcesState;
|
||||
exports.createSourceRecord = createSourceRecord;
|
||||
exports.removeSourceFromTabList = removeSourceFromTabList;
|
||||
exports.removeSourcesFromTabList = removeSourcesFromTabList;
|
||||
exports.getBlackBoxList = getBlackBoxList;
|
||||
|
@ -68,6 +69,10 @@ const RelativeSourceRecordClass = exports.RelativeSourceRecordClass = new I.Reco
|
|||
relativeUrl: undefined
|
||||
}));
|
||||
|
||||
function createSourceRecord(source) {
|
||||
return new SourceRecordClass(source);
|
||||
}
|
||||
|
||||
function update(state = initialSourcesState(), action) {
|
||||
let location = null;
|
||||
|
||||
|
@ -222,7 +227,7 @@ function updateSource(state, source) {
|
|||
return state.setIn(["sources", source.id], updatedSource);
|
||||
}
|
||||
|
||||
return state.setIn(["sources", source.id], new SourceRecordClass(source));
|
||||
return state.setIn(["sources", source.id], createSourceRecord(source));
|
||||
}
|
||||
|
||||
function removeSourceFromTabList(tabs, url) {
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getBreakpointSources = undefined;
|
||||
|
||||
var _lodash = require("devtools/client/shared/vendor/lodash");
|
||||
|
||||
var _reselect = require("devtools/client/debugger/new/dist/vendors").vendored["reselect"];
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var _source = require("../utils/source");
|
||||
|
||||
/* 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 getBreakpointsForSource(source, breakpoints) {
|
||||
return breakpoints.valueSeq().filter(bp => bp.location.sourceId == source.id && !bp.hidden && (bp.text || bp.condition)).sortBy(bp => bp.location.line).toJS();
|
||||
}
|
||||
|
||||
function findBreakpointSources(sources, breakpoints) {
|
||||
const sourceIds = (0, _lodash.uniq)(breakpoints.valueSeq().filter(bp => !bp.hidden).map(bp => bp.location.sourceId).toJS());
|
||||
const breakpointSources = sourceIds.map(id => (0, _selectors.getSourceInSources)(sources, id)).filter(source => source && !source.isBlackBoxed);
|
||||
return (0, _lodash.sortBy)(breakpointSources, source => (0, _source.getFilenameFromURL)(source.url));
|
||||
}
|
||||
|
||||
function _getBreakpointSources(breakpoints, sources, selectedSource) {
|
||||
const breakpointSources = findBreakpointSources(sources, breakpoints);
|
||||
return breakpointSources.map(source => ({
|
||||
source,
|
||||
breakpoints: getBreakpointsForSource(source, breakpoints)
|
||||
}));
|
||||
}
|
||||
|
||||
const getBreakpointSources = exports.getBreakpointSources = (0, _reselect.createSelector)(_selectors.getBreakpoints, _selectors.getSources, _getBreakpointSources);
|
|
@ -251,4 +251,13 @@ Object.defineProperty(exports, "getRelativeSources", {
|
|||
get: function () {
|
||||
return _getRelativeSources.getRelativeSources;
|
||||
}
|
||||
});
|
||||
|
||||
var _breakpointSources = require("./breakpointSources");
|
||||
|
||||
Object.defineProperty(exports, "getBreakpointSources", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _breakpointSources.getBreakpointSources;
|
||||
}
|
||||
});
|
|
@ -9,6 +9,7 @@ DIRS += [
|
|||
|
||||
DevToolsModules(
|
||||
'breakpointAtLocation.js',
|
||||
'breakpointSources.js',
|
||||
'getCallStackFrames.js',
|
||||
'getRelativeSources.js',
|
||||
'inComponent.js',
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.createEditor = createEditor;
|
||||
|
||||
var _sourceEditor = require("devtools/client/sourceeditor/editor");
|
||||
|
||||
var _sourceEditor2 = _interopRequireDefault(_sourceEditor);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/* 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 createEditor(value) {
|
||||
return new _sourceEditor2.default({
|
||||
mode: "javascript",
|
||||
foldGutter: false,
|
||||
enableCodeFolding: false,
|
||||
readOnly: "nocursor",
|
||||
lineNumbers: false,
|
||||
theme: "mozilla mozilla-breakpoint",
|
||||
styleActiveLine: false,
|
||||
lineWrapping: false,
|
||||
matchBrackets: false,
|
||||
showAnnotationRuler: false,
|
||||
gutters: false,
|
||||
value: value || "",
|
||||
scrollbarStyle: null
|
||||
});
|
||||
}
|
|
@ -3,16 +3,7 @@
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.findScopeByName = exports.getASTLocation = exports.createEditor = undefined;
|
||||
|
||||
var _createEditor = require("./create-editor");
|
||||
|
||||
Object.defineProperty(exports, "createEditor", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _createEditor.createEditor;
|
||||
}
|
||||
});
|
||||
exports.findScopeByName = exports.getASTLocation = undefined;
|
||||
|
||||
var _astBreakpointLocation = require("./astBreakpointLocation");
|
||||
|
||||
|
@ -31,6 +22,7 @@ Object.defineProperty(exports, "findScopeByName", {
|
|||
exports.firstString = firstString;
|
||||
exports.locationMoved = locationMoved;
|
||||
exports.makeLocationId = makeLocationId;
|
||||
exports.getLocationWithoutColumn = getLocationWithoutColumn;
|
||||
exports.makePendingLocationId = makePendingLocationId;
|
||||
exports.assertBreakpoint = assertBreakpoint;
|
||||
exports.assertPendingBreakpoint = assertPendingBreakpoint;
|
||||
|
@ -77,6 +69,14 @@ function makeLocationId(location) {
|
|||
return `${sourceId}:${line}:${columnString}`;
|
||||
}
|
||||
|
||||
function getLocationWithoutColumn(location) {
|
||||
const {
|
||||
sourceId,
|
||||
line
|
||||
} = location;
|
||||
return `${sourceId}:${line}`;
|
||||
}
|
||||
|
||||
function makePendingLocationId(location) {
|
||||
assertPendingLocation(location);
|
||||
const {
|
||||
|
|
|
@ -9,6 +9,5 @@ DIRS += [
|
|||
|
||||
DevToolsModules(
|
||||
'astBreakpointLocation.js',
|
||||
'create-editor.js',
|
||||
'index.js',
|
||||
)
|
||||
|
|
|
@ -65,6 +65,7 @@ Object.keys(_createEditor).forEach(function (key) {
|
|||
});
|
||||
exports.setEditor = setEditor;
|
||||
exports.getEditor = getEditor;
|
||||
exports.getCodeMirror = getCodeMirror;
|
||||
exports.removeEditor = removeEditor;
|
||||
exports.shouldShowPrettyPrint = shouldShowPrettyPrint;
|
||||
exports.shouldShowFooter = shouldShowFooter;
|
||||
|
@ -103,6 +104,10 @@ function getEditor() {
|
|||
return editor;
|
||||
}
|
||||
|
||||
function getCodeMirror() {
|
||||
return editor && editor.codeMirror;
|
||||
}
|
||||
|
||||
function removeEditor() {
|
||||
editor = null;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ require("codemirror/addon/fold/indent-fold/index");
|
|||
|
||||
require("codemirror/addon/fold/foldgutter/index");
|
||||
|
||||
require("codemirror/addon/runmode/runmode/index");
|
||||
|
||||
require("codemirror/addon/selection/active-line/index");
|
||||
|
||||
require("codemirror/addon/edit/matchbrackets/index");
|
||||
|
|
|
@ -9,6 +9,8 @@ var _parser = require("../../../workers/parser/index");
|
|||
|
||||
var _locColumn = require("./locColumn");
|
||||
|
||||
var _rangeMetadata = require("./rangeMetadata");
|
||||
|
||||
var _findGeneratedBindingFromPosition = require("./findGeneratedBindingFromPosition");
|
||||
|
||||
var _buildGeneratedBindingList = require("./buildGeneratedBindingList");
|
||||
|
@ -30,10 +32,11 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) {
|
|||
}
|
||||
|
||||
const generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this);
|
||||
const originalRanges = await (0, _rangeMetadata.loadRangeMetadata)(source, frame, originalAstScopes, sourceMaps);
|
||||
const {
|
||||
mappedOriginalScopes,
|
||||
expressionLookup
|
||||
} = await mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps);
|
||||
} = await mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps);
|
||||
const mappedGeneratedScopes = generateClientScope(scopes, mappedOriginalScopes);
|
||||
return isReliableScope(mappedGeneratedScopes) ? {
|
||||
mappings: expressionLookup,
|
||||
|
@ -41,7 +44,7 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) {
|
|||
} : null;
|
||||
}
|
||||
|
||||
async function mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps) {
|
||||
async function mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps) {
|
||||
const expressionLookup = {};
|
||||
const mappedOriginalScopes = [];
|
||||
const cachedSourceMaps = batchScopeMappings(originalAstScopes, source, sourceMaps);
|
||||
|
@ -51,7 +54,7 @@ async function mapOriginalBindingsToGenerated(source, originalAstScopes, generat
|
|||
|
||||
for (const name of Object.keys(item.bindings)) {
|
||||
const binding = item.bindings[name];
|
||||
const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, generatedAstBindings);
|
||||
const result = await findGeneratedBinding(cachedSourceMaps, client, source, name, binding, originalRanges, generatedAstBindings);
|
||||
|
||||
if (result) {
|
||||
generatedBindings[name] = result.grip;
|
||||
|
@ -213,7 +216,14 @@ function generateClientScope(scopes, originalScopes) {
|
|||
return result;
|
||||
}
|
||||
|
||||
async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, generatedAstBindings) {
|
||||
function hasValidIdent(range, pos) {
|
||||
return range.type === "match" || // For declarations, we allow the range on the identifier to be a
|
||||
// more general "contains" to increase the chances of a match.
|
||||
pos.type !== "ref" && range.type === "contains";
|
||||
} // eslint-disable-next-line complexity
|
||||
|
||||
|
||||
async function findGeneratedBinding(sourceMaps, client, source, name, originalBinding, originalRanges, generatedAstBindings) {
|
||||
// If there are no references to the implicits, then we have no way to
|
||||
// even attempt to map it back to the original since there is no location
|
||||
// data to use. Bail out instead of just showing it as unmapped.
|
||||
|
@ -227,27 +237,43 @@ async function findGeneratedBinding(sourceMaps, client, source, name, originalBi
|
|||
let genContent = null;
|
||||
|
||||
for (const pos of refs) {
|
||||
if (originalBinding.type === "import") {
|
||||
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
} else {
|
||||
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
const range = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos);
|
||||
|
||||
if (range && hasValidIdent(range, pos)) {
|
||||
if (originalBinding.type === "import") {
|
||||
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
} else {
|
||||
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
}
|
||||
}
|
||||
|
||||
if ((pos.type === "class-decl" || pos.type === "class-inner") && source.contentType && source.contentType.match(/\/typescript/)) {
|
||||
// Resolve to first binding in the range
|
||||
const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration);
|
||||
|
||||
if (declContent) {
|
||||
// Prefer the declaration mapping in this case because TS sometimes
|
||||
// maps class declaration names to "export.Foo = Foo;" or to
|
||||
// the decorator logic itself
|
||||
genContent = declContent;
|
||||
if (declRange && declRange.type !== "multiple") {
|
||||
// Resolve to first binding in the range
|
||||
const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
|
||||
if (declContent) {
|
||||
// Prefer the declaration mapping in this case because TS sometimes
|
||||
// maps class declaration names to "export.Foo = Foo;" or to
|
||||
// the decorator logic itself
|
||||
genContent = declContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!genContent && (pos.type === "import-decl" || pos.type === "import-ns-decl")) {
|
||||
// match the import declaration location
|
||||
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration); // The import declaration should have an original position mapping,
|
||||
// but otherwise we don't really have preferences on the range type
|
||||
// because it can have multiple bindings, but we do want to make sure
|
||||
// that all of the bindings that match the range are part of the same
|
||||
// import declaration.
|
||||
|
||||
if (declRange && declRange.singleDeclaration) {
|
||||
// match the import declaration location
|
||||
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
|
||||
}
|
||||
}
|
||||
|
||||
if (genContent) {
|
||||
|
|
|
@ -16,4 +16,5 @@ DevToolsModules(
|
|||
'locColumn.js',
|
||||
'mappingContains.js',
|
||||
'positionCmp.js',
|
||||
'rangeMetadata.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.loadRangeMetadata = loadRangeMetadata;
|
||||
exports.findMatchingRange = findMatchingRange;
|
||||
|
||||
var _locColumn = require("./locColumn");
|
||||
|
||||
var _positionCmp = require("./positionCmp");
|
||||
|
||||
var _filtering = require("./filtering");
|
||||
|
||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
async function loadRangeMetadata(source, frame, originalAstScopes, sourceMaps) {
|
||||
const originalRanges = await sourceMaps.getOriginalRanges(frame.location.sourceId, source.url);
|
||||
const sortedOriginalAstBindings = [];
|
||||
|
||||
for (const item of originalAstScopes) {
|
||||
for (const name of Object.keys(item.bindings)) {
|
||||
for (const ref of item.bindings[name].refs) {
|
||||
sortedOriginalAstBindings.push(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortedOriginalAstBindings.sort((a, b) => (0, _positionCmp.positionCmp)(a.start, b.start));
|
||||
let i = 0;
|
||||
return originalRanges.map(range => {
|
||||
const bindings = [];
|
||||
|
||||
while (i < sortedOriginalAstBindings.length && (sortedOriginalAstBindings[i].start.line < range.line || sortedOriginalAstBindings[i].start.line === range.line && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) < range.columnStart)) {
|
||||
i++;
|
||||
}
|
||||
|
||||
while (i < sortedOriginalAstBindings.length && sortedOriginalAstBindings[i].start.line === range.line && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) >= range.columnStart && (0, _locColumn.locColumn)(sortedOriginalAstBindings[i].start) < range.columnEnd) {
|
||||
bindings.push(sortedOriginalAstBindings[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
let type = "empty";
|
||||
let singleDeclaration = true;
|
||||
|
||||
if (bindings.length === 1) {
|
||||
const binding = bindings[0];
|
||||
|
||||
if (binding.start.line === range.line && binding.start.column === range.columnStart) {
|
||||
type = "match";
|
||||
} else {
|
||||
type = "contains";
|
||||
}
|
||||
} else if (bindings.length > 1) {
|
||||
type = "multiple";
|
||||
const binding = bindings[0];
|
||||
const declStart = binding.type !== "ref" ? binding.declaration.start : null;
|
||||
singleDeclaration = bindings.every(b => {
|
||||
return declStart && b.type !== "ref" && (0, _positionCmp.positionCmp)(declStart, b.declaration.start) === 0;
|
||||
});
|
||||
}
|
||||
|
||||
return _objectSpread({
|
||||
type,
|
||||
singleDeclaration
|
||||
}, range);
|
||||
});
|
||||
}
|
||||
|
||||
function findMatchingRange(sortedOriginalRanges, bindingRange) {
|
||||
return (0, _filtering.filterSortedArray)(sortedOriginalRanges, range => {
|
||||
if (range.line < bindingRange.start.line) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (range.line > bindingRange.start.line) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (range.columnEnd <= (0, _locColumn.locColumn)(bindingRange.start)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (range.columnStart > (0, _locColumn.locColumn)(bindingRange.start)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}).pop();
|
||||
}
|
|
@ -466,5 +466,5 @@ function getSourceClassnames(source, sourceMetaData) {
|
|||
return "blackBox";
|
||||
}
|
||||
|
||||
return sourceTypes[(0, _sourcesTree.getExtension)(source)] || defaultClassName;
|
||||
return sourceTypes[(0, _sourcesTree.getExtension)(source.url)] || defaultClassName;
|
||||
}
|
|
@ -47,8 +47,7 @@ function isDirectory(url) {
|
|||
return (parts.length === 0 || url.path.slice(-1) === "/" || nodeHasChildren(url)) && url.name != "(index)";
|
||||
}
|
||||
|
||||
function getExtension(source) {
|
||||
const url = source.get ? source.get("url") : source.url;
|
||||
function getExtension(url = "") {
|
||||
const parsedUrl = (0, _url.parse)(url).pathname;
|
||||
|
||||
if (!parsedUrl) {
|
||||
|
@ -59,7 +58,7 @@ function getExtension(source) {
|
|||
}
|
||||
|
||||
function isNotJavaScript(source) {
|
||||
return ["css", "svg", "png"].includes(getExtension(source));
|
||||
return ["css", "svg", "png"].includes(getExtension(source.url));
|
||||
}
|
||||
|
||||
function isInvalidUrl(url, source) {
|
||||
|
|
|
@ -1,167 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.getHistory = exports.waitForState = exports.makeSymbolDeclaration = exports.makeSourceRecord = exports.makeOriginalSource = exports.makeSource = exports.makeFrame = exports.commonLog = exports.createStore = exports.reducers = exports.selectors = exports.actions = undefined;
|
||||
|
||||
var _redux = require("devtools/client/shared/vendor/redux");
|
||||
|
||||
var _devtoolsSourceMap = require("devtools/client/shared/source-map/index.js");
|
||||
|
||||
var _devtoolsSourceMap2 = _interopRequireDefault(_devtoolsSourceMap);
|
||||
|
||||
var _reducers = require("../reducers/index");
|
||||
|
||||
var _reducers2 = _interopRequireDefault(_reducers);
|
||||
|
||||
var _actions = require("../actions/index");
|
||||
|
||||
var _actions2 = _interopRequireDefault(_actions);
|
||||
|
||||
var _selectors = require("../selectors/index");
|
||||
|
||||
var selectors = _interopRequireWildcard(_selectors);
|
||||
|
||||
var _history = require("../test/utils/history");
|
||||
|
||||
var _createStore = require("../actions/utils/create-store");
|
||||
|
||||
var _createStore2 = _interopRequireDefault(_createStore);
|
||||
|
||||
var _immutable = require("devtools/client/shared/vendor/immutable");
|
||||
|
||||
var I = _interopRequireWildcard(_immutable);
|
||||
|
||||
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)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
/**
|
||||
* @memberof utils/test-head
|
||||
* @static
|
||||
*/
|
||||
function createStore(client, initialState = {}, sourceMapsMock) {
|
||||
return (0, _createStore2.default)({
|
||||
log: false,
|
||||
history: (0, _history.getHistory)(),
|
||||
makeThunkArgs: args => {
|
||||
return _objectSpread({}, args, {
|
||||
client,
|
||||
sourceMaps: sourceMapsMock !== undefined ? sourceMapsMock : _devtoolsSourceMap2.default
|
||||
});
|
||||
}
|
||||
})((0, _redux.combineReducers)(_reducers2.default), initialState);
|
||||
}
|
||||
/**
|
||||
* @memberof utils/test-head
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function commonLog(msg, data = {}) {
|
||||
console.log(`[INFO] ${msg} ${JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
function makeFrame({
|
||||
id,
|
||||
sourceId
|
||||
}, opts = {}) {
|
||||
return _objectSpread({
|
||||
id,
|
||||
scope: [],
|
||||
location: {
|
||||
sourceId,
|
||||
line: 4
|
||||
}
|
||||
}, opts);
|
||||
}
|
||||
/**
|
||||
* @memberof utils/test-head
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function makeSource(name, props = {}) {
|
||||
return _objectSpread({
|
||||
id: name,
|
||||
loadedState: "unloaded",
|
||||
url: `http://localhost:8000/examples/${name}`
|
||||
}, props);
|
||||
}
|
||||
|
||||
function makeOriginalSource(name, props) {
|
||||
const source = makeSource(name, props);
|
||||
return _objectSpread({}, source, {
|
||||
id: `${name}-original`
|
||||
});
|
||||
}
|
||||
|
||||
function makeSourceRecord(name, props = {}) {
|
||||
return I.Map(makeSource(name, props));
|
||||
}
|
||||
|
||||
function makeFuncLocation(startLine, endLine) {
|
||||
if (!endLine) {
|
||||
endLine = startLine + 1;
|
||||
}
|
||||
|
||||
return {
|
||||
start: {
|
||||
line: startLine
|
||||
},
|
||||
end: {
|
||||
line: endLine
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function makeSymbolDeclaration(name, start, end, klass) {
|
||||
return {
|
||||
id: `${name}:${start}`,
|
||||
name,
|
||||
location: makeFuncLocation(start, end),
|
||||
klass
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @memberof utils/test-head
|
||||
* @static
|
||||
*/
|
||||
|
||||
|
||||
function waitForState(store, predicate) {
|
||||
return new Promise(resolve => {
|
||||
let ret = predicate(store.getState());
|
||||
|
||||
if (ret) {
|
||||
resolve(ret);
|
||||
}
|
||||
|
||||
const unsubscribe = store.subscribe(() => {
|
||||
ret = predicate(store.getState());
|
||||
|
||||
if (ret) {
|
||||
unsubscribe();
|
||||
resolve(ret);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.actions = _actions2.default;
|
||||
exports.selectors = selectors;
|
||||
exports.reducers = _reducers2.default;
|
||||
exports.createStore = createStore;
|
||||
exports.commonLog = commonLog;
|
||||
exports.makeFrame = makeFrame;
|
||||
exports.makeSource = makeSource;
|
||||
exports.makeOriginalSource = makeOriginalSource;
|
||||
exports.makeSourceRecord = makeSourceRecord;
|
||||
exports.makeSymbolDeclaration = makeSymbolDeclaration;
|
||||
exports.waitForState = waitForState;
|
||||
exports.getHistory = _history.getHistory;
|
|
@ -3,7 +3,7 @@
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.formatKeyShortcut = undefined;
|
||||
exports.truncateMiddleText = exports.formatKeyShortcut = undefined;
|
||||
|
||||
var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"];
|
||||
|
||||
|
@ -40,5 +40,26 @@ function formatKeyShortcut(shortcut) {
|
|||
|
||||
return shortcut.replace(/CommandOrControl\+|CmdOrCtrl\+/g, `${L10N.getStr("ctrl")} `).replace(/Shift\+/g, "Shift ");
|
||||
}
|
||||
/**
|
||||
* Truncates the received text to the maxLength in the format:
|
||||
* Original: 'this is a very long text and ends here'
|
||||
* Truncated: 'this is a ver...and ends here'
|
||||
* @param {String} sourceText - Source text
|
||||
* @param {Number} maxLength - Max allowed length
|
||||
* @memberof utils/text
|
||||
* @static
|
||||
*/
|
||||
|
||||
exports.formatKeyShortcut = formatKeyShortcut;
|
||||
|
||||
function truncateMiddleText(sourceText, maxLength) {
|
||||
let truncatedText = sourceText;
|
||||
|
||||
if (sourceText.length > maxLength) {
|
||||
truncatedText = `${sourceText.substring(0, Math.round(maxLength / 2) - 2)}...${sourceText.substring(sourceText.length - Math.round(maxLength / 2 - 1))}`;
|
||||
}
|
||||
|
||||
return truncatedText;
|
||||
}
|
||||
|
||||
exports.formatKeyShortcut = formatKeyShortcut;
|
||||
exports.truncateMiddleText = truncateMiddleText;
|
|
@ -89,7 +89,7 @@ function toParsedScopes(children, sourceId) {
|
|||
return {
|
||||
start: scope.loc.start,
|
||||
end: scope.loc.end,
|
||||
type: scope.type === "module" ? "block" : scope.type,
|
||||
type: scope.type === "module" || scope.type === "function-body" ? "block" : scope.type,
|
||||
displayName: scope.displayName,
|
||||
bindings: scope.bindings,
|
||||
children: toParsedScopes(scope.children, sourceId)
|
||||
|
@ -190,10 +190,20 @@ function isLetOrConst(node) {
|
|||
}
|
||||
|
||||
function hasLexicalDeclaration(node, parent) {
|
||||
const nodes = [];
|
||||
|
||||
if (t.isSwitchStatement(node)) {
|
||||
for (const caseNode of node.cases) {
|
||||
nodes.push(...caseNode.consequent);
|
||||
}
|
||||
} else {
|
||||
nodes.push(...node.body);
|
||||
}
|
||||
|
||||
const isFunctionBody = t.isFunction(parent, {
|
||||
body: node
|
||||
});
|
||||
return node.body.some(child => isLexicalVariable(child) || !isFunctionBody && child.type === "FunctionDeclaration" || child.type === "ClassDeclaration");
|
||||
return nodes.some(child => isLexicalVariable(child) || t.isClassDeclaration(child) || !isFunctionBody && t.isFunctionDeclaration(child));
|
||||
}
|
||||
|
||||
function isLexicalVariable(node) {
|
||||
|
@ -257,19 +267,27 @@ const scopeCollectionVisitor = {
|
|||
// This ignores Annex B function declaration hoisting, which
|
||||
// is probably a fine assumption.
|
||||
state.declarationBindingIds.add(node.id);
|
||||
const fnScope = getVarScope(scope);
|
||||
scope.bindings[node.id.name] = {
|
||||
type: fnScope === scope ? "var" : "let",
|
||||
refs: [{
|
||||
type: "fn-decl",
|
||||
start: fromBabelLocation(node.id.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.id.loc.end, state.sourceId),
|
||||
declaration: {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
}
|
||||
}]
|
||||
};
|
||||
const refs = [{
|
||||
type: "fn-decl",
|
||||
start: fromBabelLocation(node.id.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.id.loc.end, state.sourceId),
|
||||
declaration: {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
}
|
||||
}];
|
||||
|
||||
if (scope.type === "block") {
|
||||
scope.bindings[node.id.name] = {
|
||||
type: "let",
|
||||
refs
|
||||
};
|
||||
} else {
|
||||
getVarScope(scope).bindings[node.id.name] = {
|
||||
type: "var",
|
||||
refs
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), {
|
||||
|
@ -290,6 +308,13 @@ const scopeCollectionVisitor = {
|
|||
refs: []
|
||||
};
|
||||
}
|
||||
|
||||
if (t.isBlockStatement(node.body) && hasLexicalDeclaration(node.body, node)) {
|
||||
scope = pushTempScope(state, "function-body", "Function Body", {
|
||||
start: fromBabelLocation(node.body.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.body.loc.end, state.sourceId)
|
||||
});
|
||||
}
|
||||
} else if (t.isClass(node)) {
|
||||
if (t.isIdentifier(node.id)) {
|
||||
// For decorated classes, the AST considers the first the decorator
|
||||
|
@ -359,7 +384,8 @@ const scopeCollectionVisitor = {
|
|||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
});
|
||||
parseDeclarator(node.param, scope, "var", "catch", node, state);
|
||||
} else if (t.isBlockStatement(node) && hasLexicalDeclaration(node, parentNode)) {
|
||||
} else if (t.isBlockStatement(node) && // Function body's are handled in the function logic above.
|
||||
!t.isFunction(parentNode) && hasLexicalDeclaration(node, parentNode)) {
|
||||
// Debugger will create new lexical environment for the block.
|
||||
pushTempScope(state, "block", "Block", {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
|
@ -489,7 +515,7 @@ const scopeCollectionVisitor = {
|
|||
type: "implicit",
|
||||
refs: []
|
||||
};
|
||||
} else if (t.isSwitchStatement(node) && node.cases.some(caseNode => caseNode.consequent.some(child => isLexicalVariable(child)))) {
|
||||
} else if (t.isSwitchStatement(node) && hasLexicalDeclaration(node, parentNode)) {
|
||||
pushTempScope(state, "block", "Switch", {
|
||||
start: fromBabelLocation(node.loc.start, state.sourceId),
|
||||
end: fromBabelLocation(node.loc.end, state.sourceId)
|
||||
|
|
|
@ -31,6 +31,8 @@ support-files =
|
|||
examples/sourcemapped/fixtures/babel-for-loops/output.js.map
|
||||
examples/sourcemapped/fixtures/babel-functions/output.js
|
||||
examples/sourcemapped/fixtures/babel-functions/output.js.map
|
||||
examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js
|
||||
examples/sourcemapped/fixtures/babel-lex-and-nonlex/output.js.map
|
||||
examples/sourcemapped/fixtures/babel-type-module/output.js
|
||||
examples/sourcemapped/fixtures/babel-type-module/output.js.map
|
||||
examples/sourcemapped/fixtures/babel-type-script/output.js
|
||||
|
|
|
@ -25,7 +25,7 @@ add_task(async function() {
|
|||
let onPaused = waitForPaused(dbg);
|
||||
invokeInTab("mutate");
|
||||
await onPaused;
|
||||
await waitForLoadedSource(dbg, "script-mutate");
|
||||
await waitForSelectedSource(dbg, "script-mutate");
|
||||
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 2),
|
||||
|
|
|
@ -46,7 +46,7 @@ add_task(async function() {
|
|||
"Block",
|
||||
["three", "5"],
|
||||
["two", "4"],
|
||||
"Block",
|
||||
"Function Body",
|
||||
["three", "3"],
|
||||
["two", "2"],
|
||||
"root",
|
||||
|
@ -73,7 +73,7 @@ add_task(async function() {
|
|||
["aConst", '"const2"'],
|
||||
["aLet", '"let2"'],
|
||||
"Outer:_Outer()",
|
||||
"Block",
|
||||
"Function Body",
|
||||
["aConst", '"const1"'],
|
||||
["aLet", '"let1"'],
|
||||
"Outer()",
|
||||
|
@ -86,7 +86,7 @@ add_task(async function() {
|
|||
"babel-line-start-bindings-es6",
|
||||
{ line: 19, column: 4 },
|
||||
[
|
||||
"Block",
|
||||
"Function Body",
|
||||
["<this>", "{\u2026}"],
|
||||
["one", "1"],
|
||||
["two", "2"],
|
||||
|
@ -102,7 +102,7 @@ add_task(async function() {
|
|||
"babel-this-arguments-bindings",
|
||||
{ line: 4, column: 4 },
|
||||
[
|
||||
"Block",
|
||||
"Function Body",
|
||||
["<this>", '"this-value"'],
|
||||
["arrow", "undefined"],
|
||||
"fn",
|
||||
|
@ -123,7 +123,7 @@ add_task(async function() {
|
|||
"arrow",
|
||||
["<this>", '"this-value"'],
|
||||
["argArrow", '"arrow-arg"'],
|
||||
"Block",
|
||||
"Function Body",
|
||||
"arrow()",
|
||||
"fn",
|
||||
["arg", '"arg-value"'],
|
||||
|
@ -158,12 +158,12 @@ add_task(async function() {
|
|||
]);
|
||||
|
||||
await breakpointScopes(dbg, "babel-classes", { line: 12, column: 6 }, [
|
||||
"Block",
|
||||
"Function Body",
|
||||
["three", "3"],
|
||||
["two", "2"],
|
||||
"Class",
|
||||
"Another()",
|
||||
"Block",
|
||||
"Function Body",
|
||||
"Another()",
|
||||
["one", "1"],
|
||||
"Thing()",
|
||||
|
@ -174,7 +174,7 @@ add_task(async function() {
|
|||
await breakpointScopes(dbg, "babel-for-loops", { line: 5, column: 4 }, [
|
||||
"For",
|
||||
["i", "1"],
|
||||
"Block",
|
||||
"Function Body",
|
||||
["i", "0"],
|
||||
"Module",
|
||||
"root()"
|
||||
|
@ -183,7 +183,7 @@ add_task(async function() {
|
|||
await breakpointScopes(dbg, "babel-for-loops", { line: 9, column: 4 }, [
|
||||
"For",
|
||||
["i", '"2"'],
|
||||
"Block",
|
||||
"Function Body",
|
||||
["i", "0"],
|
||||
"Module",
|
||||
"root()"
|
||||
|
@ -192,7 +192,7 @@ add_task(async function() {
|
|||
await breakpointScopes(dbg, "babel-for-loops", { line: 13, column: 4 }, [
|
||||
"For",
|
||||
["i", "3"],
|
||||
"Block",
|
||||
"Function Body",
|
||||
["i", "0"],
|
||||
"Module",
|
||||
"root()"
|
||||
|
@ -201,13 +201,13 @@ add_task(async function() {
|
|||
await breakpointScopes(dbg, "babel-functions", { line: 6, column: 8 }, [
|
||||
"arrow",
|
||||
["p3", "undefined"],
|
||||
"Block",
|
||||
"Function Body",
|
||||
"arrow()",
|
||||
"inner",
|
||||
["p2", "undefined"],
|
||||
"Function Expression",
|
||||
"inner()",
|
||||
"Block",
|
||||
"Function Body",
|
||||
"inner()",
|
||||
"decl",
|
||||
["p1", "undefined"],
|
||||
|
@ -268,7 +268,7 @@ add_task(async function() {
|
|||
await breakpointScopes(dbg, "babel-switches", { line: 7, column: 6 }, [
|
||||
"Switch",
|
||||
["val", "2"],
|
||||
"Block",
|
||||
"Function Body",
|
||||
["val", "1"],
|
||||
"Module",
|
||||
"root()"
|
||||
|
@ -279,7 +279,7 @@ add_task(async function() {
|
|||
["val", "3"],
|
||||
"Switch",
|
||||
["val", "2"],
|
||||
"Block",
|
||||
"Function Body",
|
||||
["val", "1"],
|
||||
"Module",
|
||||
"root()"
|
||||
|
@ -290,12 +290,21 @@ add_task(async function() {
|
|||
["two", "2"],
|
||||
"Catch",
|
||||
["err", '"AnError"'],
|
||||
"Block",
|
||||
"Function Body",
|
||||
["one", "1"],
|
||||
"Module",
|
||||
"root()"
|
||||
]);
|
||||
|
||||
await breakpointScopes(dbg, "babel-lex-and-nonlex", { line: 3, column: 4 }, [
|
||||
"Function Body",
|
||||
"Thing()",
|
||||
"root",
|
||||
"someHelper()",
|
||||
"Module",
|
||||
"root()"
|
||||
]);
|
||||
|
||||
await breakpointScopes(
|
||||
dbg,
|
||||
"babel-modules-webpack",
|
||||
|
|
|
@ -40,7 +40,7 @@ add_task(async function() {
|
|||
is(getScopeLabel(dbg, 2), "na");
|
||||
is(getScopeLabel(dbg, 3), "nb");
|
||||
|
||||
is(getScopeLabel(dbg, 4), "Block");
|
||||
is(getScopeLabel(dbg, 4), "Function Body");
|
||||
|
||||
await toggleScopeNode(dbg, 4);
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
<button onclick="babelForOf()">Run babel-for-of</button>
|
||||
<script src="sourcemapped/fixtures/babel-functions/output.js"></script>
|
||||
<button onclick="babelFunctions()">Run babel-functions</button>
|
||||
<script src="sourcemapped/fixtures/babel-lex-and-nonlex/output.js"></script>
|
||||
<button onclick="babelLexAndNonlex()">Run babel-lex-and-nonlex</button>
|
||||
<script src="sourcemapped/fixtures/babel-line-start-bindings-es6/output.js"></script>
|
||||
<button onclick="babelLineStartBindingsEs6()">Run babel-line-start-bindings-es6</button>
|
||||
<script src="sourcemapped/fixtures/babel-modules-cjs/output.js"></script>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
export default function root() {
|
||||
function someHelper(){
|
||||
console.log("pause here", root, Thing);
|
||||
}
|
||||
|
||||
class Thing {}
|
||||
|
||||
someHelper();
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
var babelLexAndNonlex =
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
|
||||
/* harmony export (immutable) */ __webpack_exports__["default"] = root;
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
function root() {
|
||||
function someHelper() {
|
||||
console.log("pause here", root, Thing);
|
||||
}
|
||||
|
||||
var Thing = function Thing() {
|
||||
_classCallCheck(this, Thing);
|
||||
};
|
||||
|
||||
someHelper();
|
||||
}
|
||||
|
||||
/***/ })
|
||||
/******/ ])["default"];
|
||||
//# sourceMappingURL=output.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack:///webpack/bootstrap 683415abc3361bb5ff85","webpack:///./fixtures/babel-lex-and-nonlex/input.js"],"names":["root","someHelper","console","log","Thing"],"mappings":";;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;;;;;AC7De,SAASA,IAAT,GAAgB;AAC7B,WAASC,UAAT,GAAqB;AACnBC,YAAQC,GAAR,CAAY,YAAZ,EAA0BH,IAA1B,EAAgCI,KAAhC;AACD;;AAH4B,MAKvBA,KALuB;AAAA;AAAA;;AAO7BH;AACD,C","file":"fixtures/babel-lex-and-nonlex/output.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 683415abc3361bb5ff85","export default function root() {\n function someHelper(){\n console.log(\"pause here\", root, Thing);\n }\n\n class Thing {}\n\n someHelper();\n}\n\n\n\n// WEBPACK FOOTER //\n// ./fixtures/babel-lex-and-nonlex/input.js"],"sourceRoot":""}
|
|
@ -437,6 +437,7 @@ const {
|
|||
const dispatcher = new WorkerDispatcher();
|
||||
|
||||
const getOriginalURLs = dispatcher.task("getOriginalURLs");
|
||||
const getOriginalRanges = dispatcher.task("getOriginalRanges");
|
||||
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
|
||||
queue: true
|
||||
});
|
||||
|
@ -460,6 +461,7 @@ module.exports = {
|
|||
isOriginalId,
|
||||
hasMappedSource,
|
||||
getOriginalURLs,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
|
|
|
@ -1973,6 +1973,7 @@ exports.ArraySet = ArraySet;
|
|||
|
||||
const {
|
||||
getOriginalURLs,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
|
@ -1993,6 +1994,7 @@ const {
|
|||
// easier to unit test.
|
||||
self.onmessage = workerHandler({
|
||||
getOriginalURLs,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
|
@ -2046,6 +2048,57 @@ async function getOriginalURLs(generatedSource) {
|
|||
|
||||
const COMPUTED_SPANS = new WeakSet();
|
||||
|
||||
const SOURCE_MAPPINGS = new WeakMap();
|
||||
async function getOriginalRanges(sourceId, url) {
|
||||
if (!isOriginalId(sourceId)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const generatedSourceId = originalToGeneratedId(sourceId);
|
||||
const map = await getSourceMap(generatedSourceId);
|
||||
if (!map) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let mappings = SOURCE_MAPPINGS.get(map);
|
||||
if (!mappings) {
|
||||
mappings = new Map();
|
||||
SOURCE_MAPPINGS.set(map, mappings);
|
||||
}
|
||||
|
||||
let fileMappings = mappings.get(url);
|
||||
if (!fileMappings) {
|
||||
fileMappings = [];
|
||||
mappings.set(url, fileMappings);
|
||||
|
||||
const originalMappings = fileMappings;
|
||||
map.eachMapping(mapping => {
|
||||
if (mapping.source !== url) {
|
||||
return;
|
||||
}
|
||||
|
||||
const last = originalMappings[originalMappings.length - 1];
|
||||
|
||||
if (last && last.line === mapping.originalLine) {
|
||||
if (last.columnStart < mapping.originalColumn) {
|
||||
last.columnEnd = mapping.originalColumn;
|
||||
} else {
|
||||
// Skip this duplicate original location,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
originalMappings.push({
|
||||
line: mapping.originalLine,
|
||||
columnStart: mapping.originalColumn,
|
||||
columnEnd: Infinity
|
||||
});
|
||||
}, null, SourceMapConsumer.ORIGINAL_ORDER);
|
||||
}
|
||||
|
||||
return fileMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an original location, find the ranges on the generated file that
|
||||
* are mapped from the original range containing the location.
|
||||
|
@ -2234,6 +2287,7 @@ function applySourceMap(generatedId, url, code, mappings) {
|
|||
|
||||
module.exports = {
|
||||
getOriginalURLs,
|
||||
getOriginalRanges,
|
||||
getGeneratedRanges,
|
||||
getGeneratedLocation,
|
||||
getAllGeneratedLocations,
|
||||
|
|
|
@ -956,7 +956,9 @@ var WasmDisassembler = /** @class */ (function () {
|
|||
case 30 /* CODE_OPERATOR */:
|
||||
var operator = reader.result;
|
||||
if (operator.code == 11 /* end */ && this._indentLevel == 0) {
|
||||
// reached of the function, skipping the operator
|
||||
// reached of the function, closing function body
|
||||
this.appendBuffer(" )");
|
||||
this.newLine();
|
||||
break;
|
||||
}
|
||||
switch (operator.code) {
|
||||
|
@ -980,8 +982,7 @@ var WasmDisassembler = /** @class */ (function () {
|
|||
case 31 /* END_FUNCTION_BODY */:
|
||||
this._funcIndex++;
|
||||
this._backrefLabels = null;
|
||||
this.appendBuffer(" )");
|
||||
this.newLine();
|
||||
// See case BinaryReaderState.CODE_OPERATOR for closing of body
|
||||
break;
|
||||
default:
|
||||
throw new Error("Expectected state: " + reader.state);
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.runMode = function(string, modespec, callback, options) {
|
||||
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
|
||||
var ie = /MSIE \d/.test(navigator.userAgent);
|
||||
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
|
||||
|
||||
if (callback.appendChild) {
|
||||
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
|
||||
var node = callback, col = 0;
|
||||
node.innerHTML = "";
|
||||
callback = function(text, style) {
|
||||
if (text == "\n") {
|
||||
// Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
|
||||
// Emitting a carriage return makes everything ok.
|
||||
node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
|
||||
col = 0;
|
||||
return;
|
||||
}
|
||||
var content = "";
|
||||
// replace tabs
|
||||
for (var pos = 0;;) {
|
||||
var idx = text.indexOf("\t", pos);
|
||||
if (idx == -1) {
|
||||
content += text.slice(pos);
|
||||
col += text.length - pos;
|
||||
break;
|
||||
} else {
|
||||
col += idx - pos;
|
||||
content += text.slice(pos, idx);
|
||||
var size = tabSize - col % tabSize;
|
||||
col += size;
|
||||
for (var i = 0; i < size; ++i) content += " ";
|
||||
pos = idx + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (style) {
|
||||
var sp = node.appendChild(document.createElement("span"));
|
||||
sp.className = "cm-" + style.replace(/ +/g, " cm-");
|
||||
sp.appendChild(document.createTextNode(content));
|
||||
} else {
|
||||
node.appendChild(document.createTextNode(content));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
|
||||
for (var i = 0, e = lines.length; i < e; ++i) {
|
||||
if (i) callback("\n");
|
||||
var stream = new CodeMirror.StringStream(lines[i]);
|
||||
if (!stream.string && mode.blankLine) mode.blankLine(state);
|
||||
while (!stream.eol()) {
|
||||
var style = mode.token(stream, state);
|
||||
callback(stream.current(), style, i, stream.start, state);
|
||||
stream.start = stream.pos;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
});
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -32,6 +32,7 @@ module.exports = [{
|
|||
"./codemirror/addon/fold/comment-fold.js",
|
||||
"./codemirror/addon/fold/xml-fold.js",
|
||||
"./codemirror/addon/fold/foldgutter.js",
|
||||
"./codemirror/addon/runmode/runmode.js",
|
||||
"./codemirror/lib/codemirror.js",
|
||||
],
|
||||
output: {
|
||||
|
|
|
@ -613,7 +613,7 @@ previewers.Object = [
|
|||
isConnected: rawObj.isConnected === true,
|
||||
};
|
||||
|
||||
if (rawObj instanceof Ci.nsIDOMDocument && rawObj.location) {
|
||||
if (rawObj.nodeType == rawObj.DOCUMENT_NODE && rawObj.location) {
|
||||
preview.location = hooks.createValueGrip(rawObj.location.href);
|
||||
} else if (obj.class == "DocumentFragment") {
|
||||
preview.childNodesLength = rawObj.childNodes.length;
|
||||
|
|
|
@ -81,7 +81,6 @@
|
|||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentLoaderFactory.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMStorage.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
|
@ -552,12 +551,6 @@ nsDocShell::GetInterface(const nsIID& aIID, void** aSink)
|
|||
aIID.Equals(NS_GET_IID(nsIDOMWindow))) &&
|
||||
NS_SUCCEEDED(EnsureScriptEnvironment())) {
|
||||
return mScriptGlobal->QueryInterface(aIID, aSink);
|
||||
} else if (aIID.Equals(NS_GET_IID(nsIDOMDocument)) &&
|
||||
NS_SUCCEEDED(EnsureContentViewer())) {
|
||||
nsCOMPtr<nsIDOMDocument> doc =
|
||||
do_QueryInterface(mContentViewer->GetDocument());
|
||||
doc.forget(aSink);
|
||||
return *aSink ? NS_OK : NS_NOINTERFACE;
|
||||
} else if (aIID.Equals(NS_GET_IID(nsIDocument)) &&
|
||||
NS_SUCCEEDED(EnsureContentViewer())) {
|
||||
nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
|
||||
|
|
|
@ -1730,7 +1730,6 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
|
|||
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsDocument, nsISupports, nsINode)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsINode)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocument)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNode)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, mozilla::dom::EventTarget)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "nsWeakPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIdentifierMapEntry.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIContent.h"
|
||||
|
@ -130,7 +130,7 @@ private:
|
|||
|
||||
// Base class for our document implementations.
|
||||
class nsDocument : public nsIDocument,
|
||||
public nsIDOMDocument,
|
||||
public nsIDOMNode,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIScriptObjectPrincipal,
|
||||
public nsIRadioGroupContainer,
|
||||
|
|
|
@ -12,7 +12,6 @@ const nsIProperties = I.nsIProperties;
|
|||
const nsIFileInputStream = I.nsIFileInputStream;
|
||||
const nsIInputStream = I.nsIInputStream;
|
||||
|
||||
const nsIDOMDocument = I.nsIDOMDocument;
|
||||
const nsIDOMNode = I.nsIDOMNode;
|
||||
|
||||
Cu.importGlobalProperties(["DOMParser", "Element", "XMLSerializer"]);
|
||||
|
|
|
@ -177,7 +177,7 @@ function getParsedDocument(aPath) {
|
|||
|
||||
function processParsedDocument(doc) {
|
||||
Assert.ok(doc.documentElement.localName != "parsererror");
|
||||
Assert.ok(doc instanceof Ci.nsIDOMDocument);
|
||||
Assert.equal(ChromeUtils.getClassName(doc), "XMLDocument");
|
||||
|
||||
// Clean out whitespace.
|
||||
var walker = doc.createTreeWalker(doc,
|
||||
|
@ -447,7 +447,7 @@ function do_miscellaneous_tests(doc) {
|
|||
|
||||
// Requested by smaug: A range involving a comment as a document child.
|
||||
doc = parser.parseFromString("<!-- foo --><foo/>", "application/xml");
|
||||
Assert.ok(doc instanceof Ci.nsIDOMDocument);
|
||||
Assert.equal(ChromeUtils.getClassName(doc), "XMLDocument");
|
||||
Assert.equal(doc.childNodes.length, 2);
|
||||
baseRange = doc.createRange();
|
||||
baseRange.setStart(doc.firstChild, 1);
|
||||
|
|
|
@ -8,7 +8,7 @@ function run_test () {
|
|||
|
||||
var tests = [
|
||||
[ test1, "Unable to parse basic XML document" ],
|
||||
[ test2, "ParseXML doesn't return nsIDOMDocument" ],
|
||||
[ test2, "ParseXML doesn't return Document" ],
|
||||
[ test3, "ParseXML return value's documentElement is not Element" ],
|
||||
[ test4, "" ],
|
||||
[ test5, "" ],
|
||||
|
@ -21,7 +21,7 @@ function test1() {
|
|||
}
|
||||
|
||||
function test2() {
|
||||
return (ParseXML("<root/>") instanceof nsIDOMDocument);
|
||||
return (ChromeUtils.getClassName(ParseXML("<root/>")) === "XMLDocument");
|
||||
}
|
||||
|
||||
function test3() {
|
||||
|
|
|
@ -21,16 +21,11 @@ function ConsoleListener() {
|
|||
ConsoleListener.prototype = {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
let obj = aSubject.wrappedJSObject;
|
||||
if (obj.arguments[0] != 'test') {
|
||||
if (obj.arguments[0] != "test_bug1463614") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._cb) {
|
||||
ok(false, "Callback not set!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._cb(obj)) {
|
||||
if (!this._cb || !this._cb(obj)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -57,10 +52,10 @@ async function runTest() {
|
|||
let cl = listener.waitFor(obj => {
|
||||
return ("timer" in obj) &&
|
||||
("name" in obj.timer) &&
|
||||
obj.timer.name == 'test';
|
||||
obj.timer.name == "test_bug1463614";
|
||||
});
|
||||
|
||||
console.time('test');
|
||||
console.time("test_bug1463614");
|
||||
await cl;
|
||||
ok(true, "Console.time received!");
|
||||
|
||||
|
@ -68,7 +63,7 @@ async function runTest() {
|
|||
cl = listener.waitFor(obj => {
|
||||
return ("timer" in obj) &&
|
||||
("name" in obj.timer) &&
|
||||
obj.timer.name == 'test' &&
|
||||
obj.timer.name == "test_bug1463614" &&
|
||||
("duration" in obj.timer) &&
|
||||
obj.timer.duration >= 0 &&
|
||||
obj.arguments[1] == 1 &&
|
||||
|
@ -76,7 +71,7 @@ async function runTest() {
|
|||
obj.arguments[3] == 3 &&
|
||||
obj.arguments[4] == 4;
|
||||
});
|
||||
console.timeLog('test', 1, 2, 3, 4);
|
||||
console.timeLog("test_bug1463614", 1, 2, 3, 4);
|
||||
await cl;
|
||||
ok(true, "Console.timeLog received!");
|
||||
|
||||
|
@ -84,11 +79,11 @@ async function runTest() {
|
|||
cl = listener.waitFor(obj => {
|
||||
return ("timer" in obj) &&
|
||||
("name" in obj.timer) &&
|
||||
obj.timer.name == 'test' &&
|
||||
obj.timer.name == "test_bug1463614" &&
|
||||
("duration" in obj.timer) &&
|
||||
obj.timer.duration >= 0;
|
||||
});
|
||||
console.timeEnd('test');
|
||||
console.timeEnd("test_bug1463614");
|
||||
await cl;
|
||||
ok(true, "Console.timeEnd received!");
|
||||
|
||||
|
@ -96,10 +91,10 @@ async function runTest() {
|
|||
cl = listener.waitFor(obj => {
|
||||
return ("timer" in obj) &&
|
||||
("name" in obj.timer) &&
|
||||
obj.timer.name == 'test' &&
|
||||
obj.timer.name == "test_bug1463614" &&
|
||||
("error" in obj.timer);
|
||||
});
|
||||
console.timeLog('test');
|
||||
console.timeLog("test_bug1463614");
|
||||
await cl;
|
||||
ok(true, "Console.time with error received!");
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ NS_INTERFACE_MAP_BEGIN(IPCBlobInputStream)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIAsyncFileMetadata)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStreamLength)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIIPCBlobInputStream)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
|
|
@ -20,6 +20,22 @@ namespace dom {
|
|||
|
||||
class IPCBlobInputStreamChild;
|
||||
|
||||
#define IPCBLOBINPUTSTREAM_IID \
|
||||
{ 0xbcfa38fc, 0x8b7f, 0x4d79, \
|
||||
{ 0xbe, 0x3a, 0x1e, 0x7b, 0xbe, 0x52, 0x38, 0xcd } }
|
||||
|
||||
class nsIIPCBlobInputStream : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(IPCBLOBINPUTSTREAM_IID)
|
||||
|
||||
virtual nsIInputStream*
|
||||
GetInternalStream() const = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCBlobInputStream,
|
||||
IPCBLOBINPUTSTREAM_IID)
|
||||
|
||||
class IPCBlobInputStream final : public nsIAsyncInputStream
|
||||
, public nsIInputStreamCallback
|
||||
, public nsICloneableInputStreamWithRange
|
||||
|
@ -27,6 +43,7 @@ class IPCBlobInputStream final : public nsIAsyncInputStream
|
|||
, public nsIAsyncFileMetadata
|
||||
, public nsIInputStreamLength
|
||||
, public nsIAsyncInputStreamLength
|
||||
, public nsIIPCBlobInputStream
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
@ -49,6 +66,21 @@ public:
|
|||
void
|
||||
LengthReady(int64_t aLength);
|
||||
|
||||
// nsIIPCBlobInputStream
|
||||
nsIInputStream*
|
||||
GetInternalStream() const override
|
||||
{
|
||||
if (mRemoteStream) {
|
||||
return mRemoteStream;
|
||||
}
|
||||
|
||||
if (mAsyncRemoteStream) {
|
||||
return mAsyncRemoteStream;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
~IPCBlobInputStream();
|
||||
|
||||
|
|
|
@ -89,10 +89,26 @@ SerializeInputStreamParent(nsIInputStream* aInputStream, uint64_t aSize,
|
|||
// Parent to Child we always send a IPCBlobInputStream.
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream = aInputStream;
|
||||
|
||||
// In case this is a IPCBlobInputStream, we don't want to create a loop:
|
||||
// IPCBlobInputStreamParent -> IPCBlobInputStream ->
|
||||
// IPCBlobInputStreamParent. Let's use the underlying inputStream instead.
|
||||
nsCOMPtr<nsIIPCBlobInputStream> ipcBlobInputStream =
|
||||
do_QueryInterface(aInputStream);
|
||||
if (ipcBlobInputStream) {
|
||||
stream = ipcBlobInputStream->GetInternalStream();
|
||||
// If we don't have an underlying stream, it's better to terminate here
|
||||
// instead of sending an 'empty' IPCBlobInputStream actor on the other side,
|
||||
// unable to be used.
|
||||
if (NS_WARN_IF(!stream)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
RefPtr<IPCBlobInputStreamParent> parentActor =
|
||||
IPCBlobInputStreamParent::Create(aInputStream, aSize, aChildID, &rv,
|
||||
aManager);
|
||||
IPCBlobInputStreamParent::Create(stream, aSize, aChildID, &rv, aManager);
|
||||
if (!parentActor) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ typedef double DOMHighResTimeStamp;
|
|||
typedef unsigned long long nsViewID;
|
||||
|
||||
// Core
|
||||
interface nsIDOMDocument;
|
||||
interface nsIDOMNode;
|
||||
|
||||
// Needed for raises() in our IDL
|
||||
|
|
|
@ -8,7 +8,6 @@ with Files("**"):
|
|||
BUG_COMPONENT = ("Core", "DOM")
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMDocument.idl',
|
||||
'nsIDOMNode.idl',
|
||||
'nsIDOMNSEditableElement.idl',
|
||||
]
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#include "nsIDOMNode.idl"
|
||||
|
||||
/**
|
||||
* The nsIDOMDocument interface represents the entire HTML or XML document.
|
||||
* Conceptually, it is the root of the document tree, and provides the
|
||||
* primary access to the document's data.
|
||||
* Since elements, text nodes, comments, processing instructions, etc.
|
||||
* cannot exist outside the context of a Document, the nsIDOMDocument
|
||||
* interface also contains the factory methods needed to create these
|
||||
* objects.
|
||||
*
|
||||
* For more information on this interface please see
|
||||
* http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
|
||||
*/
|
||||
|
||||
[shim(Document), uuid(b15fa0f4-97c1-4388-af62-2ceff7a89bdf)]
|
||||
interface nsIDOMDocument : nsIDOMNode
|
||||
{
|
||||
};
|
|
@ -349,7 +349,7 @@ partial interface Document {
|
|||
[Throws, Func="IsChromeOrXBL", NeedsSubjectPrincipal]
|
||||
void loadBindingDocument(DOMString documentURL);
|
||||
|
||||
// nsIDOMDocumentTouch
|
||||
// Touch bits
|
||||
// XXXbz I can't find the sane spec for this stuff, so just cribbing
|
||||
// from our xpidl for now.
|
||||
[NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"]
|
||||
|
|
29
gfx/2d/2D.h
29
gfx/2d/2D.h
|
@ -473,13 +473,35 @@ public:
|
|||
*
|
||||
* Use IsMapped() to verify whether Map() succeeded or not.
|
||||
*/
|
||||
class ScopedMap {
|
||||
class ScopedMap final {
|
||||
public:
|
||||
explicit ScopedMap(DataSourceSurface* aSurface, MapType aType)
|
||||
: mSurface(aSurface)
|
||||
, mIsMapped(aSurface->Map(aType, &mMap)) {}
|
||||
|
||||
virtual ~ScopedMap()
|
||||
ScopedMap(ScopedMap&& aOther)
|
||||
: mSurface(Move(aOther.mSurface))
|
||||
, mMap(aOther.mMap)
|
||||
, mIsMapped(aOther.mIsMapped)
|
||||
{
|
||||
aOther.mMap.mData = nullptr;
|
||||
aOther.mIsMapped = false;
|
||||
}
|
||||
|
||||
ScopedMap& operator=(ScopedMap&& aOther)
|
||||
{
|
||||
if (mIsMapped) {
|
||||
mSurface->Unmap();
|
||||
}
|
||||
mSurface = Move(aOther.mSurface);
|
||||
mMap = aOther.mMap;
|
||||
mIsMapped = aOther.mIsMapped;
|
||||
aOther.mMap.mData = nullptr;
|
||||
aOther.mIsMapped = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~ScopedMap()
|
||||
{
|
||||
if (mIsMapped) {
|
||||
mSurface->Unmap();
|
||||
|
@ -507,6 +529,9 @@ public:
|
|||
bool IsMapped() const { return mIsMapped; }
|
||||
|
||||
private:
|
||||
ScopedMap(const ScopedMap& aOther) = delete;
|
||||
ScopedMap& operator=(const ScopedMap& aOther) = delete;
|
||||
|
||||
RefPtr<DataSourceSurface> mSurface;
|
||||
MappedSurface mMap;
|
||||
bool mIsMapped;
|
||||
|
|
|
@ -2038,6 +2038,7 @@ gfxFont::DrawOneGlyph(uint32_t aGlyphID, const gfx::Point& aPt,
|
|||
}
|
||||
|
||||
if (fontParams.haveColorGlyphs &&
|
||||
!gfxPlatform::GetPlatform()->HasNativeColrFontSupport() &&
|
||||
RenderColorGlyph(runParams.dt, runParams.context,
|
||||
fontParams.scaledFont,
|
||||
fontParams.drawOptions,
|
||||
|
|
|
@ -737,6 +737,10 @@ public:
|
|||
return mHasVariationFontSupport;
|
||||
}
|
||||
|
||||
bool HasNativeColrFontSupport() const {
|
||||
return mHasNativeColrFontSupport;
|
||||
}
|
||||
|
||||
// you probably want to use gfxVars::UseWebRender() instead of this
|
||||
static bool WebRenderPrefEnabled();
|
||||
// you probably want to use gfxVars::UseWebRender() instead of this
|
||||
|
@ -830,6 +834,10 @@ protected:
|
|||
// Whether the platform supports rendering OpenType font variations
|
||||
bool mHasVariationFontSupport;
|
||||
|
||||
// Whether the platform font APIs have native support for COLR fonts.
|
||||
// Set to true during initialization on platforms that implement this.
|
||||
bool mHasNativeColrFontSupport = false;
|
||||
|
||||
// max character limit for words in word cache
|
||||
int32_t mWordCacheCharLimit;
|
||||
|
||||
|
|
|
@ -82,6 +82,10 @@ gfxPlatformMac::gfxPlatformMac()
|
|||
InitBackendPrefs(GetBackendPrefs());
|
||||
|
||||
MacIOSurfaceLib::LoadLibrary();
|
||||
|
||||
if (nsCocoaFeatures::OnHighSierraOrLater()) {
|
||||
mHasNativeColrFontSupport = true;
|
||||
}
|
||||
}
|
||||
|
||||
gfxPlatformMac::~gfxPlatformMac()
|
||||
|
|
|
@ -176,18 +176,18 @@ AnimationFrameBuffer::MarkComplete()
|
|||
return mPending > 0;
|
||||
}
|
||||
|
||||
DrawableFrameRef
|
||||
imgFrame*
|
||||
AnimationFrameBuffer::Get(size_t aFrame)
|
||||
{
|
||||
// We should not have asked for a frame if we never inserted.
|
||||
if (mFrames.IsEmpty()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Calling Get() when we have no frames");
|
||||
return DrawableFrameRef();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If we don't have that frame, return an empty frame ref.
|
||||
if (aFrame >= mFrames.Length()) {
|
||||
return DrawableFrameRef();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We've got the requested frame because we are not discarding frames. While
|
||||
|
@ -195,13 +195,13 @@ AnimationFrameBuffer::Get(size_t aFrame)
|
|||
// we want them, it is possible the decoder is behind.
|
||||
if (!mFrames[aFrame]) {
|
||||
MOZ_ASSERT(MayDiscard());
|
||||
return DrawableFrameRef();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If we are advancing on behalf of the animation, we don't expect it to be
|
||||
// getting any frames (besides the first) until we get the desired frame.
|
||||
MOZ_ASSERT(aFrame == 0 || mAdvance == 0);
|
||||
return mFrames[aFrame]->DrawableRef();
|
||||
return mFrames[aFrame].get();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
*
|
||||
* @returns The frame, if available.
|
||||
*/
|
||||
DrawableFrameRef Get(size_t aFrame);
|
||||
imgFrame* Get(size_t aFrame);
|
||||
|
||||
/**
|
||||
* Inserts a frame into the frame buffer. If it has yet to fully decode the
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_image_AnimationParams_h
|
||||
#define mozilla_image_AnimationParams_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
#include "FrameTimeout.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
enum class BlendMethod : int8_t {
|
||||
// All color components of the frame, including alpha, overwrite the current
|
||||
// contents of the frame's output buffer region.
|
||||
SOURCE,
|
||||
|
||||
// The frame should be composited onto the output buffer based on its alpha,
|
||||
// using a simple OVER operation.
|
||||
OVER
|
||||
};
|
||||
|
||||
enum class DisposalMethod : int8_t {
|
||||
CLEAR_ALL = -1, // Clear the whole image, revealing what's underneath.
|
||||
NOT_SPECIFIED, // Leave the frame and let the new frame draw on top.
|
||||
KEEP, // Leave the frame and let the new frame draw on top.
|
||||
CLEAR, // Clear the frame's area, revealing what's underneath.
|
||||
RESTORE_PREVIOUS // Restore the previous (composited) frame.
|
||||
};
|
||||
|
||||
struct AnimationParams
|
||||
{
|
||||
gfx::IntRect mBlendRect;
|
||||
FrameTimeout mTimeout;
|
||||
uint32_t mFrameNum;
|
||||
BlendMethod mBlendMethod;
|
||||
DisposalMethod mDisposalMethod;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_image_AnimationParams_h
|
|
@ -134,7 +134,30 @@ AnimationSurfaceProvider::DrawableRef(size_t aFrame)
|
|||
return DrawableFrameRef();
|
||||
}
|
||||
|
||||
return mFrames.Get(aFrame);
|
||||
imgFrame* frame = mFrames.Get(aFrame);
|
||||
if (!frame) {
|
||||
return DrawableFrameRef();
|
||||
}
|
||||
|
||||
return frame->DrawableRef();
|
||||
}
|
||||
|
||||
RawAccessFrameRef
|
||||
AnimationSurfaceProvider::RawAccessRef(size_t aFrame)
|
||||
{
|
||||
MutexAutoLock lock(mFramesMutex);
|
||||
|
||||
if (Availability().IsPlaceholder()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Calling RawAccessRef() on a placeholder");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
imgFrame* frame = mFrames.Get(aFrame);
|
||||
if (!frame) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
return frame->RawAccessRef(/* aOnlyFinished */ true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
|
||||
protected:
|
||||
DrawableFrameRef DrawableRef(size_t aFrame) override;
|
||||
RawAccessFrameRef RawAccessRef(size_t aFrame) override;
|
||||
|
||||
// Animation frames are always locked. This is because we only want to release
|
||||
// their memory atomically (due to the surface cache discarding them). If they
|
||||
|
|
|
@ -283,14 +283,14 @@ Decoder::Telemetry() const
|
|||
}
|
||||
|
||||
nsresult
|
||||
Decoder::AllocateFrame(uint32_t aFrameNum,
|
||||
const gfx::IntSize& aOutputSize,
|
||||
Decoder::AllocateFrame(const gfx::IntSize& aOutputSize,
|
||||
const gfx::IntRect& aFrameRect,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth)
|
||||
uint8_t aPaletteDepth,
|
||||
const Maybe<AnimationParams>& aAnimParams)
|
||||
{
|
||||
mCurrentFrame = AllocateFrameInternal(aFrameNum, aOutputSize, aFrameRect,
|
||||
aFormat, aPaletteDepth,
|
||||
mCurrentFrame = AllocateFrameInternal(aOutputSize, aFrameRect, aFormat,
|
||||
aPaletteDepth, aAnimParams,
|
||||
mCurrentFrame.get());
|
||||
|
||||
if (mCurrentFrame) {
|
||||
|
@ -302,7 +302,7 @@ Decoder::AllocateFrame(uint32_t aFrameNum,
|
|||
|
||||
// We should now be on |aFrameNum|. (Note that we're comparing the frame
|
||||
// number, which is zero-based, with the frame count, which is one-based.)
|
||||
MOZ_ASSERT(aFrameNum + 1 == mFrameCount);
|
||||
MOZ_ASSERT_IF(aAnimParams, aAnimParams->mFrameNum + 1 == mFrameCount);
|
||||
|
||||
// If we're past the first frame, PostIsAnimated() should've been called.
|
||||
MOZ_ASSERT_IF(mFrameCount > 1, HasAnimation());
|
||||
|
@ -316,18 +316,19 @@ Decoder::AllocateFrame(uint32_t aFrameNum,
|
|||
}
|
||||
|
||||
RawAccessFrameRef
|
||||
Decoder::AllocateFrameInternal(uint32_t aFrameNum,
|
||||
const gfx::IntSize& aOutputSize,
|
||||
Decoder::AllocateFrameInternal(const gfx::IntSize& aOutputSize,
|
||||
const gfx::IntRect& aFrameRect,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
const Maybe<AnimationParams>& aAnimParams,
|
||||
imgFrame* aPreviousFrame)
|
||||
{
|
||||
if (HasError()) {
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
if (aFrameNum != mFrameCount) {
|
||||
uint32_t frameNum = aAnimParams ? aAnimParams->mFrameNum : 0;
|
||||
if (frameNum != mFrameCount) {
|
||||
MOZ_ASSERT_UNREACHABLE("Allocating frames out of order");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
@ -342,7 +343,7 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum,
|
|||
bool nonPremult = bool(mSurfaceFlags & SurfaceFlags::NO_PREMULTIPLY_ALPHA);
|
||||
if (NS_FAILED(frame->InitForDecoder(aOutputSize, aFrameRect, aFormat,
|
||||
aPaletteDepth, nonPremult,
|
||||
aFrameNum > 0))) {
|
||||
aAnimParams))) {
|
||||
NS_WARNING("imgFrame::Init should succeed");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
@ -353,24 +354,20 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum,
|
|||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
if (aFrameNum == 1) {
|
||||
if (frameNum == 1) {
|
||||
MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated");
|
||||
aPreviousFrame->SetRawAccessOnly();
|
||||
|
||||
// If we dispose of the first frame by clearing it, then the first frame's
|
||||
// refresh area is all of itself.
|
||||
// RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR).
|
||||
AnimationData previousFrameData = aPreviousFrame->GetAnimationData();
|
||||
if (previousFrameData.mDisposalMethod == DisposalMethod::CLEAR ||
|
||||
previousFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL ||
|
||||
previousFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) {
|
||||
mFirstFrameRefreshArea = previousFrameData.mRect;
|
||||
DisposalMethod prevDisposal = aPreviousFrame->GetDisposalMethod();
|
||||
if (prevDisposal == DisposalMethod::CLEAR ||
|
||||
prevDisposal == DisposalMethod::CLEAR_ALL ||
|
||||
prevDisposal == DisposalMethod::RESTORE_PREVIOUS) {
|
||||
mFirstFrameRefreshArea = aPreviousFrame->GetRect();
|
||||
}
|
||||
}
|
||||
|
||||
if (aFrameNum > 0) {
|
||||
ref->SetRawAccessOnly();
|
||||
|
||||
if (frameNum > 0) {
|
||||
// Some GIFs are huge but only have a small area that they animate. We only
|
||||
// need to refresh that small area when frame 0 comes around again.
|
||||
mFirstFrameRefreshArea.UnionRect(mFirstFrameRefreshArea, frame->GetRect());
|
||||
|
@ -453,13 +450,7 @@ Decoder::PostIsAnimated(FrameTimeout aFirstFrameTimeout)
|
|||
}
|
||||
|
||||
void
|
||||
Decoder::PostFrameStop(Opacity aFrameOpacity
|
||||
/* = Opacity::SOME_TRANSPARENCY */,
|
||||
DisposalMethod aDisposalMethod
|
||||
/* = DisposalMethod::KEEP */,
|
||||
FrameTimeout aTimeout /* = FrameTimeout::Forever() */,
|
||||
BlendMethod aBlendMethod /* = BlendMethod::OVER */,
|
||||
const Maybe<nsIntRect>& aBlendRect /* = Nothing() */)
|
||||
Decoder::PostFrameStop(Opacity aFrameOpacity)
|
||||
{
|
||||
// We should be mid-frame
|
||||
MOZ_ASSERT(!IsMetadataDecode(), "Stopping frame during metadata decode");
|
||||
|
@ -470,12 +461,11 @@ Decoder::PostFrameStop(Opacity aFrameOpacity
|
|||
mInFrame = false;
|
||||
mFinishedNewFrame = true;
|
||||
|
||||
mCurrentFrame->Finish(aFrameOpacity, aDisposalMethod, aTimeout,
|
||||
aBlendMethod, aBlendRect, mFinalizeFrames);
|
||||
mCurrentFrame->Finish(aFrameOpacity, mFinalizeFrames);
|
||||
|
||||
mProgress |= FLAG_FRAME_COMPLETE;
|
||||
|
||||
mLoopLength += aTimeout;
|
||||
mLoopLength += mCurrentFrame->GetTimeout();
|
||||
|
||||
// If we're not sending partial invalidations, then we send an invalidation
|
||||
// here when the first frame is complete.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/NotNull.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "AnimationParams.h"
|
||||
#include "DecoderFlags.h"
|
||||
#include "Downscaler.h"
|
||||
#include "ImageMetadata.h"
|
||||
|
@ -27,6 +28,8 @@ namespace Telemetry {
|
|||
|
||||
namespace image {
|
||||
|
||||
class imgFrame;
|
||||
|
||||
struct DecoderFinalStatus final
|
||||
{
|
||||
DecoderFinalStatus(bool aWasMetadataDecode,
|
||||
|
@ -477,11 +480,7 @@ protected:
|
|||
// Specify whether this frame is opaque as an optimization.
|
||||
// For animated images, specify the disposal, blend method and timeout for
|
||||
// this frame.
|
||||
void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY,
|
||||
DisposalMethod aDisposalMethod = DisposalMethod::KEEP,
|
||||
FrameTimeout aTimeout = FrameTimeout::Forever(),
|
||||
BlendMethod aBlendMethod = BlendMethod::OVER,
|
||||
const Maybe<nsIntRect>& aBlendRect = Nothing());
|
||||
void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY);
|
||||
|
||||
/**
|
||||
* Called by the decoders when they have a region to invalidate. We may not
|
||||
|
@ -510,16 +509,13 @@ protected:
|
|||
/**
|
||||
* Allocates a new frame, making it our current frame if successful.
|
||||
*
|
||||
* The @aFrameNum parameter only exists as a sanity check; it's illegal to
|
||||
* create a new frame anywhere but immediately after the existing frames.
|
||||
*
|
||||
* If a non-paletted frame is desired, pass 0 for aPaletteDepth.
|
||||
*/
|
||||
nsresult AllocateFrame(uint32_t aFrameNum,
|
||||
const gfx::IntSize& aOutputSize,
|
||||
nsresult AllocateFrame(const gfx::IntSize& aOutputSize,
|
||||
const gfx::IntRect& aFrameRect,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth = 0);
|
||||
uint8_t aPaletteDepth = 0,
|
||||
const Maybe<AnimationParams>& aAnimParams = Nothing());
|
||||
|
||||
private:
|
||||
/// Report that an error was encountered while decoding.
|
||||
|
@ -543,11 +539,11 @@ private:
|
|||
return mInFrame ? mFrameCount - 1 : mFrameCount;
|
||||
}
|
||||
|
||||
RawAccessFrameRef AllocateFrameInternal(uint32_t aFrameNum,
|
||||
const gfx::IntSize& aOutputSize,
|
||||
RawAccessFrameRef AllocateFrameInternal(const gfx::IntSize& aOutputSize,
|
||||
const gfx::IntRect& aFrameRect,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
const Maybe<AnimationParams>& aAnimParams,
|
||||
imgFrame* aPreviousFrame);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -70,7 +70,7 @@ public:
|
|||
Maybe<SurfaceInvalidRect> TakeInvalidRect() override { return Nothing(); }
|
||||
|
||||
template <typename... Rest>
|
||||
nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest)
|
||||
nsresult Configure(const DownscalingConfig& aConfig, const Rest&... aRest)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ public:
|
|||
}
|
||||
|
||||
template <typename... Rest>
|
||||
nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest)
|
||||
nsresult Configure(const DownscalingConfig& aConfig, const Rest&... aRest)
|
||||
{
|
||||
nsresult rv = mNext.Configure(aRest...);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -212,40 +212,30 @@ AnimationState::LoopLength() const
|
|||
// FrameAnimator implementation.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Maybe<TimeStamp>
|
||||
TimeStamp
|
||||
FrameAnimator::GetCurrentImgFrameEndTime(AnimationState& aState,
|
||||
DrawableSurface& aFrames) const
|
||||
FrameTimeout aCurrentTimeout) const
|
||||
{
|
||||
TimeStamp currentFrameTime = aState.mCurrentAnimationFrameTime;
|
||||
Maybe<FrameTimeout> timeout =
|
||||
GetTimeoutForFrame(aState, aFrames, aState.mCurrentAnimationFrameIndex);
|
||||
|
||||
if (timeout.isNothing()) {
|
||||
MOZ_ASSERT(aState.GetHasRequestedDecode() && !aState.GetIsCurrentlyDecoded());
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
if (*timeout == FrameTimeout::Forever()) {
|
||||
if (aCurrentTimeout == FrameTimeout::Forever()) {
|
||||
// We need to return a sentinel value in this case, because our logic
|
||||
// doesn't work correctly if we have an infinitely long timeout. We use one
|
||||
// year in the future as the sentinel because it works with the loop in
|
||||
// RequestRefresh() below.
|
||||
// XXX(seth): It'd be preferable to make our logic work correctly with
|
||||
// infinitely long timeouts.
|
||||
return Some(TimeStamp::NowLoRes() +
|
||||
TimeDuration::FromMilliseconds(31536000.0));
|
||||
return TimeStamp::NowLoRes() +
|
||||
TimeDuration::FromMilliseconds(31536000.0);
|
||||
}
|
||||
|
||||
TimeDuration durationOfTimeout =
|
||||
TimeDuration::FromMilliseconds(double(timeout->AsMilliseconds()));
|
||||
TimeStamp currentFrameEndTime = currentFrameTime + durationOfTimeout;
|
||||
|
||||
return Some(currentFrameEndTime);
|
||||
TimeDuration::FromMilliseconds(double(aCurrentTimeout.AsMilliseconds()));
|
||||
return aState.mCurrentAnimationFrameTime + durationOfTimeout;
|
||||
}
|
||||
|
||||
RefreshResult
|
||||
FrameAnimator::AdvanceFrame(AnimationState& aState,
|
||||
DrawableSurface& aFrames,
|
||||
RawAccessFrameRef& aCurrentFrame,
|
||||
TimeStamp aTime)
|
||||
{
|
||||
NS_ASSERTION(aTime <= TimeStamp::Now(),
|
||||
|
@ -306,13 +296,14 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
|
|||
// the appropriate notification on the main thread. Make sure we stay in sync
|
||||
// with AnimationState.
|
||||
MOZ_ASSERT(nextFrameIndex < aState.KnownFrameCount());
|
||||
RawAccessFrameRef nextFrame = GetRawFrame(aFrames, nextFrameIndex);
|
||||
RawAccessFrameRef nextFrame = aFrames.RawAccessRef(nextFrameIndex);
|
||||
|
||||
// We should always check to see if we have the next frame even if we have
|
||||
// previously finished decoding. If we needed to redecode (e.g. due to a draw
|
||||
// failure) we would have discarded all the old frames and may not yet have
|
||||
// the new ones.
|
||||
if (!nextFrame || !nextFrame->IsFinished()) {
|
||||
// the new ones. DrawableSurface::RawAccessRef promises to only return
|
||||
// finished frames.
|
||||
if (!nextFrame) {
|
||||
// Uh oh, the frame we want to show is currently being decoded (partial).
|
||||
// Similar to the above case, we could be blocked by network or decoding,
|
||||
// and so we should advance our current time rather than risk jumping
|
||||
|
@ -322,11 +313,7 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
|
|||
return ret;
|
||||
}
|
||||
|
||||
Maybe<FrameTimeout> nextFrameTimeout = GetTimeoutForFrame(aState, aFrames, nextFrameIndex);
|
||||
// GetTimeoutForFrame can only return none if frame doesn't exist,
|
||||
// but we just got it above.
|
||||
MOZ_ASSERT(nextFrameTimeout.isSome());
|
||||
if (*nextFrameTimeout == FrameTimeout::Forever()) {
|
||||
if (nextFrame->GetTimeout() == FrameTimeout::Forever()) {
|
||||
ret.mAnimationFinished = true;
|
||||
}
|
||||
|
||||
|
@ -336,15 +323,15 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
|
|||
MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1);
|
||||
|
||||
// Change frame
|
||||
if (!DoBlend(aFrames, &ret.mDirtyRect, currentFrameIndex, nextFrameIndex)) {
|
||||
if (!DoBlend(aCurrentFrame, nextFrame, nextFrameIndex, &ret.mDirtyRect)) {
|
||||
// something went wrong, move on to next
|
||||
NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed");
|
||||
nextFrame->SetCompositingFailed(true);
|
||||
Maybe<TimeStamp> currentFrameEndTime = GetCurrentImgFrameEndTime(aState, aFrames);
|
||||
MOZ_ASSERT(currentFrameEndTime.isSome());
|
||||
aState.mCurrentAnimationFrameTime = *currentFrameEndTime;
|
||||
aState.mCurrentAnimationFrameTime =
|
||||
GetCurrentImgFrameEndTime(aState, aCurrentFrame->GetTimeout());
|
||||
aState.mCurrentAnimationFrameIndex = nextFrameIndex;
|
||||
aState.mCompositedFrameRequested = false;
|
||||
aCurrentFrame = Move(nextFrame);
|
||||
aFrames.Advance(nextFrameIndex);
|
||||
|
||||
return ret;
|
||||
|
@ -353,9 +340,8 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
|
|||
nextFrame->SetCompositingFailed(false);
|
||||
}
|
||||
|
||||
Maybe<TimeStamp> currentFrameEndTime = GetCurrentImgFrameEndTime(aState, aFrames);
|
||||
MOZ_ASSERT(currentFrameEndTime.isSome());
|
||||
aState.mCurrentAnimationFrameTime = *currentFrameEndTime;
|
||||
aState.mCurrentAnimationFrameTime =
|
||||
GetCurrentImgFrameEndTime(aState, aCurrentFrame->GetTimeout());
|
||||
|
||||
// If we can get closer to the current time by a multiple of the image's loop
|
||||
// time, we should. We can only do this if we're done decoding; otherwise, we
|
||||
|
@ -392,6 +378,7 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
|
|||
// Set currentAnimationFrameIndex at the last possible moment
|
||||
aState.mCurrentAnimationFrameIndex = nextFrameIndex;
|
||||
aState.mCompositedFrameRequested = false;
|
||||
aCurrentFrame = Move(nextFrame);
|
||||
aFrames.Advance(nextFrameIndex);
|
||||
|
||||
// If we're here, we successfully advanced the frame.
|
||||
|
@ -451,11 +438,12 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
|
|||
return ret;
|
||||
}
|
||||
|
||||
RawAccessFrameRef currentFrame =
|
||||
result.Surface().RawAccessRef(aState.mCurrentAnimationFrameIndex);
|
||||
|
||||
// only advance the frame if the current time is greater than or
|
||||
// equal to the current frame's end time.
|
||||
Maybe<TimeStamp> currentFrameEndTime =
|
||||
GetCurrentImgFrameEndTime(aState, result.Surface());
|
||||
if (currentFrameEndTime.isNothing()) {
|
||||
if (!currentFrame) {
|
||||
MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable());
|
||||
MOZ_ASSERT(aState.GetHasRequestedDecode() && !aState.GetIsCurrentlyDecoded());
|
||||
MOZ_ASSERT(aState.mCompositedFrameInvalid);
|
||||
|
@ -465,6 +453,9 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
|
|||
return ret;
|
||||
}
|
||||
|
||||
TimeStamp currentFrameEndTime =
|
||||
GetCurrentImgFrameEndTime(aState, currentFrame->GetTimeout());
|
||||
|
||||
// If nothing has accessed the composited frame since the last time we
|
||||
// advanced, then there is no point in continuing to advance the animation.
|
||||
// This has the effect of freezing the animation while not in view.
|
||||
|
@ -473,28 +464,29 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
|
|||
return ret;
|
||||
}
|
||||
|
||||
while (*currentFrameEndTime <= aTime) {
|
||||
TimeStamp oldFrameEndTime = *currentFrameEndTime;
|
||||
while (currentFrameEndTime <= aTime) {
|
||||
TimeStamp oldFrameEndTime = currentFrameEndTime;
|
||||
|
||||
RefreshResult frameRes = AdvanceFrame(aState, result.Surface(), aTime);
|
||||
RefreshResult frameRes = AdvanceFrame(aState, result.Surface(),
|
||||
currentFrame, aTime);
|
||||
|
||||
// Accumulate our result for returning to callers.
|
||||
ret.Accumulate(frameRes);
|
||||
|
||||
currentFrameEndTime = GetCurrentImgFrameEndTime(aState, result.Surface());
|
||||
// AdvanceFrame can't advance to a frame that doesn't exist yet.
|
||||
MOZ_ASSERT(currentFrameEndTime.isSome());
|
||||
// currentFrame was updated by AdvanceFrame so it is still current.
|
||||
currentFrameEndTime =
|
||||
GetCurrentImgFrameEndTime(aState, currentFrame->GetTimeout());
|
||||
|
||||
// If we didn't advance a frame, and our frame end time didn't change,
|
||||
// then we need to break out of this loop & wait for the frame(s)
|
||||
// to finish downloading.
|
||||
if (!frameRes.mFrameAdvanced && (*currentFrameEndTime == oldFrameEndTime)) {
|
||||
if (!frameRes.mFrameAdvanced && currentFrameEndTime == oldFrameEndTime) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Advanced to the correct frame, the composited frame is now valid to be drawn.
|
||||
if (*currentFrameEndTime > aTime) {
|
||||
if (currentFrameEndTime > aTime) {
|
||||
aState.mCompositedFrameInvalid = false;
|
||||
ret.mDirtyRect = IntRect(IntPoint(0,0), mSize);
|
||||
}
|
||||
|
@ -509,6 +501,13 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState)
|
|||
{
|
||||
aState.mCompositedFrameRequested = true;
|
||||
|
||||
// If we have a composited version of this frame, return that.
|
||||
if (!aState.mCompositedFrameInvalid && mLastCompositedFrameIndex >= 0 &&
|
||||
(uint32_t(mLastCompositedFrameIndex) == aState.mCurrentAnimationFrameIndex)) {
|
||||
return LookupResult(DrawableSurface(mCompositingFrame->DrawableRef()),
|
||||
MatchType::EXACT);
|
||||
}
|
||||
|
||||
LookupResult result =
|
||||
SurfaceCache::Lookup(ImageKey(mImage),
|
||||
RasterSurfaceKey(mSize,
|
||||
|
@ -525,13 +524,6 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState)
|
|||
return LookupResult(MatchType::PENDING);
|
||||
}
|
||||
|
||||
// If we have a composited version of this frame, return that.
|
||||
if (mLastCompositedFrameIndex >= 0 &&
|
||||
(uint32_t(mLastCompositedFrameIndex) == aState.mCurrentAnimationFrameIndex)) {
|
||||
return LookupResult(DrawableSurface(mCompositingFrame->DrawableRef()),
|
||||
MatchType::EXACT);
|
||||
}
|
||||
|
||||
// Otherwise return the raw frame. DoBlend is required to ensure that we only
|
||||
// hit this case if the frame is not paletted and doesn't require compositing.
|
||||
if (!result) {
|
||||
|
@ -553,21 +545,6 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState)
|
|||
return result;
|
||||
}
|
||||
|
||||
Maybe<FrameTimeout>
|
||||
FrameAnimator::GetTimeoutForFrame(AnimationState& aState,
|
||||
DrawableSurface& aFrames,
|
||||
uint32_t aFrameNum) const
|
||||
{
|
||||
RawAccessFrameRef frame = GetRawFrame(aFrames, aFrameNum);
|
||||
if (frame) {
|
||||
AnimationData data = frame->GetAnimationData();
|
||||
return Some(data.mTimeout);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aState.mHasRequestedDecode && !aState.mIsCurrentlyDecoded);
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
static void
|
||||
DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface,
|
||||
SurfaceMemoryCounterType aType,
|
||||
|
@ -615,64 +592,44 @@ FrameAnimator::CollectSizeOfCompositingSurfaces(
|
|||
}
|
||||
}
|
||||
|
||||
RawAccessFrameRef
|
||||
FrameAnimator::GetRawFrame(DrawableSurface& aFrames, uint32_t aFrameNum) const
|
||||
{
|
||||
// Seek to the frame we want. If seeking fails, it means we couldn't get the
|
||||
// frame we're looking for, so we bail here to avoid returning the wrong frame
|
||||
// to the caller.
|
||||
if (NS_FAILED(aFrames.Seek(aFrameNum))) {
|
||||
return RawAccessFrameRef(); // Not available yet.
|
||||
}
|
||||
|
||||
return aFrames->RawAccessRef();
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// DoBlend gets called when the timer for animation get fired and we have to
|
||||
// update the composited frame of the animation.
|
||||
bool
|
||||
FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
||||
IntRect* aDirtyRect,
|
||||
uint32_t aPrevFrameIndex,
|
||||
uint32_t aNextFrameIndex)
|
||||
FrameAnimator::DoBlend(const RawAccessFrameRef& aPrevFrame,
|
||||
const RawAccessFrameRef& aNextFrame,
|
||||
uint32_t aNextFrameIndex,
|
||||
IntRect* aDirtyRect)
|
||||
{
|
||||
RawAccessFrameRef prevFrame = GetRawFrame(aFrames, aPrevFrameIndex);
|
||||
RawAccessFrameRef nextFrame = GetRawFrame(aFrames, aNextFrameIndex);
|
||||
MOZ_ASSERT(aPrevFrame && aNextFrame, "Should have frames here");
|
||||
|
||||
MOZ_ASSERT(prevFrame && nextFrame, "Should have frames here");
|
||||
|
||||
AnimationData prevFrameData = prevFrame->GetAnimationData();
|
||||
if (prevFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS &&
|
||||
DisposalMethod prevDisposalMethod = aPrevFrame->GetDisposalMethod();
|
||||
bool prevHasAlpha = aPrevFrame->FormatHasAlpha();
|
||||
if (prevDisposalMethod == DisposalMethod::RESTORE_PREVIOUS &&
|
||||
!mCompositingPrevFrame) {
|
||||
prevFrameData.mDisposalMethod = DisposalMethod::CLEAR;
|
||||
prevDisposalMethod = DisposalMethod::CLEAR;
|
||||
}
|
||||
|
||||
IntRect prevRect = prevFrameData.mBlendRect
|
||||
? prevFrameData.mRect.Intersect(*prevFrameData.mBlendRect)
|
||||
: prevFrameData.mRect;
|
||||
|
||||
IntRect prevRect = aPrevFrame->GetBoundedBlendRect();
|
||||
bool isFullPrevFrame = prevRect.IsEqualRect(0, 0, mSize.width, mSize.height);
|
||||
|
||||
// Optimization: DisposeClearAll if the previous frame is the same size as
|
||||
// container and it's clearing itself
|
||||
if (isFullPrevFrame &&
|
||||
(prevFrameData.mDisposalMethod == DisposalMethod::CLEAR)) {
|
||||
prevFrameData.mDisposalMethod = DisposalMethod::CLEAR_ALL;
|
||||
(prevDisposalMethod == DisposalMethod::CLEAR)) {
|
||||
prevDisposalMethod = DisposalMethod::CLEAR_ALL;
|
||||
}
|
||||
|
||||
AnimationData nextFrameData = nextFrame->GetAnimationData();
|
||||
|
||||
IntRect nextRect = nextFrameData.mBlendRect
|
||||
? nextFrameData.mRect.Intersect(*nextFrameData.mBlendRect)
|
||||
: nextFrameData.mRect;
|
||||
DisposalMethod nextDisposalMethod = aNextFrame->GetDisposalMethod();
|
||||
bool nextHasAlpha = aNextFrame->FormatHasAlpha();
|
||||
|
||||
IntRect nextRect = aNextFrame->GetBoundedBlendRect();
|
||||
bool isFullNextFrame = nextRect.IsEqualRect(0, 0, mSize.width, mSize.height);
|
||||
|
||||
if (!nextFrame->GetIsPaletted()) {
|
||||
if (!aNextFrame->GetIsPaletted()) {
|
||||
// Optimization: Skip compositing if the previous frame wants to clear the
|
||||
// whole image
|
||||
if (prevFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL) {
|
||||
if (prevDisposalMethod == DisposalMethod::CLEAR_ALL) {
|
||||
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
|
||||
return true;
|
||||
}
|
||||
|
@ -680,15 +637,15 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
|||
// Optimization: Skip compositing if this frame is the same size as the
|
||||
// container and it's fully drawing over prev frame (no alpha)
|
||||
if (isFullNextFrame &&
|
||||
(nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) &&
|
||||
!nextFrameData.mHasAlpha) {
|
||||
(nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) &&
|
||||
!nextHasAlpha) {
|
||||
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate area that needs updating
|
||||
switch (prevFrameData.mDisposalMethod) {
|
||||
switch (prevDisposalMethod) {
|
||||
default:
|
||||
MOZ_FALLTHROUGH_ASSERT("Unexpected DisposalMethod");
|
||||
case DisposalMethod::NOT_SPECIFIED:
|
||||
|
@ -705,7 +662,7 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
|||
// Calc area that needs to be redrawn (the combination of previous and
|
||||
// this frame)
|
||||
// XXX - This could be done with multiple framechanged calls
|
||||
// Having prevFrame way at the top of the image, and nextFrame
|
||||
// Having aPrevFrame way at the top of the image, and aNextFrame
|
||||
// way at the bottom, and both frames being small, we'd be
|
||||
// telling framechanged to refresh the whole image when only two
|
||||
// small areas are needed.
|
||||
|
@ -747,8 +704,6 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
|||
needToBlankComposite = true;
|
||||
}
|
||||
|
||||
AnimationData compositingFrameData = mCompositingFrame->GetAnimationData();
|
||||
|
||||
// More optimizations possible when next frame is not transparent
|
||||
// But if the next frame has DisposalMethod::RESTORE_PREVIOUS,
|
||||
// this "no disposal" optimization is not possible,
|
||||
|
@ -756,8 +711,7 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
|||
// needs to be stored in compositingFrame, so it can be
|
||||
// copied into compositingPrevFrame later.
|
||||
bool doDisposal = true;
|
||||
if (!nextFrameData.mHasAlpha &&
|
||||
nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) {
|
||||
if (!nextHasAlpha && nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) {
|
||||
if (isFullNextFrame) {
|
||||
// Optimization: No need to dispose prev.frame when
|
||||
// next frame is full frame and not transparent.
|
||||
|
@ -777,46 +731,42 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
|||
|
||||
if (doDisposal) {
|
||||
// Dispose of previous: clear, restore, or keep (copy)
|
||||
switch (prevFrameData.mDisposalMethod) {
|
||||
switch (prevDisposalMethod) {
|
||||
case DisposalMethod::CLEAR:
|
||||
if (needToBlankComposite) {
|
||||
// If we just created the composite, it could have anything in its
|
||||
// buffer. Clear whole frame
|
||||
ClearFrame(compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect);
|
||||
ClearFrame(mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect());
|
||||
} else {
|
||||
// Only blank out previous frame area (both color & Mask/Alpha)
|
||||
ClearFrame(compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect,
|
||||
ClearFrame(mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect(),
|
||||
prevRect);
|
||||
}
|
||||
break;
|
||||
|
||||
case DisposalMethod::CLEAR_ALL:
|
||||
ClearFrame(compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect);
|
||||
ClearFrame(mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect());
|
||||
break;
|
||||
|
||||
case DisposalMethod::RESTORE_PREVIOUS:
|
||||
// It would be better to copy only the area changed back to
|
||||
// compositingFrame.
|
||||
if (mCompositingPrevFrame) {
|
||||
AnimationData compositingPrevFrameData =
|
||||
mCompositingPrevFrame->GetAnimationData();
|
||||
|
||||
CopyFrameImage(compositingPrevFrameData.mRawData,
|
||||
compositingPrevFrameData.mRect,
|
||||
compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect);
|
||||
CopyFrameImage(mCompositingPrevFrame.Data(),
|
||||
mCompositingPrevFrame->GetRect(),
|
||||
mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect());
|
||||
|
||||
// destroy only if we don't need it for this frame's disposal
|
||||
if (nextFrameData.mDisposalMethod !=
|
||||
DisposalMethod::RESTORE_PREVIOUS) {
|
||||
if (nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) {
|
||||
mCompositingPrevFrame.reset();
|
||||
}
|
||||
} else {
|
||||
ClearFrame(compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect);
|
||||
ClearFrame(mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -832,44 +782,44 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
|||
// Note: Frame 1 never gets into DoBlend(), so (aNextFrameIndex - 1)
|
||||
// will always be a valid frame number.
|
||||
if (mLastCompositedFrameIndex != int32_t(aNextFrameIndex - 1)) {
|
||||
if (isFullPrevFrame && !prevFrame->GetIsPaletted()) {
|
||||
if (isFullPrevFrame && !aPrevFrame->GetIsPaletted()) {
|
||||
// Just copy the bits
|
||||
CopyFrameImage(prevFrameData.mRawData,
|
||||
CopyFrameImage(aPrevFrame.Data(),
|
||||
prevRect,
|
||||
compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect);
|
||||
mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect());
|
||||
} else {
|
||||
if (needToBlankComposite) {
|
||||
// Only blank composite when prev is transparent or not full.
|
||||
if (prevFrameData.mHasAlpha || !isFullPrevFrame) {
|
||||
ClearFrame(compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect);
|
||||
if (prevHasAlpha || !isFullPrevFrame) {
|
||||
ClearFrame(mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect());
|
||||
}
|
||||
}
|
||||
DrawFrameTo(prevFrameData.mRawData, prevFrameData.mRect,
|
||||
prevFrameData.mPaletteDataLength,
|
||||
prevFrameData.mHasAlpha,
|
||||
compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect,
|
||||
prevFrameData.mBlendMethod,
|
||||
prevFrameData.mBlendRect);
|
||||
DrawFrameTo(aPrevFrame.Data(), aPrevFrame->GetRect(),
|
||||
aPrevFrame.PaletteDataLength(),
|
||||
prevHasAlpha,
|
||||
mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect(),
|
||||
aPrevFrame->GetBlendMethod(),
|
||||
aPrevFrame->GetBlendRect());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (needToBlankComposite) {
|
||||
// If we just created the composite, it could have anything in its
|
||||
// buffers. Clear them
|
||||
ClearFrame(compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect);
|
||||
ClearFrame(mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect());
|
||||
}
|
||||
|
||||
// Check if the frame we are composing wants the previous image restored after
|
||||
// it is done. Don't store it (again) if last frame wanted its image restored
|
||||
// too
|
||||
if ((nextFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) &&
|
||||
(prevFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) {
|
||||
if ((nextDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) &&
|
||||
(prevDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) {
|
||||
// We are storing the whole image.
|
||||
// It would be better if we just stored the area that nextFrame is going to
|
||||
// It would be better if we just stored the area that aNextFrame is going to
|
||||
// overwrite.
|
||||
if (!mCompositingPrevFrame) {
|
||||
RefPtr<imgFrame> newFrame = new imgFrame;
|
||||
|
@ -883,25 +833,22 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
|
|||
mCompositingPrevFrame = newFrame->RawAccessRef();
|
||||
}
|
||||
|
||||
AnimationData compositingPrevFrameData =
|
||||
mCompositingPrevFrame->GetAnimationData();
|
||||
|
||||
CopyFrameImage(compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect,
|
||||
compositingPrevFrameData.mRawData,
|
||||
compositingPrevFrameData.mRect);
|
||||
CopyFrameImage(mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect(),
|
||||
mCompositingPrevFrame.Data(),
|
||||
mCompositingPrevFrame->GetRect());
|
||||
|
||||
mCompositingPrevFrame->Finish();
|
||||
}
|
||||
|
||||
// blit next frame into it's correct spot
|
||||
DrawFrameTo(nextFrameData.mRawData, nextFrameData.mRect,
|
||||
nextFrameData.mPaletteDataLength,
|
||||
nextFrameData.mHasAlpha,
|
||||
compositingFrameData.mRawData,
|
||||
compositingFrameData.mRect,
|
||||
nextFrameData.mBlendMethod,
|
||||
nextFrameData.mBlendRect);
|
||||
DrawFrameTo(aNextFrame.Data(), aNextFrame->GetRect(),
|
||||
aNextFrame.PaletteDataLength(),
|
||||
nextHasAlpha,
|
||||
mCompositingFrame.Data(),
|
||||
mCompositingFrame->GetRect(),
|
||||
aNextFrame->GetBlendMethod(),
|
||||
aNextFrame->GetBlendRect());
|
||||
|
||||
// Tell the image that it is fully 'downloaded'.
|
||||
mCompositingFrame->Finish();
|
||||
|
@ -970,7 +917,7 @@ nsresult
|
|||
FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect,
|
||||
uint32_t aSrcPaletteLength, bool aSrcHasAlpha,
|
||||
uint8_t* aDstPixels, const IntRect& aDstRect,
|
||||
BlendMethod aBlendMethod, const Maybe<IntRect>& aBlendRect)
|
||||
BlendMethod aBlendMethod, const IntRect& aBlendRect)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aSrcData);
|
||||
NS_ENSURE_ARG_POINTER(aDstPixels);
|
||||
|
@ -1067,8 +1014,8 @@ FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect,
|
|||
auto op = aBlendMethod == BlendMethod::SOURCE ? PIXMAN_OP_SRC
|
||||
: PIXMAN_OP_OVER;
|
||||
|
||||
if (aBlendMethod == BlendMethod::OVER || !aBlendRect ||
|
||||
(aBlendMethod == BlendMethod::SOURCE && aSrcRect.IsEqualEdges(*aBlendRect))) {
|
||||
if (aBlendMethod == BlendMethod::OVER ||
|
||||
(aBlendMethod == BlendMethod::SOURCE && aSrcRect.IsEqualEdges(aBlendRect))) {
|
||||
// We don't need to do anything clever. (Or, in the case where no blend
|
||||
// rect was specified, we can't.)
|
||||
pixman_image_composite32(op,
|
||||
|
@ -1093,10 +1040,10 @@ FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect,
|
|||
src,
|
||||
nullptr,
|
||||
dst,
|
||||
aBlendRect->X(), aBlendRect->Y(),
|
||||
aBlendRect.X(), aBlendRect.Y(),
|
||||
0, 0,
|
||||
aBlendRect->X(), aBlendRect->Y(),
|
||||
aBlendRect->Width(), aBlendRect->Height());
|
||||
aBlendRect.X(), aBlendRect.Y(),
|
||||
aBlendRect.Width(), aBlendRect.Height());
|
||||
}
|
||||
|
||||
pixman_image_unref(src);
|
||||
|
|
|
@ -343,37 +343,31 @@ private: // methods
|
|||
* @param aTime the time that the animation should advance to. This will
|
||||
* typically be <= TimeStamp::Now().
|
||||
*
|
||||
* @param aCurrentFrame the currently displayed frame of the animation. If
|
||||
* we advance, it will replace aCurrentFrame with the
|
||||
* new current frame we advanced to.
|
||||
*
|
||||
* @returns a RefreshResult that shows whether the frame was successfully
|
||||
* advanced, and its resulting dirty rect.
|
||||
*/
|
||||
RefreshResult AdvanceFrame(AnimationState& aState,
|
||||
DrawableSurface& aFrames,
|
||||
RawAccessFrameRef& aCurrentFrame,
|
||||
TimeStamp aTime);
|
||||
|
||||
/**
|
||||
* Get the @aIndex-th frame in the frame index, ignoring results of blending.
|
||||
*/
|
||||
RawAccessFrameRef GetRawFrame(DrawableSurface& aFrames,
|
||||
uint32_t aFrameNum) const;
|
||||
|
||||
/// @return the given frame's timeout if it is available
|
||||
Maybe<FrameTimeout> GetTimeoutForFrame(AnimationState& aState,
|
||||
DrawableSurface& aFrames,
|
||||
uint32_t aFrameNum) const;
|
||||
|
||||
/**
|
||||
* Get the time the frame we're currently displaying is supposed to end.
|
||||
*
|
||||
* In the error case (like if the requested frame is not currently
|
||||
* decoded), returns None().
|
||||
*/
|
||||
Maybe<TimeStamp> GetCurrentImgFrameEndTime(AnimationState& aState,
|
||||
DrawableSurface& aFrames) const;
|
||||
TimeStamp GetCurrentImgFrameEndTime(AnimationState& aState,
|
||||
FrameTimeout aCurrentTimeout) const;
|
||||
|
||||
bool DoBlend(DrawableSurface& aFrames,
|
||||
gfx::IntRect* aDirtyRect,
|
||||
uint32_t aPrevFrameIndex,
|
||||
uint32_t aNextFrameIndex);
|
||||
bool DoBlend(const RawAccessFrameRef& aPrevFrame,
|
||||
const RawAccessFrameRef& aNextFrame,
|
||||
uint32_t aNextFrameIndex,
|
||||
gfx::IntRect* aDirtyRect);
|
||||
|
||||
/** Clears an area of <aFrame> with transparent black.
|
||||
*
|
||||
|
@ -413,7 +407,7 @@ private: // methods
|
|||
uint32_t aSrcPaletteLength, bool aSrcHasAlpha,
|
||||
uint8_t* aDstPixels, const gfx::IntRect& aDstRect,
|
||||
BlendMethod aBlendMethod,
|
||||
const Maybe<gfx::IntRect>& aBlendRect);
|
||||
const gfx::IntRect& aBlendRect);
|
||||
|
||||
private: // data
|
||||
//! A weak pointer to our owning image.
|
||||
|
|
|
@ -110,6 +110,15 @@ protected:
|
|||
/// index of the desired frame.
|
||||
virtual DrawableFrameRef DrawableRef(size_t aFrame) = 0;
|
||||
|
||||
/// @return an eagerly computed raw access reference to a surface. For
|
||||
/// dynamically generated animation surfaces, @aFrame specifies the 0-based
|
||||
/// index of the desired frame.
|
||||
virtual RawAccessFrameRef RawAccessRef(size_t aFrame)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Surface provider does not support raw access!");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
/// @return true if this ISurfaceProvider is locked. (@see SetLocked())
|
||||
/// Should only be called from SurfaceCache code as it relies on SurfaceCache
|
||||
/// for synchronization.
|
||||
|
@ -199,6 +208,18 @@ public:
|
|||
return mDrawableRef ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RawAccessFrameRef RawAccessRef(size_t aFrame)
|
||||
{
|
||||
MOZ_ASSERT(mHaveSurface, "Trying to get on an empty DrawableSurface?");
|
||||
|
||||
if (!mProvider) {
|
||||
MOZ_ASSERT_UNREACHABLE("Trying to get on a static DrawableSurface?");
|
||||
return RawAccessFrameRef();
|
||||
}
|
||||
|
||||
return mProvider->RawAccessRef(aFrame);
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (!mProvider) {
|
||||
|
|
|
@ -70,7 +70,7 @@ public:
|
|||
{ }
|
||||
|
||||
template <typename... Rest>
|
||||
nsresult Configure(const DeinterlacingConfig<PixelType>& aConfig, Rest... aRest)
|
||||
nsresult Configure(const DeinterlacingConfig<PixelType>& aConfig, const Rest&... aRest)
|
||||
{
|
||||
nsresult rv = mNext.Configure(aRest...);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -360,7 +360,7 @@ public:
|
|||
{ }
|
||||
|
||||
template <typename... Rest>
|
||||
nsresult Configure(const RemoveFrameRectConfig& aConfig, Rest... aRest)
|
||||
nsresult Configure(const RemoveFrameRectConfig& aConfig, const Rest&... aRest)
|
||||
{
|
||||
nsresult rv = mNext.Configure(aRest...);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
@ -590,7 +590,7 @@ public:
|
|||
{ }
|
||||
|
||||
template <typename... Rest>
|
||||
nsresult Configure(const ADAM7InterpolatingConfig& aConfig, Rest... aRest)
|
||||
nsresult Configure(const ADAM7InterpolatingConfig& aConfig, const Rest&... aRest)
|
||||
{
|
||||
nsresult rv = mNext.Configure(aRest...);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -75,10 +75,11 @@ SurfaceSink::Configure(const SurfaceConfig& aConfig)
|
|||
// XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
|
||||
// to allocate the frame directly here and get rid of Decoder::AllocateFrame
|
||||
// altogether.
|
||||
nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum,
|
||||
surfaceSize,
|
||||
nsresult rv = aConfig.mDecoder->AllocateFrame(surfaceSize,
|
||||
frameRect,
|
||||
aConfig.mFormat);
|
||||
aConfig.mFormat,
|
||||
/* aPaletteDepth */ 0,
|
||||
aConfig.mAnimParams);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -127,11 +128,11 @@ PalettedSurfaceSink::Configure(const PalettedSurfaceConfig& aConfig)
|
|||
// XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
|
||||
// to allocate the frame directly here and get rid of Decoder::AllocateFrame
|
||||
// altogether.
|
||||
nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum,
|
||||
aConfig.mOutputSize,
|
||||
nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mOutputSize,
|
||||
aConfig.mFrameRect,
|
||||
aConfig.mFormat,
|
||||
aConfig.mPaletteDepth);
|
||||
aConfig.mPaletteDepth,
|
||||
aConfig.mAnimParams);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "mozilla/Variant.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
||||
#include "AnimationParams.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
|
@ -775,10 +777,10 @@ struct SurfaceConfig
|
|||
{
|
||||
using Filter = SurfaceSink;
|
||||
Decoder* mDecoder; /// Which Decoder to use to allocate the surface.
|
||||
uint32_t mFrameNum; /// Which frame of animation this surface is for.
|
||||
gfx::IntSize mOutputSize; /// The size of the surface.
|
||||
gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX).
|
||||
bool mFlipVertically; /// If true, write the rows from bottom to top.
|
||||
Maybe<AnimationParams> mAnimParams; /// Given for animated images.
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -803,12 +805,12 @@ struct PalettedSurfaceConfig
|
|||
{
|
||||
using Filter = PalettedSurfaceSink;
|
||||
Decoder* mDecoder; /// Which Decoder to use to allocate the surface.
|
||||
uint32_t mFrameNum; /// Which frame of animation this surface is for.
|
||||
gfx::IntSize mOutputSize; /// The logical size of the surface.
|
||||
gfx::IntRect mFrameRect; /// The surface subrect which contains data.
|
||||
gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX).
|
||||
uint8_t mPaletteDepth; /// The palette depth of this surface.
|
||||
bool mFlipVertically; /// If true, write the rows from bottom to top.
|
||||
Maybe<AnimationParams> mAnimParams; /// Given for animated images.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,8 +70,6 @@ public:
|
|||
*
|
||||
* @param aDecoder The decoder whose current frame the SurfacePipe will write
|
||||
* to.
|
||||
* @param aFrameNum Which frame the SurfacePipe will write to. This will be 0
|
||||
* for non-animated images.
|
||||
* @param aInputSize The original size of the image.
|
||||
* @param aOutputSize The size the SurfacePipe should output. Must be the same
|
||||
* as @aInputSize or smaller. If smaller, the image will be
|
||||
|
@ -79,6 +77,7 @@ public:
|
|||
* @param aFrameRect The portion of the image that actually contains data.
|
||||
* @param aFormat The surface format of the image; generally B8G8R8A8 or
|
||||
* B8G8R8X8.
|
||||
* @param aAnimParams Extra parameters used by animated images.
|
||||
* @param aFlags Flags enabling or disabling various functionality for the
|
||||
* SurfacePipe; see the SurfacePipeFlags documentation for more
|
||||
* information.
|
||||
|
@ -89,11 +88,11 @@ public:
|
|||
*/
|
||||
static Maybe<SurfacePipe>
|
||||
CreateSurfacePipe(Decoder* aDecoder,
|
||||
uint32_t aFrameNum,
|
||||
const nsIntSize& aInputSize,
|
||||
const nsIntSize& aOutputSize,
|
||||
const nsIntRect& aFrameRect,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const Maybe<AnimationParams>& aAnimParams,
|
||||
SurfacePipeFlags aFlags)
|
||||
{
|
||||
const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE);
|
||||
|
@ -125,8 +124,8 @@ public:
|
|||
ADAM7InterpolatingConfig interpolatingConfig;
|
||||
RemoveFrameRectConfig removeFrameRectConfig { aFrameRect };
|
||||
DownscalingConfig downscalingConfig { aInputSize, aFormat };
|
||||
SurfaceConfig surfaceConfig { aDecoder, aFrameNum, aOutputSize,
|
||||
aFormat, flipVertically };
|
||||
SurfaceConfig surfaceConfig { aDecoder, aOutputSize, aFormat,
|
||||
flipVertically, aAnimParams };
|
||||
|
||||
Maybe<SurfacePipe> pipe;
|
||||
|
||||
|
@ -181,13 +180,12 @@ public:
|
|||
*
|
||||
* @param aDecoder The decoder whose current frame the SurfacePipe will write
|
||||
* to.
|
||||
* @param aFrameNum Which frame the SurfacePipe will write to. This will be 0
|
||||
* for non-animated images.
|
||||
* @param aInputSize The original size of the image.
|
||||
* @param aFrameRect The portion of the image that actually contains data.
|
||||
* @param aFormat The surface format of the image; generally B8G8R8A8 or
|
||||
* B8G8R8X8.
|
||||
* @param aPaletteDepth The palette depth of the image.
|
||||
* @param aAnimParams Extra parameters used by animated images.
|
||||
* @param aFlags Flags enabling or disabling various functionality for the
|
||||
* SurfacePipe; see the SurfacePipeFlags documentation for more
|
||||
* information.
|
||||
|
@ -198,11 +196,11 @@ public:
|
|||
*/
|
||||
static Maybe<SurfacePipe>
|
||||
CreatePalettedSurfacePipe(Decoder* aDecoder,
|
||||
uint32_t aFrameNum,
|
||||
const nsIntSize& aInputSize,
|
||||
const nsIntRect& aFrameRect,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth,
|
||||
const Maybe<AnimationParams>& aAnimParams,
|
||||
SurfacePipeFlags aFlags)
|
||||
{
|
||||
const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE);
|
||||
|
@ -211,9 +209,9 @@ public:
|
|||
|
||||
// Construct configurations for the SurfaceFilters.
|
||||
DeinterlacingConfig<uint8_t> deinterlacingConfig { progressiveDisplay };
|
||||
PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aFrameNum, aInputSize,
|
||||
aFrameRect, aFormat, aPaletteDepth,
|
||||
flipVertically };
|
||||
PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aInputSize, aFrameRect,
|
||||
aFormat, aPaletteDepth,
|
||||
flipVertically, aAnimParams };
|
||||
|
||||
Maybe<SurfacePipe> pipe;
|
||||
|
||||
|
@ -229,7 +227,7 @@ public:
|
|||
private:
|
||||
template <typename... Configs>
|
||||
static Maybe<SurfacePipe>
|
||||
MakePipe(Configs... aConfigs)
|
||||
MakePipe(const Configs&... aConfigs)
|
||||
{
|
||||
auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>();
|
||||
nsresult rv = pipe->Configure(aConfigs...);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче