Merge inbound to mozilla-central. a=merge

This commit is contained in:
Noemi Erli 2018-05-30 00:41:41 +03:00
Родитель 6954584948 5dc0c9ea8e
Коммит 846f00f83f
1954 изменённых файлов: 25541 добавлений и 337622 удалений

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

@ -115,3 +115,6 @@ jobs:
mozilla-central: mozilla-central:
- {weekday: 'Monday', hour: 10, minute: 0} - {weekday: 'Monday', hour: 10, minute: 0}
- {weekday: 'Thursday', 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("// computedStyle( ")
cpp_quote("// /* [in] */ unsigned short maxStyleProperties,") cpp_quote("// /* [in] */ unsigned short maxStyleProperties,")
cpp_quote("// /* [out] */ unsigned short *numStyleProperties, ") 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 *styleProperties, ")
cpp_quote("// /* [out] */ BSTR *styleValues);") cpp_quote("// /* [out] */ BSTR *styleValues);")
cpp_quote("// ---------------------------------------------------------------------------------------------------=") cpp_quote("// ---------------------------------------------------------------------------------------------------=")
@ -52,7 +52,7 @@ cpp_quote("// useAlternateView=TRUE: properties for media types set w/ nsIDOMSi
cpp_quote("//") cpp_quote("//")
cpp_quote("// computedStyleForProperties( ") cpp_quote("// computedStyleForProperties( ")
cpp_quote("// /* [in] */ unsigned short numStyleProperties, ") 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("// /* [in] */ BSTR *styleProperties, ")
cpp_quote("// /* [out] */ BSTR *styleValues);") cpp_quote("// /* [out] */ BSTR *styleValues);")
cpp_quote("// ---------------------------------------------------------------------------------------------------=") cpp_quote("// ---------------------------------------------------------------------------------------------------=")
@ -141,7 +141,7 @@ interface ISimpleDOMNode : IUnknown
[propget] HRESULT computedStyle( [propget] HRESULT computedStyle(
[in] unsigned short maxStyleProperties, [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 *styleProperties,
[out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleValues, [out, size_is(maxStyleProperties), length_is(*numStyleProperties)] BSTR *styleValues,
[out, retval] unsigned short *numStyleProperties [out, retval] unsigned short *numStyleProperties
@ -149,7 +149,7 @@ interface ISimpleDOMNode : IUnknown
[propget] HRESULT computedStyleForProperties( [propget] HRESULT computedStyleForProperties(
[in] unsigned short numStyleProperties, [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, [in, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleProperties,
[out, retval, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleValues [out, retval, size_is(numStyleProperties), length_is(numStyleProperties)] BSTR *styleValues
); );

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

@ -44,7 +44,6 @@ const nsIAccessibleValue = Ci.nsIAccessibleValue;
const nsIObserverService = Ci.nsIObserverService; const nsIObserverService = Ci.nsIObserverService;
const nsIDOMDocument = Ci.nsIDOMDocument;
const nsIDOMNode = Ci.nsIDOMNode; const nsIDOMNode = Ci.nsIDOMNode;
const nsIDOMWindow = Ci.nsIDOMWindow; const nsIDOMWindow = Ci.nsIDOMWindow;

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

@ -1062,7 +1062,7 @@ function synthClick(aNodeOrID, aCheckerOrEventSeq, aArgs) {
this.invoke = function synthClick_invoke() { this.invoke = function synthClick_invoke() {
var targetNode = this.DOMNode; var targetNode = this.DOMNode;
if (targetNode instanceof nsIDOMDocument) { if (targetNode.nodeType == targetNode.DOCUMENT_NODE) {
targetNode = targetNode =
this.DOMNode.body ? this.DOMNode.body : this.DOMNode.documentElement; 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", // is(docAcc.docType, "HTML",
// "Wrong type of document!"); // "Wrong type of document!");
// Test for correct nsIDOMDocument retrieval. // Test for correct Document retrieval.
var domDoc = null; var domDoc = null;
try { try {
domDoc = docAcc.DOMDocument.QueryInterface(nsIDOMDocument); domDoc = docAcc.DOMDocument;
} catch (e) {} } 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!"); is(domDoc, document, "Document nodes do not match!");
// Test for correct nsIDOMWindow retrieval. // Test for correct nsIDOMWindow retrieval.

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

@ -588,12 +588,8 @@ var AboutNetAndCertErrorListener = {
}, },
handleEvent(aEvent) { handleEvent(aEvent) {
let doc; // Documents have a null ownerDocument.
if (aEvent.originalTarget instanceof Ci.nsIDOMDocument) { let doc = aEvent.originalTarget.ownerDocument || aEvent.originalTarget;
doc = aEvent.originalTarget;
} else {
doc = aEvent.originalTarget.ownerDocument;
}
if (!this.isAboutNetError(doc) && !this.isAboutCertError(doc)) { if (!this.isAboutNetError(doc) && !this.isAboutCertError(doc)) {
return; return;

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

@ -74,7 +74,7 @@ function focusInChild() {
var id; var id;
if (event.target instanceof Ci.nsIDOMWindow) if (event.target instanceof Ci.nsIDOMWindow)
id = getWindowDocId(event.originalTarget) + "-window"; 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"; id = getWindowDocId(event.originalTarget) + "-document";
else else
id = event.originalTarget.id; id = event.originalTarget.id;

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

@ -966,8 +966,8 @@ this.tabs = class extends ExtensionAPI {
let browser = event.originalTarget; let browser = event.originalTarget;
// For non-remote browsers, this event is dispatched on the document // For non-remote browsers, this event is dispatched on the document
// rather than on the <browser>. // rather than on the <browser>. But either way we have a node here.
if (browser instanceof Ci.nsIDOMDocument) { if (browser.nodeType == browser.DOCUMENT_NODE) {
browser = browser.docShell.chromeEventHandler; browser = browser.docShell.chromeEventHandler;
} }

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

@ -1,5 +1,5 @@
This is the PDF.js project output, https://github.com/mozilla/pdf.js 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"; "use strict";
var pdfjsVersion = '2.0.506'; var pdfjsVersion = '2.0.517';
var pdfjsBuild = 'b7a3a5e7'; var pdfjsBuild = '7cd6c0fb';
var pdfjsSharedUtil = __w_pdfjs_require__(0); var pdfjsSharedUtil = __w_pdfjs_require__(0);
var pdfjsDisplayAPI = __w_pdfjs_require__(9); var pdfjsDisplayAPI = __w_pdfjs_require__(9);
var pdfjsDisplayTextLayer = __w_pdfjs_require__(17); var pdfjsDisplayTextLayer = __w_pdfjs_require__(17);
@ -4929,7 +4929,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
} }
return worker.messageHandler.sendWithPromise('GetDocRequest', { return worker.messageHandler.sendWithPromise('GetDocRequest', {
docId, docId,
apiVersion: '2.0.506', apiVersion: '2.0.517',
source: { source: {
data: source.data, data: source.data,
url: source.url, url: source.url,
@ -6252,8 +6252,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() {
}(); }();
var version, build; var version, build;
{ {
exports.version = version = '2.0.506'; exports.version = version = '2.0.517';
exports.build = build = 'b7a3a5e7'; exports.build = build = '7cd6c0fb';
} }
exports.getDocument = getDocument; exports.getDocument = getDocument;
exports.LoopbackPort = LoopbackPort; exports.LoopbackPort = LoopbackPort;

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

@ -21103,8 +21103,8 @@ exports.PostScriptCompiler = PostScriptCompiler;
"use strict"; "use strict";
var pdfjsVersion = '2.0.506'; var pdfjsVersion = '2.0.517';
var pdfjsBuild = 'b7a3a5e7'; var pdfjsBuild = '7cd6c0fb';
var pdfjsCoreWorker = __w_pdfjs_require__(20); var pdfjsCoreWorker = __w_pdfjs_require__(20);
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
@ -21305,7 +21305,7 @@ var WorkerMessageHandler = {
var cancelXHRs = null; var cancelXHRs = null;
var WorkerTasks = []; var WorkerTasks = [];
let apiVersion = docParams.apiVersion; let apiVersion = docParams.apiVersion;
let workerVersion = '2.0.506'; let workerVersion = '2.0.517';
if (apiVersion !== null && apiVersion !== workerVersion) { if (apiVersion !== null && apiVersion !== workerVersion) {
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${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(); var glyph = this.getToken();
length = this.readInt(); length = this.readInt();
this.getToken(); this.getToken();
data = stream.makeSubStream(stream.pos, length); data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
lenIV = program.properties.privateData['lenIV']; lenIV = program.properties.privateData['lenIV'];
encoded = this.readCharStrings(data.getBytes(), lenIV); encoded = this.readCharStrings(data, lenIV);
stream.skip(length);
this.nextChar(); this.nextChar();
token = this.getToken(); token = this.getToken();
if (token === 'noaccess') { if (token === 'noaccess') {
@ -36260,10 +36259,9 @@ var Type1Parser = function Type1ParserClosure() {
var index = this.readInt(); var index = this.readInt();
length = this.readInt(); length = this.readInt();
this.getToken(); this.getToken();
data = stream.makeSubStream(stream.pos, length); data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
lenIV = program.properties.privateData['lenIV']; lenIV = program.properties.privateData['lenIV'];
encoded = this.readCharStrings(data.getBytes(), lenIV); encoded = this.readCharStrings(data, lenIV);
stream.skip(length);
this.nextChar(); this.nextChar();
token = this.getToken(); token = this.getToken();
if (token === 'noaccess') { if (token === 'noaccess') {

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

@ -95,7 +95,7 @@
Object.defineProperty(exports, "__esModule", { Object.defineProperty(exports, "__esModule", {
value: true 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); var _pdfjsLib = __webpack_require__(1);
@ -397,14 +397,6 @@ function getVisibleElements(scrollEl, views, sortByVisibility = false, horizonta
function noContextMenuHandler(evt) { function noContextMenuHandler(evt) {
evt.preventDefault(); 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) { function isDataSchema(url) {
let i = 0, let i = 0,
ii = url.length; ii = url.length;
@ -614,7 +606,6 @@ exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING;
exports.VERTICAL_PADDING = VERTICAL_PADDING; exports.VERTICAL_PADDING = VERTICAL_PADDING;
exports.isValidRotation = isValidRotation; exports.isValidRotation = isValidRotation;
exports.isPortraitOrientation = isPortraitOrientation; exports.isPortraitOrientation = isPortraitOrientation;
exports.isFileSchema = isFileSchema;
exports.cloneObj = cloneObj; exports.cloneObj = cloneObj;
exports.PresentationModeState = PresentationModeState; exports.PresentationModeState = PresentationModeState;
exports.RendererType = RendererType; exports.RendererType = RendererType;
@ -1438,11 +1429,6 @@ let PDFViewerApplication = {
parameters[prop] = args[prop]; 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); let loadingTask = (0, _pdfjsLib.getDocument)(parameters);
this.pdfLoadingTask = loadingTask; this.pdfLoadingTask = loadingTask;
loadingTask.onPassword = (updateCallback, reason) => { loadingTask.onPassword = (updateCallback, reason) => {

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

@ -17,6 +17,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
setTimeout: "resource://gre/modules/Timer.jsm", setTimeout: "resource://gre/modules/Timer.jsm",
ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm", ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
OfflineAppCacheHelper: "resource://gre/modules/offlineAppCache.jsm", OfflineAppCacheHelper: "resource://gre/modules/offlineAppCache.jsm",
ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm",
}); });
XPCOMUtils.defineLazyServiceGetter(this, "sas", XPCOMUtils.defineLazyServiceGetter(this, "sas",
@ -71,6 +72,12 @@ var Sanitizer = {
*/ */
PREF_TIMESPAN: "privacy.sanitize.timeSpan", 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 * Time span constants corresponding to values of the privacy.sanitize.timeSpan
* pref. Used to determine how much history to clear, for various items * pref. Used to determine how much history to clear, for various items
@ -91,6 +98,11 @@ var Sanitizer = {
*/ */
shouldSanitizeOnShutdown: false, shouldSanitizeOnShutdown: false,
/**
* Whether we should sanitize the private container for about:newtab.
*/
shouldSanitizeNewTabContainer: false,
/** /**
* Shows a sanitization dialog to the user. * Shows a sanitization dialog to the user.
* *
@ -145,6 +157,17 @@ var Sanitizer = {
{fetchState: () => ({ progress })} {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 // Finally, run the sanitizations that were left pending, because we crashed
// before completing them. // before completing them.
for (let {itemsToClear, options} of pendingSanitizations) { for (let {itemsToClear, options} of pendingSanitizations) {
@ -272,6 +295,12 @@ var Sanitizer = {
let itemsToClear = getItemsToClearFromPrefBranch(Sanitizer.PREF_SHUTDOWN_BRANCH); let itemsToClear = getItemsToClearFromPrefBranch(Sanitizer.PREF_SHUTDOWN_BRANCH);
addPendingSanitization("shutdown", itemsToClear, {}); 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) { if (Sanitizer.shouldSanitizeOnShutdown) {
// We didn't crash during shutdown sanitization, so annotate it to avoid // We didn't crash during shutdown sanitization, so annotate it to avoid
// sanitizing again on startup. // 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. * Gets an array of items to clear from the given pref branch.
* @param branch The pref branch to fetch. * @param branch The pref branch to fetch.

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

@ -11,9 +11,13 @@ do_get_profile();
add_task(async function() { add_task(async function() {
ChromeUtils.import("resource:///modules/Sanitizer.jsm"); ChromeUtils.import("resource:///modules/Sanitizer.jsm");
Services.prefs.setBoolPref(Sanitizer.PREF_NEWTAB_SEGREGATION, false);
registerCleanupFunction(() => { registerCleanupFunction(() => {
Services.prefs.clearUserPref(Sanitizer.PREF_SANITIZE_ON_SHUTDOWN); Services.prefs.clearUserPref(Sanitizer.PREF_SANITIZE_ON_SHUTDOWN);
Services.prefs.clearUserPref(Sanitizer.PREF_SHUTDOWN_BRANCH + "formdata"); 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_SANITIZE_ON_SHUTDOWN, true);
Services.prefs.setBoolPref(Sanitizer.PREF_SHUTDOWN_BRANCH + "formdata", true); Services.prefs.setBoolPref(Sanitizer.PREF_SHUTDOWN_BRANCH + "formdata", true);

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

@ -1,13 +1,13 @@
This is the debugger.html project output. This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html 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: Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.2 - babel-plugin-transform-es2015-modules-commonjs @6.26.2
- babel-preset-react @6.24.1 - babel-preset-react @6.24.1
- react @16.2.0 - react @16.2.0
- react-dom @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.magnifying-glass,
.search-field i.sad-face { .search-field i.sad-face {
padding: 6px; padding-top: 5px;
padding-bottom: 5px;
padding-inline-end: 10px;
padding-inline-start: 5px;
width: 24px; width: 24px;
} }
@ -1118,6 +1121,11 @@ html .toggle-button.end.vertical svg {
width: 40px; width: 40px;
} }
.search-field.big i.sad-face {
padding-top: 4px;
padding-inline-start: 4px;
}
.search-field .magnifying-glass path, .search-field .magnifying-glass path,
.search-field .magnifying-glass ellipse { .search-field .magnifying-glass ellipse {
stroke: var(--theme-comment); stroke: var(--theme-comment);
@ -1134,18 +1142,13 @@ html .toggle-button.end.vertical svg {
.search-field .summary { .search-field .summary {
line-height: 27px; line-height: 27px;
text-align: center; text-align: center;
padding-right: 10px; padding-inline-end: 10px;
color: var(--theme-body-color-inactive); color: var(--theme-body-color-inactive);
align-self: center; align-self: center;
padding-top: 1px; padding-top: 1px;
white-space: nowrap; white-space: nowrap;
} }
.search-field.big .summary {
padding: 5px 0 5px 0;
line-height: 2rem;
}
.search-field .search-nav-buttons { .search-field .search-nav-buttons {
display: flex; display: flex;
user-select: none; user-select: none;
@ -1261,7 +1264,7 @@ html .toggle-button.end.vertical svg {
} }
.project-text-search .search-field .close-btn.big { .project-text-search .search-field .close-btn.big {
margin-top: 6px; margin-top: 2px;
} }
.project-text-search .managed-tree { .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)); max-width: calc(100% - var(--breakpoint-expression-right-clear-space));
display: inline-block; display: inline-block;
padding-inline-end: 8px; padding-inline-end: 8px;
cursor: default; cursor: pointer;
flex-grow: 1; flex-grow: 1;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
@ -3261,7 +3264,7 @@ html[dir="rtl"] .breakpoints-list .breakpoint .breakpoint-line {
.expression-container__close-btn { .expression-container__close-btn {
position: absolute; position: absolute;
offset-inline-end: 0px; offset-inline-end: 0px;
top: 0px; top: 1px;
} }
.expression-content { .expression-content {
@ -4049,6 +4052,7 @@ html .welcomebox .toggle-button-end.collapsed {
position: relative; position: relative;
transition: all 0.15s ease; transition: all 0.15s ease;
min-width: 40px; min-width: 40px;
max-width: 100%;
overflow: hidden; overflow: hidden;
padding: 5px; padding: 5px;
margin-inline-start: 3px; margin-inline-start: 3px;

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

@ -22811,7 +22811,7 @@ function toParsedScopes(children, sourceId) {
return { return {
start: scope.loc.start, start: scope.loc.start,
end: scope.loc.end, 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, displayName: scope.displayName,
bindings: scope.bindings, bindings: scope.bindings,
children: toParsedScopes(scope.children, sourceId) children: toParsedScopes(scope.children, sourceId)
@ -22906,9 +22906,18 @@ function isLetOrConst(node) {
} }
function hasLexicalDeclaration(node, parent) { 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 }); 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) { function isLexicalVariable(node) {
return isNode(node, "VariableDeclaration") && isLetOrConst(node); return isNode(node, "VariableDeclaration") && isLetOrConst(node);
@ -22973,19 +22982,27 @@ const scopeCollectionVisitor = {
// This ignores Annex B function declaration hoisting, which // This ignores Annex B function declaration hoisting, which
// is probably a fine assumption. // is probably a fine assumption.
state.declarationBindingIds.add(node.id); state.declarationBindingIds.add(node.id);
const fnScope = getVarScope(scope); const refs = [{
scope.bindings[node.id.name] = { type: "fn-decl",
type: fnScope === scope ? "var" : "let", start: fromBabelLocation(node.id.loc.start, state.sourceId),
refs: [{ end: fromBabelLocation(node.id.loc.end, state.sourceId),
type: "fn-decl", declaration: {
start: fromBabelLocation(node.id.loc.start, state.sourceId), start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.id.loc.end, state.sourceId), end: fromBabelLocation(node.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), { scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), {
@ -23007,6 +23024,13 @@ const scopeCollectionVisitor = {
refs: [] 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)) { } else if (t.isClass(node)) {
if (t.isIdentifier(node.id)) { if (t.isIdentifier(node.id)) {
// For decorated classes, the AST considers the first the decorator // For decorated classes, the AST considers the first the decorator
@ -23075,7 +23099,9 @@ const scopeCollectionVisitor = {
end: fromBabelLocation(node.loc.end, state.sourceId) end: fromBabelLocation(node.loc.end, state.sourceId)
}); });
parseDeclarator(node.param, scope, "var", "catch", node, state); 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. // Debugger will create new lexical environment for the block.
pushTempScope(state, "block", "Block", { pushTempScope(state, "block", "Block", {
start: fromBabelLocation(node.loc.start, state.sourceId), start: fromBabelLocation(node.loc.start, state.sourceId),
@ -23199,7 +23225,7 @@ const scopeCollectionVisitor = {
type: "implicit", type: "implicit",
refs: [] 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", { pushTempScope(state, "block", "Switch", {
start: fromBabelLocation(node.loc.start, state.sourceId), start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, state.sourceId) end: fromBabelLocation(node.loc.end, state.sourceId)
@ -25012,6 +25038,7 @@ const {
const dispatcher = new WorkerDispatcher(); const dispatcher = new WorkerDispatcher();
const getOriginalURLs = dispatcher.task("getOriginalURLs"); const getOriginalURLs = dispatcher.task("getOriginalURLs");
const getOriginalRanges = dispatcher.task("getOriginalRanges");
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", { const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
queue: true queue: true
}); });
@ -25035,6 +25062,7 @@ module.exports = {
isOriginalId, isOriginalId,
hasMappedSource, hasMappedSource,
getOriginalURLs, getOriginalURLs,
getOriginalRanges,
getGeneratedRanges, getGeneratedRanges,
getGeneratedLocation, getGeneratedLocation,
getAllGeneratedLocations, getAllGeneratedLocations,

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

@ -417,7 +417,7 @@ function toggleBreakpoint(line, column) {
line, line,
column column
}); });
const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource); const isEmptyLine = (0, _ast.isEmptyLineInSource)(state, line, selectedSource.id);
if (!bp && isEmptyLine || bp && bp.loading) { if (!bp && isEmptyLine || bp && bp.loading) {
return; return;
@ -434,8 +434,8 @@ function toggleBreakpoint(line, column) {
} }
return dispatch(addBreakpoint({ return dispatch(addBreakpoint({
sourceId: selectedSource.get("id"), sourceId: selectedSource.id,
sourceUrl: selectedSource.get("url"), sourceUrl: selectedSource.url,
line: line, line: line,
column: column column: column
})); }));

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

@ -51,7 +51,6 @@ function willNavigate(event) {
await sourceMaps.clearSourceMaps(); await sourceMaps.clearSourceMaps();
(0, _wasm.clearWasmStates)(); (0, _wasm.clearWasmStates)();
(0, _editor.clearDocuments)(); (0, _editor.clearDocuments)();
(0, _editor.removeEditor)();
(0, _parser.clearSymbols)(); (0, _parser.clearSymbols)();
(0, _parser.clearASTs)(); (0, _parser.clearASTs)();
(0, _parser.clearScopes)(); (0, _parser.clearScopes)();

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

@ -41,7 +41,7 @@ async function loadSource(source, {
const id = source.get("id"); const id = source.get("id");
if ((0, _devtoolsSourceMap.isOriginalId)(id)) { if ((0, _devtoolsSourceMap.isOriginalId)(id)) {
return await sourceMaps.getOriginalSourceText(source.toJS()); return sourceMaps.getOriginalSourceText(source.toJS());
} }
const response = await client.sourceContents(id); const response = await client.sourceContents(id);

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

@ -211,9 +211,9 @@ const mapStateToProps = state => {
return { return {
selectedLocation: (0, _selectors.getSelectedLocation)(state), selectedLocation: (0, _selectors.getSelectedLocation)(state),
selectedSource, selectedSource,
hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")), hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.id),
contextMenu: (0, _selectors.getContextMenu)(state), 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, { getFunctionLocation: line => (0, _ast.findClosestFunction)(symbols, {
line, line,
column: Infinity column: Infinity

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

@ -70,7 +70,7 @@ class EmptyLines extends _react.Component {
const mapStateToProps = state => { const mapStateToProps = state => {
const selectedSource = (0, _selectors.getSelectedSource)(state); const selectedSource = (0, _selectors.getSelectedSource)(state);
const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.toJS()); const foundEmptyLines = (0, _selectors.getEmptyLines)(state, selectedSource.id);
return { return {
selectedSource, selectedSource,
emptyLines: selectedSource ? foundEmptyLines : [] emptyLines: selectedSource ? foundEmptyLines : []

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

@ -169,7 +169,7 @@ const mapStateToProps = state => {
breakpoints: (0, _selectors.getVisibleBreakpoints)(state), breakpoints: (0, _selectors.getVisibleBreakpoints)(state),
isPaused: (0, _selectors.isPaused)(state), isPaused: (0, _selectors.isPaused)(state),
contextMenu: (0, _selectors.getContextMenu)(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 _Button = require("../shared/Button/index");
var _text = require("../../utils/text");
var _actions = require("../../actions/index"); var _actions = require("../../actions/index");
var _actions2 = _interopRequireDefault(_actions); var _actions2 = _interopRequireDefault(_actions);
@ -175,7 +177,7 @@ class Tab extends _react.PureComponent {
shouldHide: icon => ["file", "javascript"].includes(icon) shouldHide: icon => ["file", "javascript"].includes(icon)
}), _react2.default.createElement("div", { }), _react2.default.createElement("div", {
className: "filename" 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, handleClick: onClickClose,
tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip") 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);

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

@ -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 # 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 # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
set -o errexit DIRS += [
set -o nounset
set -o pipefail
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 _prefs = require("../../utils/prefs");
var _Breakpoints = require("./Breakpoints"); var _Breakpoints = require("./Breakpoints/index");
var _Breakpoints2 = _interopRequireDefault(_Breakpoints); var _Breakpoints2 = _interopRequireDefault(_Breakpoints);

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

@ -4,13 +4,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += [ DIRS += [
'Breakpoints',
'Frames', 'Frames',
] ]
DevToolsModules( DevToolsModules(
'Breakpoint.js',
'Breakpoints.js',
'BreakpointsContextMenu.js',
'CommandBar.js', 'CommandBar.js',
'EventListeners.js', 'EventListeners.js',
'Expressions.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"); return symbols.hasOwnProperty("loading");
} }
function isEmptyLineInSource(state, line, selectedSource) { function isEmptyLineInSource(state, line, selectedSourceId) {
const emptyLines = getEmptyLines(state, selectedSource); const emptyLines = getEmptyLines(state, selectedSourceId);
return emptyLines && emptyLines.includes(line); return emptyLines && emptyLines.includes(line);
} }
function getEmptyLines(state, source) { function getEmptyLines(state, sourceId) {
if (!source) { if (!sourceId) {
return null; return null;
} }
return state.ast.emptyLines.get(source.id); return state.ast.emptyLines.get(sourceId);
} }
function getPausePoints(state, 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.getSelectedSourceText = exports.getSelectedSource = exports.getSelectedLocation = exports.getSourcesForTabs = exports.getSourceTabs = exports.getTabs = exports.getSources = exports.RelativeSourceRecordClass = exports.SourceRecordClass = undefined;
exports.initialSourcesState = initialSourcesState; exports.initialSourcesState = initialSourcesState;
exports.createSourceRecord = createSourceRecord;
exports.removeSourceFromTabList = removeSourceFromTabList; exports.removeSourceFromTabList = removeSourceFromTabList;
exports.removeSourcesFromTabList = removeSourcesFromTabList; exports.removeSourcesFromTabList = removeSourcesFromTabList;
exports.getBlackBoxList = getBlackBoxList; exports.getBlackBoxList = getBlackBoxList;
@ -68,6 +69,10 @@ const RelativeSourceRecordClass = exports.RelativeSourceRecordClass = new I.Reco
relativeUrl: undefined relativeUrl: undefined
})); }));
function createSourceRecord(source) {
return new SourceRecordClass(source);
}
function update(state = initialSourcesState(), action) { function update(state = initialSourcesState(), action) {
let location = null; let location = null;
@ -222,7 +227,7 @@ function updateSource(state, source) {
return state.setIn(["sources", source.id], updatedSource); 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) { 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 () { get: function () {
return _getRelativeSources.getRelativeSources; return _getRelativeSources.getRelativeSources;
} }
});
var _breakpointSources = require("./breakpointSources");
Object.defineProperty(exports, "getBreakpointSources", {
enumerable: true,
get: function () {
return _breakpointSources.getBreakpointSources;
}
}); });

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

@ -9,6 +9,7 @@ DIRS += [
DevToolsModules( DevToolsModules(
'breakpointAtLocation.js', 'breakpointAtLocation.js',
'breakpointSources.js',
'getCallStackFrames.js', 'getCallStackFrames.js',
'getRelativeSources.js', 'getRelativeSources.js',
'inComponent.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", { Object.defineProperty(exports, "__esModule", {
value: true value: true
}); });
exports.findScopeByName = exports.getASTLocation = exports.createEditor = undefined; exports.findScopeByName = exports.getASTLocation = undefined;
var _createEditor = require("./create-editor");
Object.defineProperty(exports, "createEditor", {
enumerable: true,
get: function () {
return _createEditor.createEditor;
}
});
var _astBreakpointLocation = require("./astBreakpointLocation"); var _astBreakpointLocation = require("./astBreakpointLocation");
@ -31,6 +22,7 @@ Object.defineProperty(exports, "findScopeByName", {
exports.firstString = firstString; exports.firstString = firstString;
exports.locationMoved = locationMoved; exports.locationMoved = locationMoved;
exports.makeLocationId = makeLocationId; exports.makeLocationId = makeLocationId;
exports.getLocationWithoutColumn = getLocationWithoutColumn;
exports.makePendingLocationId = makePendingLocationId; exports.makePendingLocationId = makePendingLocationId;
exports.assertBreakpoint = assertBreakpoint; exports.assertBreakpoint = assertBreakpoint;
exports.assertPendingBreakpoint = assertPendingBreakpoint; exports.assertPendingBreakpoint = assertPendingBreakpoint;
@ -77,6 +69,14 @@ function makeLocationId(location) {
return `${sourceId}:${line}:${columnString}`; return `${sourceId}:${line}:${columnString}`;
} }
function getLocationWithoutColumn(location) {
const {
sourceId,
line
} = location;
return `${sourceId}:${line}`;
}
function makePendingLocationId(location) { function makePendingLocationId(location) {
assertPendingLocation(location); assertPendingLocation(location);
const { const {

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

@ -9,6 +9,5 @@ DIRS += [
DevToolsModules( DevToolsModules(
'astBreakpointLocation.js', 'astBreakpointLocation.js',
'create-editor.js',
'index.js', 'index.js',
) )

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

@ -65,6 +65,7 @@ Object.keys(_createEditor).forEach(function (key) {
}); });
exports.setEditor = setEditor; exports.setEditor = setEditor;
exports.getEditor = getEditor; exports.getEditor = getEditor;
exports.getCodeMirror = getCodeMirror;
exports.removeEditor = removeEditor; exports.removeEditor = removeEditor;
exports.shouldShowPrettyPrint = shouldShowPrettyPrint; exports.shouldShowPrettyPrint = shouldShowPrettyPrint;
exports.shouldShowFooter = shouldShowFooter; exports.shouldShowFooter = shouldShowFooter;
@ -103,6 +104,10 @@ function getEditor() {
return editor; return editor;
} }
function getCodeMirror() {
return editor && editor.codeMirror;
}
function removeEditor() { function removeEditor() {
editor = null; editor = null;
} }

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

@ -38,6 +38,8 @@ require("codemirror/addon/fold/indent-fold/index");
require("codemirror/addon/fold/foldgutter/index"); require("codemirror/addon/fold/foldgutter/index");
require("codemirror/addon/runmode/runmode/index");
require("codemirror/addon/selection/active-line/index"); require("codemirror/addon/selection/active-line/index");
require("codemirror/addon/edit/matchbrackets/index"); require("codemirror/addon/edit/matchbrackets/index");

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

@ -9,6 +9,8 @@ var _parser = require("../../../workers/parser/index");
var _locColumn = require("./locColumn"); var _locColumn = require("./locColumn");
var _rangeMetadata = require("./rangeMetadata");
var _findGeneratedBindingFromPosition = require("./findGeneratedBindingFromPosition"); var _findGeneratedBindingFromPosition = require("./findGeneratedBindingFromPosition");
var _buildGeneratedBindingList = require("./buildGeneratedBindingList"); 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 generatedAstBindings = (0, _buildGeneratedBindingList.buildGeneratedBindingList)(scopes, generatedAstScopes, frame.this);
const originalRanges = await (0, _rangeMetadata.loadRangeMetadata)(source, frame, originalAstScopes, sourceMaps);
const { const {
mappedOriginalScopes, mappedOriginalScopes,
expressionLookup expressionLookup
} = await mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps); } = await mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps);
const mappedGeneratedScopes = generateClientScope(scopes, mappedOriginalScopes); const mappedGeneratedScopes = generateClientScope(scopes, mappedOriginalScopes);
return isReliableScope(mappedGeneratedScopes) ? { return isReliableScope(mappedGeneratedScopes) ? {
mappings: expressionLookup, mappings: expressionLookup,
@ -41,7 +44,7 @@ async function buildMappedScopes(source, frame, scopes, sourceMaps, client) {
} : null; } : null;
} }
async function mapOriginalBindingsToGenerated(source, originalAstScopes, generatedAstBindings, client, sourceMaps) { async function mapOriginalBindingsToGenerated(source, originalRanges, originalAstScopes, generatedAstBindings, client, sourceMaps) {
const expressionLookup = {}; const expressionLookup = {};
const mappedOriginalScopes = []; const mappedOriginalScopes = [];
const cachedSourceMaps = batchScopeMappings(originalAstScopes, source, sourceMaps); const cachedSourceMaps = batchScopeMappings(originalAstScopes, source, sourceMaps);
@ -51,7 +54,7 @@ async function mapOriginalBindingsToGenerated(source, originalAstScopes, generat
for (const name of Object.keys(item.bindings)) { for (const name of Object.keys(item.bindings)) {
const binding = item.bindings[name]; 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) { if (result) {
generatedBindings[name] = result.grip; generatedBindings[name] = result.grip;
@ -213,7 +216,14 @@ function generateClientScope(scopes, originalScopes) {
return result; 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 // 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 // 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. // 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; let genContent = null;
for (const pos of refs) { for (const pos of refs) {
if (originalBinding.type === "import") { const range = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos);
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
} else { if (range && hasValidIdent(range, pos)) {
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForStandardBinding)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); 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/)) { if ((pos.type === "class-decl" || pos.type === "class-inner") && source.contentType && source.contentType.match(/\/typescript/)) {
// Resolve to first binding in the range const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration);
const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
if (declContent) { if (declRange && declRange.type !== "multiple") {
// Prefer the declaration mapping in this case because TS sometimes // Resolve to first binding in the range
// maps class declaration names to "export.Foo = Foo;" or to const declContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForNormalDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings);
// the decorator logic itself
genContent = declContent; 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")) { if (!genContent && (pos.type === "import-decl" || pos.type === "import-ns-decl")) {
// match the import declaration location const declRange = (0, _rangeMetadata.findMatchingRange)(originalRanges, pos.declaration); // The import declaration should have an original position mapping,
genContent = await (0, _findGeneratedBindingFromPosition.findGeneratedBindingForImportDeclaration)(sourceMaps, client, source, pos, name, originalBinding.type, generatedAstBindings); // 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) { if (genContent) {

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

@ -16,4 +16,5 @@ DevToolsModules(
'locColumn.js', 'locColumn.js',
'mappingContains.js', 'mappingContains.js',
'positionCmp.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 "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)"; return (parts.length === 0 || url.path.slice(-1) === "/" || nodeHasChildren(url)) && url.name != "(index)";
} }
function getExtension(source) { function getExtension(url = "") {
const url = source.get ? source.get("url") : source.url;
const parsedUrl = (0, _url.parse)(url).pathname; const parsedUrl = (0, _url.parse)(url).pathname;
if (!parsedUrl) { if (!parsedUrl) {
@ -59,7 +58,7 @@ function getExtension(source) {
} }
function isNotJavaScript(source) { function isNotJavaScript(source) {
return ["css", "svg", "png"].includes(getExtension(source)); return ["css", "svg", "png"].includes(getExtension(source.url));
} }
function isInvalidUrl(url, source) { 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", { Object.defineProperty(exports, "__esModule", {
value: true value: true
}); });
exports.formatKeyShortcut = undefined; exports.truncateMiddleText = exports.formatKeyShortcut = undefined;
var _devtoolsModules = require("devtools/client/debugger/new/dist/vendors").vendored["devtools-modules"]; 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 "); 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 { return {
start: scope.loc.start, start: scope.loc.start,
end: scope.loc.end, 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, displayName: scope.displayName,
bindings: scope.bindings, bindings: scope.bindings,
children: toParsedScopes(scope.children, sourceId) children: toParsedScopes(scope.children, sourceId)
@ -190,10 +190,20 @@ function isLetOrConst(node) {
} }
function hasLexicalDeclaration(node, parent) { 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, { const isFunctionBody = t.isFunction(parent, {
body: node 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) { function isLexicalVariable(node) {
@ -257,19 +267,27 @@ const scopeCollectionVisitor = {
// This ignores Annex B function declaration hoisting, which // This ignores Annex B function declaration hoisting, which
// is probably a fine assumption. // is probably a fine assumption.
state.declarationBindingIds.add(node.id); state.declarationBindingIds.add(node.id);
const fnScope = getVarScope(scope); const refs = [{
scope.bindings[node.id.name] = { type: "fn-decl",
type: fnScope === scope ? "var" : "let", start: fromBabelLocation(node.id.loc.start, state.sourceId),
refs: [{ end: fromBabelLocation(node.id.loc.end, state.sourceId),
type: "fn-decl", declaration: {
start: fromBabelLocation(node.id.loc.start, state.sourceId), start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.id.loc.end, state.sourceId), end: fromBabelLocation(node.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), { scope = pushTempScope(state, "function", (0, _getFunctionName2.default)(node, parentNode), {
@ -290,6 +308,13 @@ const scopeCollectionVisitor = {
refs: [] 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)) { } else if (t.isClass(node)) {
if (t.isIdentifier(node.id)) { if (t.isIdentifier(node.id)) {
// For decorated classes, the AST considers the first the decorator // For decorated classes, the AST considers the first the decorator
@ -359,7 +384,8 @@ const scopeCollectionVisitor = {
end: fromBabelLocation(node.loc.end, state.sourceId) end: fromBabelLocation(node.loc.end, state.sourceId)
}); });
parseDeclarator(node.param, scope, "var", "catch", node, state); 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. // Debugger will create new lexical environment for the block.
pushTempScope(state, "block", "Block", { pushTempScope(state, "block", "Block", {
start: fromBabelLocation(node.loc.start, state.sourceId), start: fromBabelLocation(node.loc.start, state.sourceId),
@ -489,7 +515,7 @@ const scopeCollectionVisitor = {
type: "implicit", type: "implicit",
refs: [] 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", { pushTempScope(state, "block", "Switch", {
start: fromBabelLocation(node.loc.start, state.sourceId), start: fromBabelLocation(node.loc.start, state.sourceId),
end: fromBabelLocation(node.loc.end, 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-for-loops/output.js.map
examples/sourcemapped/fixtures/babel-functions/output.js examples/sourcemapped/fixtures/babel-functions/output.js
examples/sourcemapped/fixtures/babel-functions/output.js.map 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
examples/sourcemapped/fixtures/babel-type-module/output.js.map examples/sourcemapped/fixtures/babel-type-module/output.js.map
examples/sourcemapped/fixtures/babel-type-script/output.js examples/sourcemapped/fixtures/babel-type-script/output.js

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

@ -25,7 +25,7 @@ add_task(async function() {
let onPaused = waitForPaused(dbg); let onPaused = waitForPaused(dbg);
invokeInTab("mutate"); invokeInTab("mutate");
await onPaused; await onPaused;
await waitForLoadedSource(dbg, "script-mutate"); await waitForSelectedSource(dbg, "script-mutate");
is( is(
getScopeNodeLabel(dbg, 2), getScopeNodeLabel(dbg, 2),

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

@ -46,7 +46,7 @@ add_task(async function() {
"Block", "Block",
["three", "5"], ["three", "5"],
["two", "4"], ["two", "4"],
"Block", "Function Body",
["three", "3"], ["three", "3"],
["two", "2"], ["two", "2"],
"root", "root",
@ -73,7 +73,7 @@ add_task(async function() {
["aConst", '"const2"'], ["aConst", '"const2"'],
["aLet", '"let2"'], ["aLet", '"let2"'],
"Outer:_Outer()", "Outer:_Outer()",
"Block", "Function Body",
["aConst", '"const1"'], ["aConst", '"const1"'],
["aLet", '"let1"'], ["aLet", '"let1"'],
"Outer()", "Outer()",
@ -86,7 +86,7 @@ add_task(async function() {
"babel-line-start-bindings-es6", "babel-line-start-bindings-es6",
{ line: 19, column: 4 }, { line: 19, column: 4 },
[ [
"Block", "Function Body",
["<this>", "{\u2026}"], ["<this>", "{\u2026}"],
["one", "1"], ["one", "1"],
["two", "2"], ["two", "2"],
@ -102,7 +102,7 @@ add_task(async function() {
"babel-this-arguments-bindings", "babel-this-arguments-bindings",
{ line: 4, column: 4 }, { line: 4, column: 4 },
[ [
"Block", "Function Body",
["<this>", '"this-value"'], ["<this>", '"this-value"'],
["arrow", "undefined"], ["arrow", "undefined"],
"fn", "fn",
@ -123,7 +123,7 @@ add_task(async function() {
"arrow", "arrow",
["<this>", '"this-value"'], ["<this>", '"this-value"'],
["argArrow", '"arrow-arg"'], ["argArrow", '"arrow-arg"'],
"Block", "Function Body",
"arrow()", "arrow()",
"fn", "fn",
["arg", '"arg-value"'], ["arg", '"arg-value"'],
@ -158,12 +158,12 @@ add_task(async function() {
]); ]);
await breakpointScopes(dbg, "babel-classes", { line: 12, column: 6 }, [ await breakpointScopes(dbg, "babel-classes", { line: 12, column: 6 }, [
"Block", "Function Body",
["three", "3"], ["three", "3"],
["two", "2"], ["two", "2"],
"Class", "Class",
"Another()", "Another()",
"Block", "Function Body",
"Another()", "Another()",
["one", "1"], ["one", "1"],
"Thing()", "Thing()",
@ -174,7 +174,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-for-loops", { line: 5, column: 4 }, [ await breakpointScopes(dbg, "babel-for-loops", { line: 5, column: 4 }, [
"For", "For",
["i", "1"], ["i", "1"],
"Block", "Function Body",
["i", "0"], ["i", "0"],
"Module", "Module",
"root()" "root()"
@ -183,7 +183,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-for-loops", { line: 9, column: 4 }, [ await breakpointScopes(dbg, "babel-for-loops", { line: 9, column: 4 }, [
"For", "For",
["i", '"2"'], ["i", '"2"'],
"Block", "Function Body",
["i", "0"], ["i", "0"],
"Module", "Module",
"root()" "root()"
@ -192,7 +192,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-for-loops", { line: 13, column: 4 }, [ await breakpointScopes(dbg, "babel-for-loops", { line: 13, column: 4 }, [
"For", "For",
["i", "3"], ["i", "3"],
"Block", "Function Body",
["i", "0"], ["i", "0"],
"Module", "Module",
"root()" "root()"
@ -201,13 +201,13 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-functions", { line: 6, column: 8 }, [ await breakpointScopes(dbg, "babel-functions", { line: 6, column: 8 }, [
"arrow", "arrow",
["p3", "undefined"], ["p3", "undefined"],
"Block", "Function Body",
"arrow()", "arrow()",
"inner", "inner",
["p2", "undefined"], ["p2", "undefined"],
"Function Expression", "Function Expression",
"inner()", "inner()",
"Block", "Function Body",
"inner()", "inner()",
"decl", "decl",
["p1", "undefined"], ["p1", "undefined"],
@ -268,7 +268,7 @@ add_task(async function() {
await breakpointScopes(dbg, "babel-switches", { line: 7, column: 6 }, [ await breakpointScopes(dbg, "babel-switches", { line: 7, column: 6 }, [
"Switch", "Switch",
["val", "2"], ["val", "2"],
"Block", "Function Body",
["val", "1"], ["val", "1"],
"Module", "Module",
"root()" "root()"
@ -279,7 +279,7 @@ add_task(async function() {
["val", "3"], ["val", "3"],
"Switch", "Switch",
["val", "2"], ["val", "2"],
"Block", "Function Body",
["val", "1"], ["val", "1"],
"Module", "Module",
"root()" "root()"
@ -290,12 +290,21 @@ add_task(async function() {
["two", "2"], ["two", "2"],
"Catch", "Catch",
["err", '"AnError"'], ["err", '"AnError"'],
"Block", "Function Body",
["one", "1"], ["one", "1"],
"Module", "Module",
"root()" "root()"
]); ]);
await breakpointScopes(dbg, "babel-lex-and-nonlex", { line: 3, column: 4 }, [
"Function Body",
"Thing()",
"root",
"someHelper()",
"Module",
"root()"
]);
await breakpointScopes( await breakpointScopes(
dbg, dbg,
"babel-modules-webpack", "babel-modules-webpack",

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

@ -40,7 +40,7 @@ add_task(async function() {
is(getScopeLabel(dbg, 2), "na"); is(getScopeLabel(dbg, 2), "na");
is(getScopeLabel(dbg, 3), "nb"); is(getScopeLabel(dbg, 3), "nb");
is(getScopeLabel(dbg, 4), "Block"); is(getScopeLabel(dbg, 4), "Function Body");
await toggleScopeNode(dbg, 4); await toggleScopeNode(dbg, 4);

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

@ -27,6 +27,8 @@
<button onclick="babelForOf()">Run babel-for-of</button> <button onclick="babelForOf()">Run babel-for-of</button>
<script src="sourcemapped/fixtures/babel-functions/output.js"></script> <script src="sourcemapped/fixtures/babel-functions/output.js"></script>
<button onclick="babelFunctions()">Run babel-functions</button> <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> <script src="sourcemapped/fixtures/babel-line-start-bindings-es6/output.js"></script>
<button onclick="babelLineStartBindingsEs6()">Run babel-line-start-bindings-es6</button> <button onclick="babelLineStartBindingsEs6()">Run babel-line-start-bindings-es6</button>
<script src="sourcemapped/fixtures/babel-modules-cjs/output.js"></script> <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 dispatcher = new WorkerDispatcher();
const getOriginalURLs = dispatcher.task("getOriginalURLs"); const getOriginalURLs = dispatcher.task("getOriginalURLs");
const getOriginalRanges = dispatcher.task("getOriginalRanges");
const getGeneratedRanges = dispatcher.task("getGeneratedRanges", { const getGeneratedRanges = dispatcher.task("getGeneratedRanges", {
queue: true queue: true
}); });
@ -460,6 +461,7 @@ module.exports = {
isOriginalId, isOriginalId,
hasMappedSource, hasMappedSource,
getOriginalURLs, getOriginalURLs,
getOriginalRanges,
getGeneratedRanges, getGeneratedRanges,
getGeneratedLocation, getGeneratedLocation,
getAllGeneratedLocations, getAllGeneratedLocations,

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

@ -1973,6 +1973,7 @@ exports.ArraySet = ArraySet;
const { const {
getOriginalURLs, getOriginalURLs,
getOriginalRanges,
getGeneratedRanges, getGeneratedRanges,
getGeneratedLocation, getGeneratedLocation,
getAllGeneratedLocations, getAllGeneratedLocations,
@ -1993,6 +1994,7 @@ const {
// easier to unit test. // easier to unit test.
self.onmessage = workerHandler({ self.onmessage = workerHandler({
getOriginalURLs, getOriginalURLs,
getOriginalRanges,
getGeneratedRanges, getGeneratedRanges,
getGeneratedLocation, getGeneratedLocation,
getAllGeneratedLocations, getAllGeneratedLocations,
@ -2046,6 +2048,57 @@ async function getOriginalURLs(generatedSource) {
const COMPUTED_SPANS = new WeakSet(); 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 * Given an original location, find the ranges on the generated file that
* are mapped from the original range containing the location. * are mapped from the original range containing the location.
@ -2234,6 +2287,7 @@ function applySourceMap(generatedId, url, code, mappings) {
module.exports = { module.exports = {
getOriginalURLs, getOriginalURLs,
getOriginalRanges,
getGeneratedRanges, getGeneratedRanges,
getGeneratedLocation, getGeneratedLocation,
getAllGeneratedLocations, getAllGeneratedLocations,

7
devtools/client/shared/vendor/WasmDis.js поставляемый
Просмотреть файл

@ -956,7 +956,9 @@ var WasmDisassembler = /** @class */ (function () {
case 30 /* CODE_OPERATOR */: case 30 /* CODE_OPERATOR */:
var operator = reader.result; var operator = reader.result;
if (operator.code == 11 /* end */ && this._indentLevel == 0) { 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; break;
} }
switch (operator.code) { switch (operator.code) {
@ -980,8 +982,7 @@ var WasmDisassembler = /** @class */ (function () {
case 31 /* END_FUNCTION_BODY */: case 31 /* END_FUNCTION_BODY */:
this._funcIndex++; this._funcIndex++;
this._backrefLabels = null; this._backrefLabels = null;
this.appendBuffer(" )"); // See case BinaryReaderState.CODE_OPERATOR for closing of body
this.newLine();
break; break;
default: default:
throw new Error("Expectected state: " + reader.state); 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/comment-fold.js",
"./codemirror/addon/fold/xml-fold.js", "./codemirror/addon/fold/xml-fold.js",
"./codemirror/addon/fold/foldgutter.js", "./codemirror/addon/fold/foldgutter.js",
"./codemirror/addon/runmode/runmode.js",
"./codemirror/lib/codemirror.js", "./codemirror/lib/codemirror.js",
], ],
output: { output: {

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

@ -613,7 +613,7 @@ previewers.Object = [
isConnected: rawObj.isConnected === true, 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); preview.location = hooks.createValueGrip(rawObj.location.href);
} else if (obj.class == "DocumentFragment") { } else if (obj.class == "DocumentFragment") {
preview.childNodesLength = rawObj.childNodes.length; preview.childNodesLength = rawObj.childNodes.length;

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

@ -81,7 +81,6 @@
#include "nsIDocShellTreeOwner.h" #include "nsIDocShellTreeOwner.h"
#include "nsIDocument.h" #include "nsIDocument.h"
#include "nsIDocumentLoaderFactory.h" #include "nsIDocumentLoaderFactory.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsIDOMStorage.h" #include "nsIDOMStorage.h"
#include "nsIDOMWindow.h" #include "nsIDOMWindow.h"
@ -552,12 +551,6 @@ nsDocShell::GetInterface(const nsIID& aIID, void** aSink)
aIID.Equals(NS_GET_IID(nsIDOMWindow))) && aIID.Equals(NS_GET_IID(nsIDOMWindow))) &&
NS_SUCCEEDED(EnsureScriptEnvironment())) { NS_SUCCEEDED(EnsureScriptEnvironment())) {
return mScriptGlobal->QueryInterface(aIID, aSink); 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)) && } else if (aIID.Equals(NS_GET_IID(nsIDocument)) &&
NS_SUCCEEDED(EnsureContentViewer())) { NS_SUCCEEDED(EnsureContentViewer())) {
nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument(); 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_AMBIGUOUS(nsDocument, nsISupports, nsINode)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsINode) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsINode)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNode) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNode)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIScriptObjectPrincipal)
NS_INTERFACE_TABLE_ENTRY(nsDocument, mozilla::dom::EventTarget) NS_INTERFACE_TABLE_ENTRY(nsDocument, mozilla::dom::EventTarget)

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

@ -21,7 +21,7 @@
#include "nsWeakPtr.h" #include "nsWeakPtr.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsIdentifierMapEntry.h" #include "nsIdentifierMapEntry.h"
#include "nsIDOMDocument.h" #include "nsIDOMNode.h"
#include "nsStubDocumentObserver.h" #include "nsStubDocumentObserver.h"
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
#include "nsIContent.h" #include "nsIContent.h"
@ -130,7 +130,7 @@ private:
// Base class for our document implementations. // Base class for our document implementations.
class nsDocument : public nsIDocument, class nsDocument : public nsIDocument,
public nsIDOMDocument, public nsIDOMNode,
public nsSupportsWeakReference, public nsSupportsWeakReference,
public nsIScriptObjectPrincipal, public nsIScriptObjectPrincipal,
public nsIRadioGroupContainer, public nsIRadioGroupContainer,

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

@ -12,7 +12,6 @@ const nsIProperties = I.nsIProperties;
const nsIFileInputStream = I.nsIFileInputStream; const nsIFileInputStream = I.nsIFileInputStream;
const nsIInputStream = I.nsIInputStream; const nsIInputStream = I.nsIInputStream;
const nsIDOMDocument = I.nsIDOMDocument;
const nsIDOMNode = I.nsIDOMNode; const nsIDOMNode = I.nsIDOMNode;
Cu.importGlobalProperties(["DOMParser", "Element", "XMLSerializer"]); Cu.importGlobalProperties(["DOMParser", "Element", "XMLSerializer"]);

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

@ -177,7 +177,7 @@ function getParsedDocument(aPath) {
function processParsedDocument(doc) { function processParsedDocument(doc) {
Assert.ok(doc.documentElement.localName != "parsererror"); Assert.ok(doc.documentElement.localName != "parsererror");
Assert.ok(doc instanceof Ci.nsIDOMDocument); Assert.equal(ChromeUtils.getClassName(doc), "XMLDocument");
// Clean out whitespace. // Clean out whitespace.
var walker = doc.createTreeWalker(doc, 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. // Requested by smaug: A range involving a comment as a document child.
doc = parser.parseFromString("<!-- foo --><foo/>", "application/xml"); 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); Assert.equal(doc.childNodes.length, 2);
baseRange = doc.createRange(); baseRange = doc.createRange();
baseRange.setStart(doc.firstChild, 1); baseRange.setStart(doc.firstChild, 1);

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

@ -8,7 +8,7 @@ function run_test () {
var tests = [ var tests = [
[ test1, "Unable to parse basic XML document" ], [ 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" ], [ test3, "ParseXML return value's documentElement is not Element" ],
[ test4, "" ], [ test4, "" ],
[ test5, "" ], [ test5, "" ],
@ -21,7 +21,7 @@ function test1() {
} }
function test2() { function test2() {
return (ParseXML("<root/>") instanceof nsIDOMDocument); return (ChromeUtils.getClassName(ParseXML("<root/>")) === "XMLDocument");
} }
function test3() { function test3() {

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

@ -21,16 +21,11 @@ function ConsoleListener() {
ConsoleListener.prototype = { ConsoleListener.prototype = {
observe(aSubject, aTopic, aData) { observe(aSubject, aTopic, aData) {
let obj = aSubject.wrappedJSObject; let obj = aSubject.wrappedJSObject;
if (obj.arguments[0] != 'test') { if (obj.arguments[0] != "test_bug1463614") {
return; return;
} }
if (!this._cb) { if (!this._cb || !this._cb(obj)) {
ok(false, "Callback not set!");
return;
}
if (!this._cb(obj)) {
return; return;
} }
@ -57,10 +52,10 @@ async function runTest() {
let cl = listener.waitFor(obj => { let cl = listener.waitFor(obj => {
return ("timer" in obj) && return ("timer" in obj) &&
("name" in obj.timer) && ("name" in obj.timer) &&
obj.timer.name == 'test'; obj.timer.name == "test_bug1463614";
}); });
console.time('test'); console.time("test_bug1463614");
await cl; await cl;
ok(true, "Console.time received!"); ok(true, "Console.time received!");
@ -68,7 +63,7 @@ async function runTest() {
cl = listener.waitFor(obj => { cl = listener.waitFor(obj => {
return ("timer" in obj) && return ("timer" in obj) &&
("name" in obj.timer) && ("name" in obj.timer) &&
obj.timer.name == 'test' && obj.timer.name == "test_bug1463614" &&
("duration" in obj.timer) && ("duration" in obj.timer) &&
obj.timer.duration >= 0 && obj.timer.duration >= 0 &&
obj.arguments[1] == 1 && obj.arguments[1] == 1 &&
@ -76,7 +71,7 @@ async function runTest() {
obj.arguments[3] == 3 && obj.arguments[3] == 3 &&
obj.arguments[4] == 4; obj.arguments[4] == 4;
}); });
console.timeLog('test', 1, 2, 3, 4); console.timeLog("test_bug1463614", 1, 2, 3, 4);
await cl; await cl;
ok(true, "Console.timeLog received!"); ok(true, "Console.timeLog received!");
@ -84,11 +79,11 @@ async function runTest() {
cl = listener.waitFor(obj => { cl = listener.waitFor(obj => {
return ("timer" in obj) && return ("timer" in obj) &&
("name" in obj.timer) && ("name" in obj.timer) &&
obj.timer.name == 'test' && obj.timer.name == "test_bug1463614" &&
("duration" in obj.timer) && ("duration" in obj.timer) &&
obj.timer.duration >= 0; obj.timer.duration >= 0;
}); });
console.timeEnd('test'); console.timeEnd("test_bug1463614");
await cl; await cl;
ok(true, "Console.timeEnd received!"); ok(true, "Console.timeEnd received!");
@ -96,10 +91,10 @@ async function runTest() {
cl = listener.waitFor(obj => { cl = listener.waitFor(obj => {
return ("timer" in obj) && return ("timer" in obj) &&
("name" in obj.timer) && ("name" in obj.timer) &&
obj.timer.name == 'test' && obj.timer.name == "test_bug1463614" &&
("error" in obj.timer); ("error" in obj.timer);
}); });
console.timeLog('test'); console.timeLog("test_bug1463614");
await cl; await cl;
ok(true, "Console.time with error received!"); 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(nsIAsyncFileMetadata)
NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength) NS_INTERFACE_MAP_ENTRY(nsIInputStreamLength)
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStreamLength) NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStreamLength)
NS_INTERFACE_MAP_ENTRY(nsIIPCBlobInputStream)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END

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

@ -20,6 +20,22 @@ namespace dom {
class IPCBlobInputStreamChild; 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 class IPCBlobInputStream final : public nsIAsyncInputStream
, public nsIInputStreamCallback , public nsIInputStreamCallback
, public nsICloneableInputStreamWithRange , public nsICloneableInputStreamWithRange
@ -27,6 +43,7 @@ class IPCBlobInputStream final : public nsIAsyncInputStream
, public nsIAsyncFileMetadata , public nsIAsyncFileMetadata
, public nsIInputStreamLength , public nsIInputStreamLength
, public nsIAsyncInputStreamLength , public nsIAsyncInputStreamLength
, public nsIIPCBlobInputStream
{ {
public: public:
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
@ -49,6 +66,21 @@ public:
void void
LengthReady(int64_t aLength); LengthReady(int64_t aLength);
// nsIIPCBlobInputStream
nsIInputStream*
GetInternalStream() const override
{
if (mRemoteStream) {
return mRemoteStream;
}
if (mAsyncRemoteStream) {
return mAsyncRemoteStream;
}
return nullptr;
}
private: private:
~IPCBlobInputStream(); ~IPCBlobInputStream();

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

@ -89,10 +89,26 @@ SerializeInputStreamParent(nsIInputStream* aInputStream, uint64_t aSize,
// Parent to Child we always send a IPCBlobInputStream. // Parent to Child we always send a IPCBlobInputStream.
MOZ_ASSERT(XRE_IsParentProcess()); 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; nsresult rv;
RefPtr<IPCBlobInputStreamParent> parentActor = RefPtr<IPCBlobInputStreamParent> parentActor =
IPCBlobInputStreamParent::Create(aInputStream, aSize, aChildID, &rv, IPCBlobInputStreamParent::Create(stream, aSize, aChildID, &rv, aManager);
aManager);
if (!parentActor) { if (!parentActor) {
return rv; return rv;
} }

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

@ -16,7 +16,6 @@ typedef double DOMHighResTimeStamp;
typedef unsigned long long nsViewID; typedef unsigned long long nsViewID;
// Core // Core
interface nsIDOMDocument;
interface nsIDOMNode; interface nsIDOMNode;
// Needed for raises() in our IDL // Needed for raises() in our IDL

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

@ -8,7 +8,6 @@ with Files("**"):
BUG_COMPONENT = ("Core", "DOM") BUG_COMPONENT = ("Core", "DOM")
XPIDL_SOURCES += [ XPIDL_SOURCES += [
'nsIDOMDocument.idl',
'nsIDOMNode.idl', 'nsIDOMNode.idl',
'nsIDOMNSEditableElement.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] [Throws, Func="IsChromeOrXBL", NeedsSubjectPrincipal]
void loadBindingDocument(DOMString documentURL); void loadBindingDocument(DOMString documentURL);
// nsIDOMDocumentTouch // Touch bits
// XXXbz I can't find the sane spec for this stuff, so just cribbing // XXXbz I can't find the sane spec for this stuff, so just cribbing
// from our xpidl for now. // from our xpidl for now.
[NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"] [NewObject, Func="nsGenericHTMLElement::TouchEventsEnabled"]

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

@ -473,13 +473,35 @@ public:
* *
* Use IsMapped() to verify whether Map() succeeded or not. * Use IsMapped() to verify whether Map() succeeded or not.
*/ */
class ScopedMap { class ScopedMap final {
public: public:
explicit ScopedMap(DataSourceSurface* aSurface, MapType aType) explicit ScopedMap(DataSourceSurface* aSurface, MapType aType)
: mSurface(aSurface) : mSurface(aSurface)
, mIsMapped(aSurface->Map(aType, &mMap)) {} , 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) { if (mIsMapped) {
mSurface->Unmap(); mSurface->Unmap();
@ -507,6 +529,9 @@ public:
bool IsMapped() const { return mIsMapped; } bool IsMapped() const { return mIsMapped; }
private: private:
ScopedMap(const ScopedMap& aOther) = delete;
ScopedMap& operator=(const ScopedMap& aOther) = delete;
RefPtr<DataSourceSurface> mSurface; RefPtr<DataSourceSurface> mSurface;
MappedSurface mMap; MappedSurface mMap;
bool mIsMapped; bool mIsMapped;

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

@ -2038,6 +2038,7 @@ gfxFont::DrawOneGlyph(uint32_t aGlyphID, const gfx::Point& aPt,
} }
if (fontParams.haveColorGlyphs && if (fontParams.haveColorGlyphs &&
!gfxPlatform::GetPlatform()->HasNativeColrFontSupport() &&
RenderColorGlyph(runParams.dt, runParams.context, RenderColorGlyph(runParams.dt, runParams.context,
fontParams.scaledFont, fontParams.scaledFont,
fontParams.drawOptions, fontParams.drawOptions,

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

@ -737,6 +737,10 @@ public:
return mHasVariationFontSupport; return mHasVariationFontSupport;
} }
bool HasNativeColrFontSupport() const {
return mHasNativeColrFontSupport;
}
// you probably want to use gfxVars::UseWebRender() instead of this // you probably want to use gfxVars::UseWebRender() instead of this
static bool WebRenderPrefEnabled(); static bool WebRenderPrefEnabled();
// you probably want to use gfxVars::UseWebRender() instead of this // you probably want to use gfxVars::UseWebRender() instead of this
@ -830,6 +834,10 @@ protected:
// Whether the platform supports rendering OpenType font variations // Whether the platform supports rendering OpenType font variations
bool mHasVariationFontSupport; 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 // max character limit for words in word cache
int32_t mWordCacheCharLimit; int32_t mWordCacheCharLimit;

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

@ -82,6 +82,10 @@ gfxPlatformMac::gfxPlatformMac()
InitBackendPrefs(GetBackendPrefs()); InitBackendPrefs(GetBackendPrefs());
MacIOSurfaceLib::LoadLibrary(); MacIOSurfaceLib::LoadLibrary();
if (nsCocoaFeatures::OnHighSierraOrLater()) {
mHasNativeColrFontSupport = true;
}
} }
gfxPlatformMac::~gfxPlatformMac() gfxPlatformMac::~gfxPlatformMac()

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

@ -176,18 +176,18 @@ AnimationFrameBuffer::MarkComplete()
return mPending > 0; return mPending > 0;
} }
DrawableFrameRef imgFrame*
AnimationFrameBuffer::Get(size_t aFrame) AnimationFrameBuffer::Get(size_t aFrame)
{ {
// We should not have asked for a frame if we never inserted. // We should not have asked for a frame if we never inserted.
if (mFrames.IsEmpty()) { if (mFrames.IsEmpty()) {
MOZ_ASSERT_UNREACHABLE("Calling Get() when we have no frames"); 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 we don't have that frame, return an empty frame ref.
if (aFrame >= mFrames.Length()) { if (aFrame >= mFrames.Length()) {
return DrawableFrameRef(); return nullptr;
} }
// We've got the requested frame because we are not discarding frames. While // 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. // we want them, it is possible the decoder is behind.
if (!mFrames[aFrame]) { if (!mFrames[aFrame]) {
MOZ_ASSERT(MayDiscard()); MOZ_ASSERT(MayDiscard());
return DrawableFrameRef(); return nullptr;
} }
// If we are advancing on behalf of the animation, we don't expect it to be // 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. // getting any frames (besides the first) until we get the desired frame.
MOZ_ASSERT(aFrame == 0 || mAdvance == 0); MOZ_ASSERT(aFrame == 0 || mAdvance == 0);
return mFrames[aFrame]->DrawableRef(); return mFrames[aFrame].get();
} }
bool bool

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

@ -63,7 +63,7 @@ public:
* *
* @returns The frame, if available. * @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 * Inserts a frame into the frame buffer. If it has yet to fully decode the

47
image/AnimationParams.h Normal file
Просмотреть файл

@ -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 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 bool

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

@ -57,6 +57,7 @@ public:
protected: protected:
DrawableFrameRef DrawableRef(size_t aFrame) override; 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 // 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 // their memory atomically (due to the surface cache discarding them). If they

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

@ -283,14 +283,14 @@ Decoder::Telemetry() const
} }
nsresult nsresult
Decoder::AllocateFrame(uint32_t aFrameNum, Decoder::AllocateFrame(const gfx::IntSize& aOutputSize,
const gfx::IntSize& aOutputSize,
const gfx::IntRect& aFrameRect, const gfx::IntRect& aFrameRect,
gfx::SurfaceFormat aFormat, gfx::SurfaceFormat aFormat,
uint8_t aPaletteDepth) uint8_t aPaletteDepth,
const Maybe<AnimationParams>& aAnimParams)
{ {
mCurrentFrame = AllocateFrameInternal(aFrameNum, aOutputSize, aFrameRect, mCurrentFrame = AllocateFrameInternal(aOutputSize, aFrameRect, aFormat,
aFormat, aPaletteDepth, aPaletteDepth, aAnimParams,
mCurrentFrame.get()); mCurrentFrame.get());
if (mCurrentFrame) { if (mCurrentFrame) {
@ -302,7 +302,7 @@ Decoder::AllocateFrame(uint32_t aFrameNum,
// We should now be on |aFrameNum|. (Note that we're comparing the frame // 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.) // 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. // If we're past the first frame, PostIsAnimated() should've been called.
MOZ_ASSERT_IF(mFrameCount > 1, HasAnimation()); MOZ_ASSERT_IF(mFrameCount > 1, HasAnimation());
@ -316,18 +316,19 @@ Decoder::AllocateFrame(uint32_t aFrameNum,
} }
RawAccessFrameRef RawAccessFrameRef
Decoder::AllocateFrameInternal(uint32_t aFrameNum, Decoder::AllocateFrameInternal(const gfx::IntSize& aOutputSize,
const gfx::IntSize& aOutputSize,
const gfx::IntRect& aFrameRect, const gfx::IntRect& aFrameRect,
SurfaceFormat aFormat, SurfaceFormat aFormat,
uint8_t aPaletteDepth, uint8_t aPaletteDepth,
const Maybe<AnimationParams>& aAnimParams,
imgFrame* aPreviousFrame) imgFrame* aPreviousFrame)
{ {
if (HasError()) { if (HasError()) {
return RawAccessFrameRef(); return RawAccessFrameRef();
} }
if (aFrameNum != mFrameCount) { uint32_t frameNum = aAnimParams ? aAnimParams->mFrameNum : 0;
if (frameNum != mFrameCount) {
MOZ_ASSERT_UNREACHABLE("Allocating frames out of order"); MOZ_ASSERT_UNREACHABLE("Allocating frames out of order");
return RawAccessFrameRef(); return RawAccessFrameRef();
} }
@ -342,7 +343,7 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum,
bool nonPremult = bool(mSurfaceFlags & SurfaceFlags::NO_PREMULTIPLY_ALPHA); bool nonPremult = bool(mSurfaceFlags & SurfaceFlags::NO_PREMULTIPLY_ALPHA);
if (NS_FAILED(frame->InitForDecoder(aOutputSize, aFrameRect, aFormat, if (NS_FAILED(frame->InitForDecoder(aOutputSize, aFrameRect, aFormat,
aPaletteDepth, nonPremult, aPaletteDepth, nonPremult,
aFrameNum > 0))) { aAnimParams))) {
NS_WARNING("imgFrame::Init should succeed"); NS_WARNING("imgFrame::Init should succeed");
return RawAccessFrameRef(); return RawAccessFrameRef();
} }
@ -353,24 +354,20 @@ Decoder::AllocateFrameInternal(uint32_t aFrameNum,
return RawAccessFrameRef(); return RawAccessFrameRef();
} }
if (aFrameNum == 1) { if (frameNum == 1) {
MOZ_ASSERT(aPreviousFrame, "Must provide a previous frame when animated"); 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 // If we dispose of the first frame by clearing it, then the first frame's
// refresh area is all of itself. // refresh area is all of itself.
// RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR). // RESTORE_PREVIOUS is invalid (assumed to be DISPOSE_CLEAR).
AnimationData previousFrameData = aPreviousFrame->GetAnimationData(); DisposalMethod prevDisposal = aPreviousFrame->GetDisposalMethod();
if (previousFrameData.mDisposalMethod == DisposalMethod::CLEAR || if (prevDisposal == DisposalMethod::CLEAR ||
previousFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL || prevDisposal == DisposalMethod::CLEAR_ALL ||
previousFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) { prevDisposal == DisposalMethod::RESTORE_PREVIOUS) {
mFirstFrameRefreshArea = previousFrameData.mRect; mFirstFrameRefreshArea = aPreviousFrame->GetRect();
} }
} }
if (aFrameNum > 0) { if (frameNum > 0) {
ref->SetRawAccessOnly();
// Some GIFs are huge but only have a small area that they animate. We only // 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. // need to refresh that small area when frame 0 comes around again.
mFirstFrameRefreshArea.UnionRect(mFirstFrameRefreshArea, frame->GetRect()); mFirstFrameRefreshArea.UnionRect(mFirstFrameRefreshArea, frame->GetRect());
@ -453,13 +450,7 @@ Decoder::PostIsAnimated(FrameTimeout aFirstFrameTimeout)
} }
void void
Decoder::PostFrameStop(Opacity aFrameOpacity Decoder::PostFrameStop(Opacity aFrameOpacity)
/* = Opacity::SOME_TRANSPARENCY */,
DisposalMethod aDisposalMethod
/* = DisposalMethod::KEEP */,
FrameTimeout aTimeout /* = FrameTimeout::Forever() */,
BlendMethod aBlendMethod /* = BlendMethod::OVER */,
const Maybe<nsIntRect>& aBlendRect /* = Nothing() */)
{ {
// We should be mid-frame // We should be mid-frame
MOZ_ASSERT(!IsMetadataDecode(), "Stopping frame during metadata decode"); MOZ_ASSERT(!IsMetadataDecode(), "Stopping frame during metadata decode");
@ -470,12 +461,11 @@ Decoder::PostFrameStop(Opacity aFrameOpacity
mInFrame = false; mInFrame = false;
mFinishedNewFrame = true; mFinishedNewFrame = true;
mCurrentFrame->Finish(aFrameOpacity, aDisposalMethod, aTimeout, mCurrentFrame->Finish(aFrameOpacity, mFinalizeFrames);
aBlendMethod, aBlendRect, mFinalizeFrames);
mProgress |= FLAG_FRAME_COMPLETE; mProgress |= FLAG_FRAME_COMPLETE;
mLoopLength += aTimeout; mLoopLength += mCurrentFrame->GetTimeout();
// If we're not sending partial invalidations, then we send an invalidation // If we're not sending partial invalidations, then we send an invalidation
// here when the first frame is complete. // here when the first frame is complete.

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

@ -11,6 +11,7 @@
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/NotNull.h" #include "mozilla/NotNull.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "AnimationParams.h"
#include "DecoderFlags.h" #include "DecoderFlags.h"
#include "Downscaler.h" #include "Downscaler.h"
#include "ImageMetadata.h" #include "ImageMetadata.h"
@ -27,6 +28,8 @@ namespace Telemetry {
namespace image { namespace image {
class imgFrame;
struct DecoderFinalStatus final struct DecoderFinalStatus final
{ {
DecoderFinalStatus(bool aWasMetadataDecode, DecoderFinalStatus(bool aWasMetadataDecode,
@ -477,11 +480,7 @@ protected:
// Specify whether this frame is opaque as an optimization. // Specify whether this frame is opaque as an optimization.
// For animated images, specify the disposal, blend method and timeout for // For animated images, specify the disposal, blend method and timeout for
// this frame. // this frame.
void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY, void PostFrameStop(Opacity aFrameOpacity = Opacity::SOME_TRANSPARENCY);
DisposalMethod aDisposalMethod = DisposalMethod::KEEP,
FrameTimeout aTimeout = FrameTimeout::Forever(),
BlendMethod aBlendMethod = BlendMethod::OVER,
const Maybe<nsIntRect>& aBlendRect = Nothing());
/** /**
* Called by the decoders when they have a region to invalidate. We may not * 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. * 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. * If a non-paletted frame is desired, pass 0 for aPaletteDepth.
*/ */
nsresult AllocateFrame(uint32_t aFrameNum, nsresult AllocateFrame(const gfx::IntSize& aOutputSize,
const gfx::IntSize& aOutputSize,
const gfx::IntRect& aFrameRect, const gfx::IntRect& aFrameRect,
gfx::SurfaceFormat aFormat, gfx::SurfaceFormat aFormat,
uint8_t aPaletteDepth = 0); uint8_t aPaletteDepth = 0,
const Maybe<AnimationParams>& aAnimParams = Nothing());
private: private:
/// Report that an error was encountered while decoding. /// Report that an error was encountered while decoding.
@ -543,11 +539,11 @@ private:
return mInFrame ? mFrameCount - 1 : mFrameCount; return mInFrame ? mFrameCount - 1 : mFrameCount;
} }
RawAccessFrameRef AllocateFrameInternal(uint32_t aFrameNum, RawAccessFrameRef AllocateFrameInternal(const gfx::IntSize& aOutputSize,
const gfx::IntSize& aOutputSize,
const gfx::IntRect& aFrameRect, const gfx::IntRect& aFrameRect,
gfx::SurfaceFormat aFormat, gfx::SurfaceFormat aFormat,
uint8_t aPaletteDepth, uint8_t aPaletteDepth,
const Maybe<AnimationParams>& aAnimParams,
imgFrame* aPreviousFrame); imgFrame* aPreviousFrame);
protected: protected:

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

@ -70,7 +70,7 @@ public:
Maybe<SurfaceInvalidRect> TakeInvalidRect() override { return Nothing(); } Maybe<SurfaceInvalidRect> TakeInvalidRect() override { return Nothing(); }
template <typename... Rest> template <typename... Rest>
nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest) nsresult Configure(const DownscalingConfig& aConfig, const Rest&... aRest)
{ {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -106,7 +106,7 @@ public:
} }
template <typename... Rest> template <typename... Rest>
nsresult Configure(const DownscalingConfig& aConfig, Rest... aRest) nsresult Configure(const DownscalingConfig& aConfig, const Rest&... aRest)
{ {
nsresult rv = mNext.Configure(aRest...); nsresult rv = mNext.Configure(aRest...);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

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

@ -212,40 +212,30 @@ AnimationState::LoopLength() const
// FrameAnimator implementation. // FrameAnimator implementation.
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
Maybe<TimeStamp> TimeStamp
FrameAnimator::GetCurrentImgFrameEndTime(AnimationState& aState, FrameAnimator::GetCurrentImgFrameEndTime(AnimationState& aState,
DrawableSurface& aFrames) const FrameTimeout aCurrentTimeout) const
{ {
TimeStamp currentFrameTime = aState.mCurrentAnimationFrameTime; if (aCurrentTimeout == FrameTimeout::Forever()) {
Maybe<FrameTimeout> timeout =
GetTimeoutForFrame(aState, aFrames, aState.mCurrentAnimationFrameIndex);
if (timeout.isNothing()) {
MOZ_ASSERT(aState.GetHasRequestedDecode() && !aState.GetIsCurrentlyDecoded());
return Nothing();
}
if (*timeout == FrameTimeout::Forever()) {
// We need to return a sentinel value in this case, because our logic // 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 // 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 // year in the future as the sentinel because it works with the loop in
// RequestRefresh() below. // RequestRefresh() below.
// XXX(seth): It'd be preferable to make our logic work correctly with // XXX(seth): It'd be preferable to make our logic work correctly with
// infinitely long timeouts. // infinitely long timeouts.
return Some(TimeStamp::NowLoRes() + return TimeStamp::NowLoRes() +
TimeDuration::FromMilliseconds(31536000.0)); TimeDuration::FromMilliseconds(31536000.0);
} }
TimeDuration durationOfTimeout = TimeDuration durationOfTimeout =
TimeDuration::FromMilliseconds(double(timeout->AsMilliseconds())); TimeDuration::FromMilliseconds(double(aCurrentTimeout.AsMilliseconds()));
TimeStamp currentFrameEndTime = currentFrameTime + durationOfTimeout; return aState.mCurrentAnimationFrameTime + durationOfTimeout;
return Some(currentFrameEndTime);
} }
RefreshResult RefreshResult
FrameAnimator::AdvanceFrame(AnimationState& aState, FrameAnimator::AdvanceFrame(AnimationState& aState,
DrawableSurface& aFrames, DrawableSurface& aFrames,
RawAccessFrameRef& aCurrentFrame,
TimeStamp aTime) TimeStamp aTime)
{ {
NS_ASSERTION(aTime <= TimeStamp::Now(), 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 // the appropriate notification on the main thread. Make sure we stay in sync
// with AnimationState. // with AnimationState.
MOZ_ASSERT(nextFrameIndex < aState.KnownFrameCount()); 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 // 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 // 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 // failure) we would have discarded all the old frames and may not yet have
// the new ones. // the new ones. DrawableSurface::RawAccessRef promises to only return
if (!nextFrame || !nextFrame->IsFinished()) { // finished frames.
if (!nextFrame) {
// Uh oh, the frame we want to show is currently being decoded (partial). // 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, // 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 // and so we should advance our current time rather than risk jumping
@ -322,11 +313,7 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
return ret; return ret;
} }
Maybe<FrameTimeout> nextFrameTimeout = GetTimeoutForFrame(aState, aFrames, nextFrameIndex); if (nextFrame->GetTimeout() == FrameTimeout::Forever()) {
// GetTimeoutForFrame can only return none if frame doesn't exist,
// but we just got it above.
MOZ_ASSERT(nextFrameTimeout.isSome());
if (*nextFrameTimeout == FrameTimeout::Forever()) {
ret.mAnimationFinished = true; ret.mAnimationFinished = true;
} }
@ -336,15 +323,15 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1); MOZ_ASSERT(nextFrameIndex == currentFrameIndex + 1);
// Change frame // Change frame
if (!DoBlend(aFrames, &ret.mDirtyRect, currentFrameIndex, nextFrameIndex)) { if (!DoBlend(aCurrentFrame, nextFrame, nextFrameIndex, &ret.mDirtyRect)) {
// something went wrong, move on to next // something went wrong, move on to next
NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed"); NS_WARNING("FrameAnimator::AdvanceFrame(): Compositing of frame failed");
nextFrame->SetCompositingFailed(true); nextFrame->SetCompositingFailed(true);
Maybe<TimeStamp> currentFrameEndTime = GetCurrentImgFrameEndTime(aState, aFrames); aState.mCurrentAnimationFrameTime =
MOZ_ASSERT(currentFrameEndTime.isSome()); GetCurrentImgFrameEndTime(aState, aCurrentFrame->GetTimeout());
aState.mCurrentAnimationFrameTime = *currentFrameEndTime;
aState.mCurrentAnimationFrameIndex = nextFrameIndex; aState.mCurrentAnimationFrameIndex = nextFrameIndex;
aState.mCompositedFrameRequested = false; aState.mCompositedFrameRequested = false;
aCurrentFrame = Move(nextFrame);
aFrames.Advance(nextFrameIndex); aFrames.Advance(nextFrameIndex);
return ret; return ret;
@ -353,9 +340,8 @@ FrameAnimator::AdvanceFrame(AnimationState& aState,
nextFrame->SetCompositingFailed(false); nextFrame->SetCompositingFailed(false);
} }
Maybe<TimeStamp> currentFrameEndTime = GetCurrentImgFrameEndTime(aState, aFrames); aState.mCurrentAnimationFrameTime =
MOZ_ASSERT(currentFrameEndTime.isSome()); GetCurrentImgFrameEndTime(aState, aCurrentFrame->GetTimeout());
aState.mCurrentAnimationFrameTime = *currentFrameEndTime;
// If we can get closer to the current time by a multiple of the image's loop // 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 // 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 // Set currentAnimationFrameIndex at the last possible moment
aState.mCurrentAnimationFrameIndex = nextFrameIndex; aState.mCurrentAnimationFrameIndex = nextFrameIndex;
aState.mCompositedFrameRequested = false; aState.mCompositedFrameRequested = false;
aCurrentFrame = Move(nextFrame);
aFrames.Advance(nextFrameIndex); aFrames.Advance(nextFrameIndex);
// If we're here, we successfully advanced the frame. // If we're here, we successfully advanced the frame.
@ -451,11 +438,12 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
return ret; return ret;
} }
RawAccessFrameRef currentFrame =
result.Surface().RawAccessRef(aState.mCurrentAnimationFrameIndex);
// only advance the frame if the current time is greater than or // only advance the frame if the current time is greater than or
// equal to the current frame's end time. // equal to the current frame's end time.
Maybe<TimeStamp> currentFrameEndTime = if (!currentFrame) {
GetCurrentImgFrameEndTime(aState, result.Surface());
if (currentFrameEndTime.isNothing()) {
MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable()); MOZ_ASSERT(gfxPrefs::ImageMemAnimatedDiscardable());
MOZ_ASSERT(aState.GetHasRequestedDecode() && !aState.GetIsCurrentlyDecoded()); MOZ_ASSERT(aState.GetHasRequestedDecode() && !aState.GetIsCurrentlyDecoded());
MOZ_ASSERT(aState.mCompositedFrameInvalid); MOZ_ASSERT(aState.mCompositedFrameInvalid);
@ -465,6 +453,9 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
return ret; return ret;
} }
TimeStamp currentFrameEndTime =
GetCurrentImgFrameEndTime(aState, currentFrame->GetTimeout());
// If nothing has accessed the composited frame since the last time we // If nothing has accessed the composited frame since the last time we
// advanced, then there is no point in continuing to advance the animation. // advanced, then there is no point in continuing to advance the animation.
// This has the effect of freezing the animation while not in view. // This has the effect of freezing the animation while not in view.
@ -473,28 +464,29 @@ FrameAnimator::RequestRefresh(AnimationState& aState,
return ret; return ret;
} }
while (*currentFrameEndTime <= aTime) { while (currentFrameEndTime <= aTime) {
TimeStamp oldFrameEndTime = *currentFrameEndTime; 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. // Accumulate our result for returning to callers.
ret.Accumulate(frameRes); ret.Accumulate(frameRes);
currentFrameEndTime = GetCurrentImgFrameEndTime(aState, result.Surface()); // currentFrame was updated by AdvanceFrame so it is still current.
// AdvanceFrame can't advance to a frame that doesn't exist yet. currentFrameEndTime =
MOZ_ASSERT(currentFrameEndTime.isSome()); GetCurrentImgFrameEndTime(aState, currentFrame->GetTimeout());
// If we didn't advance a frame, and our frame end time didn't change, // 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) // then we need to break out of this loop & wait for the frame(s)
// to finish downloading. // to finish downloading.
if (!frameRes.mFrameAdvanced && (*currentFrameEndTime == oldFrameEndTime)) { if (!frameRes.mFrameAdvanced && currentFrameEndTime == oldFrameEndTime) {
break; break;
} }
} }
// Advanced to the correct frame, the composited frame is now valid to be drawn. // Advanced to the correct frame, the composited frame is now valid to be drawn.
if (*currentFrameEndTime > aTime) { if (currentFrameEndTime > aTime) {
aState.mCompositedFrameInvalid = false; aState.mCompositedFrameInvalid = false;
ret.mDirtyRect = IntRect(IntPoint(0,0), mSize); ret.mDirtyRect = IntRect(IntPoint(0,0), mSize);
} }
@ -509,6 +501,13 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState)
{ {
aState.mCompositedFrameRequested = true; 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 = LookupResult result =
SurfaceCache::Lookup(ImageKey(mImage), SurfaceCache::Lookup(ImageKey(mImage),
RasterSurfaceKey(mSize, RasterSurfaceKey(mSize,
@ -525,13 +524,6 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState)
return LookupResult(MatchType::PENDING); 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 // 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. // hit this case if the frame is not paletted and doesn't require compositing.
if (!result) { if (!result) {
@ -553,21 +545,6 @@ FrameAnimator::GetCompositedFrame(AnimationState& aState)
return result; 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 static void
DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface, DoCollectSizeOfCompositingSurfaces(const RawAccessFrameRef& aSurface,
SurfaceMemoryCounterType aType, 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 // DoBlend gets called when the timer for animation get fired and we have to
// update the composited frame of the animation. // update the composited frame of the animation.
bool bool
FrameAnimator::DoBlend(DrawableSurface& aFrames, FrameAnimator::DoBlend(const RawAccessFrameRef& aPrevFrame,
IntRect* aDirtyRect, const RawAccessFrameRef& aNextFrame,
uint32_t aPrevFrameIndex, uint32_t aNextFrameIndex,
uint32_t aNextFrameIndex) IntRect* aDirtyRect)
{ {
RawAccessFrameRef prevFrame = GetRawFrame(aFrames, aPrevFrameIndex); MOZ_ASSERT(aPrevFrame && aNextFrame, "Should have frames here");
RawAccessFrameRef nextFrame = GetRawFrame(aFrames, aNextFrameIndex);
MOZ_ASSERT(prevFrame && nextFrame, "Should have frames here"); DisposalMethod prevDisposalMethod = aPrevFrame->GetDisposalMethod();
bool prevHasAlpha = aPrevFrame->FormatHasAlpha();
AnimationData prevFrameData = prevFrame->GetAnimationData(); if (prevDisposalMethod == DisposalMethod::RESTORE_PREVIOUS &&
if (prevFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS &&
!mCompositingPrevFrame) { !mCompositingPrevFrame) {
prevFrameData.mDisposalMethod = DisposalMethod::CLEAR; prevDisposalMethod = DisposalMethod::CLEAR;
} }
IntRect prevRect = prevFrameData.mBlendRect IntRect prevRect = aPrevFrame->GetBoundedBlendRect();
? prevFrameData.mRect.Intersect(*prevFrameData.mBlendRect)
: prevFrameData.mRect;
bool isFullPrevFrame = prevRect.IsEqualRect(0, 0, mSize.width, mSize.height); bool isFullPrevFrame = prevRect.IsEqualRect(0, 0, mSize.width, mSize.height);
// Optimization: DisposeClearAll if the previous frame is the same size as // Optimization: DisposeClearAll if the previous frame is the same size as
// container and it's clearing itself // container and it's clearing itself
if (isFullPrevFrame && if (isFullPrevFrame &&
(prevFrameData.mDisposalMethod == DisposalMethod::CLEAR)) { (prevDisposalMethod == DisposalMethod::CLEAR)) {
prevFrameData.mDisposalMethod = DisposalMethod::CLEAR_ALL; prevDisposalMethod = DisposalMethod::CLEAR_ALL;
} }
AnimationData nextFrameData = nextFrame->GetAnimationData(); DisposalMethod nextDisposalMethod = aNextFrame->GetDisposalMethod();
bool nextHasAlpha = aNextFrame->FormatHasAlpha();
IntRect nextRect = nextFrameData.mBlendRect
? nextFrameData.mRect.Intersect(*nextFrameData.mBlendRect)
: nextFrameData.mRect;
IntRect nextRect = aNextFrame->GetBoundedBlendRect();
bool isFullNextFrame = nextRect.IsEqualRect(0, 0, mSize.width, mSize.height); 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 // Optimization: Skip compositing if the previous frame wants to clear the
// whole image // whole image
if (prevFrameData.mDisposalMethod == DisposalMethod::CLEAR_ALL) { if (prevDisposalMethod == DisposalMethod::CLEAR_ALL) {
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
return true; return true;
} }
@ -680,15 +637,15 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
// Optimization: Skip compositing if this frame is the same size as the // Optimization: Skip compositing if this frame is the same size as the
// container and it's fully drawing over prev frame (no alpha) // container and it's fully drawing over prev frame (no alpha)
if (isFullNextFrame && if (isFullNextFrame &&
(nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) && (nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) &&
!nextFrameData.mHasAlpha) { !nextHasAlpha) {
aDirtyRect->SetRect(0, 0, mSize.width, mSize.height); aDirtyRect->SetRect(0, 0, mSize.width, mSize.height);
return true; return true;
} }
} }
// Calculate area that needs updating // Calculate area that needs updating
switch (prevFrameData.mDisposalMethod) { switch (prevDisposalMethod) {
default: default:
MOZ_FALLTHROUGH_ASSERT("Unexpected DisposalMethod"); MOZ_FALLTHROUGH_ASSERT("Unexpected DisposalMethod");
case DisposalMethod::NOT_SPECIFIED: case DisposalMethod::NOT_SPECIFIED:
@ -705,7 +662,7 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
// Calc area that needs to be redrawn (the combination of previous and // Calc area that needs to be redrawn (the combination of previous and
// this frame) // this frame)
// XXX - This could be done with multiple framechanged calls // 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 // way at the bottom, and both frames being small, we'd be
// telling framechanged to refresh the whole image when only two // telling framechanged to refresh the whole image when only two
// small areas are needed. // small areas are needed.
@ -747,8 +704,6 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
needToBlankComposite = true; needToBlankComposite = true;
} }
AnimationData compositingFrameData = mCompositingFrame->GetAnimationData();
// More optimizations possible when next frame is not transparent // More optimizations possible when next frame is not transparent
// But if the next frame has DisposalMethod::RESTORE_PREVIOUS, // But if the next frame has DisposalMethod::RESTORE_PREVIOUS,
// this "no disposal" optimization is not possible, // 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 // needs to be stored in compositingFrame, so it can be
// copied into compositingPrevFrame later. // copied into compositingPrevFrame later.
bool doDisposal = true; bool doDisposal = true;
if (!nextFrameData.mHasAlpha && if (!nextHasAlpha && nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) {
nextFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) {
if (isFullNextFrame) { if (isFullNextFrame) {
// Optimization: No need to dispose prev.frame when // Optimization: No need to dispose prev.frame when
// next frame is full frame and not transparent. // next frame is full frame and not transparent.
@ -777,46 +731,42 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
if (doDisposal) { if (doDisposal) {
// Dispose of previous: clear, restore, or keep (copy) // Dispose of previous: clear, restore, or keep (copy)
switch (prevFrameData.mDisposalMethod) { switch (prevDisposalMethod) {
case DisposalMethod::CLEAR: case DisposalMethod::CLEAR:
if (needToBlankComposite) { if (needToBlankComposite) {
// If we just created the composite, it could have anything in its // If we just created the composite, it could have anything in its
// buffer. Clear whole frame // buffer. Clear whole frame
ClearFrame(compositingFrameData.mRawData, ClearFrame(mCompositingFrame.Data(),
compositingFrameData.mRect); mCompositingFrame->GetRect());
} else { } else {
// Only blank out previous frame area (both color & Mask/Alpha) // Only blank out previous frame area (both color & Mask/Alpha)
ClearFrame(compositingFrameData.mRawData, ClearFrame(mCompositingFrame.Data(),
compositingFrameData.mRect, mCompositingFrame->GetRect(),
prevRect); prevRect);
} }
break; break;
case DisposalMethod::CLEAR_ALL: case DisposalMethod::CLEAR_ALL:
ClearFrame(compositingFrameData.mRawData, ClearFrame(mCompositingFrame.Data(),
compositingFrameData.mRect); mCompositingFrame->GetRect());
break; break;
case DisposalMethod::RESTORE_PREVIOUS: case DisposalMethod::RESTORE_PREVIOUS:
// It would be better to copy only the area changed back to // It would be better to copy only the area changed back to
// compositingFrame. // compositingFrame.
if (mCompositingPrevFrame) { if (mCompositingPrevFrame) {
AnimationData compositingPrevFrameData = CopyFrameImage(mCompositingPrevFrame.Data(),
mCompositingPrevFrame->GetAnimationData(); mCompositingPrevFrame->GetRect(),
mCompositingFrame.Data(),
CopyFrameImage(compositingPrevFrameData.mRawData, mCompositingFrame->GetRect());
compositingPrevFrameData.mRect,
compositingFrameData.mRawData,
compositingFrameData.mRect);
// destroy only if we don't need it for this frame's disposal // destroy only if we don't need it for this frame's disposal
if (nextFrameData.mDisposalMethod != if (nextDisposalMethod != DisposalMethod::RESTORE_PREVIOUS) {
DisposalMethod::RESTORE_PREVIOUS) {
mCompositingPrevFrame.reset(); mCompositingPrevFrame.reset();
} }
} else { } else {
ClearFrame(compositingFrameData.mRawData, ClearFrame(mCompositingFrame.Data(),
compositingFrameData.mRect); mCompositingFrame->GetRect());
} }
break; break;
@ -832,44 +782,44 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
// Note: Frame 1 never gets into DoBlend(), so (aNextFrameIndex - 1) // Note: Frame 1 never gets into DoBlend(), so (aNextFrameIndex - 1)
// will always be a valid frame number. // will always be a valid frame number.
if (mLastCompositedFrameIndex != int32_t(aNextFrameIndex - 1)) { if (mLastCompositedFrameIndex != int32_t(aNextFrameIndex - 1)) {
if (isFullPrevFrame && !prevFrame->GetIsPaletted()) { if (isFullPrevFrame && !aPrevFrame->GetIsPaletted()) {
// Just copy the bits // Just copy the bits
CopyFrameImage(prevFrameData.mRawData, CopyFrameImage(aPrevFrame.Data(),
prevRect, prevRect,
compositingFrameData.mRawData, mCompositingFrame.Data(),
compositingFrameData.mRect); mCompositingFrame->GetRect());
} else { } else {
if (needToBlankComposite) { if (needToBlankComposite) {
// Only blank composite when prev is transparent or not full. // Only blank composite when prev is transparent or not full.
if (prevFrameData.mHasAlpha || !isFullPrevFrame) { if (prevHasAlpha || !isFullPrevFrame) {
ClearFrame(compositingFrameData.mRawData, ClearFrame(mCompositingFrame.Data(),
compositingFrameData.mRect); mCompositingFrame->GetRect());
} }
} }
DrawFrameTo(prevFrameData.mRawData, prevFrameData.mRect, DrawFrameTo(aPrevFrame.Data(), aPrevFrame->GetRect(),
prevFrameData.mPaletteDataLength, aPrevFrame.PaletteDataLength(),
prevFrameData.mHasAlpha, prevHasAlpha,
compositingFrameData.mRawData, mCompositingFrame.Data(),
compositingFrameData.mRect, mCompositingFrame->GetRect(),
prevFrameData.mBlendMethod, aPrevFrame->GetBlendMethod(),
prevFrameData.mBlendRect); aPrevFrame->GetBlendRect());
} }
} }
} }
} else if (needToBlankComposite) { } else if (needToBlankComposite) {
// If we just created the composite, it could have anything in its // If we just created the composite, it could have anything in its
// buffers. Clear them // buffers. Clear them
ClearFrame(compositingFrameData.mRawData, ClearFrame(mCompositingFrame.Data(),
compositingFrameData.mRect); mCompositingFrame->GetRect());
} }
// Check if the frame we are composing wants the previous image restored after // 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 // it is done. Don't store it (again) if last frame wanted its image restored
// too // too
if ((nextFrameData.mDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) && if ((nextDisposalMethod == DisposalMethod::RESTORE_PREVIOUS) &&
(prevFrameData.mDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) { (prevDisposalMethod != DisposalMethod::RESTORE_PREVIOUS)) {
// We are storing the whole image. // 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. // overwrite.
if (!mCompositingPrevFrame) { if (!mCompositingPrevFrame) {
RefPtr<imgFrame> newFrame = new imgFrame; RefPtr<imgFrame> newFrame = new imgFrame;
@ -883,25 +833,22 @@ FrameAnimator::DoBlend(DrawableSurface& aFrames,
mCompositingPrevFrame = newFrame->RawAccessRef(); mCompositingPrevFrame = newFrame->RawAccessRef();
} }
AnimationData compositingPrevFrameData = CopyFrameImage(mCompositingFrame.Data(),
mCompositingPrevFrame->GetAnimationData(); mCompositingFrame->GetRect(),
mCompositingPrevFrame.Data(),
CopyFrameImage(compositingFrameData.mRawData, mCompositingPrevFrame->GetRect());
compositingFrameData.mRect,
compositingPrevFrameData.mRawData,
compositingPrevFrameData.mRect);
mCompositingPrevFrame->Finish(); mCompositingPrevFrame->Finish();
} }
// blit next frame into it's correct spot // blit next frame into it's correct spot
DrawFrameTo(nextFrameData.mRawData, nextFrameData.mRect, DrawFrameTo(aNextFrame.Data(), aNextFrame->GetRect(),
nextFrameData.mPaletteDataLength, aNextFrame.PaletteDataLength(),
nextFrameData.mHasAlpha, nextHasAlpha,
compositingFrameData.mRawData, mCompositingFrame.Data(),
compositingFrameData.mRect, mCompositingFrame->GetRect(),
nextFrameData.mBlendMethod, aNextFrame->GetBlendMethod(),
nextFrameData.mBlendRect); aNextFrame->GetBlendRect());
// Tell the image that it is fully 'downloaded'. // Tell the image that it is fully 'downloaded'.
mCompositingFrame->Finish(); mCompositingFrame->Finish();
@ -970,7 +917,7 @@ nsresult
FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect, FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect,
uint32_t aSrcPaletteLength, bool aSrcHasAlpha, uint32_t aSrcPaletteLength, bool aSrcHasAlpha,
uint8_t* aDstPixels, const IntRect& aDstRect, 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(aSrcData);
NS_ENSURE_ARG_POINTER(aDstPixels); 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 auto op = aBlendMethod == BlendMethod::SOURCE ? PIXMAN_OP_SRC
: PIXMAN_OP_OVER; : PIXMAN_OP_OVER;
if (aBlendMethod == BlendMethod::OVER || !aBlendRect || if (aBlendMethod == BlendMethod::OVER ||
(aBlendMethod == BlendMethod::SOURCE && aSrcRect.IsEqualEdges(*aBlendRect))) { (aBlendMethod == BlendMethod::SOURCE && aSrcRect.IsEqualEdges(aBlendRect))) {
// We don't need to do anything clever. (Or, in the case where no blend // We don't need to do anything clever. (Or, in the case where no blend
// rect was specified, we can't.) // rect was specified, we can't.)
pixman_image_composite32(op, pixman_image_composite32(op,
@ -1093,10 +1040,10 @@ FrameAnimator::DrawFrameTo(const uint8_t* aSrcData, const IntRect& aSrcRect,
src, src,
nullptr, nullptr,
dst, dst,
aBlendRect->X(), aBlendRect->Y(), aBlendRect.X(), aBlendRect.Y(),
0, 0, 0, 0,
aBlendRect->X(), aBlendRect->Y(), aBlendRect.X(), aBlendRect.Y(),
aBlendRect->Width(), aBlendRect->Height()); aBlendRect.Width(), aBlendRect.Height());
} }
pixman_image_unref(src); pixman_image_unref(src);

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

@ -343,37 +343,31 @@ private: // methods
* @param aTime the time that the animation should advance to. This will * @param aTime the time that the animation should advance to. This will
* typically be <= TimeStamp::Now(). * 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 * @returns a RefreshResult that shows whether the frame was successfully
* advanced, and its resulting dirty rect. * advanced, and its resulting dirty rect.
*/ */
RefreshResult AdvanceFrame(AnimationState& aState, RefreshResult AdvanceFrame(AnimationState& aState,
DrawableSurface& aFrames, DrawableSurface& aFrames,
RawAccessFrameRef& aCurrentFrame,
TimeStamp aTime); 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. * 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 * In the error case (like if the requested frame is not currently
* decoded), returns None(). * decoded), returns None().
*/ */
Maybe<TimeStamp> GetCurrentImgFrameEndTime(AnimationState& aState, TimeStamp GetCurrentImgFrameEndTime(AnimationState& aState,
DrawableSurface& aFrames) const; FrameTimeout aCurrentTimeout) const;
bool DoBlend(DrawableSurface& aFrames, bool DoBlend(const RawAccessFrameRef& aPrevFrame,
gfx::IntRect* aDirtyRect, const RawAccessFrameRef& aNextFrame,
uint32_t aPrevFrameIndex, uint32_t aNextFrameIndex,
uint32_t aNextFrameIndex); gfx::IntRect* aDirtyRect);
/** Clears an area of <aFrame> with transparent black. /** Clears an area of <aFrame> with transparent black.
* *
@ -413,7 +407,7 @@ private: // methods
uint32_t aSrcPaletteLength, bool aSrcHasAlpha, uint32_t aSrcPaletteLength, bool aSrcHasAlpha,
uint8_t* aDstPixels, const gfx::IntRect& aDstRect, uint8_t* aDstPixels, const gfx::IntRect& aDstRect,
BlendMethod aBlendMethod, BlendMethod aBlendMethod,
const Maybe<gfx::IntRect>& aBlendRect); const gfx::IntRect& aBlendRect);
private: // data private: // data
//! A weak pointer to our owning image. //! A weak pointer to our owning image.

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

@ -110,6 +110,15 @@ protected:
/// index of the desired frame. /// index of the desired frame.
virtual DrawableFrameRef DrawableRef(size_t aFrame) = 0; 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()) /// @return true if this ISurfaceProvider is locked. (@see SetLocked())
/// Should only be called from SurfaceCache code as it relies on SurfaceCache /// Should only be called from SurfaceCache code as it relies on SurfaceCache
/// for synchronization. /// for synchronization.
@ -199,6 +208,18 @@ public:
return mDrawableRef ? NS_OK : NS_ERROR_FAILURE; 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() void Reset()
{ {
if (!mProvider) { if (!mProvider) {

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

@ -70,7 +70,7 @@ public:
{ } { }
template <typename... Rest> 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...); nsresult rv = mNext.Configure(aRest...);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@ -360,7 +360,7 @@ public:
{ } { }
template <typename... Rest> template <typename... Rest>
nsresult Configure(const RemoveFrameRectConfig& aConfig, Rest... aRest) nsresult Configure(const RemoveFrameRectConfig& aConfig, const Rest&... aRest)
{ {
nsresult rv = mNext.Configure(aRest...); nsresult rv = mNext.Configure(aRest...);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@ -590,7 +590,7 @@ public:
{ } { }
template <typename... Rest> template <typename... Rest>
nsresult Configure(const ADAM7InterpolatingConfig& aConfig, Rest... aRest) nsresult Configure(const ADAM7InterpolatingConfig& aConfig, const Rest&... aRest)
{ {
nsresult rv = mNext.Configure(aRest...); nsresult rv = mNext.Configure(aRest...);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

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

@ -75,10 +75,11 @@ SurfaceSink::Configure(const SurfaceConfig& aConfig)
// XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
// to allocate the frame directly here and get rid of Decoder::AllocateFrame // to allocate the frame directly here and get rid of Decoder::AllocateFrame
// altogether. // altogether.
nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum, nsresult rv = aConfig.mDecoder->AllocateFrame(surfaceSize,
surfaceSize,
frameRect, frameRect,
aConfig.mFormat); aConfig.mFormat,
/* aPaletteDepth */ 0,
aConfig.mAnimParams);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }
@ -127,11 +128,11 @@ PalettedSurfaceSink::Configure(const PalettedSurfaceConfig& aConfig)
// XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want // XXX(seth): Once every Decoder subclass uses SurfacePipe, we probably want
// to allocate the frame directly here and get rid of Decoder::AllocateFrame // to allocate the frame directly here and get rid of Decoder::AllocateFrame
// altogether. // altogether.
nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mFrameNum, nsresult rv = aConfig.mDecoder->AllocateFrame(aConfig.mOutputSize,
aConfig.mOutputSize,
aConfig.mFrameRect, aConfig.mFrameRect,
aConfig.mFormat, aConfig.mFormat,
aConfig.mPaletteDepth); aConfig.mPaletteDepth,
aConfig.mAnimParams);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }

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

@ -35,6 +35,8 @@
#include "mozilla/Variant.h" #include "mozilla/Variant.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "AnimationParams.h"
namespace mozilla { namespace mozilla {
namespace image { namespace image {
@ -775,10 +777,10 @@ struct SurfaceConfig
{ {
using Filter = SurfaceSink; using Filter = SurfaceSink;
Decoder* mDecoder; /// Which Decoder to use to allocate the surface. 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::IntSize mOutputSize; /// The size of the surface.
gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX). gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX).
bool mFlipVertically; /// If true, write the rows from bottom to top. 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; using Filter = PalettedSurfaceSink;
Decoder* mDecoder; /// Which Decoder to use to allocate the surface. 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::IntSize mOutputSize; /// The logical size of the surface.
gfx::IntRect mFrameRect; /// The surface subrect which contains data. gfx::IntRect mFrameRect; /// The surface subrect which contains data.
gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX). gfx::SurfaceFormat mFormat; /// The surface format (BGRA or BGRX).
uint8_t mPaletteDepth; /// The palette depth of this surface. uint8_t mPaletteDepth; /// The palette depth of this surface.
bool mFlipVertically; /// If true, write the rows from bottom to top. 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 * @param aDecoder The decoder whose current frame the SurfacePipe will write
* to. * 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 aInputSize The original size of the image.
* @param aOutputSize The size the SurfacePipe should output. Must be the same * @param aOutputSize The size the SurfacePipe should output. Must be the same
* as @aInputSize or smaller. If smaller, the image will be * 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 aFrameRect The portion of the image that actually contains data.
* @param aFormat The surface format of the image; generally B8G8R8A8 or * @param aFormat The surface format of the image; generally B8G8R8A8 or
* B8G8R8X8. * B8G8R8X8.
* @param aAnimParams Extra parameters used by animated images.
* @param aFlags Flags enabling or disabling various functionality for the * @param aFlags Flags enabling or disabling various functionality for the
* SurfacePipe; see the SurfacePipeFlags documentation for more * SurfacePipe; see the SurfacePipeFlags documentation for more
* information. * information.
@ -89,11 +88,11 @@ public:
*/ */
static Maybe<SurfacePipe> static Maybe<SurfacePipe>
CreateSurfacePipe(Decoder* aDecoder, CreateSurfacePipe(Decoder* aDecoder,
uint32_t aFrameNum,
const nsIntSize& aInputSize, const nsIntSize& aInputSize,
const nsIntSize& aOutputSize, const nsIntSize& aOutputSize,
const nsIntRect& aFrameRect, const nsIntRect& aFrameRect,
gfx::SurfaceFormat aFormat, gfx::SurfaceFormat aFormat,
const Maybe<AnimationParams>& aAnimParams,
SurfacePipeFlags aFlags) SurfacePipeFlags aFlags)
{ {
const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE);
@ -125,8 +124,8 @@ public:
ADAM7InterpolatingConfig interpolatingConfig; ADAM7InterpolatingConfig interpolatingConfig;
RemoveFrameRectConfig removeFrameRectConfig { aFrameRect }; RemoveFrameRectConfig removeFrameRectConfig { aFrameRect };
DownscalingConfig downscalingConfig { aInputSize, aFormat }; DownscalingConfig downscalingConfig { aInputSize, aFormat };
SurfaceConfig surfaceConfig { aDecoder, aFrameNum, aOutputSize, SurfaceConfig surfaceConfig { aDecoder, aOutputSize, aFormat,
aFormat, flipVertically }; flipVertically, aAnimParams };
Maybe<SurfacePipe> pipe; Maybe<SurfacePipe> pipe;
@ -181,13 +180,12 @@ public:
* *
* @param aDecoder The decoder whose current frame the SurfacePipe will write * @param aDecoder The decoder whose current frame the SurfacePipe will write
* to. * 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 aInputSize The original size of the image.
* @param aFrameRect The portion of the image that actually contains data. * @param aFrameRect The portion of the image that actually contains data.
* @param aFormat The surface format of the image; generally B8G8R8A8 or * @param aFormat The surface format of the image; generally B8G8R8A8 or
* B8G8R8X8. * B8G8R8X8.
* @param aPaletteDepth The palette depth of the image. * @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 * @param aFlags Flags enabling or disabling various functionality for the
* SurfacePipe; see the SurfacePipeFlags documentation for more * SurfacePipe; see the SurfacePipeFlags documentation for more
* information. * information.
@ -198,11 +196,11 @@ public:
*/ */
static Maybe<SurfacePipe> static Maybe<SurfacePipe>
CreatePalettedSurfacePipe(Decoder* aDecoder, CreatePalettedSurfacePipe(Decoder* aDecoder,
uint32_t aFrameNum,
const nsIntSize& aInputSize, const nsIntSize& aInputSize,
const nsIntRect& aFrameRect, const nsIntRect& aFrameRect,
gfx::SurfaceFormat aFormat, gfx::SurfaceFormat aFormat,
uint8_t aPaletteDepth, uint8_t aPaletteDepth,
const Maybe<AnimationParams>& aAnimParams,
SurfacePipeFlags aFlags) SurfacePipeFlags aFlags)
{ {
const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE); const bool deinterlace = bool(aFlags & SurfacePipeFlags::DEINTERLACE);
@ -211,9 +209,9 @@ public:
// Construct configurations for the SurfaceFilters. // Construct configurations for the SurfaceFilters.
DeinterlacingConfig<uint8_t> deinterlacingConfig { progressiveDisplay }; DeinterlacingConfig<uint8_t> deinterlacingConfig { progressiveDisplay };
PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aFrameNum, aInputSize, PalettedSurfaceConfig palettedSurfaceConfig { aDecoder, aInputSize, aFrameRect,
aFrameRect, aFormat, aPaletteDepth, aFormat, aPaletteDepth,
flipVertically }; flipVertically, aAnimParams };
Maybe<SurfacePipe> pipe; Maybe<SurfacePipe> pipe;
@ -229,7 +227,7 @@ public:
private: private:
template <typename... Configs> template <typename... Configs>
static Maybe<SurfacePipe> static Maybe<SurfacePipe>
MakePipe(Configs... aConfigs) MakePipe(const Configs&... aConfigs)
{ {
auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>(); auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>();
nsresult rv = pipe->Configure(aConfigs...); nsresult rv = pipe->Configure(aConfigs...);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше