зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge on a CLOSED TREE
This commit is contained in:
Коммит
cf2048abd6
|
@ -1,5 +1,5 @@
|
|||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 2.2.224
|
||||
Current extension version is: 2.3.13
|
||||
|
||||
Taken from upstream commit: a98ce9cb
|
||||
Taken from upstream commit: 28326165
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '2.2.224';
|
||||
var pdfjsBuild = 'a98ce9cb';
|
||||
var pdfjsVersion = '2.3.13';
|
||||
var pdfjsBuild = '28326165';
|
||||
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(1);
|
||||
|
||||
|
@ -1304,7 +1304,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||
|
||||
return worker.messageHandler.sendWithPromise('GetDocRequest', {
|
||||
docId,
|
||||
apiVersion: '2.2.224',
|
||||
apiVersion: '2.3.13',
|
||||
source: {
|
||||
data: source.data,
|
||||
url: source.url,
|
||||
|
@ -1633,7 +1633,6 @@ class PDFPageProxy {
|
|||
const intentState = this.intentStates[renderingIntent];
|
||||
|
||||
if (!intentState.displayReadyCapability) {
|
||||
intentState.receivingOperatorList = true;
|
||||
intentState.displayReadyCapability = (0, _util.createPromiseCapability)();
|
||||
intentState.operatorList = {
|
||||
fnArray: [],
|
||||
|
@ -1734,7 +1733,6 @@ class PDFPageProxy {
|
|||
if (!intentState.opListReadCapability) {
|
||||
opListTask = {};
|
||||
opListTask.operatorListChanged = operatorListChanged;
|
||||
intentState.receivingOperatorList = true;
|
||||
intentState.opListReadCapability = (0, _util.createPromiseCapability)();
|
||||
intentState.renderTasks = [];
|
||||
intentState.renderTasks.push(opListTask);
|
||||
|
@ -1833,7 +1831,7 @@ class PDFPageProxy {
|
|||
_tryCleanup(resetStats = false) {
|
||||
if (!this.pendingCleanup || Object.keys(this.intentStates).some(function (intent) {
|
||||
const intentState = this.intentStates[intent];
|
||||
return intentState.renderTasks.length !== 0 || intentState.receivingOperatorList;
|
||||
return intentState.renderTasks.length !== 0 || !intentState.operatorList.lastChunk;
|
||||
}, this)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1874,8 +1872,6 @@ class PDFPageProxy {
|
|||
}
|
||||
|
||||
if (operatorListChunk.lastChunk) {
|
||||
intentState.receivingOperatorList = false;
|
||||
|
||||
this._tryCleanup();
|
||||
}
|
||||
}
|
||||
|
@ -2612,18 +2608,20 @@ class WorkerTransport {
|
|||
const page = this.pageCache[data.pageIndex];
|
||||
const intentState = page.intentStates[data.intent];
|
||||
|
||||
if (intentState.displayReadyCapability) {
|
||||
intentState.displayReadyCapability.reject(new Error(data.error));
|
||||
} else {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
if (intentState.operatorList) {
|
||||
intentState.operatorList.lastChunk = true;
|
||||
|
||||
for (let i = 0; i < intentState.renderTasks.length; i++) {
|
||||
intentState.renderTasks[i].operatorListChanged();
|
||||
}
|
||||
|
||||
page._tryCleanup();
|
||||
}
|
||||
|
||||
if (intentState.displayReadyCapability) {
|
||||
intentState.displayReadyCapability.reject(new Error(data.error));
|
||||
} else {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
}, this);
|
||||
messageHandler.on('UnsupportedFeature', this._onUnsupportedFeature, this);
|
||||
|
@ -3100,9 +3098,9 @@ const InternalRenderTask = function InternalRenderTaskClosure() {
|
|||
return InternalRenderTask;
|
||||
}();
|
||||
|
||||
const version = '2.2.224';
|
||||
const version = '2.3.13';
|
||||
exports.version = version;
|
||||
const build = 'a98ce9cb';
|
||||
const build = '28326165';
|
||||
exports.build = build;
|
||||
|
||||
/***/ }),
|
||||
|
@ -8642,7 +8640,7 @@ var renderTextLayer = function renderTextLayerClosure() {
|
|||
this._layoutTextCtx.canvas.height = 0;
|
||||
this._layoutTextCtx = null;
|
||||
}
|
||||
});
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
TextLayerRenderTask.prototype = {
|
||||
|
|
|
@ -123,8 +123,8 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
|
||||
|
||||
const pdfjsVersion = '2.2.224';
|
||||
const pdfjsBuild = 'a98ce9cb';
|
||||
const pdfjsVersion = '2.3.13';
|
||||
const pdfjsBuild = '28326165';
|
||||
|
||||
const pdfjsCoreWorker = __w_pdfjs_require__(1);
|
||||
|
||||
|
@ -240,7 +240,7 @@ var WorkerMessageHandler = {
|
|||
var WorkerTasks = [];
|
||||
const verbosity = (0, _util.getVerbosityLevel)();
|
||||
let apiVersion = docParams.apiVersion;
|
||||
let workerVersion = '2.2.224';
|
||||
let workerVersion = '2.3.13';
|
||||
|
||||
if (apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
|
||||
|
@ -3176,22 +3176,9 @@ exports.Page = Page;
|
|||
const FINGERPRINT_FIRST_BYTES = 1024;
|
||||
const EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + '\x00\x00\x00\x00\x00\x00\x00\x00\x00';
|
||||
|
||||
function find(stream, needle, limit, backwards) {
|
||||
const pos = stream.pos;
|
||||
const end = stream.end;
|
||||
|
||||
if (pos + limit > end) {
|
||||
limit = end - pos;
|
||||
}
|
||||
|
||||
const strBuf = [];
|
||||
|
||||
for (let i = 0; i < limit; ++i) {
|
||||
strBuf.push(String.fromCharCode(stream.getByte()));
|
||||
}
|
||||
|
||||
const str = strBuf.join('');
|
||||
stream.pos = pos;
|
||||
function find(stream, needle, limit, backwards = false) {
|
||||
(0, _util.assert)(limit > 0, 'The "limit" must be a positive integer.');
|
||||
const str = (0, _util.bytesToString)(stream.peekBytes(limit));
|
||||
const index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
|
||||
|
||||
if (index === -1) {
|
||||
|
|
|
@ -622,6 +622,10 @@ let PDFViewerApplication = {
|
|||
},
|
||||
|
||||
zoomIn(ticks) {
|
||||
if (this.pdfViewer.isInPresentationMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newScale = this.pdfViewer.currentScale;
|
||||
|
||||
do {
|
||||
|
@ -634,6 +638,10 @@ let PDFViewerApplication = {
|
|||
},
|
||||
|
||||
zoomOut(ticks) {
|
||||
if (this.pdfViewer.isInPresentationMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newScale = this.pdfViewer.currentScale;
|
||||
|
||||
do {
|
||||
|
@ -8655,6 +8663,10 @@ class BaseViewer {
|
|||
}
|
||||
|
||||
onePageRenderedCapability.promise.then(() => {
|
||||
if (this.findController) {
|
||||
this.findController.setDocument(pdfDocument);
|
||||
}
|
||||
|
||||
if (pdfDocument.loadingParams['disableAutoFetch']) {
|
||||
pagesCapability.resolve();
|
||||
return;
|
||||
|
@ -8688,10 +8700,6 @@ class BaseViewer {
|
|||
source: this
|
||||
});
|
||||
|
||||
if (this.findController) {
|
||||
this.findController.setDocument(pdfDocument);
|
||||
}
|
||||
|
||||
if (this.defaultRenderingQueue) {
|
||||
this.update();
|
||||
}
|
||||
|
@ -11834,18 +11842,23 @@ function FirefoxPrintService(pdfDocument, pagesOverview, printContainer) {
|
|||
|
||||
FirefoxPrintService.prototype = {
|
||||
layout() {
|
||||
let pdfDocument = this.pdfDocument;
|
||||
let printContainer = this.printContainer;
|
||||
let body = document.querySelector('body');
|
||||
const {
|
||||
pdfDocument,
|
||||
pagesOverview,
|
||||
printContainer
|
||||
} = this;
|
||||
const body = document.querySelector('body');
|
||||
body.setAttribute('data-pdfjsprinting', true);
|
||||
|
||||
for (let i = 0, ii = this.pagesOverview.length; i < ii; ++i) {
|
||||
composePage(pdfDocument, i + 1, this.pagesOverview[i], printContainer);
|
||||
for (let i = 0, ii = pagesOverview.length; i < ii; ++i) {
|
||||
composePage(pdfDocument, i + 1, pagesOverview[i], printContainer);
|
||||
}
|
||||
},
|
||||
|
||||
destroy() {
|
||||
this.printContainer.textContent = '';
|
||||
const body = document.querySelector('body');
|
||||
body.removeAttribute('data-pdfjsprinting');
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ origin:
|
|||
|
||||
# Human-readable identifier for this version/release
|
||||
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
||||
release: version 2.2.224
|
||||
release: version 2.3.13
|
||||
|
||||
# The package's license, where possible using the mnemonic from
|
||||
# https://spdx.org/licenses/
|
||||
|
|
|
@ -69,6 +69,7 @@ export async function buildOriginalScopes(
|
|||
const actor = (await generatedScopes).actor;
|
||||
const scope = {
|
||||
type: "function",
|
||||
scopeKind: "",
|
||||
actor,
|
||||
bindings,
|
||||
parent: null,
|
||||
|
|
|
@ -49,8 +49,6 @@ let breakpoints: { [string]: Object };
|
|||
let eventBreakpoints: ?EventListenerActiveList;
|
||||
let supportsWasm: boolean;
|
||||
|
||||
let shouldWaitForWorkers = false;
|
||||
|
||||
type Dependencies = {
|
||||
threadFront: ThreadFront,
|
||||
tabTarget: TabTarget,
|
||||
|
@ -121,15 +119,23 @@ function listWorkerThreadFronts() {
|
|||
return (Object.values(workerClients): any).map(({ thread }) => thread);
|
||||
}
|
||||
|
||||
function forEachWorkerThread(iteratee) {
|
||||
const promises = listWorkerThreadFronts().map(thread => iteratee(thread));
|
||||
|
||||
// Do not return promises for the caller to wait on unless a flag is set.
|
||||
// Currently, worker threads are not guaranteed to respond to all requests,
|
||||
// if we send a request while they are shutting down. See bug 1529163.
|
||||
if (shouldWaitForWorkers) {
|
||||
return Promise.all(promises);
|
||||
}
|
||||
function forEachThread(iteratee) {
|
||||
// We have to be careful here to atomically initiate the operation on every
|
||||
// thread, with no intervening await. Otherwise, other code could run and
|
||||
// trigger additional thread operations. Requests on server threads will
|
||||
// resolve in FIFO order, and this could result in client and server state
|
||||
// going out of sync.
|
||||
const mainThreadPromise = iteratee(threadFront);
|
||||
const workerPromises = listWorkerThreadFronts().map(t => {
|
||||
try {
|
||||
iteratee(t);
|
||||
} catch (e) {
|
||||
// If a worker thread shuts down while sending the message then it will
|
||||
// throw. Ignore these errors.
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
return Promise.all([mainThreadPromise, ...workerPromises]);
|
||||
}
|
||||
|
||||
function resume(thread: string): Promise<*> {
|
||||
|
@ -186,10 +192,6 @@ function locationKey(location: BreakpointLocation) {
|
|||
return `${(sourceUrl: any)}:${(sourceId: any)}:${line}:${(column: any)}`;
|
||||
}
|
||||
|
||||
function waitForWorkers(shouldWait: boolean) {
|
||||
shouldWaitForWorkers = shouldWait;
|
||||
}
|
||||
|
||||
function detachWorkers() {
|
||||
for (const thread of listWorkerThreadFronts()) {
|
||||
thread.detach();
|
||||
|
@ -217,7 +219,7 @@ function hasBreakpoint(location: BreakpointLocation) {
|
|||
return !!breakpoints[locationKey(location)];
|
||||
}
|
||||
|
||||
async function setBreakpoint(
|
||||
function setBreakpoint(
|
||||
location: BreakpointLocation,
|
||||
options: BreakpointOptions
|
||||
) {
|
||||
|
@ -225,27 +227,14 @@ async function setBreakpoint(
|
|||
options = maybeGenerateLogGroupId(options);
|
||||
breakpoints[locationKey(location)] = { location, options };
|
||||
|
||||
// We have to be careful here to atomically initiate the setBreakpoint() call
|
||||
// on every thread, with no intervening await. Otherwise, other code could run
|
||||
// and change or remove the breakpoint before we finish calling setBreakpoint
|
||||
// on all threads. Requests on server threads will resolve in FIFO order, and
|
||||
// this could result in the breakpoint state here being out of sync with the
|
||||
// breakpoints that are installed in the server.
|
||||
const mainThreadPromise = threadFront.setBreakpoint(location, options);
|
||||
|
||||
await forEachWorkerThread(thread => thread.setBreakpoint(location, options));
|
||||
await mainThreadPromise;
|
||||
return forEachThread(thread => thread.setBreakpoint(location, options));
|
||||
}
|
||||
|
||||
async function removeBreakpoint(location: PendingLocation) {
|
||||
function removeBreakpoint(location: PendingLocation) {
|
||||
maybeClearLogpoint((location: any));
|
||||
delete breakpoints[locationKey((location: any))];
|
||||
|
||||
// Delay waiting on this promise, for the same reason as in setBreakpoint.
|
||||
const mainThreadPromise = threadFront.removeBreakpoint(location);
|
||||
|
||||
await forEachWorkerThread(thread => thread.removeBreakpoint(location));
|
||||
await mainThreadPromise;
|
||||
return forEachThread(thread => thread.removeBreakpoint(location));
|
||||
}
|
||||
|
||||
async function evaluateInFrame(script: Script, options: EvaluateParam) {
|
||||
|
@ -325,20 +314,15 @@ async function getFrameScopes(frame: Frame): Promise<*> {
|
|||
return sourceThreadFront.getEnvironment(frame.id);
|
||||
}
|
||||
|
||||
async function pauseOnExceptions(
|
||||
function pauseOnExceptions(
|
||||
shouldPauseOnExceptions: boolean,
|
||||
shouldPauseOnCaughtExceptions: boolean
|
||||
): Promise<*> {
|
||||
await threadFront.pauseOnExceptions(
|
||||
shouldPauseOnExceptions,
|
||||
// Providing opposite value because server
|
||||
// uses "shouldIgnoreCaughtExceptions"
|
||||
!shouldPauseOnCaughtExceptions
|
||||
);
|
||||
|
||||
await forEachWorkerThread(thread =>
|
||||
return forEachThread(thread =>
|
||||
thread.pauseOnExceptions(
|
||||
shouldPauseOnExceptions,
|
||||
// Providing opposite value because server
|
||||
// uses "shouldIgnoreCaughtExceptions"
|
||||
!shouldPauseOnCaughtExceptions
|
||||
)
|
||||
);
|
||||
|
@ -357,20 +341,18 @@ async function blackBox(
|
|||
}
|
||||
}
|
||||
|
||||
async function setSkipPausing(shouldSkip: boolean) {
|
||||
await threadFront.skipBreakpoints(shouldSkip);
|
||||
await forEachWorkerThread(thread => thread.skipBreakpoints(shouldSkip));
|
||||
function setSkipPausing(shouldSkip: boolean) {
|
||||
return forEachThread(thread => thread.skipBreakpoints(shouldSkip));
|
||||
}
|
||||
|
||||
function interrupt(thread: string): Promise<*> {
|
||||
return lookupThreadFront(thread).interrupt();
|
||||
}
|
||||
|
||||
async function setEventListenerBreakpoints(ids: string[]) {
|
||||
function setEventListenerBreakpoints(ids: string[]) {
|
||||
eventBreakpoints = ids;
|
||||
|
||||
await threadFront.setActiveEventBreakpoints(ids);
|
||||
await forEachWorkerThread(thread => thread.setActiveEventBreakpoints(ids));
|
||||
return forEachThread(thread => thread.setActiveEventBreakpoints(ids));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line
|
||||
|
@ -563,7 +545,6 @@ const clientCommands = {
|
|||
setSkipPausing,
|
||||
setEventListenerBreakpoints,
|
||||
getEventListenerBreakpointTypes,
|
||||
waitForWorkers,
|
||||
detachWorkers,
|
||||
hasWasmSupport,
|
||||
lookupConsoleClient,
|
||||
|
|
|
@ -34,6 +34,7 @@ exports[`Frame getFrameTitle 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -86,6 +87,7 @@ exports[`Frame getFrameTitle 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -145,6 +147,7 @@ exports[`Frame library frame 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -198,6 +201,7 @@ exports[`Frame library frame 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -256,6 +260,7 @@ exports[`Frame user frame (not selected) 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -308,6 +313,7 @@ exports[`Frame user frame (not selected) 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -366,6 +372,7 @@ exports[`Frame user frame 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -418,6 +425,7 @@ exports[`Frame user frame 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
|
|
@ -31,6 +31,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -75,6 +76,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -121,6 +123,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -165,6 +168,7 @@ exports[`Frames Blackboxed Frames filters blackboxed frames 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
|
|
@ -38,6 +38,7 @@ exports[`Group displays a group 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -110,6 +111,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -181,6 +183,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -227,6 +230,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -286,6 +290,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -332,6 +337,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -391,6 +397,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -437,6 +444,7 @@ exports[`Group passes the getFrameTitle prop to the Frame components 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -501,6 +509,7 @@ exports[`Group renders group with anonymous functions 1`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -573,6 +582,7 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -644,6 +654,7 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -689,6 +700,7 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -748,6 +760,7 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -793,6 +806,7 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -852,6 +866,7 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
@ -897,6 +912,7 @@ exports[`Group renders group with anonymous functions 2`] = `
|
|||
"function": null,
|
||||
"object": null,
|
||||
"parent": null,
|
||||
"scopeKind": "",
|
||||
"type": "block",
|
||||
},
|
||||
"source": Object {
|
||||
|
|
|
@ -457,6 +457,7 @@ export type Scope = {|
|
|||
parameterNames: string[],
|
||||
},
|
||||
type: string,
|
||||
scopeKind: string,
|
||||
|};
|
||||
|
||||
export type MainThread = {
|
||||
|
|
|
@ -301,6 +301,7 @@ function generateClientScope(
|
|||
parent: acc,
|
||||
actor: `originalActor${i}`,
|
||||
type: orig.type,
|
||||
scopeKind: orig.scopeKind,
|
||||
bindings: {
|
||||
arguments: [],
|
||||
variables,
|
||||
|
|
|
@ -15,6 +15,7 @@ import type { NamedValue } from "./types";
|
|||
|
||||
export type RenderableScope = {
|
||||
type: $ElementType<Scope, "type">,
|
||||
scopeKind: $ElementType<Scope, "scopeKind">,
|
||||
actor: $ElementType<Scope, "actor">,
|
||||
bindings: $ElementType<Scope, "bindings">,
|
||||
parent: ?RenderableScope,
|
||||
|
@ -109,3 +110,22 @@ export function getScope(
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function mergeScopes(
|
||||
scope: RenderableScope,
|
||||
parentScope: RenderableScope,
|
||||
item: NamedValue,
|
||||
parentItem: NamedValue
|
||||
) {
|
||||
if (scope.scopeKind == "function lexical" && parentScope.type == "function") {
|
||||
const contents = (item.contents: any).concat(parentItem.contents);
|
||||
contents.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
return {
|
||||
name: parentItem.name,
|
||||
path: parentItem.path,
|
||||
contents,
|
||||
type: NODE_TYPES.BLOCK,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// @flow
|
||||
|
||||
import { getScope, type RenderableScope } from "./getScope";
|
||||
import { getScope, mergeScopes, type RenderableScope } from "./getScope";
|
||||
|
||||
import type { Frame, Why, BindingContents } from "../../../types";
|
||||
|
||||
|
@ -32,9 +32,11 @@ export function getScopes(
|
|||
|
||||
let scope = frameScopes;
|
||||
let scopeIndex = 1;
|
||||
let prev = null,
|
||||
prevItem = null;
|
||||
|
||||
while (scope) {
|
||||
const scopeItem = getScope(
|
||||
let scopeItem = getScope(
|
||||
scope,
|
||||
selectedFrame,
|
||||
frameScopes,
|
||||
|
@ -43,8 +45,16 @@ export function getScopes(
|
|||
);
|
||||
|
||||
if (scopeItem) {
|
||||
const mergedItem =
|
||||
prev && prevItem ? mergeScopes(prev, scope, prevItem, scopeItem) : null;
|
||||
if (mergedItem) {
|
||||
scopeItem = mergedItem;
|
||||
scopes.pop();
|
||||
}
|
||||
scopes.push(scopeItem);
|
||||
}
|
||||
prev = scope;
|
||||
prevItem = scopeItem;
|
||||
scopeIndex++;
|
||||
scope = scope.parent;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ function makeMockScope(
|
|||
object: null,
|
||||
function: null,
|
||||
type,
|
||||
scopeKind: "",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ function findScopes(
|
|||
return found.map(i => {
|
||||
return {
|
||||
type: i.type,
|
||||
scopeKind: i.scopeKind,
|
||||
displayName: i.displayName,
|
||||
start: i.start,
|
||||
end: i.end,
|
||||
|
|
|
@ -118,6 +118,7 @@ export type ScopeBindingList = {
|
|||
|
||||
export type SourceScope = {
|
||||
type: "object" | "function" | "block",
|
||||
scopeKind: string,
|
||||
displayName: string,
|
||||
start: SourceLocation,
|
||||
end: SourceLocation,
|
||||
|
@ -222,6 +223,7 @@ function toParsedScopes(
|
|||
scope.type === "module" || scope.type === "function-body"
|
||||
? "block"
|
||||
: scope.type,
|
||||
scopeKind: "",
|
||||
displayName: scope.displayName,
|
||||
bindings: scope.bindings,
|
||||
children: toParsedScopes(scope.children, sourceId),
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -674,6 +674,7 @@ support-files =
|
|||
examples/doc-scopes-xrays.html
|
||||
examples/doc-message-run-to-completion.html
|
||||
examples/doc-message-run-to-completion-frame.html
|
||||
examples/doc-merge-scopes.html
|
||||
|
||||
[browser_dbg-asm.js]
|
||||
[browser_dbg-audiocontext.js]
|
||||
|
@ -813,4 +814,5 @@ skip-if = (os == 'linux' && debug) || (os == 'linux' && asan) || ccov #Bug 1456
|
|||
[browser_dbg-old-breakpoint.js]
|
||||
[browser_dbg-idb-run-to-completion.js]
|
||||
[browser_dbg-scopes-xrays.js]
|
||||
[browser_dbg-merge-scopes.js]
|
||||
[browser_dbg-message-run-to-completion.js]
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function getLabel(dbg, index) {
|
||||
return findElement(dbg, "scopeNode", index).innerText;
|
||||
}
|
||||
|
||||
function expectLabels(dbg, array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
is(getLabel(dbg, i + 1), array[i], `Correct label ${array[i]} for index ${i + 1}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that adjacent scopes are merged together as expected.
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-merge-scopes.html");
|
||||
|
||||
invokeInTab("run");
|
||||
await waitForPaused(dbg, "doc-merge-scopes.html");
|
||||
|
||||
// Function body and function lexical scopes are merged together.
|
||||
expectLabels(dbg, ["first", "<this>", "arguments", "x", "y", "z"]);
|
||||
|
||||
await resume(dbg);
|
||||
await waitForPaused(dbg);
|
||||
|
||||
// Function body and inner lexical scopes are not merged together.
|
||||
await toggleScopeNode(dbg, 4);
|
||||
expectLabels(dbg, ["Block", "<this>", "y", "second", "arguments", "x"]);
|
||||
|
||||
await resume(dbg);
|
||||
await waitForPaused(dbg);
|
||||
|
||||
// When there is a function body, function lexical, and inner lexical scope,
|
||||
// the first two are merged together.
|
||||
await toggleScopeNode(dbg, 4);
|
||||
expectLabels(dbg, ["Block", "<this>", "z", "third", "arguments", "v", "x", "y"]);
|
||||
});
|
|
@ -33,41 +33,41 @@ add_task(async function() {
|
|||
'The second element in the scope panel is "<this>"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 3),
|
||||
getScopeNodeLabel(dbg, 4),
|
||||
"phonebook",
|
||||
'The third element in the scope panel is "phonebook"'
|
||||
'The fourth element in the scope panel is "phonebook"'
|
||||
);
|
||||
|
||||
info("Expand `phonebook`");
|
||||
await expandNode(dbg, 3);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 4),
|
||||
"S",
|
||||
'The fourth element in the scope panel is "S"'
|
||||
);
|
||||
|
||||
info("Expand `S`");
|
||||
await expandNode(dbg, 4);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 5),
|
||||
"sarah",
|
||||
'The fifth element in the scope panel is "sarah"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 6),
|
||||
"serena",
|
||||
'The sixth element in the scope panel is "serena"'
|
||||
"S",
|
||||
'The fifth element in the scope panel is "S"'
|
||||
);
|
||||
|
||||
info("Expand `sarah`");
|
||||
info("Expand `S`");
|
||||
await expandNode(dbg, 5);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 6),
|
||||
"lastName",
|
||||
'The sixth element in the scope panel is now "lastName"'
|
||||
"sarah",
|
||||
'The sixth element in the scope panel is "sarah"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeValue(dbg, 6),
|
||||
getScopeNodeLabel(dbg, 7),
|
||||
"serena",
|
||||
'The seventh element in the scope panel is "serena"'
|
||||
);
|
||||
|
||||
info("Expand `sarah`");
|
||||
await expandNode(dbg, 6);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 7),
|
||||
"lastName",
|
||||
'The seventh element in the scope panel is now "lastName"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeValue(dbg, 7),
|
||||
'"Doe"',
|
||||
'The "lastName" element has the expected "Doe" value'
|
||||
);
|
||||
|
@ -81,8 +81,8 @@ add_task(async function() {
|
|||
'The second element in the scope panel is "<this>"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 3),
|
||||
getScopeNodeLabel(dbg, 4),
|
||||
"phonebook",
|
||||
'The third element in the scope panel is "phonebook"'
|
||||
'The fourth element in the scope panel is "phonebook"'
|
||||
);
|
||||
});
|
||||
|
|
|
@ -9,11 +9,6 @@ add_task(async function() {
|
|||
|
||||
const workerSource = findSource(dbg, "simple-worker.js");
|
||||
|
||||
// NOTE: by default we do not wait on worker
|
||||
// commands to complete because the thread could be
|
||||
// shutting down.
|
||||
dbg.client.waitForWorkers(true);
|
||||
|
||||
await selectSource(dbg, "simple-worker.js");
|
||||
await waitForSelectedSource(dbg, "simple-worker.js");
|
||||
await addBreakpoint(dbg, workerSource, 1);
|
||||
|
|
|
@ -44,11 +44,6 @@ add_task(async function() {
|
|||
const dbg = await initDebugger("doc-windowless-workers.html");
|
||||
const mainThread = dbg.toolbox.threadFront.actor;
|
||||
|
||||
// NOTE: by default we do not wait on worker
|
||||
// commands to complete because the thread could be
|
||||
// shutting down.
|
||||
dbg.client.waitForWorkers(true);
|
||||
|
||||
const workers = await getWorkers(dbg);
|
||||
ok(workers.length == 2, "Got two workers");
|
||||
const thread1 = workers[0].actor;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<script>
|
||||
function run() {
|
||||
setTimeout(first);
|
||||
setTimeout(second);
|
||||
setTimeout(third);
|
||||
}
|
||||
|
||||
function first(x) {
|
||||
let y = 0;
|
||||
var z = 1;
|
||||
debugger;
|
||||
}
|
||||
|
||||
function second(x) {
|
||||
if (second) {
|
||||
let y = 0;
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
|
||||
function third(x) {
|
||||
let y = 1;
|
||||
if (y) {
|
||||
let z = 0;
|
||||
var v = 2;
|
||||
debugger;
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -531,7 +531,6 @@ async function initDebugger(url, ...sources) {
|
|||
await clearDebuggerPreferences();
|
||||
const toolbox = await openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
|
||||
const dbg = createDebuggerContext(toolbox);
|
||||
dbg.client.waitForWorkers(false);
|
||||
|
||||
await waitForSources(dbg, ...sources);
|
||||
return dbg;
|
||||
|
|
|
@ -49,6 +49,8 @@ const EnvironmentActor = ActorClassWithSpec(environmentSpec, {
|
|||
form.type = this.obj.type;
|
||||
}
|
||||
|
||||
form.scopeKind = this.obj.scopeKind;
|
||||
|
||||
// Does this environment have a parent?
|
||||
if (this.obj.parent) {
|
||||
form.parent = this.threadActor
|
||||
|
|
|
@ -37,7 +37,8 @@ class BasicRenderingContext2D {
|
|||
virtual void Transform(double aM11, double aM12, double aM21, double aM22,
|
||||
double aDx, double aDy,
|
||||
mozilla::ErrorResult& aError) = 0;
|
||||
virtual already_AddRefed<DOMMatrix> GetTransform(mozilla::ErrorResult& aError) = 0;
|
||||
virtual already_AddRefed<DOMMatrix> GetTransform(
|
||||
mozilla::ErrorResult& aError) = 0;
|
||||
virtual void SetTransform(double aM11, double aM12, double aM21, double aM22,
|
||||
double aDx, double aDy,
|
||||
mozilla::ErrorResult& aError) = 0;
|
||||
|
|
|
@ -95,7 +95,8 @@ class CanvasRenderingContext2D final : public nsICanvasRenderingContextInternal,
|
|||
void Translate(double aX, double aY, mozilla::ErrorResult& aError) override;
|
||||
void Transform(double aM11, double aM12, double aM21, double aM22, double aDx,
|
||||
double aDy, mozilla::ErrorResult& aError) override;
|
||||
already_AddRefed<DOMMatrix> GetTransform(mozilla::ErrorResult& aError) override;
|
||||
already_AddRefed<DOMMatrix> GetTransform(
|
||||
mozilla::ErrorResult& aError) override;
|
||||
void SetTransform(double aM11, double aM12, double aM21, double aM22,
|
||||
double aDx, double aDy,
|
||||
mozilla::ErrorResult& aError) override;
|
||||
|
|
|
@ -75,8 +75,7 @@ class APZTestData {
|
|||
}
|
||||
void RecordHitResult(const ScreenPoint& aPoint,
|
||||
const mozilla::gfx::CompositorHitTestInfo& aResult,
|
||||
const LayersId& aLayersId,
|
||||
const ViewID& aScrollId) {
|
||||
const LayersId& aLayersId, const ViewID& aScrollId) {
|
||||
mHitResults.AppendElement(HitResult{aPoint, aResult, aLayersId, aScrollId});
|
||||
}
|
||||
void RecordAdditionalData(const std::string& aKey,
|
||||
|
|
|
@ -105,8 +105,8 @@ already_AddRefed<gfx::DrawTarget> CanvasChild::CreateDrawTarget(
|
|||
|
||||
RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget(
|
||||
gfx::BackendType::SKIA, gfx::IntSize(1, 1), aFormat);
|
||||
RefPtr<gfx::DrawTarget> dt =
|
||||
MakeAndAddRef<gfx::DrawTargetRecording>(mRecorder, dummyDt, gfx::IntRect(gfx::IntPoint(0, 0), aSize));
|
||||
RefPtr<gfx::DrawTarget> dt = MakeAndAddRef<gfx::DrawTargetRecording>(
|
||||
mRecorder, dummyDt, gfx::IntRect(gfx::IntPoint(0, 0), aSize));
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -676,8 +676,8 @@ struct DIGroup {
|
|||
RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget(
|
||||
gfx::BackendType::SKIA, gfx::IntSize(1, 1), format);
|
||||
|
||||
RefPtr<gfx::DrawTarget> dt =
|
||||
gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, IntRect(IntPoint(0, 0), dtSize));
|
||||
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(
|
||||
recorder, dummyDt, IntRect(IntPoint(0, 0), dtSize));
|
||||
// Setup the gfxContext
|
||||
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
|
||||
GP("ctx-offset %f %f\n", bounds.x, bounds.y);
|
||||
|
@ -1336,11 +1336,11 @@ void Grouper::ConstructItemInsideInactive(
|
|||
// still
|
||||
aGroup->ComputeGeometryChange(aItem, data, mTransform, mDisplayListBuilder);
|
||||
|
||||
// Temporarily restrict the image bounds to the bounds of the container so that
|
||||
// clipped children within the container know about the clip. This ensures
|
||||
// that the bounds passed to FlushItem are contained in the bounds of the clip
|
||||
// so that we don't include items in the recording without including their
|
||||
// corresponding clipping items.
|
||||
// Temporarily restrict the image bounds to the bounds of the container so
|
||||
// that clipped children within the container know about the clip. This
|
||||
// ensures that the bounds passed to FlushItem are contained in the bounds of
|
||||
// the clip so that we don't include items in the recording without including
|
||||
// their corresponding clipping items.
|
||||
IntRect oldClippedImageBounds = aGroup->mClippedImageBounds;
|
||||
aGroup->mClippedImageBounds =
|
||||
aGroup->mClippedImageBounds.Intersect(data->mRect);
|
||||
|
@ -1607,10 +1607,9 @@ void WebRenderCommandBuilder::BuildWebRenderCommands(
|
|||
}
|
||||
}
|
||||
if (ShouldDumpDisplayList(aDisplayListBuilder)) {
|
||||
mBuilderDumpIndex[aBuilder.GetRenderRoot()] =
|
||||
aBuilder.Dump(mDumpIndent + 1,
|
||||
Some(mBuilderDumpIndex[aBuilder.GetRenderRoot()]),
|
||||
Nothing());
|
||||
mBuilderDumpIndex[aBuilder.GetRenderRoot()] = aBuilder.Dump(
|
||||
mDumpIndent + 1, Some(mBuilderDumpIndex[aBuilder.GetRenderRoot()]),
|
||||
Nothing());
|
||||
}
|
||||
MOZ_ASSERT(mRootStackingContexts == nullptr);
|
||||
AutoRestore<wr::RenderRootArray<Maybe<StackingContextHelper>>*> rootScs(
|
||||
|
@ -1684,10 +1683,9 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
|||
if (dumpEnabled) {
|
||||
// If we're inside a nested display list, print the WR DL items from the
|
||||
// wrapper item before we start processing the nested items.
|
||||
mBuilderDumpIndex[aBuilder.GetRenderRoot()] =
|
||||
aBuilder.Dump(mDumpIndent + 1,
|
||||
Some(mBuilderDumpIndex[aBuilder.GetRenderRoot()]),
|
||||
Nothing());
|
||||
mBuilderDumpIndex[aBuilder.GetRenderRoot()] = aBuilder.Dump(
|
||||
mDumpIndent + 1, Some(mBuilderDumpIndex[aBuilder.GetRenderRoot()]),
|
||||
Nothing());
|
||||
}
|
||||
|
||||
mDumpIndent++;
|
||||
|
@ -1796,10 +1794,9 @@ void WebRenderCommandBuilder::CreateWebRenderCommandsFromDisplayList(
|
|||
}
|
||||
|
||||
if (dumpEnabled) {
|
||||
mBuilderDumpIndex[aBuilder.GetRenderRoot()] =
|
||||
aBuilder.Dump(mDumpIndent + 1,
|
||||
Some(mBuilderDumpIndex[aBuilder.GetRenderRoot()]),
|
||||
Nothing());
|
||||
mBuilderDumpIndex[aBuilder.GetRenderRoot()] = aBuilder.Dump(
|
||||
mDumpIndent + 1, Some(mBuilderDumpIndex[aBuilder.GetRenderRoot()]),
|
||||
Nothing());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2492,8 +2489,8 @@ Maybe<wr::ImageMask> WebRenderCommandBuilder::BuildWrMaskImage(
|
|||
|
||||
RefPtr<DrawTarget> dummyDt = Factory::CreateDrawTarget(
|
||||
BackendType::SKIA, IntSize(1, 1), SurfaceFormat::A8);
|
||||
RefPtr<DrawTarget> dt =
|
||||
Factory::CreateRecordingDrawTarget(recorder, dummyDt, IntRect(IntPoint(0, 0), size));
|
||||
RefPtr<DrawTarget> dt = Factory::CreateRecordingDrawTarget(
|
||||
recorder, dummyDt, IntRect(IntPoint(0, 0), size));
|
||||
|
||||
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
|
||||
MOZ_ASSERT(context);
|
||||
|
|
|
@ -343,8 +343,8 @@ void WebRenderLayerManager::EndTransactionWithoutLayer(
|
|||
mWebRenderCommandBuilder.BuildWebRenderCommands(
|
||||
builder, resourceUpdates, aDisplayList, aDisplayListBuilder,
|
||||
mScrollDatas, std::move(aFilters));
|
||||
builderDumpIndex = mWebRenderCommandBuilder.GetBuilderDumpIndex(
|
||||
builder.GetRenderRoot());
|
||||
builderDumpIndex =
|
||||
mWebRenderCommandBuilder.GetBuilderDumpIndex(builder.GetRenderRoot());
|
||||
containsSVGGroup = mWebRenderCommandBuilder.GetContainsSVGGroup();
|
||||
} else {
|
||||
// ViewToPaint does not have frame yet, then render only background clolor.
|
||||
|
|
|
@ -885,9 +885,7 @@ WebRenderThreadPool::WebRenderThreadPool() {
|
|||
mThreadPool = wr_thread_pool_new();
|
||||
}
|
||||
|
||||
WebRenderThreadPool::~WebRenderThreadPool() {
|
||||
Release();
|
||||
}
|
||||
WebRenderThreadPool::~WebRenderThreadPool() { Release(); }
|
||||
|
||||
void WebRenderThreadPool::Release() {
|
||||
if (mThreadPool) {
|
||||
|
@ -896,7 +894,6 @@ void WebRenderThreadPool::Release() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
WebRenderProgramCache::WebRenderProgramCache(wr::WrThreadPool* aThreadPool) {
|
||||
MOZ_ASSERT(aThreadPool);
|
||||
|
||||
|
|
|
@ -12925,6 +12925,29 @@ bool DebuggerEnvironment::typeGetter(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DebuggerEnvironment::scopeKindGetter(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
THIS_DEBUGGER_ENVIRONMENT(cx, argc, vp, "get scopeKind", args, environment);
|
||||
|
||||
if (!environment->requireDebuggee(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Maybe<ScopeKind> kind = environment->scopeKind();
|
||||
if (kind.isSome()) {
|
||||
const char* s = ScopeKindString(*kind);
|
||||
JSAtom* str = Atomize(cx, s, strlen(s), PinAtom);
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
args.rval().setString(str);
|
||||
} else {
|
||||
args.rval().setNull();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool DebuggerEnvironment::parentGetter(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
|
@ -13110,6 +13133,7 @@ bool DebuggerEnvironment::requireDebuggee(JSContext* cx) const {
|
|||
|
||||
const JSPropertySpec DebuggerEnvironment::properties_[] = {
|
||||
JS_PSG("type", DebuggerEnvironment::typeGetter, 0),
|
||||
JS_PSG("scopeKind", DebuggerEnvironment::scopeKindGetter, 0),
|
||||
JS_PSG("parent", DebuggerEnvironment::parentGetter, 0),
|
||||
JS_PSG("object", DebuggerEnvironment::objectGetter, 0),
|
||||
JS_PSG("callee", DebuggerEnvironment::calleeGetter, 0),
|
||||
|
@ -13163,6 +13187,15 @@ DebuggerEnvironmentType DebuggerEnvironment::type() const {
|
|||
return DebuggerEnvironmentType::Object;
|
||||
}
|
||||
|
||||
mozilla::Maybe<ScopeKind> DebuggerEnvironment::scopeKind() const {
|
||||
if (!referent()->is<DebugEnvironmentProxy>()) {
|
||||
return Nothing();
|
||||
}
|
||||
EnvironmentObject& env = referent()->as<DebugEnvironmentProxy>().environment();
|
||||
Scope* scope = GetEnvironmentScope(env);
|
||||
return scope ? Some(scope->kind()) : Nothing();
|
||||
}
|
||||
|
||||
bool DebuggerEnvironment::getParent(
|
||||
JSContext* cx, MutableHandleDebuggerEnvironment result) const {
|
||||
// Don't bother switching compartments just to get env's parent.
|
||||
|
|
|
@ -1369,6 +1369,7 @@ class DebuggerEnvironment : public NativeObject {
|
|||
HandleNativeObject debugger);
|
||||
|
||||
DebuggerEnvironmentType type() const;
|
||||
mozilla::Maybe<ScopeKind> scopeKind() const;
|
||||
MOZ_MUST_USE bool getParent(JSContext* cx,
|
||||
MutableHandleDebuggerEnvironment result) const;
|
||||
MOZ_MUST_USE bool getObject(JSContext* cx,
|
||||
|
@ -1411,6 +1412,8 @@ class DebuggerEnvironment : public NativeObject {
|
|||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static MOZ_MUST_USE bool typeGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool scopeKindGetter(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
static MOZ_MUST_USE bool parentGetter(JSContext* cx, unsigned argc,
|
||||
Value* vp);
|
||||
static MOZ_MUST_USE bool objectGetter(JSContext* cx, unsigned argc,
|
||||
|
|
|
@ -75,6 +75,20 @@ properties from its prototype:
|
|||
* "with", indicating that the environment was introduced by a `with`
|
||||
statement.
|
||||
|
||||
`scopeKind`
|
||||
: If this is a declarative environment, a string describing the kind of scope
|
||||
which this environment is associated with, or `null` for other types of
|
||||
environments. There is an assortment of possible scope kinds which can be
|
||||
generated, with a selection of possible values below. Unlike the type
|
||||
accessor, the categorization this performs is specific to SpiderMonkey's
|
||||
implementation, and not derived from distinctions made in the ECMAScript
|
||||
language specification.
|
||||
|
||||
* "function", indicating the top level body scope of a function for
|
||||
arguments and 'var' variables.
|
||||
|
||||
* "function lexical", indicating the top level lexical scope in a function.
|
||||
|
||||
`parent`
|
||||
: The environment that encloses this one (the "outer" environment, in
|
||||
ECMAScript terminology), or `null` if this is the outermost environment.
|
||||
|
|
|
@ -4894,7 +4894,7 @@ MOZ_NEVER_INLINE bool BytecodeEmitter::emitLexicalScope(
|
|||
? ScopeKind::SimpleCatch
|
||||
: ScopeKind::Catch;
|
||||
} else {
|
||||
kind = ScopeKind::Lexical;
|
||||
kind = lexicalScope->kind();
|
||||
}
|
||||
|
||||
if (!lse.emitScope(kind, lexicalScope->scopeBindings())) {
|
||||
|
|
|
@ -213,6 +213,7 @@ NameLocation EmitterScope::searchInEnclosingScope(JSAtom* name, Scope* scope,
|
|||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::FunctionLexical:
|
||||
if (hasEnv) {
|
||||
for (BindingIter bi(si.scope()); bi; bi++) {
|
||||
if (bi.name() != name) {
|
||||
|
@ -1014,6 +1015,7 @@ bool EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) {
|
|||
case ScopeKind::Lexical:
|
||||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::FunctionLexical:
|
||||
if (!bce->emit1(hasEnvironment() ? JSOP_POPLEXICALENV
|
||||
: JSOP_DEBUGLEAVELEXICALENV)) {
|
||||
return false;
|
||||
|
|
|
@ -833,8 +833,8 @@ class FullParseHandler {
|
|||
}
|
||||
|
||||
LexicalScopeNodeType newLexicalScope(LexicalScope::Data* bindings,
|
||||
Node body) {
|
||||
return new_<LexicalScopeNode>(bindings, body);
|
||||
Node body, ScopeKind kind = ScopeKind::Lexical) {
|
||||
return new_<LexicalScopeNode>(bindings, body, kind);
|
||||
}
|
||||
|
||||
CallNodeType newNewExpression(uint32_t begin, Node ctor, Node args,
|
||||
|
|
|
@ -1544,12 +1544,15 @@ class BigIntLiteral : public ParseNode {
|
|||
class LexicalScopeNode : public ParseNode {
|
||||
LexicalScope::Data* bindings;
|
||||
ParseNode* body;
|
||||
ScopeKind kind_;
|
||||
|
||||
public:
|
||||
LexicalScopeNode(LexicalScope::Data* bindings, ParseNode* body)
|
||||
LexicalScopeNode(LexicalScope::Data* bindings, ParseNode* body,
|
||||
ScopeKind kind = ScopeKind::Lexical)
|
||||
: ParseNode(ParseNodeKind::LexicalScope, body->pn_pos),
|
||||
bindings(bindings),
|
||||
body(body) {}
|
||||
body(body),
|
||||
kind_(kind) {}
|
||||
|
||||
static bool test(const ParseNode& node) {
|
||||
return node.isKind(ParseNodeKind::LexicalScope);
|
||||
|
@ -1580,6 +1583,8 @@ class LexicalScopeNode : public ParseNode {
|
|||
void setScopeBody(ParseNode* body) { this->body = body; }
|
||||
|
||||
bool isEmptyScope() const { return !bindings; }
|
||||
|
||||
ScopeKind kind() const { return kind_; }
|
||||
};
|
||||
|
||||
class LabeledStatement : public NameNode {
|
||||
|
|
|
@ -1312,7 +1312,7 @@ Maybe<LexicalScope::Data*> ParserBase::newLexicalScopeData(
|
|||
template <>
|
||||
SyntaxParseHandler::LexicalScopeNodeType
|
||||
PerHandlerParser<SyntaxParseHandler>::finishLexicalScope(
|
||||
ParseContext::Scope& scope, Node body) {
|
||||
ParseContext::Scope& scope, Node body, ScopeKind kind) {
|
||||
if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
|
||||
return null();
|
||||
}
|
||||
|
@ -1322,7 +1322,7 @@ PerHandlerParser<SyntaxParseHandler>::finishLexicalScope(
|
|||
|
||||
template <>
|
||||
LexicalScopeNode* PerHandlerParser<FullParseHandler>::finishLexicalScope(
|
||||
ParseContext::Scope& scope, ParseNode* body) {
|
||||
ParseContext::Scope& scope, ParseNode* body, ScopeKind kind) {
|
||||
if (!propagateFreeNamesAndMarkClosedOverBindings(scope)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1332,7 +1332,7 @@ LexicalScopeNode* PerHandlerParser<FullParseHandler>::finishLexicalScope(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return handler_.newLexicalScope(*bindings, body);
|
||||
return handler_.newLexicalScope(*bindings, body, kind);
|
||||
}
|
||||
|
||||
template <typename Unit>
|
||||
|
@ -1959,7 +1959,7 @@ GeneralParser<ParseHandler, Unit>::functionBody(InHandling inHandling,
|
|||
}
|
||||
}
|
||||
|
||||
return finishLexicalScope(pc_->varScope(), body);
|
||||
return finishLexicalScope(pc_->varScope(), body, ScopeKind::FunctionLexical);
|
||||
}
|
||||
|
||||
JSFunction* AllocNewFunction(JSContext* cx, HandleAtom atom,
|
||||
|
@ -7320,7 +7320,8 @@ GeneralParser<ParseHandler, Unit>::synthesizeConstructor(
|
|||
handler_.addStatementToList(stmtList, exprStatement);
|
||||
}
|
||||
|
||||
auto initializerBody = finishLexicalScope(pc_->varScope(), stmtList);
|
||||
auto initializerBody = finishLexicalScope(pc_->varScope(), stmtList,
|
||||
ScopeKind::FunctionLexical);
|
||||
if (!initializerBody) {
|
||||
return null();
|
||||
}
|
||||
|
@ -7528,7 +7529,8 @@ GeneralParser<ParseHandler, Unit>::fieldInitializerOpt(
|
|||
|
||||
// Set the function's body to the field assignment.
|
||||
LexicalScopeNodeType initializerBody =
|
||||
finishLexicalScope(pc_->varScope(), statementList);
|
||||
finishLexicalScope(pc_->varScope(), statementList,
|
||||
ScopeKind::FunctionLexical);
|
||||
if (!initializerBody) {
|
||||
return null();
|
||||
}
|
||||
|
|
|
@ -549,7 +549,8 @@ class MOZ_STACK_CLASS PerHandlerParser : public ParserBase {
|
|||
|
||||
bool finishFunctionScopes(bool isStandaloneFunction);
|
||||
LexicalScopeNodeType finishLexicalScope(ParseContext::Scope& scope,
|
||||
Node body);
|
||||
Node body,
|
||||
ScopeKind kind = ScopeKind::Lexical);
|
||||
bool finishFunction(
|
||||
bool isStandaloneFunction = false,
|
||||
IsFieldInitializer isFieldInitializer = IsFieldInitializer::No);
|
||||
|
|
|
@ -1283,7 +1283,8 @@ inline void js::GCMarker::eagerlyMarkChildren(Scope* scope) {
|
|||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda: {
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical: {
|
||||
LexicalScope::Data& data = scope->as<LexicalScope>().data();
|
||||
names = &data.trailingNames;
|
||||
length = data.length;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// Environment.prototype.scopeKind produces expected values.
|
||||
|
||||
load(libdir + 'eqArrayHelper.js');
|
||||
|
||||
var g = newGlobal({newCompartment: true});
|
||||
var dbg = Debugger(g);
|
||||
|
||||
function getScopeKinds(text) {
|
||||
const kinds = [];
|
||||
dbg.onDebuggerStatement = frame => {
|
||||
let env = frame.environment;
|
||||
while (env) {
|
||||
kinds.push(env.scopeKind);
|
||||
env = env.parent;
|
||||
}
|
||||
};
|
||||
g.eval(text);
|
||||
return kinds;
|
||||
}
|
||||
|
||||
assertEqArray(getScopeKinds("function f(x) { debugger; }; f()"),
|
||||
["function", null, null]);
|
||||
assertEqArray(getScopeKinds("function f(x) { let y = 0; debugger; }; f()"),
|
||||
["function lexical", "function", null, null]);
|
||||
assertEqArray(getScopeKinds("function f(x) { let y = 0; with(x) { debugger; } } f({})"),
|
||||
[null, "function lexical", "function", null, null]);
|
|
@ -1806,6 +1806,8 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
friend Scope* js::GetEnvironmentScope(const JSObject& env);
|
||||
|
||||
/*
|
||||
* In theory, every non-arrow function scope contains an 'arguments'
|
||||
* bindings. However, the engine only adds a binding if 'arguments' is
|
||||
|
@ -2380,6 +2382,10 @@ class DebugEnvironmentProxyHandler : public BaseProxyHandler {
|
|||
|
||||
} /* anonymous namespace */
|
||||
|
||||
Scope* js::GetEnvironmentScope(const JSObject& env) {
|
||||
return DebugEnvironmentProxyHandler::getEnvironmentScope(env);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool JSObject::is<js::DebugEnvironmentProxy>() const {
|
||||
return IsDerivedProxyObject(this, &DebugEnvironmentProxyHandler::singleton);
|
||||
|
|
|
@ -890,6 +890,7 @@ extern JSObject* GetDebugEnvironmentForFrame(JSContext* cx,
|
|||
jsbytecode* pc);
|
||||
|
||||
extern JSObject* GetDebugEnvironmentForGlobalLexicalEnvironment(JSContext* cx);
|
||||
extern Scope* GetEnvironmentScope(const JSObject& env);
|
||||
|
||||
/* Provides debugger access to a environment. */
|
||||
class DebugEnvironmentProxy : public ProxyObject {
|
||||
|
|
|
@ -973,6 +973,7 @@ static void PopEnvironment(JSContext* cx, EnvironmentIter& ei) {
|
|||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical:
|
||||
if (MOZ_UNLIKELY(cx->realm()->isDebuggee())) {
|
||||
DebugEnvironments::onPopLexical(cx, ei);
|
||||
}
|
||||
|
|
|
@ -519,6 +519,7 @@ static XDRResult XDRScope(XDRState<mode>* xdr, js::PrivateScriptData* data,
|
|||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical:
|
||||
MOZ_TRY(LexicalScope::XDR(xdr, scopeKind, enclosing, scope));
|
||||
break;
|
||||
case ScopeKind::With:
|
||||
|
|
|
@ -61,6 +61,8 @@ const char* js::ScopeKindString(ScopeKind kind) {
|
|||
return "named lambda";
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
return "strict named lambda";
|
||||
case ScopeKind::FunctionLexical:
|
||||
return "function lexical";
|
||||
case ScopeKind::With:
|
||||
return "with";
|
||||
case ScopeKind::Eval:
|
||||
|
@ -417,7 +419,8 @@ Scope* Scope::clone(JSContext* cx, HandleScope scope, HandleScope enclosing) {
|
|||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda: {
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical: {
|
||||
Rooted<UniquePtr<LexicalScope::Data>> dataClone(cx);
|
||||
dataClone =
|
||||
CopyScopeData<LexicalScope>(cx, &scope->as<LexicalScope>().data());
|
||||
|
@ -490,6 +493,7 @@ uint32_t LexicalScope::firstFrameSlot() const {
|
|||
case ScopeKind::Lexical:
|
||||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::FunctionLexical:
|
||||
// For intra-frame scopes, find the enclosing scope's next frame slot.
|
||||
return nextFrameSlot(enclosing());
|
||||
case ScopeKind::NamedLambda:
|
||||
|
@ -515,6 +519,7 @@ uint32_t LexicalScope::nextFrameSlot(Scope* scope) {
|
|||
case ScopeKind::Lexical:
|
||||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::FunctionLexical:
|
||||
return si.scope()->as<LexicalScope>().nextFrameSlot();
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
|
@ -1416,6 +1421,7 @@ BindingIter::BindingIter(Scope* scope) {
|
|||
case ScopeKind::Lexical:
|
||||
case ScopeKind::SimpleCatch:
|
||||
case ScopeKind::Catch:
|
||||
case ScopeKind::FunctionLexical:
|
||||
init(scope->as<LexicalScope>().data(),
|
||||
scope->as<LexicalScope>().firstFrameSlot(), 0);
|
||||
break;
|
||||
|
|
|
@ -60,6 +60,7 @@ enum class ScopeKind : uint8_t {
|
|||
Catch,
|
||||
NamedLambda,
|
||||
StrictNamedLambda,
|
||||
FunctionLexical,
|
||||
|
||||
// WithScope
|
||||
With,
|
||||
|
@ -91,6 +92,7 @@ static inline bool ScopeKindIsCatch(ScopeKind kind) {
|
|||
static inline bool ScopeKindIsInBody(ScopeKind kind) {
|
||||
return kind == ScopeKind::Lexical || kind == ScopeKind::SimpleCatch ||
|
||||
kind == ScopeKind::Catch || kind == ScopeKind::With ||
|
||||
kind == ScopeKind::FunctionLexical ||
|
||||
kind == ScopeKind::FunctionBodyVar ||
|
||||
kind == ScopeKind::ParameterExpressionVar;
|
||||
}
|
||||
|
@ -483,7 +485,8 @@ template <>
|
|||
inline bool Scope::is<LexicalScope>() const {
|
||||
return kind_ == ScopeKind::Lexical || kind_ == ScopeKind::SimpleCatch ||
|
||||
kind_ == ScopeKind::Catch || kind_ == ScopeKind::NamedLambda ||
|
||||
kind_ == ScopeKind::StrictNamedLambda;
|
||||
kind_ == ScopeKind::StrictNamedLambda ||
|
||||
kind_ == ScopeKind::FunctionLexical;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1039,6 +1042,7 @@ void Scope::applyScopeDataTyped(F&& f) {
|
|||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical:
|
||||
f(&as<LexicalScope>().data());
|
||||
break;
|
||||
case ScopeKind::With:
|
||||
|
|
|
@ -122,6 +122,7 @@ static inline void AssertScopeMatchesEnvironment(Scope* scope,
|
|||
case ScopeKind::Catch:
|
||||
case ScopeKind::NamedLambda:
|
||||
case ScopeKind::StrictNamedLambda:
|
||||
case ScopeKind::FunctionLexical:
|
||||
MOZ_ASSERT(&env->as<LexicalEnvironmentObject>().scope() ==
|
||||
si.scope());
|
||||
env = &env->as<LexicalEnvironmentObject>().enclosingEnvironment();
|
||||
|
|
Загрузка…
Ссылка в новой задаче