forked from mirrors/gecko-dev
Merge m-c to autoland, a=merge
MozReview-Commit-ID: 3BrkDVl7521
This commit is contained in:
commit
75c2b7a481
325 changed files with 45388 additions and 78510 deletions
|
|
@ -9,7 +9,6 @@ obj*/**
|
|||
# below.
|
||||
addon-sdk/**
|
||||
build/**
|
||||
caps/**
|
||||
chrome/**
|
||||
config/**
|
||||
db/**
|
||||
|
|
@ -78,6 +77,9 @@ browser/extensions/activity-stream/vendor/**
|
|||
# imported from chromium
|
||||
browser/extensions/mortar/**
|
||||
|
||||
# caps/ exclusions
|
||||
caps/tests/mochitest/browser_checkloaduri.js
|
||||
|
||||
# devtools/ exclusions
|
||||
devtools/client/canvasdebugger/**
|
||||
devtools/client/commandline/**
|
||||
|
|
|
|||
|
|
@ -676,6 +676,58 @@
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put ARIA owned child back when ARIA owner removed.
|
||||
*/
|
||||
function test10_removeARIAOwner()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getAccessible('t10_owner'))
|
||||
];
|
||||
|
||||
this.invoke = () => {
|
||||
let tree =
|
||||
{ SECTION: [ // t10_container
|
||||
{ SECTION: [ // t10_owner
|
||||
{ ENTRY: [] } // t10_child
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree('t10_container', tree);
|
||||
|
||||
getNode('t10_owner').remove();
|
||||
}
|
||||
|
||||
this.getID = () => {
|
||||
return 'Put aria owned child back when aria owner removed';
|
||||
}
|
||||
}
|
||||
|
||||
function test10_finishTest()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, 't10_container')
|
||||
];
|
||||
|
||||
this.invoke = () => {
|
||||
// trigger a tree update.
|
||||
getNode('t10_container').append(document.createElement('p'));
|
||||
}
|
||||
|
||||
this.finalCheck = () => {
|
||||
let tree =
|
||||
{ SECTION: [ // t10_container
|
||||
// { ENTRY: [] }, // t10_child
|
||||
{ PARAGRAPH: [] }
|
||||
] };
|
||||
testAccessibleTree('t10_container', tree);
|
||||
todo(false, 'Input accessible has be moved back in the tree');
|
||||
}
|
||||
|
||||
this.getID = () => {
|
||||
return `Put aria owned child back when aria owner removed (finish test)`;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -728,6 +780,9 @@
|
|||
gQueue.push(new test9_setARIAOwns());
|
||||
gQueue.push(new test9_finish());
|
||||
|
||||
gQueue.push(new test10_removeARIAOwner());
|
||||
gQueue.push(new test10_finishTest());
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
|
|
@ -792,6 +847,11 @@
|
|||
</div>
|
||||
|
||||
<iframe id="t9_container"></iframe>
|
||||
|
||||
<div id="t10_container">
|
||||
<div id="t10_owner" aria-owns="t10_child"></div>
|
||||
<input id="t10_child">
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -117,6 +117,10 @@
|
|||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
<emItem blockID="edad04eb-ea16-42f3-a4a7-20dded33cc37" id="@safesearchscoutee">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
<emItem blockID="i436" id="/(\{7aeae561-714b-45f6-ace3-4a8aed6e227b\})|(\{01e86e69-a2f8-48a0-b068-83869bdba3d0\})|(\{77f5fe49-12e3-4cf5-abb4-d993a0164d9e\})/">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1"/>
|
||||
|
|
@ -181,6 +185,10 @@
|
|||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
<emItem blockID="3fd71895-7fc6-4f3f-aa22-1cbb0c5fd922" id="/^({95E84BD3-3604-4AAC-B2CA-D9AC3E55B64B}|{E3605470-291B-44EB-8648-745EE356599A}|{95E5E0AD-65F9-4FFC-A2A2-0008DCF6ED25}|{FF20459C-DA6E-41A7-80BC-8F4FEFD9C575}|{6E727987-C8EA-44DA-8749-310C0FBE3C3E}|{12E8A6C2-B125-479F-AB3C-13B8757C7F04}|{EB6628CF-0675-4DAE-95CE-EFFA23169743})$/">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
</emItem>
|
||||
<emItem blockID="i716" id="{cc6cc772-f121-49e0-b1f0-c26583cb0c5e}">
|
||||
<prefs/>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3"/>
|
||||
|
|
|
|||
|
|
@ -360,12 +360,6 @@ pref("browser.download.folderList", 1);
|
|||
pref("browser.download.manager.addToRecentDocs", true);
|
||||
pref("browser.download.manager.resumeOnWakeDelay", 10000);
|
||||
|
||||
#ifdef RELEASE_OR_BETA
|
||||
pref("browser.download.showPanelDropmarker", false);
|
||||
#else
|
||||
pref("browser.download.showPanelDropmarker", true);
|
||||
#endif
|
||||
|
||||
// This allows disabling the animated notifications shown by
|
||||
// the Downloads Indicator when a download starts or completes.
|
||||
pref("browser.download.animateNotifications", true);
|
||||
|
|
|
|||
|
|
@ -71,8 +71,6 @@ XPCOMUtils.defineLazyGetter(this, "DownloadsLogger", () => {
|
|||
return new ConsoleAPI(consoleOptions);
|
||||
});
|
||||
|
||||
const nsIDM = Ci.nsIDownloadManager;
|
||||
|
||||
const kDownloadsStringBundleUrl =
|
||||
"chrome://browser/locale/downloads/downloads.properties";
|
||||
|
||||
|
|
@ -124,7 +122,6 @@ var PrefObserver = {
|
|||
PrefObserver.register({
|
||||
// prefName: defaultValue
|
||||
animateNotifications: true,
|
||||
showPanelDropmarker: true,
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -135,6 +132,19 @@ PrefObserver.register({
|
|||
* and provides shared methods for all the instances of the user interface.
|
||||
*/
|
||||
this.DownloadsCommon = {
|
||||
// The following legacy constants are still returned by stateOfDownload, but
|
||||
// individual properties of the Download object should normally be used.
|
||||
DOWNLOAD_NOTSTARTED: -1,
|
||||
DOWNLOAD_DOWNLOADING: 0,
|
||||
DOWNLOAD_FINISHED: 1,
|
||||
DOWNLOAD_FAILED: 2,
|
||||
DOWNLOAD_CANCELED: 3,
|
||||
DOWNLOAD_PAUSED: 4,
|
||||
DOWNLOAD_BLOCKED_PARENTAL: 6,
|
||||
DOWNLOAD_DIRTY: 8,
|
||||
DOWNLOAD_BLOCKED_POLICY: 9,
|
||||
|
||||
// The following are the possible values of the "attention" property.
|
||||
ATTENTION_NONE: "",
|
||||
ATTENTION_SUCCESS: "success",
|
||||
ATTENTION_WARNING: "warning",
|
||||
|
|
@ -183,13 +193,6 @@ this.DownloadsCommon = {
|
|||
return PrefObserver.animateNotifications;
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicates whether we should show the dropmarker in the Downloads Panel.
|
||||
*/
|
||||
get showPanelDropmarker() {
|
||||
return PrefObserver.showPanelDropmarker;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get access to one of the DownloadsData or PrivateDownloadsData objects,
|
||||
* depending on the privacy status of the window in question.
|
||||
|
|
@ -256,27 +259,27 @@ this.DownloadsCommon = {
|
|||
stateOfDownload(download) {
|
||||
// Collapse state using the correct priority.
|
||||
if (!download.stopped) {
|
||||
return nsIDM.DOWNLOAD_DOWNLOADING;
|
||||
return DownloadsCommon.DOWNLOAD_DOWNLOADING;
|
||||
}
|
||||
if (download.succeeded) {
|
||||
return nsIDM.DOWNLOAD_FINISHED;
|
||||
return DownloadsCommon.DOWNLOAD_FINISHED;
|
||||
}
|
||||
if (download.error) {
|
||||
if (download.error.becauseBlockedByParentalControls) {
|
||||
return nsIDM.DOWNLOAD_BLOCKED_PARENTAL;
|
||||
return DownloadsCommon.DOWNLOAD_BLOCKED_PARENTAL;
|
||||
}
|
||||
if (download.error.becauseBlockedByReputationCheck) {
|
||||
return nsIDM.DOWNLOAD_DIRTY;
|
||||
return DownloadsCommon.DOWNLOAD_DIRTY;
|
||||
}
|
||||
return nsIDM.DOWNLOAD_FAILED;
|
||||
return DownloadsCommon.DOWNLOAD_FAILED;
|
||||
}
|
||||
if (download.canceled) {
|
||||
if (download.hasPartialData) {
|
||||
return nsIDM.DOWNLOAD_PAUSED;
|
||||
return DownloadsCommon.DOWNLOAD_PAUSED;
|
||||
}
|
||||
return nsIDM.DOWNLOAD_CANCELED;
|
||||
return DownloadsCommon.DOWNLOAD_CANCELED;
|
||||
}
|
||||
return nsIDM.DOWNLOAD_NOTSTARTED;
|
||||
return DownloadsCommon.DOWNLOAD_NOTSTARTED;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -325,18 +325,18 @@ this.DownloadsViewUI.DownloadElementShell.prototype = {
|
|||
*/
|
||||
get currentDefaultCommandName() {
|
||||
switch (DownloadsCommon.stateOfDownload(this.download)) {
|
||||
case Ci.nsIDownloadManager.DOWNLOAD_NOTSTARTED:
|
||||
case DownloadsCommon.DOWNLOAD_NOTSTARTED:
|
||||
return "downloadsCmd_cancel";
|
||||
case Ci.nsIDownloadManager.DOWNLOAD_FAILED:
|
||||
case Ci.nsIDownloadManager.DOWNLOAD_CANCELED:
|
||||
case DownloadsCommon.DOWNLOAD_FAILED:
|
||||
case DownloadsCommon.DOWNLOAD_CANCELED:
|
||||
return "downloadsCmd_retry";
|
||||
case Ci.nsIDownloadManager.DOWNLOAD_PAUSED:
|
||||
case DownloadsCommon.DOWNLOAD_PAUSED:
|
||||
return "downloadsCmd_pauseResume";
|
||||
case Ci.nsIDownloadManager.DOWNLOAD_FINISHED:
|
||||
case DownloadsCommon.DOWNLOAD_FINISHED:
|
||||
return "downloadsCmd_open";
|
||||
case Ci.nsIDownloadManager.DOWNLOAD_BLOCKED_PARENTAL:
|
||||
case DownloadsCommon.DOWNLOAD_BLOCKED_PARENTAL:
|
||||
return "downloadsCmd_openReferrer";
|
||||
case Ci.nsIDownloadManager.DOWNLOAD_DIRTY:
|
||||
case DownloadsCommon.DOWNLOAD_DIRTY:
|
||||
return "downloadsCmd_showBlockedInfo";
|
||||
}
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
|
||||
const nsIDM = Ci.nsIDownloadManager;
|
||||
|
||||
const DESTINATION_FILE_URI_ANNO = "downloads/destinationFileURI";
|
||||
const DOWNLOAD_META_DATA_ANNO = "downloads/metaData";
|
||||
|
||||
|
|
@ -72,17 +70,17 @@ HistoryDownload.prototype = {
|
|||
}
|
||||
|
||||
if ("state" in metaData) {
|
||||
this.succeeded = metaData.state == nsIDM.DOWNLOAD_FINISHED;
|
||||
this.canceled = metaData.state == nsIDM.DOWNLOAD_CANCELED ||
|
||||
metaData.state == nsIDM.DOWNLOAD_PAUSED;
|
||||
this.succeeded = metaData.state == DownloadsCommon.DOWNLOAD_FINISHED;
|
||||
this.canceled = metaData.state == DownloadsCommon.DOWNLOAD_CANCELED ||
|
||||
metaData.state == DownloadsCommon.DOWNLOAD_PAUSED;
|
||||
this.endTime = metaData.endTime;
|
||||
|
||||
// Recreate partial error information from the state saved in history.
|
||||
if (metaData.state == nsIDM.DOWNLOAD_FAILED) {
|
||||
if (metaData.state == DownloadsCommon.DOWNLOAD_FAILED) {
|
||||
this.error = { message: "History download failed." };
|
||||
} else if (metaData.state == nsIDM.DOWNLOAD_BLOCKED_PARENTAL) {
|
||||
} else if (metaData.state == DownloadsCommon.DOWNLOAD_BLOCKED_PARENTAL) {
|
||||
this.error = { becauseBlockedByParentalControls: true };
|
||||
} else if (metaData.state == nsIDM.DOWNLOAD_DIRTY) {
|
||||
} else if (metaData.state == DownloadsCommon.DOWNLOAD_DIRTY) {
|
||||
this.error = {
|
||||
becauseBlockedByReputationCheck: true,
|
||||
reputationCheckVerdict: metaData.reputationCheckVerdict || "",
|
||||
|
|
|
|||
|
|
@ -13,11 +13,6 @@ richlistitem[type="download"]:not([selected]) button {
|
|||
-moz-user-focus: none;
|
||||
}
|
||||
|
||||
.downloadsHideDropmarker > #downloadsFooterButtonsSplitter,
|
||||
.downloadsHideDropmarker > #downloadsFooterDropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
richlistitem[type="download"].download-state[state="1"]:not([exists]) > .downloadButtonArea,
|
||||
richlistitem[type="download"].download-state[state="1"]:not([exists]) > toolbarseparator {
|
||||
display: none;
|
||||
|
|
@ -29,9 +24,8 @@ richlistitem[type="download"].download-state[state="1"]:not([exists]) > toolbars
|
|||
display: none;
|
||||
}
|
||||
|
||||
#downloadsFooter[showingdropdown] > stack > #downloadsSummary,
|
||||
#downloadsFooter[showingsummary] > stack:hover > #downloadsSummary,
|
||||
#downloadsFooter[showingsummary]:not([showingdropdown]) > stack:not(:hover) > #downloadsFooterButtons {
|
||||
#downloadsFooter[showingsummary] > stack:not(:hover) > #downloadsFooterButtons {
|
||||
/* If we used "visibility: hidden;" then the mouseenter event of
|
||||
#downloadsHistory wouldn't be triggered immediately, and the hover styling
|
||||
of the button would not apply until the mouse is moved again.
|
||||
|
|
|
|||
|
|
@ -224,14 +224,6 @@ const DownloadsPanel = {
|
|||
}
|
||||
|
||||
this.initialize(() => {
|
||||
let downloadsFooterButtons =
|
||||
document.getElementById("downloadsFooterButtons");
|
||||
if (DownloadsCommon.showPanelDropmarker) {
|
||||
downloadsFooterButtons.classList.remove("downloadsHideDropmarker");
|
||||
} else {
|
||||
downloadsFooterButtons.classList.add("downloadsHideDropmarker");
|
||||
}
|
||||
|
||||
// Delay displaying the panel because this function will sometimes be
|
||||
// called while another window is closing (like the window for selecting
|
||||
// whether to save or open the file), and that would cause the panel to
|
||||
|
|
@ -387,24 +379,6 @@ const DownloadsPanel = {
|
|||
this._state = this.kStateHidden;
|
||||
},
|
||||
|
||||
onFooterPopupShowing(aEvent) {
|
||||
let itemClearList = document.getElementById("downloadsDropdownItemClearList");
|
||||
if (DownloadsCommon.getData(window).canRemoveFinished) {
|
||||
itemClearList.removeAttribute("hidden");
|
||||
} else {
|
||||
itemClearList.setAttribute("hidden", "true");
|
||||
}
|
||||
DownloadsViewController.updateCommands();
|
||||
|
||||
document.getElementById("downloadsFooter")
|
||||
.setAttribute("showingdropdown", true);
|
||||
},
|
||||
|
||||
onFooterPopupHidden(aEvent) {
|
||||
document.getElementById("downloadsFooter")
|
||||
.removeAttribute("showingdropdown");
|
||||
},
|
||||
|
||||
// Related operations
|
||||
|
||||
/**
|
||||
|
|
@ -419,13 +393,6 @@ const DownloadsPanel = {
|
|||
BrowserDownloadsUI();
|
||||
},
|
||||
|
||||
openDownloadsFolder() {
|
||||
Downloads.getPreferredDownloadsDirectory().then(downloadsPath => {
|
||||
DownloadsCommon.showDirectory(new FileUtils.File(downloadsPath));
|
||||
}).catch(Cu.reportError);
|
||||
this.hidePanel();
|
||||
},
|
||||
|
||||
// Internal functions
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -154,23 +154,6 @@
|
|||
accesskey="&downloadsHistory.accesskey;"
|
||||
flex="1"
|
||||
oncommand="DownloadsPanel.showDownloadsHistory();"/>
|
||||
<toolbarseparator id="downloadsFooterButtonsSplitter"
|
||||
class="downloadsDropmarkerSplitter"/>
|
||||
<button id="downloadsFooterDropmarker"
|
||||
class="downloadsPanelFooterButton downloadsDropmarker"
|
||||
type="menu">
|
||||
<menupopup id="downloadSubPanel"
|
||||
onpopupshowing="DownloadsPanel.onFooterPopupShowing(event);"
|
||||
onpopuphidden="DownloadsPanel.onFooterPopupHidden(event);"
|
||||
position="after_end">
|
||||
<menuitem id="downloadsDropdownItemClearList"
|
||||
command="downloadsCmd_clearList"
|
||||
label="&cmd.clearList2.label;"/>
|
||||
<menuitem id="downloadsDropdownItemOpenDownloadsFolder"
|
||||
oncommand="DownloadsPanel.openDownloadsFolder();"
|
||||
label="&openDownloadsFolder.label;"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
</hbox>
|
||||
</stack>
|
||||
</vbox>
|
||||
|
|
|
|||
|
|
@ -12,5 +12,4 @@ skip-if = os == "linux" # Bug 952422
|
|||
[browser_libraryDrop.js]
|
||||
[browser_downloads_panel_block.js]
|
||||
skip-if = true # Bug 1352792
|
||||
[browser_downloads_panel_footer.js]
|
||||
[browser_downloads_panel_height.js]
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ registerCleanupFunction(function*() {
|
|||
add_task(function* test_basic_functionality() {
|
||||
// Display one of each download state.
|
||||
const DownloadData = [
|
||||
{ state: nsIDM.DOWNLOAD_NOTSTARTED },
|
||||
{ state: nsIDM.DOWNLOAD_PAUSED },
|
||||
{ state: nsIDM.DOWNLOAD_FINISHED },
|
||||
{ state: nsIDM.DOWNLOAD_FAILED },
|
||||
{ state: nsIDM.DOWNLOAD_CANCELED },
|
||||
{ state: DownloadsCommon.DOWNLOAD_NOTSTARTED },
|
||||
{ state: DownloadsCommon.DOWNLOAD_PAUSED },
|
||||
{ state: DownloadsCommon.DOWNLOAD_FINISHED },
|
||||
{ state: DownloadsCommon.DOWNLOAD_FAILED },
|
||||
{ state: DownloadsCommon.DOWNLOAD_CANCELED },
|
||||
];
|
||||
|
||||
// Wait for focus first
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ function promisePanelHidden() {
|
|||
|
||||
function makeDownload(verdict) {
|
||||
return {
|
||||
state: nsIDM.DOWNLOAD_DIRTY,
|
||||
state: DownloadsCommon.DOWNLOAD_DIRTY,
|
||||
hasBlockedData: true,
|
||||
errorObj: {
|
||||
result: Components.results.NS_ERROR_FAILURE,
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
function *task_openDownloadsSubPanel() {
|
||||
let downloadSubPanel = document.getElementById("downloadSubPanel");
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(downloadSubPanel, "popupshown");
|
||||
|
||||
let downloadsDropmarker = document.getElementById("downloadsFooterDropmarker");
|
||||
EventUtils.synthesizeMouseAtCenter(downloadsDropmarker, {}, window);
|
||||
|
||||
yield popupShownPromise;
|
||||
}
|
||||
|
||||
add_task(function* test_openDownloadsFolder() {
|
||||
yield SpecialPowers.pushPrefEnv({"set": [["browser.download.showPanelDropmarker", true]]});
|
||||
yield task_openPanel();
|
||||
|
||||
yield task_openDownloadsSubPanel();
|
||||
|
||||
yield new Promise(resolve => {
|
||||
sinon.stub(DownloadsCommon, "showDirectory", file => {
|
||||
resolve(Downloads.getPreferredDownloadsDirectory().then(downloadsPath => {
|
||||
is(file.path, downloadsPath, "Check the download folder path.");
|
||||
}));
|
||||
});
|
||||
|
||||
let itemOpenDownloadsFolder =
|
||||
document.getElementById("downloadsDropdownItemOpenDownloadsFolder");
|
||||
EventUtils.synthesizeMouseAtCenter(itemOpenDownloadsFolder, {}, window);
|
||||
});
|
||||
|
||||
yield task_resetState();
|
||||
});
|
||||
|
||||
add_task(function* test_clearList() {
|
||||
const kTestCases = [{
|
||||
downloads: [
|
||||
{ state: nsIDM.DOWNLOAD_NOTSTARTED },
|
||||
{ state: nsIDM.DOWNLOAD_FINISHED },
|
||||
{ state: nsIDM.DOWNLOAD_FAILED },
|
||||
{ state: nsIDM.DOWNLOAD_CANCELED },
|
||||
],
|
||||
expectClearListShown: true,
|
||||
expectedItemNumber: 0,
|
||||
}, {
|
||||
downloads: [
|
||||
{ state: nsIDM.DOWNLOAD_NOTSTARTED },
|
||||
{ state: nsIDM.DOWNLOAD_FINISHED },
|
||||
{ state: nsIDM.DOWNLOAD_FAILED },
|
||||
{ state: nsIDM.DOWNLOAD_PAUSED },
|
||||
{ state: nsIDM.DOWNLOAD_CANCELED },
|
||||
],
|
||||
expectClearListShown: true,
|
||||
expectedItemNumber: 1,
|
||||
}, {
|
||||
downloads: [
|
||||
{ state: nsIDM.DOWNLOAD_PAUSED },
|
||||
],
|
||||
expectClearListShown: false,
|
||||
expectedItemNumber: 1,
|
||||
}];
|
||||
|
||||
for (let testCase of kTestCases) {
|
||||
yield verify_clearList(testCase);
|
||||
}
|
||||
});
|
||||
|
||||
function *verify_clearList(testCase) {
|
||||
let downloads = testCase.downloads;
|
||||
yield task_addDownloads(downloads);
|
||||
|
||||
yield task_openPanel();
|
||||
is(DownloadsView._downloads.length, downloads.length,
|
||||
"Expect the number of download items");
|
||||
|
||||
yield task_openDownloadsSubPanel();
|
||||
|
||||
let itemClearList = document.getElementById("downloadsDropdownItemClearList");
|
||||
let itemNumberPromise = BrowserTestUtils.waitForCondition(() => {
|
||||
return DownloadsView._downloads.length === testCase.expectedItemNumber;
|
||||
});
|
||||
if (testCase.expectClearListShown) {
|
||||
isnot("true", itemClearList.getAttribute("hidden"),
|
||||
"Should show Clear Preview Panel button");
|
||||
EventUtils.synthesizeMouseAtCenter(itemClearList, {}, window);
|
||||
} else {
|
||||
is("true", itemClearList.getAttribute("hidden"),
|
||||
"Should not show Clear Preview Panel button");
|
||||
}
|
||||
|
||||
yield itemNumberPromise;
|
||||
is(DownloadsView._downloads.length, testCase.expectedItemNumber,
|
||||
"Download items remained.");
|
||||
|
||||
yield task_resetState();
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
add_task(function* test_height_reduced_after_removal() {
|
||||
yield task_addDownloads([
|
||||
{ state: nsIDM.DOWNLOAD_FINISHED },
|
||||
{ state: DownloadsCommon.DOWNLOAD_FINISHED },
|
||||
]);
|
||||
|
||||
yield task_openPanel();
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
|
||||
"resource://testing-common/httpd.js");
|
||||
|
||||
const nsIDM = Ci.nsIDownloadManager;
|
||||
|
||||
var gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]);
|
||||
gTestTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
|
||||
|
||||
|
|
@ -163,11 +161,12 @@ function* task_addDownloads(aItems) {
|
|||
target: {
|
||||
path: gTestTargetFile.path,
|
||||
},
|
||||
succeeded: item.state == nsIDM.DOWNLOAD_FINISHED,
|
||||
canceled: item.state == nsIDM.DOWNLOAD_CANCELED ||
|
||||
item.state == nsIDM.DOWNLOAD_PAUSED,
|
||||
error: item.state == nsIDM.DOWNLOAD_FAILED ? new Error("Failed.") : null,
|
||||
hasPartialData: item.state == nsIDM.DOWNLOAD_PAUSED,
|
||||
succeeded: item.state == DownloadsCommon.DOWNLOAD_FINISHED,
|
||||
canceled: item.state == DownloadsCommon.DOWNLOAD_CANCELED ||
|
||||
item.state == DownloadsCommon.DOWNLOAD_PAUSED,
|
||||
error: item.state == DownloadsCommon.DOWNLOAD_FAILED ?
|
||||
new Error("Failed.") : null,
|
||||
hasPartialData: item.state == DownloadsCommon.DOWNLOAD_PAUSED,
|
||||
hasBlockedData: item.hasBlockedData || false,
|
||||
startTime: new Date(startTimeMs++),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
This is the PDF.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 1.8.314
|
||||
Current extension version is: 1.8.331
|
||||
|
||||
Taken from upstream commit: 3adda80f
|
||||
Taken from upstream commit: 0dbc68a6
|
||||
|
|
|
|||
|
|
@ -98,7 +98,13 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
/* WEBPACK VAR INJECTION */(function(global) {
|
||||
|
||||
var compatibility = __w_pdfjs_require__(14);
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isNodeJS = exports.isSpace = exports.isString = exports.isNum = exports.isInt = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.isArray = exports.info = exports.globalScope = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.error = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.StatTimer = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
|
||||
|
||||
__w_pdfjs_require__(14);
|
||||
|
||||
var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : undefined;
|
||||
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
|
||||
var TextRenderingMode = {
|
||||
|
|
@ -3386,8 +3392,8 @@ var _UnsupportedManager = function UnsupportedManagerClosure() {
|
|||
}();
|
||||
var version, build;
|
||||
{
|
||||
exports.version = version = '1.8.314';
|
||||
exports.build = build = '3adda80f';
|
||||
exports.version = version = '1.8.331';
|
||||
exports.build = build = '0dbc68a6';
|
||||
}
|
||||
exports.getDocument = getDocument;
|
||||
exports.LoopbackPort = LoopbackPort;
|
||||
|
|
@ -4389,8 +4395,8 @@ if (!_util.globalScope.PDFJS) {
|
|||
}
|
||||
var PDFJS = _util.globalScope.PDFJS;
|
||||
{
|
||||
PDFJS.version = '1.8.314';
|
||||
PDFJS.build = '3adda80f';
|
||||
PDFJS.version = '1.8.331';
|
||||
PDFJS.build = '0dbc68a6';
|
||||
}
|
||||
PDFJS.pdfBug = false;
|
||||
if (PDFJS.verbosity !== undefined) {
|
||||
|
|
@ -6704,8 +6710,8 @@ exports.TilingPattern = TilingPattern;
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '1.8.314';
|
||||
var pdfjsBuild = '3adda80f';
|
||||
var pdfjsVersion = '1.8.331';
|
||||
var pdfjsBuild = '0dbc68a6';
|
||||
var pdfjsSharedUtil = __w_pdfjs_require__(0);
|
||||
var pdfjsDisplayGlobal = __w_pdfjs_require__(8);
|
||||
var pdfjsDisplayAPI = __w_pdfjs_require__(3);
|
||||
|
|
@ -6717,7 +6723,7 @@ exports.PDFJS = pdfjsDisplayGlobal.PDFJS;
|
|||
exports.build = pdfjsDisplayAPI.build;
|
||||
exports.version = pdfjsDisplayAPI.version;
|
||||
exports.getDocument = pdfjsDisplayAPI.getDocument;
|
||||
exports.LoobpackPort = pdfjsDisplayAPI.LoopbackPort;
|
||||
exports.LoopbackPort = pdfjsDisplayAPI.LoopbackPort;
|
||||
exports.PDFDataRangeTransport = pdfjsDisplayAPI.PDFDataRangeTransport;
|
||||
exports.PDFWorker = pdfjsDisplayAPI.PDFWorker;
|
||||
exports.renderTextLayer = pdfjsDisplayTextLayer.renderTextLayer;
|
||||
|
|
@ -6748,6 +6754,8 @@ exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes;
|
|||
"use strict";
|
||||
|
||||
|
||||
;
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
});
|
||||
|
|
@ -98,7 +98,13 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
"use strict";
|
||||
/* WEBPACK VAR INJECTION */(function(global) {
|
||||
|
||||
var compatibility = __w_pdfjs_require__(36);
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.warn = exports.utf8StringToString = exports.stringToUTF8String = exports.stringToPDFString = exports.stringToBytes = exports.string32 = exports.shadow = exports.setVerbosityLevel = exports.removeNullCharacters = exports.readUint32 = exports.readUint16 = exports.readInt8 = exports.log2 = exports.loadJpegStream = exports.isEvalSupported = exports.isLittleEndian = exports.createValidAbsoluteUrl = exports.isSameOrigin = exports.isNodeJS = exports.isSpace = exports.isString = exports.isNum = exports.isInt = exports.isEmptyObj = exports.isBool = exports.isArrayBuffer = exports.isArray = exports.info = exports.globalScope = exports.getVerbosityLevel = exports.getLookupTableFactory = exports.error = exports.deprecated = exports.createObjectURL = exports.createPromiseCapability = exports.createBlob = exports.bytesToString = exports.assert = exports.arraysToBytes = exports.arrayByteLength = exports.XRefParseException = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.StatTimer = exports.PasswordResponses = exports.PasswordException = exports.PageViewport = exports.NotImplementedException = exports.MissingPDFException = exports.MissingDataException = exports.MessageHandler = exports.InvalidPDFException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VERBOSITY_LEVELS = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = undefined;
|
||||
|
||||
__w_pdfjs_require__(36);
|
||||
|
||||
var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : undefined;
|
||||
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
|
||||
var TextRenderingMode = {
|
||||
|
|
@ -36626,8 +36632,8 @@ exports.Type1Parser = Type1Parser;
|
|||
"use strict";
|
||||
|
||||
|
||||
var pdfjsVersion = '1.8.314';
|
||||
var pdfjsBuild = '3adda80f';
|
||||
var pdfjsVersion = '1.8.331';
|
||||
var pdfjsBuild = '0dbc68a6';
|
||||
var pdfjsCoreWorker = __w_pdfjs_require__(17);
|
||||
;
|
||||
exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
||||
|
|
@ -36639,6 +36645,8 @@ exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
|
|||
"use strict";
|
||||
|
||||
|
||||
;
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
});
|
||||
|
|
@ -149,11 +149,11 @@ var FontInspector = (function FontInspectorClosure() {
|
|||
fonts.appendChild(font);
|
||||
// Somewhat of a hack, should probably add a hook for when the text layer
|
||||
// is done rendering.
|
||||
setTimeout(function() {
|
||||
setTimeout(() => {
|
||||
if (this.active) {
|
||||
resetSelection();
|
||||
}
|
||||
}.bind(this), 2000);
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.localized = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.roundToDivide = exports.getVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.mozL10n = exports.RendererType = 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.localized = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.roundToDivide = exports.getVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.mozL10n = exports.RendererType = exports.cloneObj = 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 _pdfjs = __webpack_require__(1);
|
||||
|
||||
|
|
@ -359,6 +359,15 @@ function normalizeWheelEventDelta(evt) {
|
|||
}
|
||||
return delta;
|
||||
}
|
||||
function cloneObj(obj) {
|
||||
var result = {};
|
||||
for (var i in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, i)) {
|
||||
result[i] = obj[i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
var animationStarted = new Promise(function (resolve) {
|
||||
window.requestAnimationFrame(resolve);
|
||||
});
|
||||
|
|
@ -479,6 +488,7 @@ exports.UNKNOWN_SCALE = UNKNOWN_SCALE;
|
|||
exports.MAX_AUTO_SCALE = MAX_AUTO_SCALE;
|
||||
exports.SCROLLBAR_PADDING = SCROLLBAR_PADDING;
|
||||
exports.VERTICAL_PADDING = VERTICAL_PADDING;
|
||||
exports.cloneObj = cloneObj;
|
||||
exports.RendererType = RendererType;
|
||||
exports.mozL10n = mozL10n;
|
||||
exports.EventBus = EventBus;
|
||||
|
|
@ -1167,6 +1177,7 @@ var PDFViewerApplication = {
|
|||
this.pdfThumbnailViewer.setDocument(null);
|
||||
this.pdfViewer.setDocument(null);
|
||||
this.pdfLinkService.setDocument(null, null);
|
||||
this.pdfDocumentProperties.setDocument(null, null);
|
||||
}
|
||||
this.store = null;
|
||||
this.isInitialViewSet = false;
|
||||
|
|
@ -1310,10 +1321,10 @@ var PDFViewerApplication = {
|
|||
this.disableAutoFetchLoadingBarTimeout = null;
|
||||
}
|
||||
this.loadingBar.show();
|
||||
this.disableAutoFetchLoadingBarTimeout = setTimeout(function () {
|
||||
this.disableAutoFetchLoadingBarTimeout = setTimeout(() => {
|
||||
this.loadingBar.hide();
|
||||
this.disableAutoFetchLoadingBarTimeout = null;
|
||||
}.bind(this), DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT);
|
||||
}, DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -1321,7 +1332,6 @@ var PDFViewerApplication = {
|
|||
var self = this;
|
||||
scale = scale || _ui_utils.UNKNOWN_SCALE;
|
||||
this.pdfDocument = pdfDocument;
|
||||
this.pdfDocumentProperties.setDocumentAndUrl(pdfDocument, this.url);
|
||||
var downloadedPromise = pdfDocument.getDownloadInfo().then(function () {
|
||||
self.downloadComplete = true;
|
||||
self.loadingBar.hide();
|
||||
|
|
@ -1333,6 +1343,7 @@ var PDFViewerApplication = {
|
|||
var baseDocumentUrl;
|
||||
baseDocumentUrl = this.baseUrl;
|
||||
this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl);
|
||||
this.pdfDocumentProperties.setDocument(pdfDocument, this.url);
|
||||
var pdfViewer = this.pdfViewer;
|
||||
pdfViewer.currentScale = scale;
|
||||
pdfViewer.setDocument(pdfDocument);
|
||||
|
|
@ -2273,8 +2284,8 @@ Object.defineProperty(exports, "__esModule", {
|
|||
var OverlayManager = {
|
||||
overlays: {},
|
||||
active: null,
|
||||
register: function overlayManagerRegister(name, element, callerCloseMethod, canForceClose) {
|
||||
return new Promise(function (resolve) {
|
||||
register(name, element, callerCloseMethod, canForceClose) {
|
||||
return new Promise(resolve => {
|
||||
var container;
|
||||
if (!name || !element || !(container = element.parentNode)) {
|
||||
throw new Error('Not enough parameters.');
|
||||
|
|
@ -2288,10 +2299,10 @@ var OverlayManager = {
|
|||
canForceClose: canForceClose || false
|
||||
};
|
||||
resolve();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
unregister: function overlayManagerUnregister(name) {
|
||||
return new Promise(function (resolve) {
|
||||
unregister(name) {
|
||||
return new Promise(resolve => {
|
||||
if (!this.overlays[name]) {
|
||||
throw new Error('The overlay does not exist.');
|
||||
} else if (this.active === name) {
|
||||
|
|
@ -2299,10 +2310,10 @@ var OverlayManager = {
|
|||
}
|
||||
delete this.overlays[name];
|
||||
resolve();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
open: function overlayManagerOpen(name) {
|
||||
return new Promise(function (resolve) {
|
||||
open(name) {
|
||||
return new Promise(resolve => {
|
||||
if (!this.overlays[name]) {
|
||||
throw new Error('The overlay does not exist.');
|
||||
} else if (this.active) {
|
||||
|
|
@ -2319,10 +2330,10 @@ var OverlayManager = {
|
|||
this.overlays[this.active].container.classList.remove('hidden');
|
||||
window.addEventListener('keydown', this._keyDown);
|
||||
resolve();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
close: function overlayManagerClose(name) {
|
||||
return new Promise(function (resolve) {
|
||||
close(name) {
|
||||
return new Promise(resolve => {
|
||||
if (!this.overlays[name]) {
|
||||
throw new Error('The overlay does not exist.');
|
||||
} else if (!this.active) {
|
||||
|
|
@ -2335,16 +2346,16 @@ var OverlayManager = {
|
|||
this.active = null;
|
||||
window.removeEventListener('keydown', this._keyDown);
|
||||
resolve();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
_keyDown: function overlayManager_keyDown(evt) {
|
||||
_keyDown(evt) {
|
||||
var self = OverlayManager;
|
||||
if (self.active && evt.keyCode === 27) {
|
||||
self._closeThroughCaller();
|
||||
evt.preventDefault();
|
||||
}
|
||||
},
|
||||
_closeThroughCaller: function overlayManager_closeThroughCaller() {
|
||||
_closeThroughCaller() {
|
||||
if (this.overlays[this.active].callerCloseMethod) {
|
||||
this.overlays[this.active].callerCloseMethod();
|
||||
}
|
||||
|
|
@ -2895,7 +2906,7 @@ var PDFFindController = function PDFFindControllerClosure() {
|
|||
}
|
||||
this.state = state;
|
||||
this.updateUIState(FindStates.FIND_PENDING);
|
||||
this._firstPagePromise.then(function () {
|
||||
this._firstPagePromise.then(() => {
|
||||
this.extractText();
|
||||
clearTimeout(this.findTimeout);
|
||||
if (cmd === 'find') {
|
||||
|
|
@ -2903,7 +2914,7 @@ var PDFFindController = function PDFFindControllerClosure() {
|
|||
} else {
|
||||
this.nextMatch();
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
updatePage: function PDFFindController_updatePage(index) {
|
||||
if (this.selected.pageIdx === index) {
|
||||
|
|
@ -3212,17 +3223,18 @@ var DownloadManager = function DownloadManagerClosure() {
|
|||
});
|
||||
},
|
||||
download: function DownloadManager_download(blob, url, filename) {
|
||||
var blobUrl = window.URL.createObjectURL(blob);
|
||||
FirefoxCom.request('download', {
|
||||
blobUrl,
|
||||
originalUrl: url,
|
||||
filename
|
||||
}, function response(err) {
|
||||
let blobUrl = window.URL.createObjectURL(blob);
|
||||
let onResponse = err => {
|
||||
if (err && this.onerror) {
|
||||
this.onerror(err);
|
||||
}
|
||||
window.URL.revokeObjectURL(blobUrl);
|
||||
}.bind(this));
|
||||
};
|
||||
FirefoxCom.request('download', {
|
||||
blobUrl,
|
||||
originalUrl: url,
|
||||
filename
|
||||
}, onResponse);
|
||||
}
|
||||
};
|
||||
return DownloadManager;
|
||||
|
|
@ -3608,16 +3620,16 @@ var HandTool = function HandToolClosure() {
|
|||
this.handTool.activate();
|
||||
}
|
||||
}).catch(function rejected(reason) {});
|
||||
this.eventBus.on('presentationmodechanged', function (e) {
|
||||
if (e.switchInProgress) {
|
||||
this.eventBus.on('presentationmodechanged', evt => {
|
||||
if (evt.switchInProgress) {
|
||||
return;
|
||||
}
|
||||
if (e.active) {
|
||||
if (evt.active) {
|
||||
this.enterPresentationMode();
|
||||
} else {
|
||||
this.exitPresentationMode();
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
}
|
||||
HandTool.prototype = {
|
||||
get isActive() {
|
||||
|
|
@ -3800,8 +3812,8 @@ class PDFAttachmentViewer {
|
|||
}
|
||||
this._dispatchEvent(attachmentsCount);
|
||||
}
|
||||
_appendAttachment(item) {
|
||||
this._renderedCapability.promise.then(function (id, filename, content) {
|
||||
_appendAttachment({ id, filename, content }) {
|
||||
this._renderedCapability.promise.then(() => {
|
||||
var attachments = this.attachments;
|
||||
if (!attachments) {
|
||||
attachments = Object.create(null);
|
||||
|
|
@ -3820,7 +3832,7 @@ class PDFAttachmentViewer {
|
|||
attachments,
|
||||
keepRenderedCapability: true
|
||||
});
|
||||
}.bind(this, item.id, item.filename, item.content));
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.PDFAttachmentViewer = PDFAttachmentViewer;
|
||||
|
|
@ -3843,77 +3855,101 @@ var _pdfjs = __webpack_require__(1);
|
|||
|
||||
var _overlay_manager = __webpack_require__(5);
|
||||
|
||||
const DEFAULT_FIELD_CONTENT = '-';
|
||||
class PDFDocumentProperties {
|
||||
constructor(options) {
|
||||
this.overlayName = options.overlayName;
|
||||
this.fields = options.fields;
|
||||
this.container = options.container;
|
||||
this.rawFileSize = 0;
|
||||
this.url = null;
|
||||
this.pdfDocument = null;
|
||||
if (options.closeButton) {
|
||||
options.closeButton.addEventListener('click', this.close.bind(this));
|
||||
constructor({ overlayName, fields, container, closeButton }) {
|
||||
this.overlayName = overlayName;
|
||||
this.fields = fields;
|
||||
this.container = container;
|
||||
this._reset();
|
||||
if (closeButton) {
|
||||
closeButton.addEventListener('click', this.close.bind(this));
|
||||
}
|
||||
this._dataAvailableCapability = (0, _pdfjs.createPromiseCapability)();
|
||||
_overlay_manager.OverlayManager.register(this.overlayName, this.container, this.close.bind(this));
|
||||
}
|
||||
open() {
|
||||
let freezeFieldData = data => {
|
||||
Object.defineProperty(this, 'fieldData', {
|
||||
value: Object.freeze(data),
|
||||
writable: false,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
};
|
||||
Promise.all([_overlay_manager.OverlayManager.open(this.overlayName), this._dataAvailableCapability.promise]).then(() => {
|
||||
this._getProperties();
|
||||
if (this.fieldData) {
|
||||
this._updateUI();
|
||||
return;
|
||||
}
|
||||
this.pdfDocument.getMetadata().then(({ info, metadata }) => {
|
||||
freezeFieldData({
|
||||
'fileName': (0, _ui_utils.getPDFFileNameFromURL)(this.url),
|
||||
'fileSize': this._parseFileSize(this.maybeFileSize),
|
||||
'title': info.Title,
|
||||
'author': info.Author,
|
||||
'subject': info.Subject,
|
||||
'keywords': info.Keywords,
|
||||
'creationDate': this._parseDate(info.CreationDate),
|
||||
'modificationDate': this._parseDate(info.ModDate),
|
||||
'creator': info.Creator,
|
||||
'producer': info.Producer,
|
||||
'version': info.PDFFormatVersion,
|
||||
'pageCount': this.pdfDocument.numPages
|
||||
});
|
||||
this._updateUI();
|
||||
return this.pdfDocument.getDownloadInfo();
|
||||
}).then(({ length }) => {
|
||||
let data = (0, _ui_utils.cloneObj)(this.fieldData);
|
||||
data['fileSize'] = this._parseFileSize(length);
|
||||
freezeFieldData(data);
|
||||
this._updateUI();
|
||||
});
|
||||
});
|
||||
}
|
||||
close() {
|
||||
_overlay_manager.OverlayManager.close(this.overlayName);
|
||||
}
|
||||
setFileSize(fileSize) {
|
||||
if (fileSize > 0) {
|
||||
this.rawFileSize = fileSize;
|
||||
setDocument(pdfDocument, url) {
|
||||
if (this.pdfDocument) {
|
||||
this._reset();
|
||||
this._updateUI(true);
|
||||
}
|
||||
if (!pdfDocument) {
|
||||
return;
|
||||
}
|
||||
setDocumentAndUrl(pdfDocument, url) {
|
||||
this.pdfDocument = pdfDocument;
|
||||
this.url = url;
|
||||
this._dataAvailableCapability.resolve();
|
||||
}
|
||||
_getProperties() {
|
||||
if (!_overlay_manager.OverlayManager.active) {
|
||||
setFileSize(fileSize) {
|
||||
if (typeof fileSize === 'number' && fileSize > 0) {
|
||||
this.maybeFileSize = fileSize;
|
||||
}
|
||||
}
|
||||
_reset() {
|
||||
this.pdfDocument = null;
|
||||
this.url = null;
|
||||
this.maybeFileSize = 0;
|
||||
delete this.fieldData;
|
||||
this._dataAvailableCapability = (0, _pdfjs.createPromiseCapability)();
|
||||
}
|
||||
_updateUI(reset = false) {
|
||||
if (reset || !this.fieldData) {
|
||||
for (let id in this.fields) {
|
||||
this.fields[id].textContent = DEFAULT_FIELD_CONTENT;
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.pdfDocument.getDownloadInfo().then(data => {
|
||||
if (data.length === this.rawFileSize) {
|
||||
if (_overlay_manager.OverlayManager.active !== this.overlayName) {
|
||||
return;
|
||||
}
|
||||
this.setFileSize(data.length);
|
||||
this._updateUI(this.fields['fileSize'], this._parseFileSize());
|
||||
});
|
||||
this.pdfDocument.getMetadata().then(data => {
|
||||
var content = {
|
||||
'fileName': (0, _ui_utils.getPDFFileNameFromURL)(this.url),
|
||||
'fileSize': this._parseFileSize(),
|
||||
'title': data.info.Title,
|
||||
'author': data.info.Author,
|
||||
'subject': data.info.Subject,
|
||||
'keywords': data.info.Keywords,
|
||||
'creationDate': this._parseDate(data.info.CreationDate),
|
||||
'modificationDate': this._parseDate(data.info.ModDate),
|
||||
'creator': data.info.Creator,
|
||||
'producer': data.info.Producer,
|
||||
'version': data.info.PDFFormatVersion,
|
||||
'pageCount': this.pdfDocument.numPages
|
||||
};
|
||||
for (var identifier in content) {
|
||||
this._updateUI(this.fields[identifier], content[identifier]);
|
||||
}
|
||||
});
|
||||
}
|
||||
_updateUI(field, content) {
|
||||
if (field && content !== undefined && content !== '') {
|
||||
field.textContent = content;
|
||||
for (let id in this.fields) {
|
||||
let content = this.fieldData[id];
|
||||
this.fields[id].textContent = content || content === 0 ? content : DEFAULT_FIELD_CONTENT;
|
||||
}
|
||||
}
|
||||
_parseFileSize() {
|
||||
var fileSize = this.rawFileSize,
|
||||
kb = fileSize / 1024;
|
||||
_parseFileSize(fileSize = 0) {
|
||||
let kb = fileSize / 1024;
|
||||
if (!kb) {
|
||||
return;
|
||||
} else if (kb < 1024) {
|
||||
|
|
@ -3928,10 +3964,10 @@ class PDFDocumentProperties {
|
|||
}, '{{size_mb}} MB ({{size_b}} bytes)');
|
||||
}
|
||||
_parseDate(inputDate) {
|
||||
var dateToParse = inputDate;
|
||||
if (dateToParse === undefined) {
|
||||
return '';
|
||||
if (!inputDate) {
|
||||
return;
|
||||
}
|
||||
let dateToParse = inputDate;
|
||||
if (dateToParse.substring(0, 2) === 'D:') {
|
||||
dateToParse = dateToParse.substring(2);
|
||||
}
|
||||
|
|
@ -6020,10 +6056,10 @@ var PDFThumbnailViewer = function PDFThumbnailViewerClosure() {
|
|||
if (!pdfDocument) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return pdfDocument.getPage(1).then(function (firstPage) {
|
||||
return pdfDocument.getPage(1).then(firstPage => {
|
||||
var pagesCount = pdfDocument.numPages;
|
||||
var viewport = firstPage.getViewport(1.0);
|
||||
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||
for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||
var thumbnail = new _pdf_thumbnail_view.PDFThumbnailView({
|
||||
container: this.container,
|
||||
id: pageNum,
|
||||
|
|
@ -6034,7 +6070,7 @@ var PDFThumbnailViewer = function PDFThumbnailViewerClosure() {
|
|||
});
|
||||
this.thumbnails.push(thumbnail);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
_cancelRendering: function PDFThumbnailViewer_cancelRendering() {
|
||||
for (var i = 0, ii = this.thumbnails.length; i < ii; i++) {
|
||||
|
|
@ -6354,8 +6390,8 @@ var PDFViewer = function pdfViewer() {
|
|||
return;
|
||||
}
|
||||
var getPagesLeft = pagesCount;
|
||||
for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||
pdfDocument.getPage(pageNum).then(function (pageNum, pdfPage) {
|
||||
for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
|
||||
pdfDocument.getPage(pageNum).then(pdfPage => {
|
||||
var pageView = this._pages[pageNum - 1];
|
||||
if (!pageView.pdfPage) {
|
||||
pageView.setPdfPage(pdfPage);
|
||||
|
|
@ -6364,7 +6400,7 @@ var PDFViewer = function pdfViewer() {
|
|||
if (--getPagesLeft === 0) {
|
||||
pagesCapability.resolve();
|
||||
}
|
||||
}.bind(this, pageNum));
|
||||
});
|
||||
}
|
||||
});
|
||||
this.eventBus.dispatch('pagesinit', { source: this });
|
||||
|
|
@ -6785,6 +6821,10 @@ exports.PDFViewer = PDFViewer;
|
|||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.BasePreferences = undefined;
|
||||
|
||||
var _ui_utils = __webpack_require__(0);
|
||||
|
||||
var defaultPreferences = null;
|
||||
function getDefaultPreferences() {
|
||||
if (!defaultPreferences) {
|
||||
|
|
@ -6811,15 +6851,6 @@ function getDefaultPreferences() {
|
|||
}
|
||||
return defaultPreferences;
|
||||
}
|
||||
function cloneObj(obj) {
|
||||
var result = {};
|
||||
for (var i in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, i)) {
|
||||
result[i] = obj[i];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
class BasePreferences {
|
||||
constructor() {
|
||||
if (this.constructor === BasePreferences) {
|
||||
|
|
@ -6833,7 +6864,7 @@ class BasePreferences {
|
|||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
this.prefs = cloneObj(defaults);
|
||||
this.prefs = (0, _ui_utils.cloneObj)(defaults);
|
||||
return this._readFromStorage(defaults);
|
||||
}).then(prefObj => {
|
||||
if (prefObj) {
|
||||
|
|
@ -6849,7 +6880,7 @@ class BasePreferences {
|
|||
}
|
||||
reset() {
|
||||
return this._initializedPromise.then(() => {
|
||||
this.prefs = cloneObj(this.defaults);
|
||||
this.prefs = (0, _ui_utils.cloneObj)(this.defaults);
|
||||
return this._writeToStorage(this.defaults);
|
||||
});
|
||||
}
|
||||
|
|
@ -7009,18 +7040,16 @@ var SecondaryToolbar = function SecondaryToolbarClosure() {
|
|||
},
|
||||
_bindClickListeners: function SecondaryToolbar_bindClickListeners() {
|
||||
this.toggleButton.addEventListener('click', this.toggle.bind(this));
|
||||
for (var button in this.buttons) {
|
||||
var element = this.buttons[button].element;
|
||||
var eventName = this.buttons[button].eventName;
|
||||
var close = this.buttons[button].close;
|
||||
element.addEventListener('click', function (eventName, close) {
|
||||
for (let button in this.buttons) {
|
||||
let { element, eventName, close } = this.buttons[button];
|
||||
element.addEventListener('click', evt => {
|
||||
if (eventName !== null) {
|
||||
this.eventBus.dispatch(eventName, { source: this });
|
||||
}
|
||||
if (close) {
|
||||
this.close();
|
||||
}
|
||||
}.bind(this, eventName, close));
|
||||
});
|
||||
}
|
||||
},
|
||||
_bindHandToolListener: function SecondaryToolbar_bindHandToolListener(toggleHandToolButton) {
|
||||
|
|
@ -7141,11 +7170,11 @@ var TextLayerBuilder = function TextLayerBuilderClosure() {
|
|||
timeout,
|
||||
enhanceTextSelection: this.enhanceTextSelection
|
||||
});
|
||||
this.textLayerRenderTask.promise.then(function () {
|
||||
this.textLayerRenderTask.promise.then(() => {
|
||||
this.textLayerDiv.appendChild(textLayerFrag);
|
||||
this._finishRendering();
|
||||
this.updateMatches();
|
||||
}.bind(this), function (reason) {});
|
||||
}, function (reason) {});
|
||||
},
|
||||
cancel: function TextLayerBuilder_cancel() {
|
||||
if (this.textLayerRenderTask) {
|
||||
|
|
|
|||
|
|
@ -134,6 +134,10 @@
|
|||
<!ENTITY downloadsHistory.label "Show All Downloads">
|
||||
<!ENTITY downloadsHistory.accesskey "S">
|
||||
|
||||
<!-- LOCALIZATION NOTE (openDownloadsFolder.label):
|
||||
This command is not currently available in the user interface, but the
|
||||
string was preserved by bug 1362207 to be used in a future version.
|
||||
-->
|
||||
<!ENTITY openDownloadsFolder.label "Open Downloads Folder">
|
||||
|
||||
<!ENTITY clearDownloadsButton.label "Clear Downloads">
|
||||
|
|
|
|||
|
|
@ -97,54 +97,14 @@
|
|||
padding-inline-end: 10px;
|
||||
}
|
||||
|
||||
#downloadsPanel[hasdownloads] #downloadsFooterButtons:not(.downloadsHideDropmarker) > #downloadsHistory {
|
||||
padding-inline-start: 68px;
|
||||
}
|
||||
|
||||
toolbarseparator.downloadsDropmarkerSplitter {
|
||||
margin: 7px 0;
|
||||
}
|
||||
|
||||
@item@ > toolbarseparator {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
@item@:hover > toolbarseparator,
|
||||
#downloadsFooter:hover toolbarseparator.downloadsDropmarkerSplitter,
|
||||
#downloadsFooter[showingdropdown] toolbarseparator {
|
||||
@item@:hover > toolbarseparator {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.downloadsDropmarker {
|
||||
padding: 0 21px;
|
||||
}
|
||||
|
||||
.downloadsDropmarker > .button-box > hbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.downloadsDropmarker > .button-box > .button-menu-dropmarker {
|
||||
/* This is to override the linux !important */
|
||||
-moz-appearance: none !important;
|
||||
display: -moz-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.downloadsDropmarker > .button-box > .button-menu-dropmarker > .dropmarker-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: url("chrome://global/skin/icons/menubutton-dropmarker.svg");
|
||||
filter: url("chrome://global/skin/filters.svg#fill");
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
/* Override default icon size which is too small for this dropdown */
|
||||
.downloadsDropmarker > .button-box > .button-menu-dropmarker {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#downloadsSummary {
|
||||
-moz-user-focus: normal;
|
||||
}
|
||||
|
|
|
|||
7
caps/.eslintrc.js
Normal file
7
caps/.eslintrc.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"plugin:mozilla/recommended"
|
||||
]
|
||||
};
|
||||
8
caps/tests/mochitest/.eslintrc.js
Normal file
8
caps/tests/mochitest/.eslintrc.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"plugin:mozilla/mochitest-test",
|
||||
"plugin:mozilla/browser-test"
|
||||
]
|
||||
};
|
||||
|
|
@ -22,8 +22,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1180921
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
let oldAddonIdCallback = aps.setExtensionURIToAddonIdCallback(uri => uri.host);
|
||||
SimpleTest.registerCleanupFunction(function() {
|
||||
aps.setAddonLoadURICallback('addona', null);
|
||||
aps.setAddonLoadURICallback('addonb', null);
|
||||
aps.setAddonLoadURICallback("addona", null);
|
||||
aps.setAddonLoadURICallback("addonb", null);
|
||||
aps.setExtensionURIToAddonIdCallback(oldAddonIdCallback);
|
||||
});
|
||||
|
||||
|
|
@ -41,28 +41,28 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1180921
|
|||
return p;
|
||||
}
|
||||
|
||||
let addonA = new Cu.Sandbox(ssm.createCodebasePrincipal(Services.io.newURI('moz-extension://addonA/'), {}),
|
||||
{wantGlobalProperties: ['XMLHttpRequest']});
|
||||
let addonB = new Cu.Sandbox(ssm.createCodebasePrincipal(Services.io.newURI('moz-extension://addonB/'), {}),
|
||||
{wantGlobalProperties: ['XMLHttpRequest']});
|
||||
let addonA = new Cu.Sandbox(ssm.createCodebasePrincipal(Services.io.newURI("moz-extension://addonA/"), {}),
|
||||
{wantGlobalProperties: ["XMLHttpRequest"]});
|
||||
let addonB = new Cu.Sandbox(ssm.createCodebasePrincipal(Services.io.newURI("moz-extension://addonB/"), {}),
|
||||
{wantGlobalProperties: ["XMLHttpRequest"]});
|
||||
|
||||
function uriForDomain(d) { return d + '/tests/caps/tests/mochitest/file_data.txt' }
|
||||
function uriForDomain(d) { return d + "/tests/caps/tests/mochitest/file_data.txt" }
|
||||
|
||||
tryLoad(addonA, uriForDomain('http://test1.example.org'))
|
||||
tryLoad(addonA, uriForDomain("http://test1.example.org"))
|
||||
.then(function(success) {
|
||||
ok(!success, "cross-origin load should fail for addon A");
|
||||
aps.setAddonLoadURICallback('addona', function(uri) { return /test1/.test(uri.host); });
|
||||
aps.setAddonLoadURICallback('addonb', function(uri) { return /test2/.test(uri.host); });
|
||||
return tryLoad(addonA, uriForDomain('http://test1.example.org'));
|
||||
aps.setAddonLoadURICallback("addona", function(uri) { return /test1/.test(uri.host); });
|
||||
aps.setAddonLoadURICallback("addonb", function(uri) { return /test2/.test(uri.host); });
|
||||
return tryLoad(addonA, uriForDomain("http://test1.example.org"));
|
||||
}).then(function(success) {
|
||||
ok(success, "whitelisted cross-origin load of test1 should succeed for addon A");
|
||||
return tryLoad(addonB, uriForDomain('http://test1.example.org'));
|
||||
return tryLoad(addonB, uriForDomain("http://test1.example.org"));
|
||||
}).then(function(success) {
|
||||
ok(!success, "non-whitelisted cross-origin load of test1 should fail for addon B");
|
||||
return tryLoad(addonB, uriForDomain('http://test2.example.org'));
|
||||
return tryLoad(addonB, uriForDomain("http://test2.example.org"));
|
||||
}).then(function(success) {
|
||||
ok(success, "whitelisted cross-origin load of test2 should succeed for addon B");
|
||||
return tryLoad(addonA, uriForDomain('http://test2.example.org'));
|
||||
return tryLoad(addonA, uriForDomain("http://test2.example.org"));
|
||||
}).then(function(success) {
|
||||
ok(!success, "non-whitelisted cross-origin load of test2 should fail for addon A");
|
||||
SimpleTest.finish();
|
||||
|
|
|
|||
|
|
@ -21,35 +21,31 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=246699
|
|||
** Test for Bug 246699
|
||||
** (should produce stack information for caps errors)
|
||||
**/
|
||||
function isError(e)
|
||||
{
|
||||
function isError(e) {
|
||||
return e.constructor.name === "Error" || e.constructor.name === "TypeError";
|
||||
}
|
||||
|
||||
function hasStack(e)
|
||||
{
|
||||
function hasStack(e) {
|
||||
return isError(e) && /inciteCaps/.test(e.stack);
|
||||
}
|
||||
|
||||
function inciteCaps(f)
|
||||
{
|
||||
function inciteCaps(f) {
|
||||
try {
|
||||
f();
|
||||
return "operation succeeded";
|
||||
} catch (e if hasStack(e)) {
|
||||
return "denied-stack";
|
||||
} catch (e) {
|
||||
if (hasStack(e)) {
|
||||
return "denied-stack";
|
||||
}
|
||||
return "unexpected: " + e;
|
||||
}
|
||||
}
|
||||
|
||||
function tryChromeLoad()
|
||||
{
|
||||
function tryChromeLoad() {
|
||||
window.frames[0].location = "chrome://global/content/mozilla.xhtml";
|
||||
}
|
||||
|
||||
function tryComponentsClasses()
|
||||
{
|
||||
function tryComponentsClasses() {
|
||||
return SpecialPowers.Components.classes["@mozilla.org/dummy;1"];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=292789
|
|||
** even for ALLOW_CHROME mechanisms (<script>, <img> etc)
|
||||
**/
|
||||
|
||||
/* import-globals-from ../../../toolkit/content/treeUtils.js */
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** <script src=""> test **/
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=423375
|
|||
** Test for Bug 423375
|
||||
** (content shouldn't be able to load chrome: or resource:)
|
||||
**/
|
||||
function tryLoad(url)
|
||||
{
|
||||
function tryLoad(url) {
|
||||
try {
|
||||
window.frames[0].location = url;
|
||||
return "loaded";
|
||||
} catch (e if /Access.*denied/.test(String(e))) {
|
||||
return "denied";
|
||||
} catch (e) {
|
||||
if (/Access.*denied/.test(String(e))) {
|
||||
return "denied";
|
||||
}
|
||||
return "unexpected: " + e;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
|
|||
.QueryInterface(SpecialPowers.Ci.nsISubstitutingProtocolHandler);
|
||||
|
||||
SimpleTest.registerCleanupFunction(function() {
|
||||
extensionHandler.setSubstitution('cherise', null);
|
||||
extensionHandler.setSubstitution('liebchen', null);
|
||||
extensionHandler.setSubstitution("cherise", null);
|
||||
extensionHandler.setSubstitution("liebchen", null);
|
||||
aps.setExtensionURILoadCallback(oldLoadCallback);
|
||||
aps.setExtensionURIToAddonIdCallback(oldMapCallback);
|
||||
});
|
||||
|
|
@ -33,16 +33,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
|
|||
|
||||
// First, get a file:// URI to something - open to suggestions on how to do
|
||||
// this more easily.
|
||||
var resURI = SpecialPowers.Services.io.newURI('resource://testing-common/resource_test_file.html');
|
||||
var resURI = SpecialPowers.Services.io.newURI("resource://testing-common/resource_test_file.html");
|
||||
var filePath = resourceHandler.resolveURI(resURI);
|
||||
ok(filePath.startsWith('file://'), 'resource:// URI resolves where we expect: ' + filePath);
|
||||
ok(filePath.startsWith("file://"), "resource:// URI resolves where we expect: " + filePath);
|
||||
var fileURI = SpecialPowers.Services.io.newURI(filePath);
|
||||
|
||||
// Register a moz-extension:// URI.
|
||||
extensionHandler.setSubstitution('cherise', fileURI);
|
||||
extensionHandler.setSubstitution("cherise", fileURI);
|
||||
|
||||
// Alias the above.
|
||||
extensionHandler.setSubstitution('liebchen', SpecialPowers.Services.io.newURI('moz-extension://cherise'));
|
||||
extensionHandler.setSubstitution("liebchen", SpecialPowers.Services.io.newURI("moz-extension://cherise"));
|
||||
|
||||
//
|
||||
// Make sure that non-file:// URIs don't work.
|
||||
|
|
@ -50,7 +50,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
|
|||
|
||||
// resource://
|
||||
try {
|
||||
extensionHandler.setSubstitution('interdit', resURI);
|
||||
extensionHandler.setSubstitution("interdit", resURI);
|
||||
ok(false, "Should have thrown for mapping moz-extension to resource");
|
||||
} catch (e) {
|
||||
ok(true, "Threw correctly: " + e);
|
||||
|
|
@ -58,15 +58,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
|
|||
|
||||
// chrome://
|
||||
try {
|
||||
var chromeURI = SpecialPowers.Services.io.newURI('chrome://global/content/mozilla.xhtml');
|
||||
extensionHandler.setSubstitution('verboten', chromeURI);
|
||||
var chromeURI = SpecialPowers.Services.io.newURI("chrome://global/content/mozilla.xhtml");
|
||||
extensionHandler.setSubstitution("verboten", chromeURI);
|
||||
ok(false, "Should have thrown for mapping moz-extension to chrome");
|
||||
} catch (e) {
|
||||
ok(true, "Threw correctly: " + e);
|
||||
}
|
||||
|
||||
function navigateWithLocation(ifr, url) { ifr.contentWindow.location = url; }
|
||||
function navigateWithSrc(ifr, url) { ifr.setAttribute('src', url); }
|
||||
function navigateWithSrc(ifr, url) { ifr.setAttribute("src", url); }
|
||||
function navigateFromChromeWithLocation(ifr, url) { SpecialPowers.wrap(ifr).contentWindow.location = url; }
|
||||
function navigateFromChromeWithWebNav(ifr, url) {
|
||||
SpecialPowers.wrap(ifr).contentWindow
|
||||
|
|
@ -81,25 +81,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
|
|||
aps.setExtensionURILoadCallback(cb);
|
||||
}
|
||||
|
||||
aps.setExtensionURIToAddonIdCallback(SpecialPowers.wrapCallback(function (uri) { return 'imaginaryaddon-' + uri.host[0]; }));
|
||||
aps.setExtensionURIToAddonIdCallback(SpecialPowers.wrapCallback(function(uri) { return "imaginaryaddon-" + uri.host[0]; }));
|
||||
|
||||
function testLoad(url, navigate, shouldThrow) {
|
||||
var ifr = document.createElement('iframe');
|
||||
var ifr = document.createElement("iframe");
|
||||
var p = new Promise(function(resolve, reject) {
|
||||
ifr.onload = function() {
|
||||
ok(true, 'Loaded ' + url);
|
||||
ok(true, "Loaded " + url);
|
||||
var prin = SpecialPowers.wrap(ifr.contentWindow).document.nodePrincipal;
|
||||
function stripTrailingSlash(s) { return s.replace(/\/$/, ''); };
|
||||
is(stripTrailingSlash(prin.URI.spec), url, 'Principal uri is correct: ' + url);
|
||||
function stripPath(s) { return s.replace(/(.*\/\/.+)\/.*/, '$1'); };
|
||||
is(prin.originNoSuffix, stripPath(url), 'Principal origin is correct: ' + prin.originNoSuffix);
|
||||
is(prin.addonId, 'imaginaryaddon-' + url[url.indexOf('/') + 2], 'addonId is correct');
|
||||
function stripTrailingSlash(s) { return s.replace(/\/$/, ""); }
|
||||
is(stripTrailingSlash(prin.URI.spec), url, "Principal uri is correct: " + url);
|
||||
function stripPath(s) { return s.replace(/(.*\/\/.+)\/.*/, "$1"); }
|
||||
is(prin.originNoSuffix, stripPath(url), "Principal origin is correct: " + prin.originNoSuffix);
|
||||
is(prin.addonId, "imaginaryaddon-" + url[url.indexOf("/") + 2], "addonId is correct");
|
||||
if (/_blank/.test(url)) {
|
||||
is(SpecialPowers.wrap(ifr.contentWindow).document.documentElement.innerHTML,
|
||||
'<head></head><body></body>', 'blank document looks right');
|
||||
"<head></head><body></body>", "blank document looks right");
|
||||
} else {
|
||||
is(SpecialPowers.wrap(ifr.contentWindow).document.title, 'resource test file',
|
||||
'document looks right');
|
||||
is(SpecialPowers.wrap(ifr.contentWindow).document.title, "resource test file",
|
||||
"document looks right");
|
||||
}
|
||||
ifr.remove();
|
||||
resolve();
|
||||
|
|
@ -134,20 +134,20 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1161831
|
|||
//
|
||||
// Perform some loads and make sure they work correctly.
|
||||
//
|
||||
testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithLocation)()
|
||||
.then(testLoad.bind(null, 'moz-extension://cherise', navigateFromChromeWithWebNav))
|
||||
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation, /* shouldThrow = */ true))
|
||||
.then(testXHR.bind(null, 'moz-extension://cherise', /* shouldError = */ true))
|
||||
testLoad.bind(null, "moz-extension://cherise", navigateFromChromeWithLocation)()
|
||||
.then(testLoad.bind(null, "moz-extension://cherise", navigateFromChromeWithWebNav))
|
||||
.then(testLoad.bind(null, "moz-extension://cherise", navigateWithLocation, /* shouldThrow = */ true))
|
||||
.then(testXHR.bind(null, "moz-extension://cherise", /* shouldError = */ true))
|
||||
.then(setWhitelistCallback.bind(null, /cherise/))
|
||||
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithLocation))
|
||||
.then(testXHR.bind(null, 'moz-extension://cherise'))
|
||||
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation, /* shouldThrow = */ true))
|
||||
.then(testXHR.bind(null, 'moz-extension://liebchen', /* shouldError = */ true))
|
||||
.then(testLoad.bind(null, "moz-extension://cherise", navigateWithLocation))
|
||||
.then(testXHR.bind(null, "moz-extension://cherise"))
|
||||
.then(testLoad.bind(null, "moz-extension://liebchen", navigateWithLocation, /* shouldThrow = */ true))
|
||||
.then(testXHR.bind(null, "moz-extension://liebchen", /* shouldError = */ true))
|
||||
.then(setWhitelistCallback.bind(null, /cherise|liebchen/))
|
||||
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithLocation))
|
||||
.then(testLoad.bind(null, 'moz-extension://liebchen', navigateWithSrc))
|
||||
.then(testLoad.bind(null, 'moz-extension://cherise', navigateWithSrc))
|
||||
.then(testLoad.bind(null, 'moz-extension://cherise/_blank.html', navigateWithSrc))
|
||||
.then(testLoad.bind(null, "moz-extension://liebchen", navigateWithLocation))
|
||||
.then(testLoad.bind(null, "moz-extension://liebchen", navigateWithSrc))
|
||||
.then(testLoad.bind(null, "moz-extension://cherise", navigateWithSrc))
|
||||
.then(testLoad.bind(null, "moz-extension://cherise/_blank.html", navigateWithSrc))
|
||||
.then(SimpleTest.finish.bind(SimpleTest),
|
||||
function(e) { ok(false, "rejected promise: " + e); SimpleTest.finish() }
|
||||
);
|
||||
|
|
|
|||
7
caps/tests/unit/.eslintrc.js
Normal file
7
caps/tests/unit/.eslintrc.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"plugin:mozilla/xpcshell-test"
|
||||
]
|
||||
};
|
||||
|
|
@ -25,10 +25,10 @@ function checkOriginAttributes(prin, attrs, suffix) {
|
|||
attrs = attrs || {};
|
||||
do_check_eq(prin.originAttributes.appId, attrs.appId || 0);
|
||||
do_check_eq(prin.originAttributes.inIsolatedMozBrowser, attrs.inIsolatedMozBrowser || false);
|
||||
do_check_eq(prin.originSuffix, suffix || '');
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), suffix || '');
|
||||
do_check_eq(prin.originSuffix, suffix || "");
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(attrs), suffix || "");
|
||||
do_check_true(ChromeUtils.originAttributesMatchPattern(prin.originAttributes, attrs));
|
||||
if (!prin.isNullPrincipal && !prin.origin.startsWith('[')) {
|
||||
if (!prin.isNullPrincipal && !prin.origin.startsWith("[")) {
|
||||
do_check_true(ssm.createCodebasePrincipalFromOrigin(prin.origin).equals(prin));
|
||||
} else {
|
||||
checkThrows(() => ssm.createCodebasePrincipalFromOrigin(prin.origin));
|
||||
|
|
@ -60,28 +60,28 @@ function checkValues(attrs, values) {
|
|||
do_check_eq(attrs.appId, values.appId || 0);
|
||||
do_check_eq(attrs.userContextId, values.userContextId || 0);
|
||||
do_check_eq(attrs.inIsolatedMozBrowser, values.inIsolatedMozBrowser || false);
|
||||
do_check_eq(attrs.privateBrowsingId, values.privateBrowsingId || '');
|
||||
do_check_eq(attrs.firstPartyDomain, values.firstPartyDomain || '');
|
||||
do_check_eq(attrs.privateBrowsingId, values.privateBrowsingId || "");
|
||||
do_check_eq(attrs.firstPartyDomain, values.firstPartyDomain || "");
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
// Attributeless origins.
|
||||
do_check_eq(ssm.getSystemPrincipal().origin, '[System Principal]');
|
||||
do_check_eq(ssm.getSystemPrincipal().origin, "[System Principal]");
|
||||
checkOriginAttributes(ssm.getSystemPrincipal());
|
||||
var exampleOrg = ssm.createCodebasePrincipal(makeURI('http://example.org'), {});
|
||||
do_check_eq(exampleOrg.origin, 'http://example.org');
|
||||
var exampleOrg = ssm.createCodebasePrincipal(makeURI("http://example.org"), {});
|
||||
do_check_eq(exampleOrg.origin, "http://example.org");
|
||||
checkOriginAttributes(exampleOrg);
|
||||
var exampleCom = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {});
|
||||
do_check_eq(exampleCom.origin, 'https://www.example.com:123');
|
||||
var exampleCom = ssm.createCodebasePrincipal(makeURI("https://www.example.com:123"), {});
|
||||
do_check_eq(exampleCom.origin, "https://www.example.com:123");
|
||||
checkOriginAttributes(exampleCom);
|
||||
var nullPrin = Cu.getObjectPrincipal(new Cu.Sandbox(null));
|
||||
do_check_true(/^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(nullPrin.origin));
|
||||
checkOriginAttributes(nullPrin);
|
||||
var ipv6Prin = ssm.createCodebasePrincipal(makeURI('https://[2001:db8::ff00:42:8329]:123'), {});
|
||||
do_check_eq(ipv6Prin.origin, 'https://[2001:db8::ff00:42:8329]:123');
|
||||
var ipv6Prin = ssm.createCodebasePrincipal(makeURI("https://[2001:db8::ff00:42:8329]:123"), {});
|
||||
do_check_eq(ipv6Prin.origin, "https://[2001:db8::ff00:42:8329]:123");
|
||||
checkOriginAttributes(ipv6Prin);
|
||||
var ipv6NPPrin = ssm.createCodebasePrincipal(makeURI('https://[2001:db8::ff00:42:8329]'), {});
|
||||
do_check_eq(ipv6NPPrin.origin, 'https://[2001:db8::ff00:42:8329]');
|
||||
var ipv6NPPrin = ssm.createCodebasePrincipal(makeURI("https://[2001:db8::ff00:42:8329]"), {});
|
||||
do_check_eq(ipv6NPPrin.origin, "https://[2001:db8::ff00:42:8329]");
|
||||
checkOriginAttributes(ipv6NPPrin);
|
||||
var ep = Cu.getObjectPrincipal(Cu.Sandbox([exampleCom, nullPrin, exampleOrg]));
|
||||
checkOriginAttributes(ep);
|
||||
|
|
@ -92,42 +92,42 @@ function run_test() {
|
|||
do_check_eq(ep.origin, `[Expanded Principal [${exampleOrg.origin}, ${exampleCom.origin}, ${nullPrin.origin}]]`);
|
||||
|
||||
// Make sure createCodebasePrincipal does what the rest of gecko does.
|
||||
do_check_true(exampleOrg.equals(Cu.getObjectPrincipal(new Cu.Sandbox('http://example.org'))));
|
||||
do_check_true(exampleOrg.equals(Cu.getObjectPrincipal(new Cu.Sandbox("http://example.org"))));
|
||||
|
||||
//
|
||||
// Test origin attributes.
|
||||
//
|
||||
|
||||
// Just app.
|
||||
var exampleOrg_app = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 42});
|
||||
var exampleOrg_app = ssm.createCodebasePrincipal(makeURI("http://example.org"), {appId: 42});
|
||||
var nullPrin_app = ssm.createNullPrincipal({appId: 42});
|
||||
checkOriginAttributes(exampleOrg_app, {appId: 42}, '^appId=42');
|
||||
checkOriginAttributes(nullPrin_app, {appId: 42}, '^appId=42');
|
||||
do_check_eq(exampleOrg_app.origin, 'http://example.org^appId=42');
|
||||
checkOriginAttributes(exampleOrg_app, {appId: 42}, "^appId=42");
|
||||
checkOriginAttributes(nullPrin_app, {appId: 42}, "^appId=42");
|
||||
do_check_eq(exampleOrg_app.origin, "http://example.org^appId=42");
|
||||
|
||||
// Just browser.
|
||||
var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inIsolatedMozBrowser: true});
|
||||
var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI("http://example.org"), {inIsolatedMozBrowser: true});
|
||||
var nullPrin_browser = ssm.createNullPrincipal({inIsolatedMozBrowser: true});
|
||||
checkOriginAttributes(exampleOrg_browser, {inIsolatedMozBrowser: true}, '^inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_browser, {inIsolatedMozBrowser: true}, '^inBrowser=1');
|
||||
do_check_eq(exampleOrg_browser.origin, 'http://example.org^inBrowser=1');
|
||||
checkOriginAttributes(exampleOrg_browser, {inIsolatedMozBrowser: true}, "^inBrowser=1");
|
||||
checkOriginAttributes(nullPrin_browser, {inIsolatedMozBrowser: true}, "^inBrowser=1");
|
||||
do_check_eq(exampleOrg_browser.origin, "http://example.org^inBrowser=1");
|
||||
|
||||
// App and browser.
|
||||
var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inIsolatedMozBrowser: true, appId: 42});
|
||||
var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI("http://example.org"), {inIsolatedMozBrowser: true, appId: 42});
|
||||
var nullPrin_appBrowser = ssm.createNullPrincipal({inIsolatedMozBrowser: true, appId: 42});
|
||||
checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
|
||||
checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
|
||||
do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org^appId=42&inBrowser=1');
|
||||
checkOriginAttributes(exampleOrg_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, "^appId=42&inBrowser=1");
|
||||
checkOriginAttributes(nullPrin_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, "^appId=42&inBrowser=1");
|
||||
do_check_eq(exampleOrg_appBrowser.origin, "http://example.org^appId=42&inBrowser=1");
|
||||
|
||||
// App and browser, different domain.
|
||||
var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inIsolatedMozBrowser: true});
|
||||
checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, '^appId=42&inBrowser=1');
|
||||
do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123^appId=42&inBrowser=1');
|
||||
var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI("https://www.example.com:123"), {appId: 42, inIsolatedMozBrowser: true});
|
||||
checkOriginAttributes(exampleCom_appBrowser, {appId: 42, inIsolatedMozBrowser: true}, "^appId=42&inBrowser=1");
|
||||
do_check_eq(exampleCom_appBrowser.origin, "https://www.example.com:123^appId=42&inBrowser=1");
|
||||
|
||||
// First party Uri
|
||||
var exampleOrg_firstPartyDomain = ssm.createCodebasePrincipal(makeURI('http://example.org'), {firstPartyDomain: 'example.org'});
|
||||
checkOriginAttributes(exampleOrg_firstPartyDomain, { firstPartyDomain: "example.org" }, '^firstPartyDomain=example.org');
|
||||
do_check_eq(exampleOrg_firstPartyDomain.origin, 'http://example.org^firstPartyDomain=example.org');
|
||||
var exampleOrg_firstPartyDomain = ssm.createCodebasePrincipal(makeURI("http://example.org"), {firstPartyDomain: "example.org"});
|
||||
checkOriginAttributes(exampleOrg_firstPartyDomain, { firstPartyDomain: "example.org" }, "^firstPartyDomain=example.org");
|
||||
do_check_eq(exampleOrg_firstPartyDomain.origin, "http://example.org^firstPartyDomain=example.org");
|
||||
|
||||
// Make sure we don't crash when serializing principals with UNKNOWN_APP_ID.
|
||||
try {
|
||||
|
|
@ -136,7 +136,7 @@ function run_test() {
|
|||
let pipe = Cc["@mozilla.org/pipe;1"].createInstance(Ci.nsIPipe);
|
||||
pipe.init(false, false, 0, 0xffffffff, null);
|
||||
binaryStream.setOutputStream(pipe.outputStream);
|
||||
binaryStream.writeCompoundObject(simplePrin, Ci.nsISupports, true);
|
||||
binaryStream.writeCompoundObject(simplePrin, Ci.nsISupports, true); // eslint-disable-line no-undef
|
||||
binaryStream.close();
|
||||
} catch (e) {
|
||||
do_check_true(true);
|
||||
|
|
@ -144,24 +144,24 @@ function run_test() {
|
|||
|
||||
|
||||
// Just userContext.
|
||||
var exampleOrg_userContext = ssm.createCodebasePrincipal(makeURI('http://example.org'), {userContextId: 42});
|
||||
checkOriginAttributes(exampleOrg_userContext, { userContextId: 42 }, '^userContextId=42');
|
||||
do_check_eq(exampleOrg_userContext.origin, 'http://example.org^userContextId=42');
|
||||
var exampleOrg_userContext = ssm.createCodebasePrincipal(makeURI("http://example.org"), {userContextId: 42});
|
||||
checkOriginAttributes(exampleOrg_userContext, { userContextId: 42 }, "^userContextId=42");
|
||||
do_check_eq(exampleOrg_userContext.origin, "http://example.org^userContextId=42");
|
||||
|
||||
// UserContext and App.
|
||||
var exampleOrg_userContextApp = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 24, userContextId: 42});
|
||||
var exampleOrg_userContextApp = ssm.createCodebasePrincipal(makeURI("http://example.org"), {appId: 24, userContextId: 42});
|
||||
var nullPrin_userContextApp = ssm.createNullPrincipal({appId: 24, userContextId: 42});
|
||||
checkOriginAttributes(exampleOrg_userContextApp, {appId: 24, userContextId: 42}, '^appId=24&userContextId=42');
|
||||
checkOriginAttributes(nullPrin_userContextApp, {appId: 24, userContextId: 42}, '^appId=24&userContextId=42');
|
||||
do_check_eq(exampleOrg_userContextApp.origin, 'http://example.org^appId=24&userContextId=42');
|
||||
checkOriginAttributes(exampleOrg_userContextApp, {appId: 24, userContextId: 42}, "^appId=24&userContextId=42");
|
||||
checkOriginAttributes(nullPrin_userContextApp, {appId: 24, userContextId: 42}, "^appId=24&userContextId=42");
|
||||
do_check_eq(exampleOrg_userContextApp.origin, "http://example.org^appId=24&userContextId=42");
|
||||
|
||||
checkSandboxOriginAttributes(null, {});
|
||||
checkSandboxOriginAttributes('http://example.org', {});
|
||||
checkSandboxOriginAttributes('http://example.org', {}, {originAttributes: {}});
|
||||
checkSandboxOriginAttributes('http://example.org', {appId: 42}, {originAttributes: {appId: 42}});
|
||||
checkSandboxOriginAttributes(['http://example.org'], {});
|
||||
checkSandboxOriginAttributes(['http://example.org'], {}, {originAttributes: {}});
|
||||
checkSandboxOriginAttributes(['http://example.org'], {appId: 42}, {originAttributes: {appId: 42}});
|
||||
checkSandboxOriginAttributes("http://example.org", {});
|
||||
checkSandboxOriginAttributes("http://example.org", {}, {originAttributes: {}});
|
||||
checkSandboxOriginAttributes("http://example.org", {appId: 42}, {originAttributes: {appId: 42}});
|
||||
checkSandboxOriginAttributes(["http://example.org"], {});
|
||||
checkSandboxOriginAttributes(["http://example.org"], {}, {originAttributes: {}});
|
||||
checkSandboxOriginAttributes(["http://example.org"], {appId: 42}, {originAttributes: {appId: 42}});
|
||||
|
||||
// Check that all of the above are cross-origin.
|
||||
checkCrossOrigin(exampleOrg_app, exampleOrg);
|
||||
|
|
@ -177,15 +177,15 @@ function run_test() {
|
|||
|
||||
// Check Principal kinds.
|
||||
function checkKind(prin, kind) {
|
||||
do_check_eq(prin.isNullPrincipal, kind == 'nullPrincipal');
|
||||
do_check_eq(prin.isCodebasePrincipal, kind == 'codebasePrincipal');
|
||||
do_check_eq(prin.isExpandedPrincipal, kind == 'expandedPrincipal');
|
||||
do_check_eq(prin.isSystemPrincipal, kind == 'systemPrincipal');
|
||||
do_check_eq(prin.isNullPrincipal, kind == "nullPrincipal");
|
||||
do_check_eq(prin.isCodebasePrincipal, kind == "codebasePrincipal");
|
||||
do_check_eq(prin.isExpandedPrincipal, kind == "expandedPrincipal");
|
||||
do_check_eq(prin.isSystemPrincipal, kind == "systemPrincipal");
|
||||
}
|
||||
checkKind(ssm.createNullPrincipal({}), 'nullPrincipal');
|
||||
checkKind(ssm.createCodebasePrincipal(makeURI('http://www.example.com'), {}), 'codebasePrincipal');
|
||||
checkKind(Cu.getObjectPrincipal(Cu.Sandbox([ssm.createCodebasePrincipal(makeURI('http://www.example.com'), {})])), 'expandedPrincipal');
|
||||
checkKind(ssm.getSystemPrincipal(), 'systemPrincipal');
|
||||
checkKind(ssm.createNullPrincipal({}), "nullPrincipal");
|
||||
checkKind(ssm.createCodebasePrincipal(makeURI("http://www.example.com"), {}), "codebasePrincipal");
|
||||
checkKind(Cu.getObjectPrincipal(Cu.Sandbox([ssm.createCodebasePrincipal(makeURI("http://www.example.com"), {})])), "expandedPrincipal");
|
||||
checkKind(ssm.getSystemPrincipal(), "systemPrincipal");
|
||||
|
||||
//
|
||||
// Test Origin Attribute Manipulation
|
||||
|
|
@ -260,7 +260,7 @@ function run_test() {
|
|||
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
|
||||
checkValues(orig, t[1]);
|
||||
let mod = orig;
|
||||
mod['userContextId'] = 0;
|
||||
mod["userContextId"] = 0;
|
||||
checkValues(mod, t[2]);
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
|
||||
});
|
||||
|
|
@ -281,12 +281,12 @@ function run_test() {
|
|||
let orig = ChromeUtils.createOriginAttributesFromOrigin(uri + t[0]);
|
||||
checkValues(orig, t[1]);
|
||||
let mod = orig;
|
||||
mod['firstPartyDomain'] = "";
|
||||
mod["firstPartyDomain"] = "";
|
||||
checkValues(mod, t[2]);
|
||||
do_check_eq(ChromeUtils.originAttributesToSuffix(mod), t[3]);
|
||||
});
|
||||
|
||||
var fileURI = makeURI('file:///foo/bar').QueryInterface(Ci.nsIFileURL);
|
||||
var fileURI = makeURI("file:///foo/bar").QueryInterface(Ci.nsIFileURL);
|
||||
var fileTests = [
|
||||
[true, fileURI.spec],
|
||||
[false, "file://UNIVERSAL_FILE_URI_ORIGIN"],
|
||||
|
|
@ -298,7 +298,7 @@ function run_test() {
|
|||
});
|
||||
Services.prefs.clearUserPref("security.fileuri.strict_origin_policy");
|
||||
|
||||
var aboutBlankURI = makeURI('about:blank');
|
||||
var aboutBlankURI = makeURI("about:blank");
|
||||
var aboutBlankPrin = ssm.createCodebasePrincipal(aboutBlankURI, {});
|
||||
do_check_true(/^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(aboutBlankPrin.origin));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include "nsIConsoleService.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMLocation.h"
|
||||
#include "nsIDOMWindowCollection.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
|
@ -31,6 +30,7 @@
|
|||
#include "mozilla/Printf.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
#include "mozilla/dom/Location.h"
|
||||
|
||||
#ifdef ENABLE_INTL_API
|
||||
#include "unicode/uloc.h"
|
||||
|
|
@ -42,6 +42,7 @@ nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
|
|||
// mozilla::TextRange and a TextRange in OSX headers.
|
||||
using mozilla::StyleSheet;
|
||||
using mozilla::dom::IsChromeURI;
|
||||
using mozilla::dom::Location;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -508,7 +509,7 @@ nsChromeRegistry::ReloadChrome()
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> domWindow = do_QueryInterface(protoWindow);
|
||||
if (domWindow) {
|
||||
nsIDOMLocation* location = domWindow->GetLocation();
|
||||
Location* location = domWindow->Location();
|
||||
if (location) {
|
||||
rv = location->Reload(false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -17,7 +17,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="mount"></div>
|
||||
<script type="application/javascript;version=1.8"
|
||||
<script type="application/javascript"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
<script type="text/javascript">
|
||||
const { BrowserLoader } = Components.utils.import("resource://devtools/client/shared/browser-loader.js", {});
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
|
@ -65,14 +65,16 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = assert;
|
||||
function assert(condition, message) {
|
||||
if (!condition) {
|
||||
throw new Error(`Assertion failure: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = assert;
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 802:
|
||||
|
|
@ -94,7 +96,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
} else {
|
||||
root.prettyFast = factory();
|
||||
}
|
||||
}(this, () => {
|
||||
}(this, function () {
|
||||
"use strict";
|
||||
|
||||
var acorn = this.acorn || __webpack_require__(803);
|
||||
|
|
@ -952,7 +954,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
return result.toStringWithSourceMap({ file: options.url });
|
||||
};
|
||||
|
||||
}));
|
||||
}.bind(this)));
|
||||
|
||||
|
||||
/***/ },
|
||||
|
|
@ -5855,8 +5857,15 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
|
||||
"use strict";
|
||||
|
||||
var prettyFast = __webpack_require__(802);
|
||||
var assert = __webpack_require__(223);
|
||||
var _prettyFast = __webpack_require__(802);
|
||||
|
||||
var _prettyFast2 = _interopRequireDefault(_prettyFast);
|
||||
|
||||
var _assert = __webpack_require__(223);
|
||||
|
||||
var _assert2 = _interopRequireDefault(_assert);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function prettyPrint(_ref) {
|
||||
var url = _ref.url,
|
||||
|
|
@ -5864,7 +5873,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
source = _ref.source;
|
||||
|
||||
try {
|
||||
var prettified = prettyFast(source, {
|
||||
var prettified = (0, _prettyFast2.default)(source, {
|
||||
url: url,
|
||||
indent: " ".repeat(indent)
|
||||
});
|
||||
|
|
@ -5903,7 +5912,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
id = _msg$data.id,
|
||||
args = _msg$data.args;
|
||||
|
||||
assert(msg.data.method === "prettyPrint", "Method must be `prettyPrint`");
|
||||
(0, _assert2.default)(msg.data.method === "prettyPrint", "Method must be `prettyPrint`");
|
||||
|
||||
try {
|
||||
var _prettyPrint = prettyPrint(args[0]),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ support-files =
|
|||
examples/sourcemaps2/main.min.js
|
||||
examples/sourcemaps2/main.js
|
||||
examples/sourcemaps2/main.js.map
|
||||
examples/doc-asm.html
|
||||
examples/doc-scripts.html
|
||||
examples/doc-script-mutate.html
|
||||
examples/doc-script-switching.html
|
||||
examples/doc-exceptions.html
|
||||
examples/doc-iframes.html
|
||||
|
|
@ -22,6 +24,8 @@ support-files =
|
|||
examples/doc-sourcemaps2.html
|
||||
examples/doc-sourcemap-bogus.html
|
||||
examples/doc-sources.html
|
||||
examples/doc-return-values.html
|
||||
examples/asm.js
|
||||
examples/bogus-map.js
|
||||
examples/entry.js
|
||||
examples/exceptions.js
|
||||
|
|
@ -33,6 +37,7 @@ support-files =
|
|||
examples/simple1.js
|
||||
examples/simple2.js
|
||||
examples/frames.js
|
||||
examples/script-mutate.js
|
||||
examples/script-switching-02.js
|
||||
examples/script-switching-01.js
|
||||
examples/times2.js
|
||||
|
|
@ -58,6 +63,7 @@ support-files =
|
|||
[browser_dbg-navigation.js]
|
||||
[browser_dbg-pretty-print.js]
|
||||
[browser_dbg-pretty-print-paused.js]
|
||||
[browser_dbg-scopes-mutations.js]
|
||||
[browser_dbg-searching.js]
|
||||
skip-if = true
|
||||
[browser_dbg-sourcemaps.js]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ function setConditionalBreakpoint(dbg, index, condition) {
|
|||
yield waitForElement(dbg, ".conditional-breakpoint-panel input");
|
||||
findElementWithSelector(dbg, ".conditional-breakpoint-panel input").focus();
|
||||
// Position cursor reliably at the end of the text.
|
||||
pressKey(dbg, "End")
|
||||
pressKey(dbg, "End");
|
||||
type(dbg, condition);
|
||||
pressKey(dbg, "Enter");
|
||||
});
|
||||
|
|
@ -49,4 +49,3 @@ add_task(function* () {
|
|||
bp = findBreakpoint(dbg, "simple2", 5);
|
||||
is(bp.condition, "1", "breakpoint is created with the condition");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ async function editExpression(dbg, input) {
|
|||
info("updating the expression");
|
||||
dblClickElement(dbg, "expressionNode", 1);
|
||||
// Position cursor reliably at the end of the text.
|
||||
pressKey(dbg, "End")
|
||||
pressKey(dbg, "End");
|
||||
type(dbg, input);
|
||||
pressKey(dbg, "Enter");
|
||||
await waitForDispatch(dbg, "EVALUATE_EXPRESSION");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function getScopeNodeLabel(dbg, index) {
|
||||
return findElement(dbg, "scopeNode", index).innerText;
|
||||
}
|
||||
|
||||
function getScopeNodeValue(dbg, index) {
|
||||
return findElement(dbg, "scopeValue", index).innerText;
|
||||
}
|
||||
|
||||
function expandNode(dbg, index) {
|
||||
let onLoadProperties = onLoadObjectProperties(dbg);
|
||||
clickElement(dbg, "scopeNode", index);
|
||||
return onLoadProperties;
|
||||
}
|
||||
|
||||
function toggleScopes(dbg) {
|
||||
return findElement(dbg, "scopesHeader").click();
|
||||
}
|
||||
|
||||
function onLoadObjectProperties(dbg) {
|
||||
return waitForDispatch(dbg, "LOAD_OBJECT_PROPERTIES");
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-script-mutate.html");
|
||||
|
||||
toggleScopes(dbg);
|
||||
|
||||
let onPaused = waitForPaused(dbg);
|
||||
invokeInTab("mutate");
|
||||
await onPaused;
|
||||
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 2),
|
||||
"<this>",
|
||||
'The second element in the scope panel is "<this>"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 3),
|
||||
"phonebook",
|
||||
'The third element in the scope panel is "phonebook"'
|
||||
);
|
||||
|
||||
// Expand `phonebook`
|
||||
await expandNode(dbg, 3);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 4),
|
||||
"S",
|
||||
'The fourth element in the scope panel is "S"'
|
||||
);
|
||||
|
||||
// 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"'
|
||||
);
|
||||
|
||||
// Expand `sarah`
|
||||
await expandNode(dbg, 5);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 6),
|
||||
"lastName",
|
||||
'The sixth element in the scope panel is now "lastName"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeValue(dbg, 6),
|
||||
'"Doe"',
|
||||
'The "lastName" element has the expected "Doe" value'
|
||||
);
|
||||
|
||||
info("Resuming");
|
||||
onPaused = waitForPaused(dbg);
|
||||
await resume(dbg);
|
||||
await onPaused;
|
||||
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 6),
|
||||
"lastName",
|
||||
'The sixth element in the scope panel is still "lastName"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeValue(dbg, 6),
|
||||
'"Doe"',
|
||||
'The "lastName" property is still "Doe", but it should be "Pierce"' +
|
||||
"since it was changed in the script."
|
||||
);
|
||||
|
||||
onPaused = waitForPaused(dbg);
|
||||
await resume(dbg);
|
||||
await onPaused;
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 6),
|
||||
"lastName",
|
||||
'The sixth element in the scope panel is still "lastName"'
|
||||
);
|
||||
is(
|
||||
getScopeNodeLabel(dbg, 7),
|
||||
"__proto__",
|
||||
'The seventh element in the scope panel is still "__proto__", ' +
|
||||
'but it should be now "timezone", since it was added to the "sarah" object ' +
|
||||
"in the script"
|
||||
);
|
||||
is(
|
||||
getScopeNodeValue(dbg, 7),
|
||||
"Object",
|
||||
'The seventh element in the scope panel has the value "Object", ' +
|
||||
'but it should be "PST"'
|
||||
);
|
||||
|
||||
await resume(dbg);
|
||||
});
|
||||
|
|
@ -7,5 +7,4 @@ var asmjs = (function () {
|
|||
return 1 | 0;
|
||||
}
|
||||
return { f: f };
|
||||
})()
|
||||
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,26 @@
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h3>Returns</h3>
|
||||
<button onclick="return_something(2)">return(2)</button>
|
||||
<button onclick="return_something(new Error('blah'))">return(error)</button>
|
||||
<button onclick="return_something(undefined)">return(undefined)</button>
|
||||
<button onclick="return_something(false)">return(false)</button>
|
||||
<button onclick="return_something(null)">return(null)</button>
|
||||
<button onclick="return_something(0)">return(0)</button>
|
||||
<button onclick="return_something('yay')">return('yay')</button>
|
||||
|
||||
|
||||
<h3>Throws</h3>
|
||||
<button onclick="throw_something(2)">throw(2)</button>
|
||||
<button onclick="throw_something(new Error('blah'))">throw(error)</button>
|
||||
<button onclick="throw_something(undefined)">throw(undefined)</button>
|
||||
<button onclick="throw_something(false)">throw(false)</button>
|
||||
<button onclick="throw_something(0)">throw(0)</button>
|
||||
<button onclick="throw_something(null)">throw(null)</button>
|
||||
<button onclick="throw_something('yay')">throw('yay')</button>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Debugger test page - Mutate object</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<button onclick="mutate()">Click me!</button>
|
||||
|
||||
<script type="text/javascript" src="script-mutate.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -12,10 +12,11 @@
|
|||
<script src="simple2.js"></script>
|
||||
<script src="long.js"></script>
|
||||
<script>
|
||||
// This inline script allows this HTML page to show up as a
|
||||
// source. It also needs to introduce a new global variable so
|
||||
// it's not immediately garbage collected.
|
||||
function inline_script() { var x = 5; }
|
||||
function loadScript() {
|
||||
const script = document.createElement("script");
|
||||
script.src = "math.min.js";
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
</script>
|
||||
<script src="nested/nested-source.js"></script>
|
||||
<script src="nested/deeper/deeper-source.js"></script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
function mutate() {
|
||||
const phonebook = {
|
||||
S: {
|
||||
sarah: {
|
||||
lastName: "Doe"
|
||||
},
|
||||
serena: {
|
||||
lastName: "Williams"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
debugger;
|
||||
phonebook.S.sarah.lastName = "Pierce";
|
||||
debugger;
|
||||
phonebook.S.sarah.timezone = "PST";
|
||||
debugger;
|
||||
}
|
||||
|
|
@ -38,7 +38,8 @@ Services.scriptloader.loadSubScript(
|
|||
this
|
||||
);
|
||||
var { Toolbox } = require("devtools/client/framework/toolbox");
|
||||
const EXAMPLE_URL = "http://example.com/browser/devtools/client/debugger/new/test/mochitest/examples/";
|
||||
const EXAMPLE_URL =
|
||||
"http://example.com/browser/devtools/client/debugger/new/test/mochitest/examples/";
|
||||
|
||||
Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
|
||||
|
||||
|
|
@ -336,7 +337,7 @@ window.resumeTest = undefined;
|
|||
*/
|
||||
function pauseTest() {
|
||||
info("Test paused. Invoke resumeTest to continue.");
|
||||
return new Promise(resolve => resumeTest = resolve);
|
||||
return new Promise(resolve => (resumeTest = resolve));
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
|
@ -563,12 +564,12 @@ const cmdOrCtrl = isLinux ? { ctrlKey: true } : { metaKey: true };
|
|||
// On Mac, going to beginning/end only works with meta+left/right. On
|
||||
// Windows, it only works with home/end. On Linux, apparently, either
|
||||
// ctrl+left/right or home/end work.
|
||||
const endKey = isMac ?
|
||||
{ code: "VK_RIGHT", modifiers: cmdOrCtrl } :
|
||||
{ code: "VK_END" };
|
||||
const startKey = isMac ?
|
||||
{ code: "VK_LEFT", modifiers: cmdOrCtrl } :
|
||||
{ code: "VK_HOME" };
|
||||
const endKey = isMac
|
||||
? { code: "VK_RIGHT", modifiers: cmdOrCtrl }
|
||||
: { code: "VK_END" };
|
||||
const startKey = isMac
|
||||
? { code: "VK_LEFT", modifiers: cmdOrCtrl }
|
||||
: { code: "VK_HOME" };
|
||||
const keyMappings = {
|
||||
sourceSearch: { code: "p", modifiers: cmdOrCtrl },
|
||||
fileSearch: { code: "f", modifiers: cmdOrCtrl },
|
||||
|
|
@ -622,16 +623,14 @@ function isVisibleWithin(outerEl, innerEl) {
|
|||
const selectors = {
|
||||
callStackHeader: ".call-stack-pane ._header",
|
||||
callStackBody: ".call-stack-pane .pane",
|
||||
expressionNode: i =>
|
||||
`.expressions-list .tree-node:nth-child(${i}) .object-label`,
|
||||
expressionValue: i =>
|
||||
`.expressions-list .tree-node:nth-child(${i}) .object-value`,
|
||||
expressionClose: i =>
|
||||
`.expressions-list .expression-container:nth-child(${i}) .close`,
|
||||
expressionNode: i => `.expressions-list .tree-node:nth-child(${i}) .object-label`,
|
||||
expressionValue: i => `.expressions-list .tree-node:nth-child(${i}) .object-value`,
|
||||
expressionClose: i => `.expressions-list .expression-container:nth-child(${i}) .close`,
|
||||
expressionNodes: ".expressions-list .tree-node",
|
||||
scopesHeader: ".scopes-pane ._header",
|
||||
breakpointItem: i => `.breakpoints-list .breakpoint:nth-child(${i})`,
|
||||
scopeNode: i => `.scopes-list .tree-node:nth-child(${i}) .object-label`,
|
||||
scopeValue: i => `.scopes-list .tree-node:nth-child(${i}) .object-value`,
|
||||
frame: i => `.frames ul li:nth-child(${i})`,
|
||||
frames: ".frames ul li",
|
||||
gutter: i => `.CodeMirror-code *:nth-child(${i}) .CodeMirror-linenumber`,
|
||||
|
|
|
|||
|
|
@ -2408,14 +2408,17 @@ Toolbox.prototype = {
|
|||
.then(() => {
|
||||
this._removeHostListeners();
|
||||
|
||||
// `location` may already be null if the toolbox document is already
|
||||
// in process of destruction. Otherwise if it is still around, ensure
|
||||
// releasing toolbox document and triggering cleanup thanks to unload
|
||||
// event. We do that precisely here, before nullifying the target as
|
||||
// various cleanup code depends on the target attribute to be still
|
||||
// `location` may already be 'invalid' if the toolbox document is
|
||||
// already in process of destruction. Otherwise if it is still
|
||||
// around, ensure releasing toolbox document and triggering cleanup
|
||||
// thanks to unload event. We do that precisely here, before
|
||||
// nullifying the target as various cleanup code depends on the
|
||||
// target attribute to be still
|
||||
// defined.
|
||||
if (win.location) {
|
||||
try {
|
||||
win.location.replace("about:blank");
|
||||
} catch (e) {
|
||||
// Do nothing;
|
||||
}
|
||||
|
||||
// Targets need to be notified that the toolbox is being torn down.
|
||||
|
|
|
|||
|
|
@ -22,6 +22,14 @@ copySourceUrl=Copy Source Url
|
|||
# the context menu.
|
||||
copySourceUrl.accesskey=u
|
||||
|
||||
# LOCALIZATION NOTE (copyStackTrace): This is the text that appears in the
|
||||
# context menu to copy the stack trace methods, file names and row number.
|
||||
copyStackTrace=Copy Stack Trace
|
||||
|
||||
# LOCALIZATION NOTE (copyStackTrace.accesskey): Access key to copy the stack trace data from
|
||||
# the context menu.
|
||||
copyStackTrace.accesskey=c
|
||||
|
||||
# LOCALIZATION NOTE (expandPanes): This is the tooltip for the button
|
||||
# that expands the left and right panes in the debugger UI.
|
||||
expandPanes=Expand panes
|
||||
|
|
@ -128,10 +136,6 @@ sources.search.key=P
|
|||
# does not have any sources.
|
||||
sources.noSourcesAvailable=This page has no sources
|
||||
|
||||
# LOCALIZATION NOTE (sources.searchAlt.key): Alternate key shortcut to open
|
||||
# the search for searching all the source files the debugger has seen.
|
||||
sources.searchAlt.key=O
|
||||
|
||||
# LOCALIZATION NOTE (sourceSearch.search.key): Key shortcut to open the search
|
||||
# for searching within a the currently opened files in the editor
|
||||
sourceSearch.search.key=F
|
||||
|
|
@ -246,6 +250,14 @@ editor.singleResult=1 result
|
|||
# for when no results found.
|
||||
editor.noResults=no results
|
||||
|
||||
# LOCALIZATION NOTE (editor.searchResults.nextResult): Editor Search bar
|
||||
# tooltip for traversing to the Next Result
|
||||
editor.searchResults.nextResult=Next Result
|
||||
|
||||
# LOCALIZATION NOTE (editor.searchResults.prevResult): Editor Search bar
|
||||
# tooltip for traversing to the Previous Result
|
||||
editor.searchResults.prevResult=Previous Result
|
||||
|
||||
# LOCALIZATION NOTE (editor.searchTypeToggleTitle): Search bar title for
|
||||
# toggling search type buttons(function search, variable search)
|
||||
editor.searchTypeToggleTitle=Search for:
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "ImportManager.h"
|
||||
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "HTMLLinkElement.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
|
|
@ -18,7 +19,6 @@
|
|||
#include "nsIDOMEvent.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -156,7 +156,7 @@ ImportLoader::Updater::UpdateMainReferrer(uint32_t aNewIdx)
|
|||
// Our nearest predecessor has changed. So let's add the ScriptLoader to the
|
||||
// new one if there is any. And remove it from the old one.
|
||||
RefPtr<ImportManager> manager = mLoader->Manager();
|
||||
nsScriptLoader* loader = mLoader->mDocument->ScriptLoader();
|
||||
ScriptLoader* loader = mLoader->mDocument->ScriptLoader();
|
||||
ImportLoader*& pred = mLoader->mBlockingPredecessor;
|
||||
ImportLoader* newPred = manager->GetNearestPredecessor(newMainReferrer);
|
||||
if (pred) {
|
||||
|
|
@ -339,7 +339,7 @@ ImportLoader::DispatchEventIfFinished(nsINode* aNode)
|
|||
}
|
||||
|
||||
void
|
||||
ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader)
|
||||
ImportLoader::AddBlockedScriptLoader(ScriptLoader* aScriptLoader)
|
||||
{
|
||||
if (mBlockedScriptLoaders.Contains(aScriptLoader)) {
|
||||
return;
|
||||
|
|
@ -352,7 +352,7 @@ ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader)
|
|||
}
|
||||
|
||||
bool
|
||||
ImportLoader::RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader)
|
||||
ImportLoader::RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader)
|
||||
{
|
||||
aScriptLoader->RemoveParserBlockingScriptExecutionBlocker();
|
||||
return mBlockedScriptLoaders.RemoveElement(aScriptLoader);
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@
|
|||
#include "nsIStreamListener.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsURIHashKey.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
|
||||
class nsIDocument;
|
||||
class nsIPrincipal;
|
||||
|
|
@ -184,8 +184,8 @@ public:
|
|||
// and wait for that to run its scripts. We keep track of all the
|
||||
// ScriptRunners that are waiting for this import. NOTE: updating
|
||||
// the main referrer might change this list.
|
||||
void AddBlockedScriptLoader(nsScriptLoader* aScriptLoader);
|
||||
bool RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader);
|
||||
void AddBlockedScriptLoader(ScriptLoader* aScriptLoader);
|
||||
bool RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader);
|
||||
void SetBlockingPredecessor(ImportLoader* aLoader);
|
||||
|
||||
private:
|
||||
|
|
@ -230,7 +230,7 @@ private:
|
|||
|
||||
// List of pending ScriptLoaders that are waiting for this import
|
||||
// to finish.
|
||||
nsTArray<RefPtr<nsScriptLoader>> mBlockedScriptLoaders;
|
||||
nsTArray<RefPtr<ScriptLoader>> mBlockedScriptLoaders;
|
||||
|
||||
// There is always exactly one referrer link that is flagged as
|
||||
// the main referrer the primary link. This is the one that is
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@
|
|||
#include "mozilla/Likely.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "NullPrincipal.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/LocationBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
|
@ -87,19 +87,6 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Location)
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Location)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Location)
|
||||
|
||||
void
|
||||
Location::SetDocShell(nsIDocShell *aDocShell)
|
||||
{
|
||||
mDocShell = do_GetWeakReference(aDocShell);
|
||||
}
|
||||
|
||||
nsIDocShell *
|
||||
Location::GetDocShell()
|
||||
{
|
||||
nsCOMPtr<nsIDocShell> docshell(do_QueryReferent(mDocShell));
|
||||
return docshell;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Location::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
|
||||
{
|
||||
|
|
@ -210,8 +197,12 @@ Location::GetURI(nsIURI** aURI, bool aGetInnermostURI)
|
|||
{
|
||||
*aURI = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
|
||||
if (!mDocShell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell, &rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
|
|
@ -896,9 +887,10 @@ Location::GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL)
|
|||
// this happens, try falling back on the current document associated with the
|
||||
// docshell. If that fails, just return null and hope that the caller passed
|
||||
// an absolute URI.
|
||||
if (!doc && GetDocShell()) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
|
||||
if (!doc && docShell) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> docShellWin =
|
||||
do_QueryInterface(GetDocShell()->GetScriptGlobalObject());
|
||||
do_QueryInterface(docShell->GetScriptGlobalObject());
|
||||
if (docShellWin) {
|
||||
doc = docShellWin->GetDoc();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Location,
|
||||
nsIDOMLocation)
|
||||
|
||||
void SetDocShell(nsIDocShell *aDocShell);
|
||||
nsIDocShell *GetDocShell();
|
||||
|
||||
// nsIDOMLocation
|
||||
NS_DECL_NSIDOMLOCATION
|
||||
|
||||
|
|
@ -233,7 +230,11 @@ protected:
|
|||
// In the case of jar: uris, we sometimes want the place the jar was
|
||||
// fetched from as the URI instead of the jar: uri itself. Pass in
|
||||
// true for aGetInnermostURI when that's the case.
|
||||
// Note, this method can return NS_OK with a null value for aURL. This happens
|
||||
// if the docShell is null.
|
||||
nsresult GetURI(nsIURI** aURL, bool aGetInnermostURI = false);
|
||||
// Note, this method can return NS_OK with a null value for aURL. This happens
|
||||
// if the docShell is null.
|
||||
nsresult GetWritableURI(nsIURI** aURL,
|
||||
// If not null, give it the new ref
|
||||
const nsACString* aNewRef = nullptr);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ XPIDL_SOURCES += [
|
|||
'nsIObjectLoadingContent.idl',
|
||||
'nsIRemoteWindowContext.idl',
|
||||
'nsIScriptChannel.idl',
|
||||
'nsIScriptLoaderObserver.idl',
|
||||
'nsISelection.idl',
|
||||
'nsISelectionController.idl',
|
||||
'nsISelectionDisplay.idl',
|
||||
|
|
@ -92,7 +91,6 @@ EXPORTS += [
|
|||
'nsINode.h',
|
||||
'nsINodeList.h',
|
||||
'nsIScriptContext.h',
|
||||
'nsIScriptElement.h',
|
||||
'nsIScriptGlobalObject.h',
|
||||
'nsIScriptNameSpaceManager.h',
|
||||
'nsIScriptObjectPrincipal.h',
|
||||
|
|
@ -113,7 +111,6 @@ EXPORTS += [
|
|||
'nsRange.h',
|
||||
'nsReferencedElement.h',
|
||||
'nsSandboxFlags.h',
|
||||
'nsScriptLoader.h',
|
||||
'nsStructuredCloneContainer.h',
|
||||
'nsStubAnimationObserver.h',
|
||||
'nsStubDocumentObserver.h',
|
||||
|
|
@ -198,7 +195,6 @@ EXPORTS.mozilla.dom += [
|
|||
'ResponsiveImageSelector.h',
|
||||
'SameProcessMessageQueue.h',
|
||||
'ScreenOrientation.h',
|
||||
'ScriptSettings.h',
|
||||
'ShadowRoot.h',
|
||||
'StructuredCloneHolder.h',
|
||||
'StructuredCloneTags.h',
|
||||
|
|
@ -315,8 +311,6 @@ UNIFIED_SOURCES += [
|
|||
'nsRange.cpp',
|
||||
'nsReferencedElement.cpp',
|
||||
'nsScreen.cpp',
|
||||
'nsScriptElement.cpp',
|
||||
'nsScriptLoader.cpp',
|
||||
'nsScriptNameSpaceManager.cpp',
|
||||
'nsStructuredCloneContainer.cpp',
|
||||
'nsStubAnimationObserver.cpp',
|
||||
|
|
@ -343,7 +337,6 @@ UNIFIED_SOURCES += [
|
|||
'ResponsiveImageSelector.cpp',
|
||||
'SameProcessMessageQueue.cpp',
|
||||
'ScreenOrientation.cpp',
|
||||
'ScriptSettings.cpp',
|
||||
'ShadowRoot.cpp',
|
||||
'StructuredCloneHolder.cpp',
|
||||
'StyleSheetList.cpp',
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "nsInProcessTabChildGlobal.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "ScriptSettings.h"
|
||||
|
||||
using mozilla::Unused; // <snicker>
|
||||
using namespace mozilla::dom;
|
||||
|
|
|
|||
|
|
@ -125,8 +125,7 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
|||
* their permissions.
|
||||
*/
|
||||
nsresult rv;
|
||||
nsCOMArray<nsIContentPolicy> entries;
|
||||
mPolicies.GetEntries(entries);
|
||||
const nsCOMArray<nsIContentPolicy>& entries = mPolicies.GetCachedEntries();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window;
|
||||
if (nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext)) {
|
||||
|
|
@ -187,8 +186,8 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
|||
}
|
||||
}
|
||||
|
||||
nsCOMArray<nsISimpleContentPolicy> simpleEntries;
|
||||
mSimplePolicies.GetEntries(simpleEntries);
|
||||
const nsCOMArray<nsISimpleContentPolicy>& simpleEntries =
|
||||
mSimplePolicies.GetCachedEntries();
|
||||
count = simpleEntries.Count();
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
/* check the appropriate policy */
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
*/
|
||||
|
||||
#include "nsContentSink.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "mozilla/css/Loader.h"
|
||||
|
|
@ -49,6 +48,7 @@
|
|||
#include "nsHTMLDNSPrefetch.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "nsParserConstants.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -36,13 +36,16 @@ class nsIAtom;
|
|||
class nsIChannel;
|
||||
class nsIContent;
|
||||
class nsNodeInfoManager;
|
||||
class nsScriptLoader;
|
||||
class nsIApplicationCache;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
class Loader;
|
||||
} // namespace css
|
||||
|
||||
namespace dom {
|
||||
class ScriptLoader;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
@ -276,7 +279,7 @@ protected:
|
|||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
RefPtr<mozilla::css::Loader> mCSSLoader;
|
||||
RefPtr<nsNodeInfoManager> mNodeInfoManager;
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
|
||||
|
||||
// back off timer notification after count
|
||||
int32_t mBackoffCount;
|
||||
|
|
|
|||
|
|
@ -2026,7 +2026,7 @@ nsDocument::Init()
|
|||
mScopeObject = do_GetWeakReference(global);
|
||||
MOZ_ASSERT(mScopeObject);
|
||||
|
||||
mScriptLoader = new nsScriptLoader(this);
|
||||
mScriptLoader = new dom::ScriptLoader(this);
|
||||
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
|
|
@ -5011,7 +5011,7 @@ nsDocument::GetWindowInternal() const
|
|||
return win;
|
||||
}
|
||||
|
||||
nsScriptLoader*
|
||||
ScriptLoader*
|
||||
nsDocument::ScriptLoader()
|
||||
{
|
||||
return mScriptLoader;
|
||||
|
|
@ -6877,9 +6877,7 @@ nsIDocument::GetLocation() const
|
|||
}
|
||||
|
||||
nsGlobalWindow* window = nsGlobalWindow::Cast(w);
|
||||
ErrorResult dummy;
|
||||
RefPtr<Location> loc = window->GetLocation(dummy);
|
||||
dummy.SuppressException();
|
||||
RefPtr<Location> loc = window->Location();
|
||||
return loc.forget();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "nsJSThingHashtable.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIRadioGroupContainer.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsIRequest.h"
|
||||
|
|
@ -60,6 +59,7 @@
|
|||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/PendingAnimationTracker.h"
|
||||
#include "mozilla/dom/DOMImplementation.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
|
@ -742,7 +742,7 @@ public:
|
|||
/**
|
||||
* Get the script loader for this document
|
||||
*/
|
||||
virtual nsScriptLoader* ScriptLoader() override;
|
||||
virtual mozilla::dom::ScriptLoader* ScriptLoader() override;
|
||||
|
||||
/**
|
||||
* Add/Remove an element to the document's id and name hashes
|
||||
|
|
@ -1492,7 +1492,7 @@ public:
|
|||
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
||||
RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
|
||||
RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
|
||||
nsDocHeaderData* mHeaderData;
|
||||
/* mIdentifierMap works as follows for IDs:
|
||||
* 1) Attribute changes affect the table immediately (removing and adding
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include "nsJSUtils.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
|
|
@ -256,19 +256,15 @@ nsFrameMessageManager::AddMessageListener(const nsAString& aMessage,
|
|||
nsIMessageListener* aListener,
|
||||
bool aListenWhenClosed)
|
||||
{
|
||||
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
|
||||
mListeners.Get(aMessage);
|
||||
if (!listeners) {
|
||||
listeners = new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
|
||||
mListeners.Put(aMessage, listeners);
|
||||
} else {
|
||||
auto listeners = mListeners.LookupForAdd(aMessage).OrInsert([]() {
|
||||
return new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
|
||||
});
|
||||
uint32_t len = listeners->Length();
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
if (listeners->ElementAt(i).mStrongListener == aListener) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsMessageListenerInfo* entry = listeners->AppendElement();
|
||||
NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
|
@ -323,19 +319,15 @@ nsFrameMessageManager::AddWeakMessageListener(const nsAString& aMessage,
|
|||
}
|
||||
#endif
|
||||
|
||||
nsAutoTObserverArray<nsMessageListenerInfo, 1>* listeners =
|
||||
mListeners.Get(aMessage);
|
||||
if (!listeners) {
|
||||
listeners = new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
|
||||
mListeners.Put(aMessage, listeners);
|
||||
} else {
|
||||
auto listeners = mListeners.LookupForAdd(aMessage).OrInsert([]() {
|
||||
return new nsAutoTObserverArray<nsMessageListenerInfo, 1>();
|
||||
});
|
||||
uint32_t len = listeners->Length();
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
if (listeners->ElementAt(i).mWeakListener == weak) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsMessageListenerInfo* entry = listeners->AppendElement();
|
||||
entry->mWeakListener = weak;
|
||||
|
|
@ -1640,7 +1632,7 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
|
|||
if (NS_FAILED(NS_ReadInputStreamToString(input, buffer, avail))) {
|
||||
return;
|
||||
}
|
||||
nsScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
|
||||
ScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
|
||||
EmptyString(), nullptr,
|
||||
dataStringBuf, dataStringLength);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
#include "nsReadableUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
|
|
@ -1933,7 +1933,6 @@ nsGlobalWindow::CleanUp()
|
|||
mPersonalbar = nullptr;
|
||||
mStatusbar = nullptr;
|
||||
mScrollbars = nullptr;
|
||||
mLocation = nullptr;
|
||||
mHistory = nullptr;
|
||||
mCustomElements = nullptr;
|
||||
mFrames = nullptr;
|
||||
|
|
@ -2096,7 +2095,6 @@ nsGlobalWindow::FreeInnerObjects()
|
|||
mListenerManager = nullptr;
|
||||
}
|
||||
|
||||
mLocation = nullptr;
|
||||
mHistory = nullptr;
|
||||
mCustomElements = nullptr;
|
||||
|
||||
|
|
@ -10440,28 +10438,17 @@ nsGlobalWindow::GetPrivateRoot()
|
|||
}
|
||||
|
||||
Location*
|
||||
nsGlobalWindow::GetLocation(ErrorResult& aError)
|
||||
nsGlobalWindow::Location()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(IsInnerWindow());
|
||||
|
||||
nsIDocShell *docShell = GetDocShell();
|
||||
if (!mLocation && docShell) {
|
||||
mLocation = new Location(AsInner(), docShell);
|
||||
if (!mLocation) {
|
||||
mLocation = new dom::Location(AsInner(), GetDocShell());
|
||||
}
|
||||
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
nsIDOMLocation*
|
||||
nsGlobalWindow::GetLocation()
|
||||
{
|
||||
FORWARD_TO_INNER(GetLocation, (), nullptr);
|
||||
|
||||
ErrorResult dummy;
|
||||
nsIDOMLocation* location = GetLocation(dummy);
|
||||
dummy.SuppressException();
|
||||
return location;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -855,8 +855,7 @@ public:
|
|||
void GetName(nsAString& aName, mozilla::ErrorResult& aError);
|
||||
void SetNameOuter(const nsAString& aName, mozilla::ErrorResult& aError);
|
||||
void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
|
||||
mozilla::dom::Location* GetLocation(mozilla::ErrorResult& aError);
|
||||
nsIDOMLocation* GetLocation() override;
|
||||
mozilla::dom::Location* Location() override;
|
||||
nsHistory* GetHistory(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::CustomElementRegistry* CustomElements() override;
|
||||
mozilla::dom::BarProp* GetLocationbar(mozilla::ErrorResult& aError);
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ class nsIVariant;
|
|||
class nsViewManager;
|
||||
class nsPresContext;
|
||||
class nsRange;
|
||||
class nsScriptLoader;
|
||||
class nsSMILAnimationController;
|
||||
class nsSVGElement;
|
||||
class nsTextNode;
|
||||
|
|
@ -154,6 +153,7 @@ class NodeIterator;
|
|||
enum class OrientationType : uint8_t;
|
||||
class ProcessingInstruction;
|
||||
class Promise;
|
||||
class ScriptLoader;
|
||||
class StyleSheetList;
|
||||
class SVGDocument;
|
||||
class SVGSVGElement;
|
||||
|
|
@ -1368,7 +1368,7 @@ public:
|
|||
/**
|
||||
* Get the script loader for this document
|
||||
*/
|
||||
virtual nsScriptLoader* ScriptLoader() = 0;
|
||||
virtual mozilla::dom::ScriptLoader* ScriptLoader() = 0;
|
||||
|
||||
/**
|
||||
* Add/Remove an element to the document's id and name hashes
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@
|
|||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/SameProcessMessageQueue.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "ScriptSettings.h"
|
||||
#ifdef XP_WIN
|
||||
#include <process.h>
|
||||
#define getpid _getpid
|
||||
|
|
@ -60,6 +59,7 @@
|
|||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
#include "mozilla/dom/ErrorEvent.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
|
|
|
|||
|
|
@ -91,6 +91,9 @@ enum class FullscreenReason
|
|||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Location;
|
||||
|
||||
// The states in this enum represent the different possible outcomes which the
|
||||
// window could be experiencing of loading a document with the
|
||||
// Large-Allocation header. The NONE case represents the case where no
|
||||
|
|
@ -570,7 +573,7 @@ public:
|
|||
|
||||
virtual nsIDOMScreen* GetScreen() = 0;
|
||||
virtual nsIDOMNavigator* GetNavigator() = 0;
|
||||
virtual nsIDOMLocation* GetLocation() = 0;
|
||||
virtual mozilla::dom::Location* Location() = 0;
|
||||
virtual nsresult GetPrompter(nsIPrompt** aPrompt) = 0;
|
||||
virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
|
||||
virtual already_AddRefed<nsISelection> GetSelection() = 0;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIContentSerializer.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsILineBreaker.h"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=900784 -->
|
||||
<!-- The JS bytecode cache is not supposed to be observable. To make it
|
||||
observable, the nsScriptLoader is instrumented to trigger events on the
|
||||
observable, the ScriptLoader is instrumented to trigger events on the
|
||||
script tag. These events are followed to reconstruct the code path taken by
|
||||
the script loader and associate a simple name which is checked in these
|
||||
test cases.
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script type="application/javascript">
|
||||
// This is the state machine of the trace events produced by the
|
||||
// nsScriptLoader. This state machine is used to give a name to each
|
||||
// ScriptLoader. This state machine is used to give a name to each
|
||||
// code path, such that we can assert each code path with a single word.
|
||||
var scriptLoaderStateMachine = {
|
||||
"scriptloader_load_source": {
|
||||
|
|
@ -112,7 +112,7 @@
|
|||
promise_test(async function() {
|
||||
// Setting dom.expose_test_interfaces pref causes the
|
||||
// nsScriptLoadRequest to fire event on script tags, with information
|
||||
// about its internal state. The nsScriptLoader source send events to
|
||||
// about its internal state. The ScriptLoader source send events to
|
||||
// trace these and resolve a promise with the path taken by the
|
||||
// script loader.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -211,12 +211,9 @@ nsControllerCommandGroup::AddCommandToGroup(const char* aCommand,
|
|||
const char* aGroup)
|
||||
{
|
||||
nsDependentCString groupKey(aGroup);
|
||||
nsTArray<nsCString>* commandList = mGroupsHash.Get(groupKey);
|
||||
if (!commandList) {
|
||||
// make this list
|
||||
commandList = new AutoTArray<nsCString, 8>;
|
||||
mGroupsHash.Put(groupKey, commandList);
|
||||
}
|
||||
auto commandList = mGroupsHash.LookupForAdd(groupKey).OrInsert([]() {
|
||||
return new AutoTArray<nsCString, 8>();
|
||||
});
|
||||
|
||||
#ifdef DEBUG
|
||||
nsCString* appended =
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "mozilla/dom/Performance.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/StructuredCloneHolder.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/dom/WorkletGlobalScope.h"
|
||||
|
|
@ -22,7 +23,6 @@
|
|||
#include "nsGlobalWindow.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "WorkerPrivate.h"
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include "nsIDocument.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ HTMLScriptElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
HTMLScriptElement::HTMLScriptElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
|
||||
FromParser aFromParser)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
, nsScriptElement(aFromParser)
|
||||
, ScriptElement(aFromParser)
|
||||
{
|
||||
AddMutationObserver(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,16 +8,16 @@
|
|||
#define mozilla_dom_HTMLScriptElement_h
|
||||
|
||||
#include "nsIDOMHTMLScriptElement.h"
|
||||
#include "nsScriptElement.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/ScriptElement.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class HTMLScriptElement final : public nsGenericHTMLElement,
|
||||
public nsIDOMHTMLScriptElement,
|
||||
public nsScriptElement
|
||||
public ScriptElement
|
||||
{
|
||||
public:
|
||||
using Element::GetText;
|
||||
|
|
@ -97,7 +97,8 @@ protected:
|
|||
virtual ~HTMLScriptElement();
|
||||
|
||||
virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
// nsScriptElement
|
||||
|
||||
// ScriptElement
|
||||
virtual bool HasScriptContent() override;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@
|
|||
#include "nsIDocShell.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsError.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsStyleUtil.h"
|
||||
|
|
@ -91,6 +90,7 @@
|
|||
#include "mozilla/dom/FromParser.h"
|
||||
#include "mozilla/dom/Link.h"
|
||||
#include "mozilla/BloomFilter.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
|
||||
#include "nsVariant.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@
|
|||
#include "nsIHTMLContentSink.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "mozilla/dom/NodeInfo.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "nsToken.h"
|
||||
#include "nsIAppShell.h"
|
||||
#include "nsCRT.h"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
interface nsIControllers;
|
||||
interface nsIDOMBlob;
|
||||
interface nsIDOMLocation;
|
||||
interface nsIDOMOfflineResourceList;
|
||||
interface nsIPrompt;
|
||||
interface nsISelection;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include "nsIDOMDocument.h" // for nsIDOMDocument
|
||||
#include "nsIDOMEvent.h" // for nsIDOMEvent
|
||||
#include "nsIDOMLocation.h" // for nsIDOMLocation
|
||||
#include "nsIURI.h" // for nsIURI
|
||||
#include "TabChild.h" // for TabChildGlobal, TabChildBase
|
||||
#include "mozilla/Telemetry.h" // for mozilla::Telemetry
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/dom/MessagePortBinding.h"
|
||||
#include "mozilla/dom/MessagePortChild.h"
|
||||
#include "mozilla/dom/PMessagePort.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/StructuredCloneTags.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerScope.h"
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "SharedMessagePortMessage.h"
|
||||
|
||||
#include "nsIBFCacheEntry.h"
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ DIRS += [
|
|||
'webbrowserpersist',
|
||||
'xhr',
|
||||
'worklet',
|
||||
'script',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
|
|
|
|||
103
dom/script/ModuleLoadRequest.cpp
Normal file
103
dom/script/ModuleLoadRequest.cpp
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "ModuleLoadRequest.h"
|
||||
#include "ModuleScript.h"
|
||||
#include "ScriptLoader.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest)
|
||||
NS_INTERFACE_MAP_END_INHERITING(ScriptLoadRequest)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ModuleLoadRequest, ScriptLoadRequest,
|
||||
mBaseURL,
|
||||
mLoader,
|
||||
mParent,
|
||||
mModuleScript,
|
||||
mImports)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
||||
NS_IMPL_RELEASE_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
||||
|
||||
ModuleLoadRequest::ModuleLoadRequest(nsIScriptElement* aElement,
|
||||
uint32_t aVersion,
|
||||
CORSMode aCORSMode,
|
||||
const SRIMetadata& aIntegrity,
|
||||
ScriptLoader* aLoader)
|
||||
: ScriptLoadRequest(ScriptKind::Module,
|
||||
aElement,
|
||||
aVersion,
|
||||
aCORSMode,
|
||||
aIntegrity),
|
||||
mIsTopLevel(true),
|
||||
mLoader(aLoader)
|
||||
{}
|
||||
|
||||
void
|
||||
ModuleLoadRequest::Cancel()
|
||||
{
|
||||
ScriptLoadRequest::Cancel();
|
||||
mModuleScript = nullptr;
|
||||
mProgress = ScriptLoadRequest::Progress::Ready;
|
||||
for (size_t i = 0; i < mImports.Length(); i++) {
|
||||
mImports[i]->Cancel();
|
||||
}
|
||||
mReady.RejectIfExists(NS_ERROR_FAILURE, __func__);
|
||||
}
|
||||
|
||||
void
|
||||
ModuleLoadRequest::SetReady()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0; i < mImports.Length(); i++) {
|
||||
MOZ_ASSERT(mImports[i]->IsReadyToRun());
|
||||
}
|
||||
#endif
|
||||
|
||||
ScriptLoadRequest::SetReady();
|
||||
mReady.ResolveIfExists(true, __func__);
|
||||
}
|
||||
|
||||
void
|
||||
ModuleLoadRequest::ModuleLoaded()
|
||||
{
|
||||
// A module that was found to be marked as fetching in the module map has now
|
||||
// been loaded.
|
||||
|
||||
mModuleScript = mLoader->GetFetchedModule(mURI);
|
||||
mLoader->StartFetchingModuleDependencies(this);
|
||||
}
|
||||
|
||||
void
|
||||
ModuleLoadRequest::DependenciesLoaded()
|
||||
{
|
||||
// The module and all of its dependencies have been successfully fetched and
|
||||
// compiled.
|
||||
|
||||
if (!mLoader->InstantiateModuleTree(this)) {
|
||||
LoadFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
SetReady();
|
||||
mLoader->ProcessLoadedModuleTree(this);
|
||||
mLoader = nullptr;
|
||||
mParent = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ModuleLoadRequest::LoadFailed()
|
||||
{
|
||||
Cancel();
|
||||
mLoader->ProcessLoadedModuleTree(this);
|
||||
mLoader = nullptr;
|
||||
mParent = nullptr;
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
82
dom/script/ModuleLoadRequest.h
Normal file
82
dom/script/ModuleLoadRequest.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_dom_ModuleLoadRequest_h
|
||||
#define mozilla_dom_ModuleLoadRequest_h
|
||||
|
||||
#include "ScriptLoadRequest.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ModuleScript;
|
||||
class ScriptLoader;
|
||||
|
||||
// A load request for a module, created for every top level module script and
|
||||
// every module import. Load request can share an ModuleScript if there are
|
||||
// multiple imports of the same module.
|
||||
|
||||
class ModuleLoadRequest final : public ScriptLoadRequest
|
||||
{
|
||||
~ModuleLoadRequest() = default;
|
||||
|
||||
ModuleLoadRequest(const ModuleLoadRequest& aOther) = delete;
|
||||
ModuleLoadRequest(ModuleLoadRequest&& aOther) = delete;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ModuleLoadRequest, ScriptLoadRequest)
|
||||
|
||||
ModuleLoadRequest(nsIScriptElement* aElement,
|
||||
uint32_t aVersion,
|
||||
CORSMode aCORSMode,
|
||||
const SRIMetadata& aIntegrity,
|
||||
ScriptLoader* aLoader);
|
||||
|
||||
bool IsTopLevel() const
|
||||
{
|
||||
return mIsTopLevel;
|
||||
}
|
||||
|
||||
void SetReady() override;
|
||||
void Cancel() override;
|
||||
|
||||
void ModuleLoaded();
|
||||
void DependenciesLoaded();
|
||||
void LoadFailed();
|
||||
|
||||
// Is this a request for a top level module script or an import?
|
||||
bool mIsTopLevel;
|
||||
|
||||
// The base URL used for resolving relative module imports.
|
||||
nsCOMPtr<nsIURI> mBaseURL;
|
||||
|
||||
// Pointer to the script loader, used to trigger actions when the module load
|
||||
// finishes.
|
||||
RefPtr<ScriptLoader> mLoader;
|
||||
|
||||
// The importing module, or nullptr for top level module scripts. Used to
|
||||
// implement the ancestor list checked when fetching module dependencies.
|
||||
RefPtr<ModuleLoadRequest> mParent;
|
||||
|
||||
// Set to a module script object after a successful load or nullptr on
|
||||
// failure.
|
||||
RefPtr<ModuleScript> mModuleScript;
|
||||
|
||||
// A promise that is completed on successful load of this module and all of
|
||||
// its dependencies, indicating that the module is ready for instantiation and
|
||||
// evaluation.
|
||||
MozPromiseHolder<GenericPromise> mReady;
|
||||
|
||||
// Array of imported modules.
|
||||
nsTArray<RefPtr<ModuleLoadRequest>> mImports;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_ModuleLoadRequest_h
|
||||
96
dom/script/ModuleScript.cpp
Normal file
96
dom/script/ModuleScript.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "ModuleScript.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "ScriptLoader.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// A single module script. May be used to satisfy multiple load requests.
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleScript)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
|
||||
tmp->UnlinkModuleRecord();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mException)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
|
||||
|
||||
ModuleScript::ModuleScript(ScriptLoader* aLoader, nsIURI* aBaseURL,
|
||||
JS::Handle<JSObject*> aModuleRecord)
|
||||
: mLoader(aLoader),
|
||||
mBaseURL(aBaseURL),
|
||||
mModuleRecord(aModuleRecord),
|
||||
mInstantiationState(Uninstantiated)
|
||||
{
|
||||
MOZ_ASSERT(mLoader);
|
||||
MOZ_ASSERT(mBaseURL);
|
||||
MOZ_ASSERT(mModuleRecord);
|
||||
MOZ_ASSERT(mException.isUndefined());
|
||||
|
||||
// Make module's host defined field point to this module script object.
|
||||
// This is cleared in the UnlinkModuleRecord().
|
||||
JS::SetModuleHostDefinedField(mModuleRecord, JS::PrivateValue(this));
|
||||
HoldJSObjects(this);
|
||||
}
|
||||
|
||||
void
|
||||
ModuleScript::UnlinkModuleRecord()
|
||||
{
|
||||
// Remove module's back reference to this object request if present.
|
||||
if (mModuleRecord) {
|
||||
MOZ_ASSERT(JS::GetModuleHostDefinedField(mModuleRecord).toPrivate() ==
|
||||
this);
|
||||
JS::SetModuleHostDefinedField(mModuleRecord, JS::UndefinedValue());
|
||||
}
|
||||
mModuleRecord = nullptr;
|
||||
mException.setUndefined();
|
||||
}
|
||||
|
||||
ModuleScript::~ModuleScript()
|
||||
{
|
||||
if (mModuleRecord) {
|
||||
// The object may be destroyed without being unlinked first.
|
||||
UnlinkModuleRecord();
|
||||
}
|
||||
DropJSObjects(this);
|
||||
}
|
||||
|
||||
void
|
||||
ModuleScript::SetInstantiationResult(JS::Handle<JS::Value> aMaybeException)
|
||||
{
|
||||
MOZ_ASSERT(mInstantiationState == Uninstantiated);
|
||||
MOZ_ASSERT(mModuleRecord);
|
||||
MOZ_ASSERT(mException.isUndefined());
|
||||
|
||||
if (aMaybeException.isUndefined()) {
|
||||
mInstantiationState = Instantiated;
|
||||
} else {
|
||||
mModuleRecord = nullptr;
|
||||
mException = aMaybeException;
|
||||
mInstantiationState = Errored;
|
||||
}
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
73
dom/script/ModuleScript.h
Normal file
73
dom/script/ModuleScript.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_dom_ModuleScript_h
|
||||
#define mozilla_dom_ModuleScript_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ScriptLoader;
|
||||
|
||||
class ModuleScript final : public nsISupports
|
||||
{
|
||||
enum InstantiationState {
|
||||
Uninstantiated,
|
||||
Instantiated,
|
||||
Errored
|
||||
};
|
||||
|
||||
RefPtr<ScriptLoader> mLoader;
|
||||
nsCOMPtr<nsIURI> mBaseURL;
|
||||
JS::Heap<JSObject*> mModuleRecord;
|
||||
JS::Heap<JS::Value> mException;
|
||||
InstantiationState mInstantiationState;
|
||||
|
||||
~ModuleScript();
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript)
|
||||
|
||||
ModuleScript(ScriptLoader* aLoader,
|
||||
nsIURI* aBaseURL,
|
||||
JS::Handle<JSObject*> aModuleRecord);
|
||||
|
||||
ScriptLoader* Loader() const { return mLoader; }
|
||||
JSObject* ModuleRecord() const { return mModuleRecord; }
|
||||
JS::Value Exception() const { return mException; }
|
||||
nsIURI* BaseURL() const { return mBaseURL; }
|
||||
|
||||
void SetInstantiationResult(JS::Handle<JS::Value> aMaybeException);
|
||||
|
||||
bool IsUninstantiated() const
|
||||
{
|
||||
return mInstantiationState == Uninstantiated;
|
||||
}
|
||||
|
||||
bool IsInstantiated() const
|
||||
{
|
||||
return mInstantiationState == Instantiated;
|
||||
}
|
||||
|
||||
bool InstantiationFailed() const
|
||||
{
|
||||
return mInstantiationState == Errored;
|
||||
}
|
||||
|
||||
void UnlinkModuleRecord();
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_ModuleScript_h
|
||||
|
|
@ -4,13 +4,13 @@
|
|||
* 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 "nsScriptElement.h"
|
||||
#include "ScriptElement.h"
|
||||
#include "ScriptLoader.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIParser.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsContentSink.h"
|
||||
|
|
@ -19,7 +19,7 @@ using namespace mozilla;
|
|||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptElement::ScriptAvailable(nsresult aResult,
|
||||
ScriptElement::ScriptAvailable(nsresult aResult,
|
||||
nsIScriptElement* aElement,
|
||||
bool aIsInline,
|
||||
nsIURI* aURI,
|
||||
|
|
@ -40,7 +40,7 @@ nsScriptElement::ScriptAvailable(nsresult aResult,
|
|||
}
|
||||
|
||||
/* virtual */ nsresult
|
||||
nsScriptElement::FireErrorEvent()
|
||||
ScriptElement::FireErrorEvent()
|
||||
{
|
||||
nsCOMPtr<nsIContent> cont =
|
||||
do_QueryInterface((nsIScriptElement*) this);
|
||||
|
|
@ -53,7 +53,7 @@ nsScriptElement::FireErrorEvent()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptElement::ScriptEvaluated(nsresult aResult,
|
||||
ScriptElement::ScriptEvaluated(nsresult aResult,
|
||||
nsIScriptElement* aElement,
|
||||
bool aIsInline)
|
||||
{
|
||||
|
|
@ -78,7 +78,7 @@ nsScriptElement::ScriptEvaluated(nsresult aResult,
|
|||
}
|
||||
|
||||
void
|
||||
nsScriptElement::CharacterDataChanged(nsIDocument *aDocument,
|
||||
ScriptElement::CharacterDataChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
CharacterDataChangeInfo* aInfo)
|
||||
{
|
||||
|
|
@ -86,7 +86,7 @@ nsScriptElement::CharacterDataChanged(nsIDocument *aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsScriptElement::AttributeChanged(nsIDocument* aDocument,
|
||||
ScriptElement::AttributeChanged(nsIDocument* aDocument,
|
||||
Element* aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
|
|
@ -97,7 +97,7 @@ nsScriptElement::AttributeChanged(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsScriptElement::ContentAppended(nsIDocument* aDocument,
|
||||
ScriptElement::ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aFirstNewContent,
|
||||
int32_t aNewIndexInContainer)
|
||||
|
|
@ -106,7 +106,7 @@ nsScriptElement::ContentAppended(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
void
|
||||
nsScriptElement::ContentInserted(nsIDocument *aDocument,
|
||||
ScriptElement::ContentInserted(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
int32_t aIndexInContainer)
|
||||
|
|
@ -115,7 +115,7 @@ nsScriptElement::ContentInserted(nsIDocument *aDocument,
|
|||
}
|
||||
|
||||
bool
|
||||
nsScriptElement::MaybeProcessScript()
|
||||
ScriptElement::MaybeProcessScript()
|
||||
{
|
||||
nsCOMPtr<nsIContent> cont =
|
||||
do_QueryInterface((nsIScriptElement*) this);
|
||||
|
|
@ -145,6 +145,6 @@ nsScriptElement::MaybeProcessScript()
|
|||
}
|
||||
}
|
||||
|
||||
RefPtr<nsScriptLoader> loader = ownerDoc->ScriptLoader();
|
||||
RefPtr<ScriptLoader> loader = ownerDoc->ScriptLoader();
|
||||
return loader->ProcessScriptElement(this);
|
||||
}
|
||||
|
|
@ -4,21 +4,24 @@
|
|||
* 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 nsScriptElement_h
|
||||
#define nsScriptElement_h
|
||||
#ifndef mozilla_dom_ScriptElement_h
|
||||
#define mozilla_dom_ScriptElement_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIScriptLoaderObserver.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsStubMutationObserver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* Baseclass useful for script elements (such as <xhtml:script> and
|
||||
* <svg:script>). Currently the class assumes that only the 'src'
|
||||
* attribute and the children of the class affect what script to execute.
|
||||
*/
|
||||
|
||||
class nsScriptElement : public nsIScriptElement,
|
||||
class ScriptElement : public nsIScriptElement,
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
|
|
@ -31,7 +34,7 @@ public:
|
|||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
|
||||
explicit nsScriptElement(mozilla::dom::FromParser aFromParser)
|
||||
explicit ScriptElement(FromParser aFromParser)
|
||||
: nsIScriptElement(aFromParser)
|
||||
{
|
||||
}
|
||||
|
|
@ -49,4 +52,7 @@ protected:
|
|||
virtual bool MaybeProcessScript() override;
|
||||
};
|
||||
|
||||
#endif // nsScriptElement_h
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_ScriptElement_h
|
||||
388
dom/script/ScriptLoadHandler.cpp
Normal file
388
dom/script/ScriptLoadHandler.cpp
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "ScriptLoadHandler.h"
|
||||
#include "ScriptLoader.h"
|
||||
#include "ScriptTrace.h"
|
||||
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#undef LOG
|
||||
#define LOG(args) \
|
||||
MOZ_LOG(ScriptLoader::gScriptLoaderLog, mozilla::LogLevel::Debug, args)
|
||||
|
||||
#define LOG_ENABLED() \
|
||||
MOZ_LOG_TEST(ScriptLoader::gScriptLoaderLog, mozilla::LogLevel::Debug)
|
||||
|
||||
ScriptLoadHandler::ScriptLoadHandler(ScriptLoader* aScriptLoader,
|
||||
ScriptLoadRequest* aRequest,
|
||||
SRICheckDataVerifier* aSRIDataVerifier)
|
||||
: mScriptLoader(aScriptLoader),
|
||||
mRequest(aRequest),
|
||||
mSRIDataVerifier(aSRIDataVerifier),
|
||||
mSRIStatus(NS_OK),
|
||||
mDecoder()
|
||||
{
|
||||
MOZ_ASSERT(mRequest->IsUnknownDataType());
|
||||
MOZ_ASSERT(mRequest->IsLoading());
|
||||
}
|
||||
|
||||
ScriptLoadHandler::~ScriptLoadHandler()
|
||||
{}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ScriptLoadHandler, nsIIncrementalStreamLoaderObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScriptLoadHandler::OnIncrementalData(nsIIncrementalStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
uint32_t aDataLength,
|
||||
const uint8_t* aData,
|
||||
uint32_t* aConsumedLength)
|
||||
{
|
||||
if (mRequest->IsCanceled()) {
|
||||
// If request cancelled, ignore any incoming data.
|
||||
*aConsumedLength = aDataLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (mRequest->IsUnknownDataType()) {
|
||||
rv = EnsureKnownDataType(aLoader);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mRequest->IsSource()) {
|
||||
if (!EnsureDecoder(aLoader, aData, aDataLength,
|
||||
/* aEndOfStream = */ false)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Below we will/shall consume entire data chunk.
|
||||
*aConsumedLength = aDataLength;
|
||||
|
||||
// Decoder has already been initialized. -- trying to decode all loaded bytes.
|
||||
rv = DecodeRawData(aData, aDataLength, /* aEndOfStream = */ false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If SRI is required for this load, appending new bytes to the hash.
|
||||
if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
|
||||
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mRequest->IsBytecode());
|
||||
if (!mRequest->mScriptBytecode.append(aData, aDataLength)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
*aConsumedLength = aDataLength;
|
||||
rv = MaybeDecodeSRI();
|
||||
if (NS_FAILED(rv)) {
|
||||
nsCOMPtr<nsIRequest> channelRequest;
|
||||
aLoader->GetRequest(getter_AddRefs(channelRequest));
|
||||
return channelRequest->Cancel(mScriptLoader->RestartLoad(mRequest));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ScriptLoadHandler::DecodeRawData(const uint8_t* aData,
|
||||
uint32_t aDataLength,
|
||||
bool aEndOfStream)
|
||||
{
|
||||
int32_t srcLen = aDataLength;
|
||||
const char* src = reinterpret_cast<const char*>(aData);
|
||||
int32_t dstLen;
|
||||
nsresult rv =
|
||||
mDecoder->GetMaxLength(src, srcLen, &dstLen);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t haveRead = mRequest->mScriptText.length();
|
||||
|
||||
CheckedInt<uint32_t> capacity = haveRead;
|
||||
capacity += dstLen;
|
||||
|
||||
if (!capacity.isValid() || !mRequest->mScriptText.reserve(capacity.value())) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
rv = mDecoder->Convert(src,
|
||||
&srcLen,
|
||||
mRequest->mScriptText.begin() + haveRead,
|
||||
&dstLen);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
haveRead += dstLen;
|
||||
MOZ_ASSERT(haveRead <= capacity.value(), "mDecoder produced more data than expected");
|
||||
MOZ_ALWAYS_TRUE(mRequest->mScriptText.resizeUninitialized(haveRead));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptLoadHandler::EnsureDecoder(nsIIncrementalStreamLoader* aLoader,
|
||||
const uint8_t* aData,
|
||||
uint32_t aDataLength,
|
||||
bool aEndOfStream)
|
||||
{
|
||||
// Check if decoder has already been created.
|
||||
if (mDecoder) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoCString charset;
|
||||
if (!EnsureDecoder(aLoader, aData, aDataLength, aEndOfStream, charset)) {
|
||||
return false;
|
||||
}
|
||||
if (charset.Length() == 0) {
|
||||
charset = "?";
|
||||
}
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::DOM_SCRIPT_SRC_ENCODING,
|
||||
charset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ScriptLoadHandler::EnsureDecoder(nsIIncrementalStreamLoader* aLoader,
|
||||
const uint8_t* aData,
|
||||
uint32_t aDataLength,
|
||||
bool aEndOfStream,
|
||||
nsCString& oCharset)
|
||||
{
|
||||
// JavaScript modules are always UTF-8.
|
||||
if (mRequest->IsModuleRequest()) {
|
||||
oCharset = "UTF-8";
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(oCharset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine if BOM check should be done. This occurs either
|
||||
// if end-of-stream has been reached, or at least 3 bytes have
|
||||
// been read from input.
|
||||
if (!aEndOfStream && (aDataLength < 3)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do BOM detection.
|
||||
if (nsContentUtils::CheckForBOM(aData, aDataLength, oCharset)) {
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(oCharset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// BOM detection failed, check content stream for charset.
|
||||
nsCOMPtr<nsIRequest> req;
|
||||
nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
|
||||
NS_ASSERTION(req, "StreamLoader's request went away prematurely");
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
|
||||
|
||||
if (channel &&
|
||||
NS_SUCCEEDED(channel->GetContentCharset(oCharset)) &&
|
||||
EncodingUtils::FindEncodingForLabel(oCharset, oCharset)) {
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(oCharset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the hint charset from the script element or preload
|
||||
// request.
|
||||
nsAutoString hintCharset;
|
||||
if (!mRequest->IsPreload()) {
|
||||
mRequest->mElement->GetScriptCharset(hintCharset);
|
||||
} else {
|
||||
nsTArray<ScriptLoader::PreloadInfo>::index_type i =
|
||||
mScriptLoader->mPreloads.IndexOf(mRequest, 0,
|
||||
ScriptLoader::PreloadRequestComparator());
|
||||
|
||||
NS_ASSERTION(i != mScriptLoader->mPreloads.NoIndex,
|
||||
"Incorrect preload bookkeeping");
|
||||
hintCharset = mScriptLoader->mPreloads[i].mCharset;
|
||||
}
|
||||
|
||||
if (EncodingUtils::FindEncodingForLabel(hintCharset, oCharset)) {
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(oCharset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the charset from the charset of the document.
|
||||
if (mScriptLoader->mDocument) {
|
||||
oCharset = mScriptLoader->mDocument->GetDocumentCharacterSet();
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(oCharset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Curiously, there are various callers that don't pass aDocument. The
|
||||
// fallback in the old code was ISO-8859-1, which behaved like
|
||||
// windows-1252. Saying windows-1252 for clarity and for compliance
|
||||
// with the Encoding Standard.
|
||||
oCharset = "windows-1252";
|
||||
mDecoder = EncodingUtils::DecoderForEncoding(oCharset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ScriptLoadHandler::MaybeDecodeSRI()
|
||||
{
|
||||
if (!mSRIDataVerifier || mSRIDataVerifier->IsComplete() || NS_FAILED(mSRIStatus)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Skip until the content is large enough to be decoded.
|
||||
if (mRequest->mScriptBytecode.length() <= mSRIDataVerifier->DataSummaryLength()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mSRIStatus = mSRIDataVerifier->ImportDataSummary(
|
||||
mRequest->mScriptBytecode.length(), mRequest->mScriptBytecode.begin());
|
||||
|
||||
if (NS_FAILED(mSRIStatus)) {
|
||||
// We are unable to decode the hash contained in the alternate data which
|
||||
// contains the bytecode, or it does not use the same algorithm.
|
||||
LOG(("ScriptLoadHandler::MaybeDecodeSRI, failed to decode SRI, restart request"));
|
||||
return mSRIStatus;
|
||||
}
|
||||
|
||||
mRequest->mBytecodeOffset = mSRIDataVerifier->DataSummaryLength();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ScriptLoadHandler::EnsureKnownDataType(nsIIncrementalStreamLoader* aLoader)
|
||||
{
|
||||
MOZ_ASSERT(mRequest->IsUnknownDataType());
|
||||
MOZ_ASSERT(mRequest->IsLoading());
|
||||
if (mRequest->IsLoadingSource()) {
|
||||
mRequest->mDataType = ScriptLoadRequest::DataType::Source;
|
||||
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRequest> req;
|
||||
nsresult rv = aLoader->GetRequest(getter_AddRefs(req));
|
||||
MOZ_ASSERT(req, "StreamLoader's request went away prematurely");
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(req));
|
||||
if (cic) {
|
||||
nsAutoCString altDataType;
|
||||
cic->GetAlternativeDataType(altDataType);
|
||||
if (altDataType.EqualsLiteral("javascript/moz-bytecode-" NS_STRINGIFY(MOZ_BUILDID))) {
|
||||
mRequest->mDataType = ScriptLoadRequest::DataType::Bytecode;
|
||||
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_bytecode");
|
||||
} else {
|
||||
mRequest->mDataType = ScriptLoadRequest::DataType::Source;
|
||||
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
|
||||
}
|
||||
} else {
|
||||
mRequest->mDataType = ScriptLoadRequest::DataType::Source;
|
||||
TRACE_FOR_TEST(mRequest->mElement, "scriptloader_load_source");
|
||||
}
|
||||
MOZ_ASSERT(!mRequest->IsUnknownDataType());
|
||||
MOZ_ASSERT(mRequest->IsLoading());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ScriptLoadHandler::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus,
|
||||
uint32_t aDataLength,
|
||||
const uint8_t* aData)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (LOG_ENABLED()) {
|
||||
nsAutoCString url;
|
||||
mRequest->mURI->GetAsciiSpec(url);
|
||||
LOG(("ScriptLoadRequest (%p): Stream complete (url = %s)",
|
||||
mRequest.get(), url.get()));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRequest> channelRequest;
|
||||
aLoader->GetRequest(getter_AddRefs(channelRequest));
|
||||
|
||||
if (!mRequest->IsCanceled()) {
|
||||
if (mRequest->IsUnknownDataType()) {
|
||||
rv = EnsureKnownDataType(aLoader);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (mRequest->IsSource()) {
|
||||
DebugOnly<bool> encoderSet =
|
||||
EnsureDecoder(aLoader, aData, aDataLength, /* aEndOfStream = */ true);
|
||||
MOZ_ASSERT(encoderSet);
|
||||
rv = DecodeRawData(aData, aDataLength, /* aEndOfStream = */ true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
LOG(("ScriptLoadRequest (%p): Source length = %u",
|
||||
mRequest.get(), unsigned(mRequest->mScriptText.length())));
|
||||
|
||||
// If SRI is required for this load, appending new bytes to the hash.
|
||||
if (mSRIDataVerifier && NS_SUCCEEDED(mSRIStatus)) {
|
||||
mSRIStatus = mSRIDataVerifier->Update(aDataLength, aData);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(mRequest->IsBytecode());
|
||||
if (!mRequest->mScriptBytecode.append(aData, aDataLength)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
LOG(("ScriptLoadRequest (%p): Bytecode length = %u",
|
||||
mRequest.get(), unsigned(mRequest->mScriptBytecode.length())));
|
||||
|
||||
// If we abort while decoding the SRI, we fallback on explictly requesting
|
||||
// the source. Thus, we should not continue in
|
||||
// ScriptLoader::OnStreamComplete, which removes the request from the
|
||||
// waiting lists.
|
||||
rv = MaybeDecodeSRI();
|
||||
if (NS_FAILED(rv)) {
|
||||
return channelRequest->Cancel(mScriptLoader->RestartLoad(mRequest));
|
||||
}
|
||||
|
||||
// The bytecode cache always starts with the SRI hash, thus even if there
|
||||
// is no SRI data verifier instance, we still want to skip the hash.
|
||||
rv = SRICheckDataVerifier::DataSummaryLength(mRequest->mScriptBytecode.length(),
|
||||
mRequest->mScriptBytecode.begin(),
|
||||
&mRequest->mBytecodeOffset);
|
||||
if (NS_FAILED(rv)) {
|
||||
return channelRequest->Cancel(mScriptLoader->RestartLoad(mRequest));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Everything went well, keep the CacheInfoChannel alive such that we can
|
||||
// later save the bytecode on the cache entry.
|
||||
if (NS_SUCCEEDED(rv) && mRequest->IsSource() &&
|
||||
ScriptLoader::IsBytecodeCacheEnabled()) {
|
||||
mRequest->mCacheInfo = do_QueryInterface(channelRequest);
|
||||
LOG(("ScriptLoadRequest (%p): nsICacheInfoChannel = %p",
|
||||
mRequest.get(), mRequest->mCacheInfo.get()));
|
||||
}
|
||||
|
||||
// we have to mediate and use mRequest.
|
||||
rv = mScriptLoader->OnStreamComplete(aLoader, mRequest, aStatus, mSRIStatus,
|
||||
mSRIDataVerifier);
|
||||
|
||||
// In case of failure, clear the mCacheInfoChannel to avoid keeping it alive.
|
||||
if (NS_FAILED(rv)) {
|
||||
mRequest->mCacheInfo = nullptr;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#undef LOG_ENABLED
|
||||
#undef LOG
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
83
dom/script/ScriptLoadHandler.h
Normal file
83
dom/script/ScriptLoadHandler.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* A class that handles loading and evaluation of <script> elements.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_dom_ScriptLoadHandler_h
|
||||
#define mozilla_dom_ScriptLoadHandler_h
|
||||
|
||||
#include "nsIIncrementalStreamLoader.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ScriptLoadRequest;
|
||||
class ScriptLoader;
|
||||
class SRICheckDataVerifier;
|
||||
|
||||
class ScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver
|
||||
{
|
||||
public:
|
||||
explicit ScriptLoadHandler(ScriptLoader* aScriptLoader,
|
||||
ScriptLoadRequest* aRequest,
|
||||
SRICheckDataVerifier* aSRIDataVerifier);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
|
||||
|
||||
private:
|
||||
virtual ~ScriptLoadHandler();
|
||||
|
||||
/*
|
||||
* Once the charset is found by the EnsureDecoder function, we can
|
||||
* incrementally convert the charset to the one expected by the JS Parser.
|
||||
*/
|
||||
nsresult DecodeRawData(const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream);
|
||||
|
||||
/*
|
||||
* Discover the charset by looking at the stream data, the script
|
||||
* tag, and other indicators. Returns true if charset has been
|
||||
* discovered.
|
||||
*/
|
||||
bool EnsureDecoder(nsIIncrementalStreamLoader* aLoader,
|
||||
const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream);
|
||||
bool EnsureDecoder(nsIIncrementalStreamLoader* aLoader,
|
||||
const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream, nsCString& oCharset);
|
||||
|
||||
/*
|
||||
* When streaming bytecode, we have the opportunity to fallback early if SRI
|
||||
* does not match the expectation of the document.
|
||||
*/
|
||||
nsresult MaybeDecodeSRI();
|
||||
|
||||
// Query the channel to find the data type associated with the input stream.
|
||||
nsresult EnsureKnownDataType(nsIIncrementalStreamLoader* aLoader);
|
||||
|
||||
// ScriptLoader which will handle the parsed script.
|
||||
RefPtr<ScriptLoader> mScriptLoader;
|
||||
|
||||
// The ScriptLoadRequest for this load. Decoded data are accumulated on it.
|
||||
RefPtr<ScriptLoadRequest> mRequest;
|
||||
|
||||
// SRI data verifier.
|
||||
nsAutoPtr<SRICheckDataVerifier> mSRIDataVerifier;
|
||||
|
||||
// Status of SRI data operations.
|
||||
nsresult mSRIStatus;
|
||||
|
||||
// Unicode decoder for charset.
|
||||
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ScriptLoadHandler_h
|
||||
193
dom/script/ScriptLoadRequest.cpp
Normal file
193
dom/script/ScriptLoadRequest.cpp
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "ModuleLoadRequest.h"
|
||||
#include "mozilla/HoldDropJSObjects.h"
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "ScriptLoadRequest.h"
|
||||
#include "ScriptSettings.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// ScriptLoadRequest
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoadRequest)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptLoadRequest)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptLoadRequest)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptLoadRequest)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptLoadRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheInfo)
|
||||
tmp->DropBytecodeCacheReferences();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptLoadRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheInfo)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ScriptLoadRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScript)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
ScriptLoadRequest::ScriptLoadRequest(ScriptKind aKind,
|
||||
nsIScriptElement* aElement,
|
||||
uint32_t aVersion,
|
||||
mozilla::CORSMode aCORSMode,
|
||||
const mozilla::dom::SRIMetadata& aIntegrity)
|
||||
: mKind(aKind)
|
||||
, mElement(aElement)
|
||||
, mScriptFromHead(false)
|
||||
, mProgress(Progress::Loading)
|
||||
, mDataType(DataType::Unknown)
|
||||
, mIsInline(true)
|
||||
, mHasSourceMapURL(false)
|
||||
, mIsDefer(false)
|
||||
, mIsAsync(false)
|
||||
, mIsNonAsyncScriptInserted(false)
|
||||
, mIsXSLT(false)
|
||||
, mIsCanceled(false)
|
||||
, mWasCompiledOMT(false)
|
||||
, mIsTracking(false)
|
||||
, mOffThreadToken(nullptr)
|
||||
, mScriptText()
|
||||
, mScriptBytecode()
|
||||
, mBytecodeOffset(0)
|
||||
, mJSVersion(aVersion)
|
||||
, mLineNo(1)
|
||||
, mCORSMode(aCORSMode)
|
||||
, mIntegrity(aIntegrity)
|
||||
, mReferrerPolicy(mozilla::net::RP_Unset)
|
||||
{
|
||||
}
|
||||
|
||||
ScriptLoadRequest::~ScriptLoadRequest()
|
||||
{
|
||||
// We should always clean up any off-thread script parsing resources.
|
||||
MOZ_ASSERT(!mOffThreadToken);
|
||||
|
||||
// But play it safe in release builds and try to clean them up here
|
||||
// as a fail safe.
|
||||
MaybeCancelOffThreadScript();
|
||||
|
||||
if (mScript) {
|
||||
DropBytecodeCacheReferences();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScriptLoadRequest::SetReady()
|
||||
{
|
||||
MOZ_ASSERT(mProgress != Progress::Ready);
|
||||
mProgress = Progress::Ready;
|
||||
}
|
||||
|
||||
void
|
||||
ScriptLoadRequest::Cancel()
|
||||
{
|
||||
MaybeCancelOffThreadScript();
|
||||
mIsCanceled = true;
|
||||
}
|
||||
|
||||
void
|
||||
ScriptLoadRequest::MaybeCancelOffThreadScript()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mOffThreadToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSContext* cx = danger::GetJSContext();
|
||||
// Follow the same conditions as ScriptLoader::AttemptAsyncScriptCompile
|
||||
if (IsModuleRequest()) {
|
||||
JS::CancelOffThreadModule(cx, mOffThreadToken);
|
||||
} else if (IsSource()) {
|
||||
JS::CancelOffThreadScript(cx, mOffThreadToken);
|
||||
} else {
|
||||
MOZ_ASSERT(IsBytecode());
|
||||
JS::CancelOffThreadScriptDecoder(cx, mOffThreadToken);
|
||||
}
|
||||
mOffThreadToken = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ScriptLoadRequest::DropBytecodeCacheReferences()
|
||||
{
|
||||
mCacheInfo = nullptr;
|
||||
mScript = nullptr;
|
||||
DropJSObjects(this);
|
||||
}
|
||||
|
||||
inline ModuleLoadRequest*
|
||||
ScriptLoadRequest::AsModuleRequest()
|
||||
{
|
||||
MOZ_ASSERT(IsModuleRequest());
|
||||
return static_cast<ModuleLoadRequest*>(this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// ScriptLoadRequestList
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
ScriptLoadRequestList::~ScriptLoadRequestList()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ScriptLoadRequestList::Clear()
|
||||
{
|
||||
while (!isEmpty()) {
|
||||
RefPtr<ScriptLoadRequest> first = StealFirst();
|
||||
first->Cancel();
|
||||
// And just let it go out of scope and die.
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
ScriptLoadRequestList::Contains(ScriptLoadRequest* aElem) const
|
||||
{
|
||||
for (const ScriptLoadRequest* req = getFirst();
|
||||
req; req = req->getNext()) {
|
||||
if (req == aElem) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
inline void
|
||||
ImplCycleCollectionUnlink(ScriptLoadRequestList& aField)
|
||||
{
|
||||
while (!aField.isEmpty()) {
|
||||
RefPtr<ScriptLoadRequest> first = aField.StealFirst();
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
ScriptLoadRequestList& aField,
|
||||
const char* aName,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
for (ScriptLoadRequest* request = aField.getFirst();
|
||||
request; request = request->getNext())
|
||||
{
|
||||
CycleCollectionNoteChild(aCallback, request, aName, aFlags);
|
||||
}
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
249
dom/script/ScriptLoadRequest.h
Normal file
249
dom/script/ScriptLoadRequest.h
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_dom_ScriptLoadRequest_h
|
||||
#define mozilla_dom_ScriptLoadRequest_h
|
||||
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/dom/SRIMetadata.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/net/ReferrerPolicy.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIScriptElement.h"
|
||||
|
||||
class nsICacheInfoChannel;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ModuleLoadRequest;
|
||||
class ScriptLoadRequestList;
|
||||
|
||||
enum class ScriptKind {
|
||||
Classic,
|
||||
Module
|
||||
};
|
||||
|
||||
/*
|
||||
* A class that handles loading and evaluation of <script> elements.
|
||||
*/
|
||||
|
||||
class ScriptLoadRequest : public nsISupports,
|
||||
private mozilla::LinkedListElement<ScriptLoadRequest>
|
||||
{
|
||||
typedef LinkedListElement<ScriptLoadRequest> super;
|
||||
|
||||
// Allow LinkedListElement<ScriptLoadRequest> to cast us to itself as needed.
|
||||
friend class mozilla::LinkedListElement<ScriptLoadRequest>;
|
||||
friend class ScriptLoadRequestList;
|
||||
|
||||
protected:
|
||||
virtual ~ScriptLoadRequest();
|
||||
|
||||
public:
|
||||
ScriptLoadRequest(ScriptKind aKind,
|
||||
nsIScriptElement* aElement,
|
||||
uint32_t aVersion,
|
||||
mozilla::CORSMode aCORSMode,
|
||||
const mozilla::dom::SRIMetadata &aIntegrity);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ScriptLoadRequest)
|
||||
|
||||
bool IsModuleRequest() const
|
||||
{
|
||||
return mKind == ScriptKind::Module;
|
||||
}
|
||||
|
||||
ModuleLoadRequest* AsModuleRequest();
|
||||
|
||||
void FireScriptAvailable(nsresult aResult)
|
||||
{
|
||||
mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
|
||||
}
|
||||
void FireScriptEvaluated(nsresult aResult)
|
||||
{
|
||||
mElement->ScriptEvaluated(aResult, mElement, mIsInline);
|
||||
}
|
||||
|
||||
bool IsPreload()
|
||||
{
|
||||
return mElement == nullptr;
|
||||
}
|
||||
|
||||
virtual void Cancel();
|
||||
|
||||
bool IsCanceled() const
|
||||
{
|
||||
return mIsCanceled;
|
||||
}
|
||||
|
||||
virtual void SetReady();
|
||||
|
||||
void** OffThreadTokenPtr()
|
||||
{
|
||||
return mOffThreadToken ? &mOffThreadToken : nullptr;
|
||||
}
|
||||
|
||||
bool IsTracking() const
|
||||
{
|
||||
return mIsTracking;
|
||||
}
|
||||
void SetIsTracking()
|
||||
{
|
||||
MOZ_ASSERT(!mIsTracking);
|
||||
mIsTracking = true;
|
||||
}
|
||||
|
||||
enum class Progress : uint8_t {
|
||||
Loading, // Request either source or bytecode
|
||||
Loading_Source, // Explicitly Request source stream
|
||||
Compiling,
|
||||
FetchingImports,
|
||||
Ready
|
||||
};
|
||||
|
||||
bool IsReadyToRun() const {
|
||||
return mProgress == Progress::Ready;
|
||||
}
|
||||
bool IsLoading() const {
|
||||
return mProgress == Progress::Loading ||
|
||||
mProgress == Progress::Loading_Source;
|
||||
}
|
||||
bool IsLoadingSource() const {
|
||||
return mProgress == Progress::Loading_Source;
|
||||
}
|
||||
bool InCompilingStage() const {
|
||||
return mProgress == Progress::Compiling ||
|
||||
(IsReadyToRun() && mWasCompiledOMT);
|
||||
}
|
||||
|
||||
// Type of data provided by the nsChannel.
|
||||
enum class DataType : uint8_t {
|
||||
Unknown,
|
||||
Source,
|
||||
Bytecode
|
||||
};
|
||||
|
||||
bool IsUnknownDataType() const {
|
||||
return mDataType == DataType::Unknown;
|
||||
}
|
||||
bool IsSource() const {
|
||||
return mDataType == DataType::Source;
|
||||
}
|
||||
bool IsBytecode() const {
|
||||
return mDataType == DataType::Bytecode;
|
||||
}
|
||||
|
||||
void MaybeCancelOffThreadScript();
|
||||
void DropBytecodeCacheReferences();
|
||||
|
||||
using super::getNext;
|
||||
using super::isInList;
|
||||
|
||||
const ScriptKind mKind;
|
||||
nsCOMPtr<nsIScriptElement> mElement;
|
||||
bool mScriptFromHead; // Synchronous head script block loading of other non js/css content.
|
||||
Progress mProgress; // Are we still waiting for a load to complete?
|
||||
DataType mDataType; // Does this contain Source or Bytecode?
|
||||
bool mIsInline; // Is the script inline or loaded?
|
||||
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
|
||||
bool mIsDefer; // True if we live in mDeferRequests.
|
||||
bool mIsAsync; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
|
||||
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
|
||||
bool mIsXSLT; // True if we live in mXSLTRequests.
|
||||
bool mIsCanceled; // True if we have been explicitly canceled.
|
||||
bool mWasCompiledOMT; // True if the script has been compiled off main thread.
|
||||
bool mIsTracking; // True if the script comes from a source on our tracking protection list.
|
||||
void* mOffThreadToken; // Off-thread parsing token.
|
||||
nsString mSourceMapURL; // Holds source map url for loaded scripts
|
||||
|
||||
// Holds the top-level JSScript that corresponds to the current source, once
|
||||
// it is parsed, and planned to be saved in the bytecode cache.
|
||||
JS::Heap<JSScript*> mScript;
|
||||
|
||||
// Holds script text for non-inline scripts. Don't use nsString so we can give
|
||||
// ownership to jsapi.
|
||||
mozilla::Vector<char16_t> mScriptText;
|
||||
|
||||
// Holds the SRI serialized hash and the script bytecode for non-inline
|
||||
// scripts.
|
||||
mozilla::Vector<uint8_t> mScriptBytecode;
|
||||
uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
|
||||
|
||||
uint32_t mJSVersion;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
|
||||
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
|
||||
int32_t mLineNo;
|
||||
const mozilla::CORSMode mCORSMode;
|
||||
const mozilla::dom::SRIMetadata mIntegrity;
|
||||
mozilla::net::ReferrerPolicy mReferrerPolicy;
|
||||
|
||||
// Holds the Cache information, which is used to register the bytecode
|
||||
// on the cache entry, such that we can load it the next time.
|
||||
nsCOMPtr<nsICacheInfoChannel> mCacheInfo;
|
||||
};
|
||||
|
||||
class ScriptLoadRequestList : private mozilla::LinkedList<ScriptLoadRequest>
|
||||
{
|
||||
typedef mozilla::LinkedList<ScriptLoadRequest> super;
|
||||
|
||||
public:
|
||||
~ScriptLoadRequestList();
|
||||
|
||||
void Clear();
|
||||
|
||||
#ifdef DEBUG
|
||||
bool Contains(ScriptLoadRequest* aElem) const;
|
||||
#endif // DEBUG
|
||||
|
||||
using super::getFirst;
|
||||
using super::isEmpty;
|
||||
|
||||
void AppendElement(ScriptLoadRequest* aElem)
|
||||
{
|
||||
MOZ_ASSERT(!aElem->isInList());
|
||||
NS_ADDREF(aElem);
|
||||
insertBack(aElem);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE
|
||||
already_AddRefed<ScriptLoadRequest> Steal(ScriptLoadRequest* aElem)
|
||||
{
|
||||
aElem->removeFrom(*this);
|
||||
return dont_AddRef(aElem);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE
|
||||
already_AddRefed<ScriptLoadRequest> StealFirst()
|
||||
{
|
||||
MOZ_ASSERT(!isEmpty());
|
||||
return Steal(getFirst());
|
||||
}
|
||||
|
||||
void Remove(ScriptLoadRequest* aElem)
|
||||
{
|
||||
aElem->removeFrom(*this);
|
||||
NS_RELEASE(aElem);
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
ImplCycleCollectionUnlink(ScriptLoadRequestList& aField);
|
||||
|
||||
void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
ScriptLoadRequestList& aField,
|
||||
const char* aName,
|
||||
uint32_t aFlags);
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ScriptLoadRequest_h
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -4,12 +4,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* A class that handles loading and evaluation of <script> elements.
|
||||
*/
|
||||
|
||||
#ifndef __nsScriptLoader_h__
|
||||
#define __nsScriptLoader_h__
|
||||
#ifndef mozilla_dom_ScriptLoader_h
|
||||
#define mozilla_dom_ScriptLoader_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
|
@ -24,16 +20,13 @@
|
|||
#include "nsIIncrementalStreamLoader.h"
|
||||
#include "nsURIHashKey.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/dom/ScriptLoadRequest.h"
|
||||
#include "mozilla/dom/SRIMetadata.h"
|
||||
#include "mozilla/dom/SRICheck.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/net/ReferrerPolicy.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
class nsModuleLoadRequest;
|
||||
class nsModuleScript;
|
||||
class nsScriptLoadRequestList;
|
||||
class nsIURI;
|
||||
|
||||
namespace JS {
|
||||
|
|
@ -42,280 +35,50 @@ namespace JS {
|
|||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AutoJSAPI;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Per-request data structure
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
enum class nsScriptKind {
|
||||
Classic,
|
||||
Module
|
||||
};
|
||||
|
||||
class nsScriptLoadRequest : public nsISupports,
|
||||
private mozilla::LinkedListElement<nsScriptLoadRequest>
|
||||
{
|
||||
typedef LinkedListElement<nsScriptLoadRequest> super;
|
||||
|
||||
// Allow LinkedListElement<nsScriptLoadRequest> to cast us to itself as needed.
|
||||
friend class mozilla::LinkedListElement<nsScriptLoadRequest>;
|
||||
friend class nsScriptLoadRequestList;
|
||||
|
||||
protected:
|
||||
virtual ~nsScriptLoadRequest();
|
||||
|
||||
public:
|
||||
nsScriptLoadRequest(nsScriptKind aKind,
|
||||
nsIScriptElement* aElement,
|
||||
uint32_t aVersion,
|
||||
mozilla::CORSMode aCORSMode,
|
||||
const mozilla::dom::SRIMetadata &aIntegrity)
|
||||
: mKind(aKind),
|
||||
mElement(aElement),
|
||||
mScriptFromHead(false),
|
||||
mProgress(Progress::Loading),
|
||||
mDataType(DataType::Unknown),
|
||||
mIsInline(true),
|
||||
mHasSourceMapURL(false),
|
||||
mIsDefer(false),
|
||||
mIsAsync(false),
|
||||
mIsNonAsyncScriptInserted(false),
|
||||
mIsXSLT(false),
|
||||
mIsCanceled(false),
|
||||
mWasCompiledOMT(false),
|
||||
mIsTracking(false),
|
||||
mOffThreadToken(nullptr),
|
||||
mScriptText(),
|
||||
mScriptBytecode(),
|
||||
mBytecodeOffset(0),
|
||||
mJSVersion(aVersion),
|
||||
mLineNo(1),
|
||||
mCORSMode(aCORSMode),
|
||||
mIntegrity(aIntegrity),
|
||||
mReferrerPolicy(mozilla::net::RP_Unset)
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsScriptLoadRequest)
|
||||
|
||||
bool IsModuleRequest() const
|
||||
{
|
||||
return mKind == nsScriptKind::Module;
|
||||
}
|
||||
|
||||
nsModuleLoadRequest* AsModuleRequest();
|
||||
|
||||
void FireScriptAvailable(nsresult aResult)
|
||||
{
|
||||
mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
|
||||
}
|
||||
void FireScriptEvaluated(nsresult aResult)
|
||||
{
|
||||
mElement->ScriptEvaluated(aResult, mElement, mIsInline);
|
||||
}
|
||||
|
||||
bool IsPreload()
|
||||
{
|
||||
return mElement == nullptr;
|
||||
}
|
||||
|
||||
virtual void Cancel();
|
||||
|
||||
bool IsCanceled() const
|
||||
{
|
||||
return mIsCanceled;
|
||||
}
|
||||
|
||||
virtual void SetReady();
|
||||
|
||||
void** OffThreadTokenPtr()
|
||||
{
|
||||
return mOffThreadToken ? &mOffThreadToken : nullptr;
|
||||
}
|
||||
|
||||
bool IsTracking() const
|
||||
{
|
||||
return mIsTracking;
|
||||
}
|
||||
void SetIsTracking()
|
||||
{
|
||||
MOZ_ASSERT(!mIsTracking);
|
||||
mIsTracking = true;
|
||||
}
|
||||
|
||||
enum class Progress : uint8_t {
|
||||
Loading, // Request either source or bytecode
|
||||
Loading_Source, // Explicitly Request source stream
|
||||
Compiling,
|
||||
FetchingImports,
|
||||
Ready
|
||||
};
|
||||
|
||||
bool IsReadyToRun() const {
|
||||
return mProgress == Progress::Ready;
|
||||
}
|
||||
bool IsLoading() const {
|
||||
return mProgress == Progress::Loading ||
|
||||
mProgress == Progress::Loading_Source;
|
||||
}
|
||||
bool IsLoadingSource() const {
|
||||
return mProgress == Progress::Loading_Source;
|
||||
}
|
||||
bool InCompilingStage() const {
|
||||
return mProgress == Progress::Compiling ||
|
||||
(IsReadyToRun() && mWasCompiledOMT);
|
||||
}
|
||||
|
||||
// Type of data provided by the nsChannel.
|
||||
enum class DataType : uint8_t {
|
||||
Unknown,
|
||||
Source,
|
||||
Bytecode
|
||||
};
|
||||
|
||||
bool IsUnknownDataType() const {
|
||||
return mDataType == DataType::Unknown;
|
||||
}
|
||||
bool IsSource() const {
|
||||
return mDataType == DataType::Source;
|
||||
}
|
||||
bool IsBytecode() const {
|
||||
return mDataType == DataType::Bytecode;
|
||||
}
|
||||
|
||||
void MaybeCancelOffThreadScript();
|
||||
void DropBytecodeCacheReferences();
|
||||
|
||||
using super::getNext;
|
||||
using super::isInList;
|
||||
|
||||
const nsScriptKind mKind;
|
||||
nsCOMPtr<nsIScriptElement> mElement;
|
||||
bool mScriptFromHead; // Synchronous head script block loading of other non js/css content.
|
||||
Progress mProgress; // Are we still waiting for a load to complete?
|
||||
DataType mDataType; // Does this contain Source or Bytecode?
|
||||
bool mIsInline; // Is the script inline or loaded?
|
||||
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
|
||||
bool mIsDefer; // True if we live in mDeferRequests.
|
||||
bool mIsAsync; // True if we live in mLoadingAsyncRequests or mLoadedAsyncRequests.
|
||||
bool mIsNonAsyncScriptInserted; // True if we live in mNonAsyncExternalScriptInsertedRequests
|
||||
bool mIsXSLT; // True if we live in mXSLTRequests.
|
||||
bool mIsCanceled; // True if we have been explicitly canceled.
|
||||
bool mWasCompiledOMT; // True if the script has been compiled off main thread.
|
||||
bool mIsTracking; // True if the script comes from a source on our tracking protection list.
|
||||
void* mOffThreadToken; // Off-thread parsing token.
|
||||
nsString mSourceMapURL; // Holds source map url for loaded scripts
|
||||
|
||||
// Holds the top-level JSScript that corresponds to the current source, once
|
||||
// it is parsed, and planned to be saved in the bytecode cache.
|
||||
JS::Heap<JSScript*> mScript;
|
||||
|
||||
// Holds script text for non-inline scripts. Don't use nsString so we can give
|
||||
// ownership to jsapi.
|
||||
mozilla::Vector<char16_t> mScriptText;
|
||||
|
||||
// Holds the SRI serialized hash and the script bytecode for non-inline
|
||||
// scripts.
|
||||
mozilla::Vector<uint8_t> mScriptBytecode;
|
||||
uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
|
||||
|
||||
uint32_t mJSVersion;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
|
||||
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
|
||||
int32_t mLineNo;
|
||||
const mozilla::CORSMode mCORSMode;
|
||||
const mozilla::dom::SRIMetadata mIntegrity;
|
||||
mozilla::net::ReferrerPolicy mReferrerPolicy;
|
||||
|
||||
// Holds the Cache information, which is used to register the bytecode
|
||||
// on the cache entry, such that we can load it the next time.
|
||||
nsCOMPtr<nsICacheInfoChannel> mCacheInfo;
|
||||
};
|
||||
|
||||
class nsScriptLoadRequestList : private mozilla::LinkedList<nsScriptLoadRequest>
|
||||
{
|
||||
typedef mozilla::LinkedList<nsScriptLoadRequest> super;
|
||||
|
||||
public:
|
||||
~nsScriptLoadRequestList();
|
||||
|
||||
void Clear();
|
||||
|
||||
#ifdef DEBUG
|
||||
bool Contains(nsScriptLoadRequest* aElem) const;
|
||||
#endif // DEBUG
|
||||
|
||||
using super::getFirst;
|
||||
using super::isEmpty;
|
||||
|
||||
void AppendElement(nsScriptLoadRequest* aElem)
|
||||
{
|
||||
MOZ_ASSERT(!aElem->isInList());
|
||||
NS_ADDREF(aElem);
|
||||
insertBack(aElem);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE
|
||||
already_AddRefed<nsScriptLoadRequest> Steal(nsScriptLoadRequest* aElem)
|
||||
{
|
||||
aElem->removeFrom(*this);
|
||||
return dont_AddRef(aElem);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE
|
||||
already_AddRefed<nsScriptLoadRequest> StealFirst()
|
||||
{
|
||||
MOZ_ASSERT(!isEmpty());
|
||||
return Steal(getFirst());
|
||||
}
|
||||
|
||||
void Remove(nsScriptLoadRequest* aElem)
|
||||
{
|
||||
aElem->removeFrom(*this);
|
||||
NS_RELEASE(aElem);
|
||||
}
|
||||
};
|
||||
class ModuleLoadRequest;
|
||||
class ModuleScript;
|
||||
class ScriptLoadHandler;
|
||||
class ScriptRequestProcessor;
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Script loader implementation
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
class nsScriptLoader final : public nsISupports
|
||||
class ScriptLoader final : public nsISupports
|
||||
{
|
||||
class MOZ_STACK_CLASS AutoCurrentScriptUpdater
|
||||
{
|
||||
public:
|
||||
AutoCurrentScriptUpdater(nsScriptLoader* aScriptLoader,
|
||||
AutoCurrentScriptUpdater(ScriptLoader* aScriptLoader,
|
||||
nsIScriptElement* aCurrentScript)
|
||||
: mOldScript(aScriptLoader->mCurrentScript)
|
||||
, mScriptLoader(aScriptLoader)
|
||||
{
|
||||
mScriptLoader->mCurrentScript = aCurrentScript;
|
||||
}
|
||||
|
||||
~AutoCurrentScriptUpdater()
|
||||
{
|
||||
mScriptLoader->mCurrentScript.swap(mOldScript);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIScriptElement> mOldScript;
|
||||
nsScriptLoader* mScriptLoader;
|
||||
ScriptLoader* mScriptLoader;
|
||||
};
|
||||
|
||||
friend class nsModuleLoadRequest;
|
||||
friend class nsScriptRequestProcessor;
|
||||
friend class nsScriptLoadHandler;
|
||||
friend class ModuleLoadRequest;
|
||||
friend class ScriptRequestProcessor;
|
||||
friend class ScriptLoadHandler;
|
||||
friend class AutoCurrentScriptUpdater;
|
||||
|
||||
public:
|
||||
explicit nsScriptLoader(nsIDocument* aDocument);
|
||||
explicit ScriptLoader(nsIDocument* aDocument);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptLoader)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(ScriptLoader)
|
||||
|
||||
/**
|
||||
* The loader maintains a weak reference to the document with
|
||||
|
|
@ -390,6 +153,7 @@ public:
|
|||
{
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
void SetEnabled(bool aEnabled)
|
||||
{
|
||||
if (!mEnabled && aEnabled) {
|
||||
|
|
@ -407,6 +171,7 @@ public:
|
|||
{
|
||||
++mParserBlockingBlockerCount;
|
||||
}
|
||||
|
||||
void RemoveParserBlockingScriptExecutionBlocker()
|
||||
{
|
||||
if (!--mParserBlockingBlockerCount && ReadyToExecuteScripts()) {
|
||||
|
|
@ -422,6 +187,7 @@ public:
|
|||
{
|
||||
++mBlockerCount;
|
||||
}
|
||||
|
||||
void RemoveExecuteBlocker()
|
||||
{
|
||||
MOZ_ASSERT(mBlockerCount);
|
||||
|
|
@ -458,8 +224,8 @@ public:
|
|||
JS::UniqueTwoByteChars& aBufOut, size_t& aLengthOut)
|
||||
{
|
||||
char16_t* bufOut;
|
||||
nsresult rv = ConvertToUTF16(aChannel, aData, aLength, aHintCharset, aDocument,
|
||||
bufOut, aLengthOut);
|
||||
nsresult rv = ConvertToUTF16(aChannel, aData, aLength, aHintCharset,
|
||||
aDocument, bufOut, aLengthOut);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aBufOut.reset(bufOut);
|
||||
}
|
||||
|
|
@ -468,12 +234,12 @@ public:
|
|||
|
||||
/**
|
||||
* Handle the completion of a stream. This is called by the
|
||||
* nsScriptLoadHandler object which observes the IncrementalStreamLoader
|
||||
* ScriptLoadHandler object which observes the IncrementalStreamLoader
|
||||
* loading the script. The streamed content is expected to be stored on the
|
||||
* aRequest argument.
|
||||
*/
|
||||
nsresult OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
|
||||
nsScriptLoadRequest* aRequest,
|
||||
ScriptLoadRequest* aRequest,
|
||||
nsresult aChannelStatus,
|
||||
nsresult aSRIStatus,
|
||||
mozilla::dom::SRICheckDataVerifier* aSRIDataVerifier);
|
||||
|
|
@ -541,9 +307,10 @@ public:
|
|||
* Process a request that was deferred so that the script could be compiled
|
||||
* off thread.
|
||||
*/
|
||||
nsresult ProcessOffThreadRequest(nsScriptLoadRequest *aRequest);
|
||||
nsresult ProcessOffThreadRequest(ScriptLoadRequest* aRequest);
|
||||
|
||||
bool AddPendingChildLoader(nsScriptLoader* aChild) {
|
||||
bool AddPendingChildLoader(ScriptLoader* aChild)
|
||||
{
|
||||
return mPendingChildLoaders.AppendElement(aChild) != nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -560,10 +327,9 @@ public:
|
|||
void LoadEventFired();
|
||||
|
||||
private:
|
||||
virtual ~nsScriptLoader();
|
||||
virtual ~ScriptLoader();
|
||||
|
||||
nsScriptLoadRequest* CreateLoadRequest(
|
||||
nsScriptKind aKind,
|
||||
ScriptLoadRequest* CreateLoadRequest(ScriptKind aKind,
|
||||
nsIScriptElement* aElement,
|
||||
uint32_t aVersion,
|
||||
mozilla::CORSMode aCORSMode,
|
||||
|
|
@ -572,12 +338,12 @@ private:
|
|||
/**
|
||||
* Unblocks the creator parser of the parser-blocking scripts.
|
||||
*/
|
||||
void UnblockParser(nsScriptLoadRequest* aParserBlockingRequest);
|
||||
void UnblockParser(ScriptLoadRequest* aParserBlockingRequest);
|
||||
|
||||
/**
|
||||
* Asynchronously resumes the creator parser of the parser-blocking scripts.
|
||||
*/
|
||||
void ContinueParserAsync(nsScriptLoadRequest* aParserBlockingRequest);
|
||||
void ContinueParserAsync(ScriptLoadRequest* aParserBlockingRequest);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -592,14 +358,14 @@ private:
|
|||
/**
|
||||
* Start a load for aRequest's URI.
|
||||
*/
|
||||
nsresult StartLoad(nsScriptLoadRequest *aRequest);
|
||||
nsresult StartLoad(ScriptLoadRequest* aRequest);
|
||||
|
||||
/**
|
||||
* Abort the current stream, and re-start with a new load request from scratch
|
||||
* without requesting any alternate data. Returns NS_BINDING_RETARGETED on
|
||||
* success, as this error code is used to abort the input stream.
|
||||
*/
|
||||
nsresult RestartLoad(nsScriptLoadRequest *aRequest);
|
||||
nsresult RestartLoad(ScriptLoadRequest* aRequest);
|
||||
|
||||
/**
|
||||
* Process any pending requests asynchronously (i.e. off an event) if there
|
||||
|
|
@ -635,14 +401,14 @@ private:
|
|||
return mEnabled && !mBlockerCount;
|
||||
}
|
||||
|
||||
nsresult AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest);
|
||||
nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
|
||||
nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest);
|
||||
nsresult AttemptAsyncScriptCompile(ScriptLoadRequest* aRequest);
|
||||
nsresult ProcessRequest(ScriptLoadRequest* aRequest);
|
||||
nsresult CompileOffThreadOrProcessRequest(ScriptLoadRequest* aRequest);
|
||||
void FireScriptAvailable(nsresult aResult,
|
||||
nsScriptLoadRequest* aRequest);
|
||||
ScriptLoadRequest* aRequest);
|
||||
void FireScriptEvaluated(nsresult aResult,
|
||||
nsScriptLoadRequest* aRequest);
|
||||
nsresult EvaluateScript(nsScriptLoadRequest* aRequest);
|
||||
ScriptLoadRequest* aRequest);
|
||||
nsresult EvaluateScript(ScriptLoadRequest* aRequest);
|
||||
|
||||
/**
|
||||
* Queue the current script load request to be saved, when the page
|
||||
|
|
@ -650,7 +416,7 @@ private:
|
|||
* time when the load event got received, and when no more scripts are waiting
|
||||
* to be executed.
|
||||
*/
|
||||
void RegisterForBytecodeEncoding(nsScriptLoadRequest* aRequest);
|
||||
void RegisterForBytecodeEncoding(ScriptLoadRequest* aRequest);
|
||||
|
||||
/**
|
||||
* Check if all conditions are met, i-e that the onLoad event fired and that
|
||||
|
|
@ -664,94 +430,101 @@ private:
|
|||
* functions on the cache provided by the channel.
|
||||
*/
|
||||
void EncodeBytecode();
|
||||
void EncodeRequestBytecode(JSContext* aCx, nsScriptLoadRequest* aRequest);
|
||||
void EncodeRequestBytecode(JSContext* aCx, ScriptLoadRequest* aRequest);
|
||||
|
||||
void GiveUpBytecodeEncoding();
|
||||
|
||||
already_AddRefed<nsIScriptGlobalObject> GetScriptGlobalObject();
|
||||
nsresult FillCompileOptionsForRequest(const mozilla::dom::AutoJSAPI& jsapi,
|
||||
nsScriptLoadRequest* aRequest,
|
||||
ScriptLoadRequest* aRequest,
|
||||
JS::Handle<JSObject*> aScopeChain,
|
||||
JS::CompileOptions* aOptions);
|
||||
|
||||
uint32_t NumberOfProcessors();
|
||||
nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
|
||||
nsresult PrepareLoadedRequest(ScriptLoadRequest* aRequest,
|
||||
nsIIncrementalStreamLoader* aLoader,
|
||||
nsresult aStatus);
|
||||
|
||||
void AddDeferRequest(nsScriptLoadRequest* aRequest);
|
||||
void AddDeferRequest(ScriptLoadRequest* aRequest);
|
||||
bool MaybeRemovedDeferRequests();
|
||||
|
||||
void MaybeMoveToLoadedList(nsScriptLoadRequest* aRequest);
|
||||
void MaybeMoveToLoadedList(ScriptLoadRequest* aRequest);
|
||||
|
||||
JS::SourceBufferHolder GetScriptSource(nsScriptLoadRequest* aRequest,
|
||||
JS::SourceBufferHolder GetScriptSource(ScriptLoadRequest* aRequest,
|
||||
nsAutoString& inlineData);
|
||||
|
||||
bool ModuleScriptsEnabled();
|
||||
|
||||
void SetModuleFetchStarted(nsModuleLoadRequest *aRequest);
|
||||
void SetModuleFetchFinishedAndResumeWaitingRequests(nsModuleLoadRequest *aRequest,
|
||||
void SetModuleFetchStarted(ModuleLoadRequest *aRequest);
|
||||
void SetModuleFetchFinishedAndResumeWaitingRequests(ModuleLoadRequest* aRequest,
|
||||
nsresult aResult);
|
||||
|
||||
bool IsFetchingModule(nsModuleLoadRequest *aRequest) const;
|
||||
bool IsFetchingModule(ModuleLoadRequest* aRequest) const;
|
||||
|
||||
bool ModuleMapContainsModule(nsModuleLoadRequest *aRequest) const;
|
||||
RefPtr<mozilla::GenericPromise> WaitForModuleFetch(nsModuleLoadRequest *aRequest);
|
||||
nsModuleScript* GetFetchedModule(nsIURI* aURL) const;
|
||||
bool ModuleMapContainsModule(ModuleLoadRequest* aRequest) const;
|
||||
RefPtr<mozilla::GenericPromise> WaitForModuleFetch(ModuleLoadRequest* aRequest);
|
||||
ModuleScript* GetFetchedModule(nsIURI* aURL) const;
|
||||
|
||||
friend bool
|
||||
HostResolveImportedModule(JSContext* aCx, unsigned argc, JS::Value* vp);
|
||||
|
||||
nsresult CreateModuleScript(nsModuleLoadRequest* aRequest);
|
||||
nsresult ProcessFetchedModuleSource(nsModuleLoadRequest* aRequest);
|
||||
void ProcessLoadedModuleTree(nsModuleLoadRequest* aRequest);
|
||||
bool InstantiateModuleTree(nsModuleLoadRequest* aRequest);
|
||||
void StartFetchingModuleDependencies(nsModuleLoadRequest* aRequest);
|
||||
static bool
|
||||
IsBytecodeCacheEnabled();
|
||||
|
||||
nsresult CreateModuleScript(ModuleLoadRequest* aRequest);
|
||||
nsresult ProcessFetchedModuleSource(ModuleLoadRequest* aRequest);
|
||||
void ProcessLoadedModuleTree(ModuleLoadRequest* aRequest);
|
||||
bool InstantiateModuleTree(ModuleLoadRequest* aRequest);
|
||||
void StartFetchingModuleDependencies(ModuleLoadRequest* aRequest);
|
||||
|
||||
RefPtr<mozilla::GenericPromise>
|
||||
StartFetchingModuleAndDependencies(nsModuleLoadRequest* aRequest, nsIURI* aURI);
|
||||
StartFetchingModuleAndDependencies(ModuleLoadRequest* aRequest, nsIURI* aURI);
|
||||
|
||||
nsIDocument* mDocument; // [WEAK]
|
||||
nsCOMArray<nsIScriptLoaderObserver> mObservers;
|
||||
nsScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
|
||||
ScriptLoadRequestList mNonAsyncExternalScriptInsertedRequests;
|
||||
// mLoadingAsyncRequests holds async requests while they're loading; when they
|
||||
// have been loaded they are moved to mLoadedAsyncRequests.
|
||||
nsScriptLoadRequestList mLoadingAsyncRequests;
|
||||
nsScriptLoadRequestList mLoadedAsyncRequests;
|
||||
nsScriptLoadRequestList mDeferRequests;
|
||||
nsScriptLoadRequestList mXSLTRequests;
|
||||
RefPtr<nsScriptLoadRequest> mParserBlockingRequest;
|
||||
ScriptLoadRequestList mLoadingAsyncRequests;
|
||||
ScriptLoadRequestList mLoadedAsyncRequests;
|
||||
ScriptLoadRequestList mDeferRequests;
|
||||
ScriptLoadRequestList mXSLTRequests;
|
||||
RefPtr<ScriptLoadRequest> mParserBlockingRequest;
|
||||
|
||||
// List of script load request that are holding a buffer which has to be saved
|
||||
// on the cache.
|
||||
nsScriptLoadRequestList mBytecodeEncodingQueue;
|
||||
ScriptLoadRequestList mBytecodeEncodingQueue;
|
||||
|
||||
// In mRequests, the additional information here is stored by the element.
|
||||
struct PreloadInfo {
|
||||
RefPtr<nsScriptLoadRequest> mRequest;
|
||||
struct PreloadInfo
|
||||
{
|
||||
RefPtr<ScriptLoadRequest> mRequest;
|
||||
nsString mCharset;
|
||||
};
|
||||
|
||||
friend void ImplCycleCollectionUnlink(nsScriptLoader::PreloadInfo& aField);
|
||||
friend void ImplCycleCollectionUnlink(ScriptLoader::PreloadInfo& aField);
|
||||
friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
nsScriptLoader::PreloadInfo& aField,
|
||||
ScriptLoader::PreloadInfo& aField,
|
||||
const char* aName, uint32_t aFlags);
|
||||
|
||||
struct PreloadRequestComparator {
|
||||
bool Equals(const PreloadInfo &aPi, nsScriptLoadRequest * const &aRequest)
|
||||
const
|
||||
struct PreloadRequestComparator
|
||||
{
|
||||
bool Equals(const PreloadInfo& aPi, ScriptLoadRequest* const& aRequest) const
|
||||
{
|
||||
return aRequest == aPi.mRequest;
|
||||
}
|
||||
};
|
||||
struct PreloadURIComparator {
|
||||
|
||||
struct PreloadURIComparator
|
||||
{
|
||||
bool Equals(const PreloadInfo& aPi, nsIURI* const &aURI) const;
|
||||
};
|
||||
|
||||
nsTArray<PreloadInfo> mPreloads;
|
||||
|
||||
nsCOMPtr<nsIScriptElement> mCurrentScript;
|
||||
nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
|
||||
nsTArray< RefPtr<nsScriptLoader> > mPendingChildLoaders;
|
||||
nsTArray< RefPtr<ScriptLoader> > mPendingChildLoaders;
|
||||
uint32_t mParserBlockingBlockerCount;
|
||||
uint32_t mBlockerCount;
|
||||
uint32_t mNumberOfProcessors;
|
||||
|
|
@ -763,66 +536,13 @@ private:
|
|||
|
||||
// Module map
|
||||
nsRefPtrHashtable<nsURIHashKey, mozilla::GenericPromise::Private> mFetchingModules;
|
||||
nsRefPtrHashtable<nsURIHashKey, nsModuleScript> mFetchedModules;
|
||||
nsRefPtrHashtable<nsURIHashKey, ModuleScript> mFetchedModules;
|
||||
|
||||
nsCOMPtr<nsIConsoleReportCollector> mReporter;
|
||||
};
|
||||
|
||||
class nsScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver
|
||||
{
|
||||
public:
|
||||
explicit nsScriptLoadHandler(nsScriptLoader* aScriptLoader,
|
||||
nsScriptLoadRequest *aRequest,
|
||||
mozilla::dom::SRICheckDataVerifier *aSRIDataVerifier);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
|
||||
|
||||
private:
|
||||
virtual ~nsScriptLoadHandler();
|
||||
|
||||
/*
|
||||
* Once the charset is found by the EnsureDecoder function, we can
|
||||
* incrementally convert the charset to the one expected by the JS Parser.
|
||||
*/
|
||||
nsresult DecodeRawData(const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream);
|
||||
|
||||
/*
|
||||
* Discover the charset by looking at the stream data, the script
|
||||
* tag, and other indicators. Returns true if charset has been
|
||||
* discovered.
|
||||
*/
|
||||
bool EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
|
||||
const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream);
|
||||
bool EnsureDecoder(nsIIncrementalStreamLoader *aLoader,
|
||||
const uint8_t* aData, uint32_t aDataLength,
|
||||
bool aEndOfStream, nsCString& oCharset);
|
||||
|
||||
/*
|
||||
* When streaming bytecode, we have the opportunity to fallback early if SRI
|
||||
* does not match the expectation of the document.
|
||||
*/
|
||||
nsresult MaybeDecodeSRI();
|
||||
|
||||
// Query the channel to find the data type associated with the input stream.
|
||||
nsresult EnsureKnownDataType(nsIIncrementalStreamLoader *aLoader);
|
||||
|
||||
// ScriptLoader which will handle the parsed script.
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
|
||||
// The nsScriptLoadRequest for this load. Decoded data are accumulated on it.
|
||||
RefPtr<nsScriptLoadRequest> mRequest;
|
||||
|
||||
// SRI data verifier.
|
||||
nsAutoPtr<mozilla::dom::SRICheckDataVerifier> mSRIDataVerifier;
|
||||
|
||||
// Status of SRI data operations.
|
||||
nsresult mSRIStatus;
|
||||
|
||||
// Unicode decoder for charset.
|
||||
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
|
||||
// Logging
|
||||
static LazyLogModule gCspPRLog;
|
||||
static LazyLogModule gScriptLoaderLog;
|
||||
};
|
||||
|
||||
class nsAutoScriptLoaderDisabler
|
||||
|
|
@ -845,7 +565,10 @@ public:
|
|||
}
|
||||
|
||||
bool mWasEnabled;
|
||||
RefPtr<nsScriptLoader> mLoader;
|
||||
RefPtr<ScriptLoader> mLoader;
|
||||
};
|
||||
|
||||
#endif //__nsScriptLoader_h__
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ScriptLoader_h
|
||||
|
|
@ -29,13 +29,15 @@ namespace dom {
|
|||
static MOZ_THREAD_LOCAL(ScriptSettingsStackEntry*) sScriptSettingsTLS;
|
||||
static bool sScriptSettingsTLSInitialized;
|
||||
|
||||
class ScriptSettingsStack {
|
||||
class ScriptSettingsStack
|
||||
{
|
||||
public:
|
||||
static ScriptSettingsStackEntry* Top() {
|
||||
return sScriptSettingsTLS.get();
|
||||
}
|
||||
|
||||
static void Push(ScriptSettingsStackEntry *aEntry) {
|
||||
static void Push(ScriptSettingsStackEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(!aEntry->mOlder);
|
||||
// Whenever JSAPI use is disabled, the next stack entry pushed must
|
||||
// not be an AutoIncumbentScript.
|
||||
|
|
@ -50,12 +52,14 @@ public:
|
|||
sScriptSettingsTLS.set(aEntry);
|
||||
}
|
||||
|
||||
static void Pop(ScriptSettingsStackEntry *aEntry) {
|
||||
static void Pop(ScriptSettingsStackEntry* aEntry)
|
||||
{
|
||||
MOZ_ASSERT(aEntry == Top());
|
||||
sScriptSettingsTLS.set(aEntry->mOlder);
|
||||
}
|
||||
|
||||
static nsIGlobalObject* IncumbentGlobal() {
|
||||
static nsIGlobalObject* IncumbentGlobal()
|
||||
{
|
||||
ScriptSettingsStackEntry* entry = Top();
|
||||
while (entry) {
|
||||
if (entry->IsIncumbentCandidate()) {
|
||||
|
|
@ -66,7 +70,8 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static ScriptSettingsStackEntry* EntryPoint() {
|
||||
static ScriptSettingsStackEntry* EntryPoint()
|
||||
{
|
||||
ScriptSettingsStackEntry* entry = Top();
|
||||
while (entry) {
|
||||
if (entry->IsEntryCandidate()) {
|
||||
|
|
@ -77,7 +82,8 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static nsIGlobalObject* EntryGlobal() {
|
||||
static nsIGlobalObject* EntryGlobal()
|
||||
{
|
||||
ScriptSettingsStackEntry* entry = EntryPoint();
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
|
|
@ -86,7 +92,8 @@ public:
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static ScriptSettingsStackEntry* TopNonIncumbentScript() {
|
||||
static ScriptSettingsStackEntry* TopNonIncumbentScript()
|
||||
{
|
||||
ScriptSettingsStackEntry* entry = Top();
|
||||
while (entry) {
|
||||
if (!entry->IsIncumbentScript()) {
|
||||
41
dom/script/ScriptTrace.cpp
Normal file
41
dom/script/ScriptTrace.cpp
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "ScriptTrace.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace script {
|
||||
|
||||
static nsresult
|
||||
TestingDispatchEvent(nsIScriptElement* aScriptElement,
|
||||
const nsAString& aEventType)
|
||||
{
|
||||
static bool sExposeTestInterfaceEnabled = false;
|
||||
static bool sExposeTestInterfacePrefCached = false;
|
||||
if (!sExposeTestInterfacePrefCached) {
|
||||
sExposeTestInterfacePrefCached = true;
|
||||
Preferences::AddBoolVarCache(&sExposeTestInterfaceEnabled,
|
||||
"dom.expose_test_interfaces",
|
||||
false);
|
||||
}
|
||||
if (!sExposeTestInterfaceEnabled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> target(do_QueryInterface(aScriptElement));
|
||||
if (!target) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<AsyncEventDispatcher> dispatcher =
|
||||
new AsyncEventDispatcher(target, aEventType, true, false);
|
||||
return dispatcher->PostDOMEvent();
|
||||
}
|
||||
|
||||
} // script namespace
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
46
dom/script/ScriptTrace.h
Normal file
46
dom/script/ScriptTrace.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_dom_ScriptTrace_h
|
||||
#define mozilla_dom_ScriptTrace_h
|
||||
|
||||
#include "ScriptLoader.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace script {
|
||||
|
||||
// This macro is used to wrap a tracing mechanism which is scheduling events
|
||||
// which are then used by the JavaScript code of test cases to track the code
|
||||
// path to verify the optimizations are working as expected.
|
||||
#define TRACE_FOR_TEST(elem, str) \
|
||||
PR_BEGIN_MACRO \
|
||||
nsresult rv = NS_OK; \
|
||||
rv = script::TestingDispatchEvent(elem, NS_LITERAL_STRING(str)); \
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
PR_END_MACRO
|
||||
|
||||
#define TRACE_FOR_TEST_BOOL(elem, str) \
|
||||
PR_BEGIN_MACRO \
|
||||
nsresult rv = NS_OK; \
|
||||
rv = script::TestingDispatchEvent(elem, NS_LITERAL_STRING(str)); \
|
||||
NS_ENSURE_SUCCESS(rv, false); \
|
||||
PR_END_MACRO
|
||||
|
||||
#define TRACE_FOR_TEST_NONE(elem, str) \
|
||||
PR_BEGIN_MACRO \
|
||||
script::TestingDispatchEvent(elem, NS_LITERAL_STRING(str)); \
|
||||
PR_END_MACRO
|
||||
|
||||
static nsresult
|
||||
TestingDispatchEvent(nsIScriptElement* aScriptElement,
|
||||
const nsAString& aEventType);
|
||||
|
||||
} // script namespace
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_ScriptTrace_h
|
||||
45
dom/script/moz.build
Normal file
45
dom/script/moz.build
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Core", "DOM")
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIScriptLoaderObserver.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom'
|
||||
|
||||
EXPORTS += [
|
||||
'nsIScriptElement.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'ScriptElement.h',
|
||||
'ScriptLoader.h',
|
||||
'ScriptLoadRequest.h',
|
||||
'ScriptSettings.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'ModuleLoadRequest.cpp',
|
||||
'ModuleScript.cpp',
|
||||
'ScriptElement.cpp',
|
||||
'ScriptLoader.cpp',
|
||||
'ScriptLoadHandler.cpp',
|
||||
'ScriptLoadRequest.cpp',
|
||||
'ScriptSettings.cpp',
|
||||
'ScriptTrace.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/dom/workers',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue