mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 05:15:45 +00:00
Merge m-c to fig.
This commit is contained in:
commit
988f90b952
@ -94,6 +94,9 @@ ifdef ENABLE_TESTS
|
||||
include $(topsrcdir)/testing/testsuite-targets.mk
|
||||
endif
|
||||
|
||||
# Hacky way for precompile tier to bypass default tier traversal mechanism.
|
||||
TIER_precompile_CUSTOM := 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
distclean::
|
||||
|
@ -509,6 +509,14 @@ UpdatePrompt.prototype = {
|
||||
this._applyPromptTimer = null;
|
||||
this.finishUpdate();
|
||||
this._update = null;
|
||||
return;
|
||||
}
|
||||
if (aTimer == this._watchdogTimer) {
|
||||
log("Download watchdog fired");
|
||||
this._watchdogTimer = null;
|
||||
this._autoRestartDownload = true;
|
||||
Services.aus.pauseDownload();
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
@ -523,26 +531,29 @@ UpdatePrompt.prototype = {
|
||||
_startedSent: false,
|
||||
|
||||
_watchdogTimer: null,
|
||||
_watchdogTimeout: 0,
|
||||
|
||||
_autoRestartDownload: false,
|
||||
_autoRestartCount: 0,
|
||||
|
||||
watchdogTimerFired: function UP_watchdogTimerFired() {
|
||||
log("Download watchdog fired");
|
||||
this._autoRestartDownload = true;
|
||||
Services.aus.pauseDownload();
|
||||
},
|
||||
|
||||
startWatchdogTimer: function UP_startWatchdogTimer() {
|
||||
let watchdogTimeout = 120000; // 120 seconds
|
||||
try {
|
||||
watchdogTimeout = Services.prefs.getIntPref(PREF_DOWNLOAD_WATCHDOG_TIMEOUT);
|
||||
} catch (e) {
|
||||
// This means that the preference doesn't exist. watchdogTimeout will
|
||||
// retain its default assigned above.
|
||||
}
|
||||
if (watchdogTimeout <= 0) {
|
||||
// 0 implies don't bother using the watchdog timer at all.
|
||||
this._watchdogTimer = null;
|
||||
return;
|
||||
}
|
||||
if (this._watchdogTimer) {
|
||||
this._watchdogTimer.cancel();
|
||||
} else {
|
||||
this._watchdogTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this._watchdogTimeout = Services.prefs.getIntPref(PREF_DOWNLOAD_WATCHDOG_TIMEOUT);
|
||||
}
|
||||
this._watchdogTimer.initWithCallback(this.watchdogTimerFired.bind(this),
|
||||
this._watchdogTimeout,
|
||||
this._watchdogTimer.initWithCallback(this, watchdogTimeout,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "f98ec5e292dffd144f0a6520cc18ff5cb7762d09",
|
||||
"revision": "dbaee540a7d23d271e62e7da80d7db226be8860b",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ pref("browser.download.manager.scanWhenDone", true);
|
||||
pref("browser.download.manager.resumeOnWakeDelay", 10000);
|
||||
|
||||
// Enables the asynchronous Downloads API in the Downloads Panel.
|
||||
pref("browser.download.useJSTransfer", true);
|
||||
pref("browser.download.useJSTransfer", false);
|
||||
|
||||
// This allows disabling the Downloads Panel in favor of the old interface.
|
||||
pref("browser.download.useToolkitUI", false);
|
||||
|
@ -87,8 +87,7 @@ Sanitizer.prototype = {
|
||||
item.clear();
|
||||
} catch(er) {
|
||||
seenError = true;
|
||||
Components.utils.reportError("Error sanitizing " + itemName +
|
||||
": " + er + "\n");
|
||||
Cu.reportError("Error sanitizing " + itemName + ": " + er + "\n");
|
||||
}
|
||||
onItemComplete();
|
||||
};
|
||||
@ -322,7 +321,7 @@ Sanitizer.prototype = {
|
||||
|
||||
let privateList = yield Downloads.getPrivateDownloadList();
|
||||
privateList.removeFinished(filterByTime);
|
||||
}.bind(this)).then(null, Components.utils.reportError);
|
||||
}.bind(this)).then(null, Cu.reportError);
|
||||
}
|
||||
else {
|
||||
var dlMgr = Components.classes["@mozilla.org/download-manager;1"]
|
||||
|
@ -4,6 +4,8 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||
// Bug 453440 - Test the timespan-based logic of the sanitizer code
|
||||
var now_uSec = Date.now() * 1000;
|
||||
|
||||
const dm = Cc["@mozilla.org/download-manager;1"].getService(Ci.nsIDownloadManager);
|
||||
|
||||
const kUsecPerMin = 60 * 1000000;
|
||||
|
||||
let tempScope = {};
|
||||
@ -12,7 +14,6 @@ Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
|
||||
let Sanitizer = tempScope.Sanitizer;
|
||||
|
||||
let FormHistory = (Components.utils.import("resource://gre/modules/FormHistory.jsm", {})).FormHistory;
|
||||
let Downloads = (Components.utils.import("resource://gre/modules/Downloads.jsm", {})).Downloads;
|
||||
|
||||
function promiseFormHistoryRemoved() {
|
||||
let deferred = Promise.defer();
|
||||
@ -23,26 +24,11 @@ function promiseFormHistoryRemoved() {
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promiseDownloadRemoved(list) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let view = {
|
||||
onDownloadRemoved: function(download) {
|
||||
list.removeView(view);
|
||||
deferred.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
list.addView(view);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
Task.spawn(function() {
|
||||
yield setupDownloads();
|
||||
setupDownloads();
|
||||
yield setupFormHistory();
|
||||
yield setupHistory();
|
||||
yield onHistoryReady();
|
||||
@ -94,16 +80,12 @@ function onHistoryReady() {
|
||||
itemPrefs.setBoolPref("sessions", false);
|
||||
itemPrefs.setBoolPref("siteSettings", false);
|
||||
|
||||
let publicList = yield Downloads.getPublicDownloadList();
|
||||
let downloadPromise = promiseDownloadRemoved(publicList);
|
||||
|
||||
// Clear 10 minutes ago
|
||||
s.range = [now_uSec - 10*60*1000000, now_uSec];
|
||||
s.sanitize();
|
||||
s.range = null;
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://10minutes.com"))),
|
||||
"Pretend visit to 10minutes.com should now be deleted");
|
||||
@ -140,27 +122,23 @@ function onHistoryReady() {
|
||||
yield countEntries("today", "today form entry should still exist", checkOne);
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
|
||||
let downloads = yield publicList.getAll();
|
||||
ok(!(yield downloadExists(publicList, "fakefile-10-minutes")), "10 minute download should now be deleted");
|
||||
ok((yield downloadExists(publicList, "fakefile-1-hour")), "<1 hour download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-1-hour-10-minutes")), "1 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour")), "<2 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour-10-minutes")), "2 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour")), "<4 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "4 hour 10 minute download should still be present");
|
||||
ok(!downloadExists(5555555), "10 minute download should now be deleted");
|
||||
ok(downloadExists(5555551), "<1 hour download should still be present");
|
||||
ok(downloadExists(5555556), "1 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
ok(downloadExists(5555552), "<2 hour old download should still be present");
|
||||
ok(downloadExists(5555557), "2 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555553), "<4 hour old download should still be present");
|
||||
ok(downloadExists(5555558), "4 hour 10 minute download should still be present");
|
||||
|
||||
if (minutesSinceMidnight > 10)
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "'Today' download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
ok(downloadExists(5555554), "'Today' download should still be present");
|
||||
|
||||
// Clear 1 hour
|
||||
Sanitizer.prefs.setIntPref("timeSpan", 1);
|
||||
s.sanitize();
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://1hour.com"))),
|
||||
"Pretend visit to 1hour.com should now be deleted");
|
||||
@ -191,26 +169,23 @@ function onHistoryReady() {
|
||||
yield countEntries("today", "today form entry should still exist", checkOne);
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
|
||||
ok(!(yield downloadExists(publicList, "fakefile-1-hour")), "<1 hour download should now be deleted");
|
||||
ok((yield downloadExists(publicList, "fakefile-1-hour-10-minutes")), "1 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour")), "<2 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour-10-minutes")), "2 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour")), "<4 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "4 hour 10 minute download should still be present");
|
||||
ok(!downloadExists(5555551), "<1 hour download should now be deleted");
|
||||
ok(downloadExists(5555556), "1 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
ok(downloadExists(5555552), "<2 hour old download should still be present");
|
||||
ok(downloadExists(5555557), "2 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555553), "<4 hour old download should still be present");
|
||||
ok(downloadExists(5555558), "4 hour 10 minute download should still be present");
|
||||
|
||||
if (hoursSinceMidnight > 1)
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "'Today' download should still be present");
|
||||
ok(downloadExists(5555554), "'Today' download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
|
||||
// Clear 1 hour 10 minutes
|
||||
s.range = [now_uSec - 70*60*1000000, now_uSec];
|
||||
s.sanitize();
|
||||
s.range = null;
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://1hour10minutes.com"))),
|
||||
"Pretend visit to 1hour10minutes.com should now be deleted");
|
||||
@ -238,23 +213,20 @@ function onHistoryReady() {
|
||||
yield countEntries("today", "today form entry should still exist", checkOne);
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
|
||||
ok(!(yield downloadExists(publicList, "fakefile-1-hour-10-minutes")), "1 hour 10 minute old download should now be deleted");
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour")), "<2 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour-10-minutes")), "2 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour")), "<4 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "4 hour 10 minute download should still be present");
|
||||
ok(!downloadExists(5555556), "1 hour 10 minute old download should now be deleted");
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
ok(downloadExists(5555552), "<2 hour old download should still be present");
|
||||
ok(downloadExists(5555557), "2 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555553), "<4 hour old download should still be present");
|
||||
ok(downloadExists(5555558), "4 hour 10 minute download should still be present");
|
||||
if (minutesSinceMidnight > 70)
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "'Today' download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
ok(downloadExists(5555554), "'Today' download should still be present");
|
||||
|
||||
// Clear 2 hours
|
||||
Sanitizer.prefs.setIntPref("timeSpan", 2);
|
||||
s.sanitize();
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://2hour.com"))),
|
||||
"Pretend visit to 2hour.com should now be deleted");
|
||||
@ -279,23 +251,20 @@ function onHistoryReady() {
|
||||
yield countEntries("today", "today form entry should still exist", checkOne);
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
|
||||
ok(!(yield downloadExists(publicList, "fakefile-2-hour")), "<2 hour old download should now be deleted");
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour-10-minutes")), "2 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour")), "<4 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "4 hour 10 minute download should still be present");
|
||||
ok(!downloadExists(5555552), "<2 hour old download should now be deleted");
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
ok(downloadExists(5555557), "2 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555553), "<4 hour old download should still be present");
|
||||
ok(downloadExists(5555558), "4 hour 10 minute download should still be present");
|
||||
if (hoursSinceMidnight > 2)
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "'Today' download should still be present");
|
||||
ok(downloadExists(5555554), "'Today' download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
|
||||
// Clear 2 hours 10 minutes
|
||||
s.range = [now_uSec - 130*60*1000000, now_uSec];
|
||||
s.sanitize();
|
||||
s.range = null;
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://2hour10minutes.com"))),
|
||||
"Pretend visit to 2hour10minutes.com should now be deleted");
|
||||
@ -317,21 +286,18 @@ function onHistoryReady() {
|
||||
yield countEntries("today", "today form entry should still exist", checkOne);
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
|
||||
ok(!(yield downloadExists(publicList, "fakefile-2-hour-10-minutes")), "2 hour 10 minute old download should now be deleted");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour")), "<4 hour old download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "4 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
ok(!downloadExists(5555557), "2 hour 10 minute old download should now be deleted");
|
||||
ok(downloadExists(5555553), "<4 hour old download should still be present");
|
||||
ok(downloadExists(5555558), "4 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
if (minutesSinceMidnight > 130)
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "'Today' download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
ok(downloadExists(5555554), "'Today' download should still be present");
|
||||
|
||||
// Clear 4 hours
|
||||
Sanitizer.prefs.setIntPref("timeSpan", 3);
|
||||
s.sanitize();
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://4hour.com"))),
|
||||
"Pretend visit to 4hour.com should now be deleted");
|
||||
@ -350,13 +316,11 @@ function onHistoryReady() {
|
||||
yield countEntries("today", "today form entry should still exist", checkOne);
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
|
||||
ok(!(yield downloadExists(publicList, "fakefile-4-hour")), "<4 hour old download should now be deleted");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "4 hour 10 minute download should still be present");
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
ok(!downloadExists(5555553), "<4 hour old download should now be deleted");
|
||||
ok(downloadExists(5555558), "4 hour 10 minute download should still be present");
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
if (hoursSinceMidnight > 4)
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "'Today' download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
ok(downloadExists(5555554), "'Today' download should still be present");
|
||||
|
||||
// Clear 4 hours 10 minutes
|
||||
s.range = [now_uSec - 250*60*1000000, now_uSec];
|
||||
@ -364,7 +328,6 @@ function onHistoryReady() {
|
||||
s.range = null;
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://4hour10minutes.com"))),
|
||||
"Pretend visit to 4hour10minutes.com should now be deleted");
|
||||
@ -380,19 +343,16 @@ function onHistoryReady() {
|
||||
yield countEntries("today", "today form entry should still exist", checkOne);
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
|
||||
ok(!(yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "4 hour 10 minute download should now be deleted");
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
ok(!downloadExists(5555558), "4 hour 10 minute download should now be deleted");
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
if (minutesSinceMidnight > 250)
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "'Today' download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
ok(downloadExists(5555554), "'Today' download should still be present");
|
||||
|
||||
// Clear Today
|
||||
Sanitizer.prefs.setIntPref("timeSpan", 4);
|
||||
s.sanitize();
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
// Be careful. If we add our objectss just before midnight, and sanitize
|
||||
// runs immediately after, they won't be expired. This is expected, but
|
||||
@ -405,29 +365,26 @@ function onHistoryReady() {
|
||||
"Pretend visit to today.com should now be deleted");
|
||||
|
||||
yield countEntries("today", "today form entry should be deleted", checkZero);
|
||||
ok(!(yield downloadExists(publicList, "fakefile-today")), "'Today' download should now be deleted");
|
||||
ok(!downloadExists(5555554), "'Today' download should now be deleted");
|
||||
}
|
||||
|
||||
ok((yield promiseIsURIVisited(makeURI("http://before-today.com"))),
|
||||
"Pretend visit to before-today.com should still exist");
|
||||
yield countEntries("b4today", "b4today form entry should still exist", checkOne);
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Year old download should still be present");
|
||||
|
||||
downloadPromise = promiseDownloadRemoved(publicList);
|
||||
ok(downloadExists(5555550), "Year old download should still be present");
|
||||
|
||||
// Choose everything
|
||||
Sanitizer.prefs.setIntPref("timeSpan", 0);
|
||||
s.sanitize();
|
||||
|
||||
yield promiseFormHistoryRemoved();
|
||||
yield downloadPromise;
|
||||
|
||||
ok(!(yield promiseIsURIVisited(makeURI("http://before-today.com"))),
|
||||
"Pretend visit to before-today.com should now be deleted");
|
||||
|
||||
yield countEntries("b4today", "b4today form entry should be deleted", checkZero);
|
||||
|
||||
ok(!(yield downloadExists(publicList, "fakefile-old")), "Year old download should now be deleted");
|
||||
ok(!downloadExists(5555550), "Year old download should now be deleted");
|
||||
}
|
||||
|
||||
function setupHistory() {
|
||||
@ -605,103 +562,227 @@ function setupFormHistory() {
|
||||
|
||||
function setupDownloads() {
|
||||
|
||||
let publicList = yield Downloads.getPublicDownloadList();
|
||||
|
||||
let download = yield Downloads.createDownload({
|
||||
// Add 10-minutes download to DB
|
||||
let data = {
|
||||
id: "5555555",
|
||||
name: "fakefile-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-10-minutes"
|
||||
});
|
||||
download.startTime = new Date(now_uSec - 10 * kUsecPerMin), // 10 minutes ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-10-minutes",
|
||||
startTime: now_uSec - 10 * kUsecPerMin, // 10 minutes ago, in uSec
|
||||
endTime: now_uSec - 11 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "a1bcD23eF4g5"
|
||||
};
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
let db = dm.DBConnection;
|
||||
let stmt = db.createStatement(
|
||||
"INSERT INTO moz_downloads (id, name, source, target, startTime, endTime, " +
|
||||
"state, currBytes, maxBytes, preferredAction, autoResume, guid) " +
|
||||
"VALUES (:id, :name, :source, :target, :startTime, :endTime, :state, " +
|
||||
":currBytes, :maxBytes, :preferredAction, :autoResume, :guid)");
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add within-1-hour download to DB
|
||||
data = {
|
||||
id: "5555551",
|
||||
name: "fakefile-1-hour",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-1-hour"
|
||||
});
|
||||
download.startTime = new Date(now_uSec - 45 * kUsecPerMin), // 45 minutes ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-1-hour",
|
||||
startTime: now_uSec - 45 * kUsecPerMin, // 45 minutes ago, in uSec
|
||||
endTime: now_uSec - 44 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "1bcD23eF4g5a"
|
||||
};
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add 1-hour-10-minutes download to DB
|
||||
data = {
|
||||
id: "5555556",
|
||||
name: "fakefile-1-hour-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-1-hour-10-minutes"
|
||||
});
|
||||
download.startTime = new Date(now_uSec - 70 * kUsecPerMin), // 70 minutes ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-1-hour-10-minutes",
|
||||
startTime: now_uSec - 70 * kUsecPerMin, // 70 minutes ago, in uSec
|
||||
endTime: now_uSec - 71 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "a1cbD23e4Fg5"
|
||||
};
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add within-2-hour download
|
||||
data = {
|
||||
id: "5555552",
|
||||
name: "fakefile-2-hour",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-2-hour"
|
||||
});
|
||||
download.startTime = new Date(now_uSec - 90 * kUsecPerMin), // 90 minutes ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-2-hour",
|
||||
startTime: now_uSec - 90 * kUsecPerMin, // 90 minutes ago, in uSec
|
||||
endTime: now_uSec - 89 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "b1aDc23eFg54"
|
||||
};
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add 2-hour-10-minutes download
|
||||
data = {
|
||||
id: "5555557",
|
||||
name: "fakefile-2-hour-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-2-hour-10-minutes"
|
||||
});
|
||||
download.startTime = new Date(now_uSec - 130 * kUsecPerMin), // 130 minutes ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-2-hour-10-minutes",
|
||||
startTime: now_uSec - 130 * kUsecPerMin, // 130 minutes ago, in uSec
|
||||
endTime: now_uSec - 131 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "z1bcD23eF4g5"
|
||||
};
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add within-4-hour download
|
||||
data = {
|
||||
id: "5555553",
|
||||
name: "fakefile-4-hour",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-4-hour"
|
||||
});
|
||||
download.startTime = new Date(now_uSec - 180 * kUsecPerMin), // 180 minutes ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
target: "fakefile-4-hour",
|
||||
startTime: now_uSec - 180 * kUsecPerMin, // 180 minutes ago, in uSec
|
||||
endTime: now_uSec - 179 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "zzzcD23eF4g5"
|
||||
};
|
||||
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add 4-hour-10-minutes download
|
||||
data = {
|
||||
id: "5555558",
|
||||
name: "fakefile-4-hour-10-minutes",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: "fakefile-4-hour-10-minutes"
|
||||
});
|
||||
download.startTime = new Date(now_uSec - 250 * kUsecPerMin), // 250 minutes ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-4-hour-10-minutes",
|
||||
startTime: now_uSec - 250 * kUsecPerMin, // 250 minutes ago, in uSec
|
||||
endTime: now_uSec - 251 * kUsecPerMin, // 1 minute later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "z1bzz23eF4gz"
|
||||
};
|
||||
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add "today" download
|
||||
let today = new Date();
|
||||
today.setHours(0);
|
||||
today.setMinutes(0);
|
||||
today.setSeconds(1);
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
|
||||
data = {
|
||||
id: "5555554",
|
||||
name: "fakefile-today",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-today"
|
||||
});
|
||||
download.startTime = new Date(today.getTime() * 1000), // 12:00:30am this morning, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-today",
|
||||
startTime: today.getTime() * 1000, // 12:00:30am this morning, in uSec
|
||||
endTime: (today.getTime() + 1000) * 1000, // 1 second later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "ffffD23eF4g5"
|
||||
};
|
||||
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
// Add "before today" download
|
||||
let lastYear = new Date();
|
||||
lastYear.setFullYear(lastYear.getFullYear() - 1);
|
||||
|
||||
download = yield Downloads.createDownload({
|
||||
data = {
|
||||
id: "5555550",
|
||||
name: "fakefile-old",
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
|
||||
target: "fakefile-old"
|
||||
});
|
||||
download.startTime = new Date(lastYear.getTime() * 1000), // 1 year ago, in uSec
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
target: "fakefile-old",
|
||||
startTime: lastYear.getTime() * 1000, // 1 year ago, in uSec
|
||||
endTime: (lastYear.getTime() + 1000) * 1000, // 1 second later
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0,
|
||||
guid: "ggggg23eF4g5"
|
||||
};
|
||||
|
||||
try {
|
||||
for (let prop in data)
|
||||
stmt.params[prop] = data[prop];
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
|
||||
// Confirm everything worked
|
||||
let downloads = yield publicList.getAll();
|
||||
is(downloads.length, 9, "9 Pretend downloads added");
|
||||
|
||||
ok((yield downloadExists(publicList, "fakefile-old")), "Pretend download for everything case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-10-minutes")), "Pretend download for 10-minutes case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-1-hour")), "Pretend download for 1-hour case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-1-hour-10-minutes")), "Pretend download for 1-hour-10-minutes case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour")), "Pretend download for 2-hour case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-2-hour-10-minutes")), "Pretend download for 2-hour-10-minutes case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour")), "Pretend download for 4-hour case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-4-hour-10-minutes")), "Pretend download for 4-hour-10-minutes case should exist");
|
||||
ok((yield downloadExists(publicList, "fakefile-today")), "Pretend download for Today case should exist");
|
||||
ok(downloadExists(5555550), "Pretend download for everything case should exist");
|
||||
ok(downloadExists(5555555), "Pretend download for 10-minutes case should exist");
|
||||
ok(downloadExists(5555551), "Pretend download for 1-hour case should exist");
|
||||
ok(downloadExists(5555556), "Pretend download for 1-hour-10-minutes case should exist");
|
||||
ok(downloadExists(5555552), "Pretend download for 2-hour case should exist");
|
||||
ok(downloadExists(5555557), "Pretend download for 2-hour-10-minutes case should exist");
|
||||
ok(downloadExists(5555553), "Pretend download for 4-hour case should exist");
|
||||
ok(downloadExists(5555558), "Pretend download for 4-hour-10-minutes case should exist");
|
||||
ok(downloadExists(5555554), "Pretend download for Today case should exist");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -710,12 +791,18 @@ function setupDownloads() {
|
||||
* @param aID
|
||||
* The ids of the downloads to check.
|
||||
*/
|
||||
function downloadExists(list, path)
|
||||
function downloadExists(aID)
|
||||
{
|
||||
return Task.spawn(function() {
|
||||
let listArray = yield list.getAll();
|
||||
throw new Task.Result(listArray.some(i => i.target.path == path));
|
||||
});
|
||||
let db = dm.DBConnection;
|
||||
let stmt = db.createStatement(
|
||||
"SELECT * " +
|
||||
"FROM moz_downloads " +
|
||||
"WHERE id = :id"
|
||||
);
|
||||
stmt.params.id = aID;
|
||||
var rows = stmt.executeStep();
|
||||
stmt.finalize();
|
||||
return rows;
|
||||
}
|
||||
|
||||
function isToday(aDate) {
|
||||
|
@ -21,17 +21,18 @@ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FormHistory",
|
||||
"resource://gre/modules/FormHistory.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
|
||||
"resource://gre/modules/Downloads.jsm");
|
||||
|
||||
let tempScope = {};
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://browser/content/sanitize.js", tempScope);
|
||||
let Sanitizer = tempScope.Sanitizer;
|
||||
|
||||
const dm = Cc["@mozilla.org/download-manager;1"].
|
||||
getService(Ci.nsIDownloadManager);
|
||||
|
||||
const kUsecPerMin = 60 * 1000000;
|
||||
|
||||
let formEntries, downloadIDs, olderDownloadIDs;
|
||||
let formEntries;
|
||||
|
||||
// Add tests here. Each is a function that's called by doNextTest().
|
||||
var gAllTests = [
|
||||
@ -91,23 +92,6 @@ var gAllTests = [
|
||||
});
|
||||
},
|
||||
|
||||
function () {
|
||||
// Add downloads (within the past hour).
|
||||
Task.spawn(function () {
|
||||
downloadIDs = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
yield addDownloadWithMinutesAgo(downloadIDs, i);
|
||||
}
|
||||
// Add downloads (over an hour ago).
|
||||
olderDownloadIDs = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
yield addDownloadWithMinutesAgo(olderDownloadIDs, 61 + i);
|
||||
}
|
||||
|
||||
doNextTest();
|
||||
}).then(null, Components.utils.reportError);
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensures that the combined history-downloads checkbox clears both history
|
||||
* visits and downloads when checked; the dialog respects simple timespan.
|
||||
@ -131,6 +115,16 @@ var gAllTests = [
|
||||
}
|
||||
|
||||
addVisits(places, function() {
|
||||
// Add downloads (within the past hour).
|
||||
let downloadIDs = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
downloadIDs.push(addDownloadWithMinutesAgo(i));
|
||||
}
|
||||
// Add downloads (over an hour ago).
|
||||
let olderDownloadIDs = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
olderDownloadIDs.push(addDownloadWithMinutesAgo(61 + i));
|
||||
}
|
||||
let totalHistoryVisits = uris.length + olderURIs.length;
|
||||
|
||||
let wh = new WindowHelper();
|
||||
@ -152,16 +146,16 @@ var gAllTests = [
|
||||
wh.onunload = function () {
|
||||
// History visits and downloads within one hour should be cleared.
|
||||
yield promiseHistoryClearedState(uris, true);
|
||||
yield ensureDownloadsClearedState(downloadIDs, true);
|
||||
ensureDownloadsClearedState(downloadIDs, true);
|
||||
|
||||
// Visits and downloads > 1 hour should still exist.
|
||||
yield promiseHistoryClearedState(olderURIs, false);
|
||||
yield ensureDownloadsClearedState(olderDownloadIDs, false);
|
||||
ensureDownloadsClearedState(olderDownloadIDs, false);
|
||||
|
||||
// OK, done, cleanup after ourselves.
|
||||
yield blankSlate();
|
||||
yield promiseHistoryClearedState(olderURIs, true);
|
||||
yield ensureDownloadsClearedState(olderDownloadIDs, true);
|
||||
ensureDownloadsClearedState(olderDownloadIDs, true);
|
||||
};
|
||||
wh.open();
|
||||
});
|
||||
@ -184,18 +178,6 @@ var gAllTests = [
|
||||
iter.next();
|
||||
},
|
||||
|
||||
function () {
|
||||
// Add downloads (within the past hour).
|
||||
Task.spawn(function () {
|
||||
downloadIDs = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
yield addDownloadWithMinutesAgo(downloadIDs, i);
|
||||
}
|
||||
|
||||
doNextTest();
|
||||
}).then(null, Components.utils.reportError);
|
||||
},
|
||||
|
||||
/**
|
||||
* Ensures that the combined history-downloads checkbox removes neither
|
||||
* history visits nor downloads when not checked.
|
||||
@ -212,6 +194,11 @@ var gAllTests = [
|
||||
}
|
||||
|
||||
addVisits(places, function() {
|
||||
let downloadIDs = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
downloadIDs.push(addDownloadWithMinutesAgo(i));
|
||||
}
|
||||
|
||||
let wh = new WindowHelper();
|
||||
wh.onload = function () {
|
||||
is(this.isWarningPanelVisible(), false,
|
||||
@ -237,7 +224,7 @@ var gAllTests = [
|
||||
wh.onunload = function () {
|
||||
// Of the three only form entries should be cleared.
|
||||
yield promiseHistoryClearedState(uris, false);
|
||||
yield ensureDownloadsClearedState(downloadIDs, false);
|
||||
ensureDownloadsClearedState(downloadIDs, false);
|
||||
|
||||
formEntries.forEach(function (entry) {
|
||||
let exists = yield formNameExists(entry);
|
||||
@ -247,7 +234,7 @@ var gAllTests = [
|
||||
// OK, done, cleanup after ourselves.
|
||||
yield blankSlate();
|
||||
yield promiseHistoryClearedState(uris, true);
|
||||
yield ensureDownloadsClearedState(downloadIDs, true);
|
||||
ensureDownloadsClearedState(downloadIDs, true);
|
||||
};
|
||||
wh.open();
|
||||
});
|
||||
@ -652,6 +639,10 @@ var gAllTests = [
|
||||
}
|
||||
];
|
||||
|
||||
// Used as the download database ID for a new download. Incremented for each
|
||||
// new download. See addDownloadWithMinutesAgo().
|
||||
var gDownloadId = 5555551;
|
||||
|
||||
// Index in gAllTests of the test currently being run. Incremented for each
|
||||
// test run. See doNextTest().
|
||||
var gCurrTest = 0;
|
||||
@ -856,7 +847,7 @@ WindowHelper.prototype = {
|
||||
if (wh.onunload) {
|
||||
Task.spawn(wh.onunload).then(function() {
|
||||
waitForAsyncUpdates(doNextTest);
|
||||
}).then(null, Components.utils.reportError);
|
||||
});
|
||||
} else {
|
||||
waitForAsyncUpdates(doNextTest);
|
||||
}
|
||||
@ -909,23 +900,40 @@ WindowHelper.prototype = {
|
||||
* @param aMinutesAgo
|
||||
* The download will be downloaded this many minutes ago
|
||||
*/
|
||||
function addDownloadWithMinutesAgo(aExpectedPathList, aMinutesAgo) {
|
||||
let publicList = yield Downloads.getPublicDownloadList();
|
||||
|
||||
function addDownloadWithMinutesAgo(aMinutesAgo) {
|
||||
let name = "fakefile-" + aMinutesAgo + "-minutes-ago";
|
||||
let download = yield Downloads.createDownload({
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: name
|
||||
});
|
||||
download.startTime = now_uSec - (aMinutesAgo * kUsecPerMin);
|
||||
download.canceled = true;
|
||||
publicList.add(download);
|
||||
let data = {
|
||||
id: gDownloadId,
|
||||
name: name,
|
||||
source: "https://bugzilla.mozilla.org/show_bug.cgi?id=480169",
|
||||
target: name,
|
||||
startTime: now_uSec - (aMinutesAgo * kUsecPerMin),
|
||||
endTime: now_uSec - ((aMinutesAgo + 1) * kUsecPerMin),
|
||||
state: Ci.nsIDownloadManager.DOWNLOAD_FINISHED,
|
||||
currBytes: 0, maxBytes: -1, preferredAction: 0, autoResume: 0
|
||||
};
|
||||
|
||||
ok((yield downloadExists(name)),
|
||||
"Sanity check: download " + name +
|
||||
let db = dm.DBConnection;
|
||||
let stmt = db.createStatement(
|
||||
"INSERT INTO moz_downloads (id, name, source, target, startTime, endTime, " +
|
||||
"state, currBytes, maxBytes, preferredAction, autoResume) " +
|
||||
"VALUES (:id, :name, :source, :target, :startTime, :endTime, :state, " +
|
||||
":currBytes, :maxBytes, :preferredAction, :autoResume)");
|
||||
try {
|
||||
for (let prop in data) {
|
||||
stmt.params[prop] = data[prop];
|
||||
}
|
||||
stmt.execute();
|
||||
}
|
||||
finally {
|
||||
stmt.reset();
|
||||
}
|
||||
|
||||
is(downloadExists(gDownloadId), true,
|
||||
"Sanity check: download " + gDownloadId +
|
||||
" should exist after creating it");
|
||||
|
||||
aExpectedPathList.push(name);
|
||||
return gDownloadId++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -976,37 +984,15 @@ function formNameExists(name)
|
||||
*/
|
||||
function blankSlate() {
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
dm.cleanUp();
|
||||
|
||||
// The promise is resolved only when removing both downloads and form history are done.
|
||||
let deferred = Promise.defer();
|
||||
let formHistoryDone = false, downloadsDone = false;
|
||||
|
||||
Task.spawn(function deleteAllDownloads() {
|
||||
let publicList = yield Downloads.getPublicDownloadList();
|
||||
let downloads = yield publicList.getAll();
|
||||
for (let download of downloads) {
|
||||
publicList.remove(download);
|
||||
yield download.finalize(true);
|
||||
}
|
||||
downloadsDone = true;
|
||||
if (formHistoryDone) {
|
||||
deferred.resolve();
|
||||
}
|
||||
}).then(null, Components.utils.reportError);
|
||||
|
||||
FormHistory.update({ op: "remove" },
|
||||
{ handleError: function (error) {
|
||||
do_throw("Error occurred updating form history: " + error);
|
||||
deferred.reject(error);
|
||||
},
|
||||
handleCompletion: function (reason) {
|
||||
if (!reason) {
|
||||
formHistoryDone = true;
|
||||
if (downloadsDone) {
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
handleCompletion: function (reason) { if (!reason) deferred.resolve(); }
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
@ -1026,19 +1012,24 @@ function boolPrefIs(aPrefName, aExpectedVal, aMsg) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the download with the specified path exists.
|
||||
* Checks to see if the download with the specified ID exists.
|
||||
*
|
||||
* @param aPath
|
||||
* The path of the download to check
|
||||
* @param aID
|
||||
* The ID of the download to check
|
||||
* @return True if the download exists, false otherwise
|
||||
*/
|
||||
function downloadExists(aPath)
|
||||
function downloadExists(aID)
|
||||
{
|
||||
return Task.spawn(function() {
|
||||
let publicList = yield Downloads.getPublicDownloadList();
|
||||
let listArray = yield publicList.getAll();
|
||||
throw new Task.Result(listArray.some(i => i.target.path == aPath));
|
||||
});
|
||||
let db = dm.DBConnection;
|
||||
let stmt = db.createStatement(
|
||||
"SELECT * " +
|
||||
"FROM moz_downloads " +
|
||||
"WHERE id = :id"
|
||||
);
|
||||
stmt.params.id = aID;
|
||||
let rows = stmt.executeStep();
|
||||
stmt.finalize();
|
||||
return !!rows;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1068,7 +1059,7 @@ function doNextTest() {
|
||||
function ensureDownloadsClearedState(aDownloadIDs, aShouldBeCleared) {
|
||||
let niceStr = aShouldBeCleared ? "no longer" : "still";
|
||||
aDownloadIDs.forEach(function (id) {
|
||||
is((yield downloadExists(id)), !aShouldBeCleared,
|
||||
is(downloadExists(id), !aShouldBeCleared,
|
||||
"download " + id + " should " + niceStr + " exist");
|
||||
});
|
||||
}
|
||||
|
@ -49,7 +49,11 @@ const EXPECTED_REFLOWS = [
|
||||
|
||||
// tabPreviews.capture()
|
||||
"tabPreviews_capture@chrome://browser/content/browser.js|" +
|
||||
"tabPreviews_handleEvent/<@chrome://browser/content/browser.js|"
|
||||
"tabPreviews_handleEvent/<@chrome://browser/content/browser.js|",
|
||||
|
||||
// tabPreviews.capture()
|
||||
"tabPreviews_capture@chrome://browser/content/browser.js|" +
|
||||
"@chrome://browser/content/browser.js|"
|
||||
];
|
||||
|
||||
const PREF_PRELOAD = "browser.newtab.preload";
|
||||
|
@ -7,33 +7,39 @@
|
||||
* Make sure the downloads panel can display items in the right order and
|
||||
* contains the expected data.
|
||||
*/
|
||||
function test_task()
|
||||
function gen_test()
|
||||
{
|
||||
// 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 },
|
||||
{ endTime: 1180493839859239, state: nsIDM.DOWNLOAD_NOTSTARTED },
|
||||
{ endTime: 1180493839859238, state: nsIDM.DOWNLOAD_DOWNLOADING },
|
||||
{ endTime: 1180493839859237, state: nsIDM.DOWNLOAD_PAUSED },
|
||||
{ endTime: 1180493839859236, state: nsIDM.DOWNLOAD_SCANNING },
|
||||
{ endTime: 1180493839859235, state: nsIDM.DOWNLOAD_QUEUED },
|
||||
{ endTime: 1180493839859234, state: nsIDM.DOWNLOAD_FINISHED },
|
||||
{ endTime: 1180493839859233, state: nsIDM.DOWNLOAD_FAILED },
|
||||
{ endTime: 1180493839859232, state: nsIDM.DOWNLOAD_CANCELED },
|
||||
{ endTime: 1180493839859231, state: nsIDM.DOWNLOAD_BLOCKED_PARENTAL },
|
||||
{ endTime: 1180493839859230, state: nsIDM.DOWNLOAD_DIRTY },
|
||||
{ endTime: 1180493839859229, state: nsIDM.DOWNLOAD_BLOCKED_POLICY },
|
||||
];
|
||||
|
||||
// For testing purposes, show all the download items at once.
|
||||
var originalCountLimit = DownloadsView.kItemCountLimit;
|
||||
DownloadsView.kItemCountLimit = DownloadData.length;
|
||||
registerCleanupFunction(function () {
|
||||
DownloadsView.kItemCountLimit = originalCountLimit;
|
||||
});
|
||||
|
||||
try {
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
|
||||
// For testing purposes, show all the download items at once.
|
||||
var originalCountLimit = DownloadsView.kItemCountLimit;
|
||||
DownloadsView.kItemCountLimit = DownloadData.length;
|
||||
registerCleanupFunction(function () {
|
||||
DownloadsView.kItemCountLimit = originalCountLimit;
|
||||
});
|
||||
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield undefined;
|
||||
|
||||
// Populate the downloads database with the data required by this test.
|
||||
yield task_addDownloads(DownloadData);
|
||||
for (let yy in gen_addDownloadRows(DownloadData)) yield undefined;
|
||||
|
||||
// Open the user interface and wait for data to be fully loaded.
|
||||
yield task_openPanel();
|
||||
for (let yy in gen_openPanel(DownloadsCommon.getData(window))) yield undefined;
|
||||
|
||||
// Test item data and count. This also tests the ordering of the display.
|
||||
let richlistbox = document.getElementById("downloadsListBox");
|
||||
@ -41,14 +47,16 @@ function test_task()
|
||||
is(richlistbox.children.length, DownloadData.length,
|
||||
"There is the correct number of richlistitems");
|
||||
*/
|
||||
let itemCount = richlistbox.children.length;
|
||||
for (let i = 0; i < itemCount; i++) {
|
||||
let element = richlistbox.children[itemCount - i - 1];
|
||||
for (let i = 0; i < richlistbox.children.length; i++) {
|
||||
let element = richlistbox.children[i];
|
||||
let dataItem = new DownloadsViewItemController(element).dataItem;
|
||||
is(dataItem.target, DownloadData[i].name, "Download names match up");
|
||||
is(dataItem.state, DownloadData[i].state, "Download states match up");
|
||||
is(dataItem.file, DownloadData[i].target, "Download targets match up");
|
||||
is(dataItem.uri, DownloadData[i].source, "Download sources match up");
|
||||
}
|
||||
} finally {
|
||||
// Clean up when the test finishes.
|
||||
yield task_resetState();
|
||||
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield undefined;
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,19 @@
|
||||
* download it notices. All subsequent downloads, even across sessions, should
|
||||
* not open the panel automatically.
|
||||
*/
|
||||
function test_task()
|
||||
function gen_test()
|
||||
{
|
||||
try {
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
yield task_resetState();
|
||||
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield undefined;
|
||||
|
||||
// With this set to false, we should automatically open the panel the first
|
||||
// time a download is started.
|
||||
// With this set to false, we should automatically open the panel
|
||||
// the first time a download is started.
|
||||
DownloadsCommon.getData(window).panelHasShownBefore = false;
|
||||
|
||||
let promise = promisePanelOpened();
|
||||
prepareForPanelOpen();
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
yield promise;
|
||||
yield undefined;
|
||||
|
||||
// If we got here, that means the panel opened.
|
||||
DownloadsPanel.hidePanel();
|
||||
@ -28,26 +28,29 @@ function test_task()
|
||||
ok(DownloadsCommon.getData(window).panelHasShownBefore,
|
||||
"Should have recorded that the panel was opened on a download.")
|
||||
|
||||
// Next, make sure that if we start another download, we don't open the
|
||||
// panel automatically.
|
||||
let originalOnPopupShown = DownloadsPanel.onPopupShown;
|
||||
DownloadsPanel.onPopupShown = function () {
|
||||
originalOnPopupShown.apply(this, arguments);
|
||||
ok(false, "Should not have opened the downloads panel.");
|
||||
};
|
||||
|
||||
try {
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
|
||||
// Wait 2 seconds to ensure that the panel does not open.
|
||||
let deferTimeout = Promise.defer();
|
||||
setTimeout(deferTimeout.resolve, 2000);
|
||||
yield deferTimeout.promise;
|
||||
} finally {
|
||||
DownloadsPanel.onPopupShown = originalOnPopupShown;
|
||||
}
|
||||
// Next, make sure that if we start another download, we don't open
|
||||
// the panel automatically.
|
||||
panelShouldNotOpen();
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
yield waitFor(2);
|
||||
} catch(e) {
|
||||
ok(false, e);
|
||||
} finally {
|
||||
// Clean up when the test finishes.
|
||||
yield task_resetState();
|
||||
for (let yy in gen_resetState(DownloadsCommon.getData(window))) yield undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this to record a test failure for the next time the downloads panel
|
||||
* opens.
|
||||
*/
|
||||
function panelShouldNotOpen()
|
||||
{
|
||||
// Hook to wait until the test data has been loaded.
|
||||
let originalOnViewLoadCompleted = DownloadsPanel.onViewLoadCompleted;
|
||||
DownloadsPanel.onViewLoadCompleted = function () {
|
||||
DownloadsPanel.onViewLoadCompleted = originalOnViewLoadCompleted;
|
||||
ok(false, "Should not have opened the downloads panel.");
|
||||
};
|
||||
}
|
||||
|
@ -10,16 +10,10 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Globals
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
|
||||
"resource://gre/modules/Downloads.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
||||
"resource:///modules/DownloadsCommon.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||
"resource://gre/modules/FileUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||
"resource://gre/modules/Task.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
||||
"resource:///modules/DownloadsCommon.jsm");
|
||||
const nsIDM = Ci.nsIDownloadManager;
|
||||
|
||||
let gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]);
|
||||
@ -28,85 +22,253 @@ registerCleanupFunction(function () {
|
||||
gTestTargetFile.remove(false);
|
||||
});
|
||||
|
||||
/**
|
||||
* This objects contains a property for each column in the downloads table.
|
||||
*/
|
||||
let gDownloadRowTemplate = {
|
||||
name: "test-download.txt",
|
||||
source: "http://www.example.com/test-download.txt",
|
||||
target: NetUtil.newURI(gTestTargetFile).spec,
|
||||
startTime: 1180493839859230,
|
||||
endTime: 1180493839859234,
|
||||
state: nsIDM.DOWNLOAD_FINISHED,
|
||||
currBytes: 0,
|
||||
maxBytes: -1,
|
||||
preferredAction: 0,
|
||||
autoResume: 0
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Infrastructure
|
||||
|
||||
// All test are run through the test runner.
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
Task.spawn(test_task).then(null, ex => ok(false, ex)).then(finish);
|
||||
testRunner.runTest(this.gen_test);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a browser-chrome test defined through a generator function.
|
||||
*
|
||||
* This object is a singleton, initialized automatically when this script is
|
||||
* included. Every browser-chrome test file includes a new copy of this object.
|
||||
*/
|
||||
var testRunner = {
|
||||
_testIterator: null,
|
||||
_lastEventResult: undefined,
|
||||
_testRunning: false,
|
||||
_eventRaised: false,
|
||||
|
||||
// --- Main test runner ---
|
||||
|
||||
/**
|
||||
* Runs the test described by the provided generator function asynchronously.
|
||||
*
|
||||
* Calling yield in the generator will cause it to wait until continueTest is
|
||||
* called. The parameter provided to continueTest will be the return value of
|
||||
* the yield operator.
|
||||
*
|
||||
* @param aGenerator
|
||||
* Test generator function. The function will be called with no
|
||||
* arguments to retrieve its iterator.
|
||||
*/
|
||||
runTest: function TR_runTest(aGenerator) {
|
||||
waitForExplicitFinish();
|
||||
testRunner._testIterator = aGenerator();
|
||||
testRunner.continueTest();
|
||||
},
|
||||
|
||||
/**
|
||||
* Continues the currently running test.
|
||||
*
|
||||
* @param aEventResult
|
||||
* This will be the return value of the yield operator in the test.
|
||||
*/
|
||||
continueTest: function TR_continueTest(aEventResult) {
|
||||
// Store the last event result, or set it to undefined.
|
||||
testRunner._lastEventResult = aEventResult;
|
||||
|
||||
// Never reenter the main loop, but notify that the event has been raised.
|
||||
if (testRunner._testRunning) {
|
||||
testRunner._eventRaised = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Enter the main iteration loop.
|
||||
testRunner._testRunning = true;
|
||||
try {
|
||||
do {
|
||||
// Call the iterator, but don't leave the loop if the expected event is
|
||||
// raised during the execution of the generator.
|
||||
testRunner._eventRaised = false;
|
||||
testRunner._testIterator.send(testRunner._lastEventResult);
|
||||
} while (testRunner._eventRaised);
|
||||
}
|
||||
catch (e) {
|
||||
// This block catches exceptions raised by the generator, including the
|
||||
// normal StopIteration exception. Unexpected exceptions are reported as
|
||||
// test failures.
|
||||
if (!(e instanceof StopIteration))
|
||||
ok(false, e);
|
||||
// In any case, stop the tests in this file.
|
||||
finish();
|
||||
}
|
||||
|
||||
// Wait for the next event or finish.
|
||||
testRunner._testRunning = false;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Asynchronous support subroutines
|
||||
//// Asynchronous generator-based support subroutines
|
||||
|
||||
function promiseFocus()
|
||||
//
|
||||
// The following functions are all generators that can be used inside the main
|
||||
// test generator to perform specific tasks asynchronously. To invoke these
|
||||
// subroutines correctly, an iteration syntax should be used:
|
||||
//
|
||||
// for (let yy in gen_example("Parameter")) yield undefined;
|
||||
//
|
||||
|
||||
function gen_resetState(aData)
|
||||
{
|
||||
let deferred = Promise.defer();
|
||||
waitForFocus(deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function promisePanelOpened()
|
||||
{
|
||||
let deferred = Promise.defer();
|
||||
|
||||
// Hook to wait until the panel is shown.
|
||||
let originalOnPopupShown = DownloadsPanel.onPopupShown;
|
||||
DownloadsPanel.onPopupShown = function () {
|
||||
DownloadsPanel.onPopupShown = originalOnPopupShown;
|
||||
originalOnPopupShown.apply(this, arguments);
|
||||
|
||||
// Defer to the next tick of the event loop so that we don't continue
|
||||
// processing during the DOM event handler itself.
|
||||
setTimeout(deferred.resolve, 0);
|
||||
};
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function task_resetState()
|
||||
{
|
||||
// Remove all downloads.
|
||||
let publicList = yield Downloads.getPublicDownloadList();
|
||||
let downloads = yield publicList.getAll();
|
||||
for (let download of downloads) {
|
||||
publicList.remove(download);
|
||||
yield download.finalize(true);
|
||||
let statement = Services.downloads.DBConnection.createAsyncStatement(
|
||||
"DELETE FROM moz_downloads");
|
||||
try {
|
||||
statement.executeAsync({
|
||||
handleResult: function(aResultSet) { },
|
||||
handleError: function(aError)
|
||||
{
|
||||
Cu.reportError(aError);
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
testRunner.continueTest();
|
||||
}
|
||||
});
|
||||
yield undefined;
|
||||
} finally {
|
||||
statement.finalize();
|
||||
}
|
||||
|
||||
// Reset any prefs that might have been changed.
|
||||
Services.prefs.clearUserPref("browser.download.panel.shown");
|
||||
|
||||
// Ensure that the panel is closed and data is unloaded.
|
||||
aData.clear();
|
||||
aData._loadState = aData.kLoadNone;
|
||||
DownloadsPanel.hidePanel();
|
||||
|
||||
yield promiseFocus();
|
||||
// Wait for focus on the main window.
|
||||
waitForFocus(testRunner.continueTest);
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
function task_addDownloads(aItems)
|
||||
function gen_addDownloadRows(aDataRows)
|
||||
{
|
||||
let startTimeMs = Date.now();
|
||||
let columnNames = Object.keys(gDownloadRowTemplate).join(", ");
|
||||
let parameterNames = Object.keys(gDownloadRowTemplate)
|
||||
.map(function(n) ":" + n)
|
||||
.join(", ");
|
||||
let statement = Services.downloads.DBConnection.createAsyncStatement(
|
||||
"INSERT INTO moz_downloads (" + columnNames +
|
||||
", guid) VALUES(" + parameterNames + ", GENERATE_GUID())");
|
||||
try {
|
||||
// Execute the statement for each of the provided downloads in reverse.
|
||||
for (let i = aDataRows.length - 1; i >= 0; i--) {
|
||||
let dataRow = aDataRows[i];
|
||||
|
||||
let publicList = yield Downloads.getPublicDownloadList();
|
||||
for (let item of aItems) {
|
||||
publicList.add(yield Downloads.createDownload({
|
||||
source: "http://www.example.com/test-download.txt",
|
||||
target: gTestTargetFile,
|
||||
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,
|
||||
startTime: new Date(startTimeMs++),
|
||||
}));
|
||||
// Populate insert parameters from the provided data.
|
||||
for (let columnName in gDownloadRowTemplate) {
|
||||
if (!(columnName in dataRow)) {
|
||||
// Update the provided row object with data from the global template,
|
||||
// for columns whose value is not provided explicitly.
|
||||
dataRow[columnName] = gDownloadRowTemplate[columnName];
|
||||
}
|
||||
statement.params[columnName] = dataRow[columnName];
|
||||
}
|
||||
|
||||
// Run the statement asynchronously and wait.
|
||||
statement.executeAsync({
|
||||
handleResult: function(aResultSet) { },
|
||||
handleError: function(aError)
|
||||
{
|
||||
Cu.reportError(aError.message + " (Result = " + aError.result + ")");
|
||||
},
|
||||
handleCompletion: function(aReason)
|
||||
{
|
||||
testRunner.continueTest();
|
||||
}
|
||||
});
|
||||
yield undefined;
|
||||
|
||||
// At each iteration, ensure that the start and end time in the global
|
||||
// template is distinct, as these column are used to sort each download
|
||||
// in its category.
|
||||
gDownloadRowTemplate.startTime++;
|
||||
gDownloadRowTemplate.endTime++;
|
||||
}
|
||||
} finally {
|
||||
statement.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
function task_openPanel()
|
||||
function gen_openPanel(aData)
|
||||
{
|
||||
yield promiseFocus();
|
||||
// Hook to wait until the test data has been loaded.
|
||||
let originalOnViewLoadCompleted = DownloadsPanel.onViewLoadCompleted;
|
||||
DownloadsPanel.onViewLoadCompleted = function () {
|
||||
DownloadsPanel.onViewLoadCompleted = originalOnViewLoadCompleted;
|
||||
originalOnViewLoadCompleted.apply(this);
|
||||
testRunner.continueTest();
|
||||
};
|
||||
|
||||
let promise = promisePanelOpened();
|
||||
// Start loading all the downloads from the database asynchronously.
|
||||
aData.ensurePersistentDataLoaded(false);
|
||||
|
||||
// Wait for focus on the main window.
|
||||
waitForFocus(testRunner.continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Open the downloads panel, waiting until loading is completed.
|
||||
DownloadsPanel.showPanel();
|
||||
yield promise;
|
||||
yield undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spin the event loop for aSeconds seconds, and then signal the test to
|
||||
* continue.
|
||||
*
|
||||
* @param aSeconds the number of seconds to wait.
|
||||
* @note This helper should _only_ be used when there's no valid event to
|
||||
* listen to and one can't be made.
|
||||
*/
|
||||
function waitFor(aSeconds)
|
||||
{
|
||||
setTimeout(function() {
|
||||
testRunner.continueTest();
|
||||
}, aSeconds * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make it so that the next time the downloads panel opens, we signal to
|
||||
* continue the test. This function needs to be called each time you want
|
||||
* to wait for the panel to open.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* prepareForPanelOpen();
|
||||
* // Do something to open the panel
|
||||
* yield undefined;
|
||||
* // We can assume the panel is open now.
|
||||
*/
|
||||
function prepareForPanelOpen()
|
||||
{
|
||||
// Hook to wait until the test data has been loaded.
|
||||
let originalOnPopupShown = DownloadsPanel.onPopupShown;
|
||||
DownloadsPanel.onPopupShown = function (aEvent) {
|
||||
DownloadsPanel.onPopupShown = originalOnPopupShown;
|
||||
DownloadsPanel.onPopupShown.apply(this, [aEvent]);
|
||||
testRunner.continueTest();
|
||||
};
|
||||
}
|
||||
|
@ -77,6 +77,9 @@ const TAB_EVENTS = [
|
||||
"TabUnpinned"
|
||||
];
|
||||
|
||||
// The number of milliseconds in a day
|
||||
const MS_PER_DAY = 1000.0 * 60.0 * 60.0 * 24.0;
|
||||
|
||||
#ifndef XP_WIN
|
||||
#define BROKEN_WM_Z_ORDER
|
||||
#endif
|
||||
@ -464,10 +467,8 @@ let SessionStoreInternal = {
|
||||
}
|
||||
}
|
||||
|
||||
// Load the session start time from the previous state
|
||||
this._sessionStartTime = state.session &&
|
||||
state.session.startTime ||
|
||||
this._sessionStartTime;
|
||||
// Update the session start time using the restored session state.
|
||||
this._updateSessionStartTime(state);
|
||||
|
||||
// make sure that at least the first window doesn't have anything hidden
|
||||
delete state.windows[0].hidden;
|
||||
@ -1801,9 +1802,9 @@ let SessionStoreInternal = {
|
||||
// Set data that persists between sessions
|
||||
this._recentCrashes = lastSessionState.session &&
|
||||
lastSessionState.session.recentCrashes || 0;
|
||||
this._sessionStartTime = lastSessionState.session &&
|
||||
lastSessionState.session.startTime ||
|
||||
this._sessionStartTime;
|
||||
|
||||
// Update the session start time using the restored session state.
|
||||
this._updateSessionStartTime(lastSessionState);
|
||||
|
||||
this._lastSessionState = null;
|
||||
},
|
||||
@ -3635,6 +3636,28 @@ let SessionStoreInternal = {
|
||||
|
||||
/* ........ Auxiliary Functions .............. */
|
||||
|
||||
/**
|
||||
* Update the session start time and send a telemetry measurement
|
||||
* for the number of days elapsed since the session was started.
|
||||
*
|
||||
* @param state
|
||||
* The session state.
|
||||
*/
|
||||
_updateSessionStartTime: function ssi_updateSessionStartTime(state) {
|
||||
// Attempt to load the session start time from the session state
|
||||
if (state.session && state.session.startTime) {
|
||||
this._sessionStartTime = state.session.startTime;
|
||||
|
||||
// ms to days
|
||||
let sessionLength = (Date.now() - this._sessionStartTime) / MS_PER_DAY;
|
||||
|
||||
if (sessionLength > 0) {
|
||||
// Submit the session length telemetry measurement
|
||||
Services.telemetry.getHistogramById("FX_SESSION_RESTORE_SESSION_LENGTH").add(sessionLength);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* call a callback for all currently opened browser windows
|
||||
* (might miss the most recent one)
|
||||
|
@ -1219,81 +1219,102 @@ ElementEditor.prototype = {
|
||||
return this.node.startModifyingAttributes();
|
||||
},
|
||||
|
||||
_createAttribute: function EE_createAttribute(aAttr, aBefore)
|
||||
_createAttribute: function EE_createAttribute(aAttr, aBefore = null)
|
||||
{
|
||||
if (this.attrs.hasOwnProperty(aAttr.name)) {
|
||||
var attr = this.attrs[aAttr.name];
|
||||
var name = attr.querySelector(".attrname");
|
||||
var val = attr.querySelector(".attrvalue");
|
||||
} else {
|
||||
// Create the template editor, which will save some variables here.
|
||||
let data = {
|
||||
attrName: aAttr.name,
|
||||
};
|
||||
this.template("attribute", data);
|
||||
var {attr, inner, name, val} = data;
|
||||
// Create the template editor, which will save some variables here.
|
||||
let data = {
|
||||
attrName: aAttr.name,
|
||||
};
|
||||
this.template("attribute", data);
|
||||
var {attr, inner, name, val} = data;
|
||||
|
||||
// Figure out where we should place the attribute.
|
||||
let before = aBefore || null;
|
||||
if (aAttr.name == "id") {
|
||||
before = this.attrList.firstChild;
|
||||
} else if (aAttr.name == "class") {
|
||||
let idNode = this.attrs["id"];
|
||||
before = idNode ? idNode.nextSibling : this.attrList.firstChild;
|
||||
}
|
||||
this.attrList.insertBefore(attr, before);
|
||||
// Double quotes need to be handled specially to prevent DOMParser failing.
|
||||
// name="v"a"l"u"e" when editing -> name='v"a"l"u"e"'
|
||||
// name="v'a"l'u"e" when editing -> name="v'a"l'u"e"
|
||||
let editValueDisplayed = aAttr.value;
|
||||
let hasDoubleQuote = editValueDisplayed.contains('"');
|
||||
let hasSingleQuote = editValueDisplayed.contains("'");
|
||||
let initial = aAttr.name + '="' + editValueDisplayed + '"';
|
||||
|
||||
// Make the attribute editable.
|
||||
editableField({
|
||||
element: inner,
|
||||
trigger: "dblclick",
|
||||
stopOnReturn: true,
|
||||
selectAll: false,
|
||||
contentType: InplaceEditor.CONTENT_TYPES.CSS_MIXED,
|
||||
popup: this.markup.popup,
|
||||
start: (aEditor, aEvent) => {
|
||||
// If the editing was started inside the name or value areas,
|
||||
// select accordingly.
|
||||
if (aEvent && aEvent.target === name) {
|
||||
aEditor.input.setSelectionRange(0, name.textContent.length);
|
||||
} else if (aEvent && aEvent.target === val) {
|
||||
let length = val.textContent.length;
|
||||
let editorLength = aEditor.input.value.length;
|
||||
let start = editorLength - (length + 1);
|
||||
aEditor.input.setSelectionRange(start, start + length);
|
||||
} else {
|
||||
aEditor.input.select();
|
||||
}
|
||||
},
|
||||
done: (aVal, aCommit) => {
|
||||
if (!aCommit) {
|
||||
return;
|
||||
}
|
||||
|
||||
let doMods = this._startModifyingAttributes();
|
||||
let undoMods = this._startModifyingAttributes();
|
||||
|
||||
// Remove the attribute stored in this editor and re-add any attributes
|
||||
// parsed out of the input element. Restore original attribute if
|
||||
// parsing fails.
|
||||
try {
|
||||
this._saveAttribute(aAttr.name, undoMods);
|
||||
doMods.removeAttribute(aAttr.name);
|
||||
this._applyAttributes(aVal, attr, doMods, undoMods);
|
||||
this.undo.do(() => {
|
||||
doMods.apply();
|
||||
}, () => {
|
||||
undoMods.apply();
|
||||
})
|
||||
} catch(ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.attrs[aAttr.name] = attr;
|
||||
// Can't just wrap value with ' since the value contains both " and '.
|
||||
if (hasDoubleQuote && hasSingleQuote) {
|
||||
editValueDisplayed = editValueDisplayed.replace(/\"/g, """);
|
||||
initial = aAttr.name + '="' + editValueDisplayed + '"';
|
||||
}
|
||||
|
||||
// Wrap with ' since there are no single quotes in the attribute value.
|
||||
if (hasDoubleQuote && !hasSingleQuote) {
|
||||
initial = aAttr.name + "='" + editValueDisplayed + "'";
|
||||
}
|
||||
|
||||
// Make the attribute editable.
|
||||
editableField({
|
||||
element: inner,
|
||||
trigger: "dblclick",
|
||||
stopOnReturn: true,
|
||||
selectAll: false,
|
||||
initial: initial,
|
||||
contentType: InplaceEditor.CONTENT_TYPES.CSS_MIXED,
|
||||
popup: this.markup.popup,
|
||||
start: (aEditor, aEvent) => {
|
||||
// If the editing was started inside the name or value areas,
|
||||
// select accordingly.
|
||||
if (aEvent && aEvent.target === name) {
|
||||
aEditor.input.setSelectionRange(0, name.textContent.length);
|
||||
} else if (aEvent && aEvent.target === val) {
|
||||
let length = editValueDisplayed.length;
|
||||
let editorLength = aEditor.input.value.length;
|
||||
let start = editorLength - (length + 1);
|
||||
aEditor.input.setSelectionRange(start, start + length);
|
||||
} else {
|
||||
aEditor.input.select();
|
||||
}
|
||||
},
|
||||
done: (aVal, aCommit) => {
|
||||
if (!aCommit) {
|
||||
return;
|
||||
}
|
||||
|
||||
let doMods = this._startModifyingAttributes();
|
||||
let undoMods = this._startModifyingAttributes();
|
||||
|
||||
// Remove the attribute stored in this editor and re-add any attributes
|
||||
// parsed out of the input element. Restore original attribute if
|
||||
// parsing fails.
|
||||
try {
|
||||
this._saveAttribute(aAttr.name, undoMods);
|
||||
doMods.removeAttribute(aAttr.name);
|
||||
this._applyAttributes(aVal, attr, doMods, undoMods);
|
||||
this.undo.do(() => {
|
||||
doMods.apply();
|
||||
}, () => {
|
||||
undoMods.apply();
|
||||
})
|
||||
} catch(ex) {
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Figure out where we should place the attribute.
|
||||
let before = aBefore;
|
||||
if (aAttr.name == "id") {
|
||||
before = this.attrList.firstChild;
|
||||
} else if (aAttr.name == "class") {
|
||||
let idNode = this.attrs["id"];
|
||||
before = idNode ? idNode.nextSibling : this.attrList.firstChild;
|
||||
}
|
||||
this.attrList.insertBefore(attr, before);
|
||||
|
||||
// Remove the old version of this attribute from the DOM.
|
||||
let oldAttr = this.attrs[aAttr.name];
|
||||
if (oldAttr && oldAttr.parentNode) {
|
||||
oldAttr.parentNode.removeChild(oldAttr);
|
||||
}
|
||||
|
||||
this.attrs[aAttr.name] = attr;
|
||||
|
||||
name.textContent = aAttr.name;
|
||||
val.textContent = aAttr.value;
|
||||
|
||||
|
@ -40,5 +40,7 @@
|
||||
<div id="retag-me-2"></div>
|
||||
</div>
|
||||
<div id="node25"></div>
|
||||
<div id="node26" style='background-image: url("moz-page-thumb://thumbnail?url=http%3A%2F%2Fwww.mozilla.org%2F");'></div>
|
||||
<div id="node27" class="Double " and single '"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -239,6 +239,79 @@ function test() {
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Modify inline style containing \"",
|
||||
before: function() {
|
||||
assertAttributes(doc.querySelector("#node26"), {
|
||||
id: "node26",
|
||||
style: 'background-image: url("moz-page-thumb://thumbnail?url=http%3A%2F%2Fwww.mozilla.org%2F");'
|
||||
});
|
||||
},
|
||||
execute: function(after) {
|
||||
inspector.once("markupmutation", after);
|
||||
let editor = getContainerForRawNode(markup, doc.querySelector("#node26")).editor;
|
||||
let attr = editor.attrs["style"].querySelector(".editable");
|
||||
|
||||
|
||||
attr.focus();
|
||||
EventUtils.sendKey("return", inspector.panelWin);
|
||||
|
||||
let input = inplaceEditor(attr).input;
|
||||
let value = input.value;
|
||||
|
||||
is (value,
|
||||
"style='background-image: url(\"moz-page-thumb://thumbnail?url=http%3A%2F%2Fwww.mozilla.org%2F\");'",
|
||||
"Value contains actual double quotes"
|
||||
);
|
||||
|
||||
value = value.replace(/mozilla\.org/, "mozilla.com");
|
||||
input.value = value;
|
||||
|
||||
EventUtils.sendKey("return", inspector.panelWin);
|
||||
},
|
||||
after: function() {
|
||||
assertAttributes(doc.querySelector("#node26"), {
|
||||
id: "node26",
|
||||
style: 'background-image: url("moz-page-thumb://thumbnail?url=http%3A%2F%2Fwww.mozilla.com%2F");'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Modify inline style containing \" and \'",
|
||||
before: function() {
|
||||
assertAttributes(doc.querySelector("#node27"), {
|
||||
id: "node27",
|
||||
class: 'Double " and single \''
|
||||
});
|
||||
},
|
||||
execute: function(after) {
|
||||
inspector.once("markupmutation", after);
|
||||
let editor = getContainerForRawNode(markup, doc.querySelector("#node27")).editor;
|
||||
let attr = editor.attrs["class"].querySelector(".editable");
|
||||
|
||||
attr.focus();
|
||||
EventUtils.sendKey("return", inspector.panelWin);
|
||||
|
||||
let input = inplaceEditor(attr).input;
|
||||
let value = input.value;
|
||||
|
||||
is (value, "class=\"Double " and single '\"", "Value contains "");
|
||||
|
||||
value = value.replace(/Double/, """).replace(/single/, "'");
|
||||
input.value = value;
|
||||
|
||||
EventUtils.sendKey("return", inspector.panelWin);
|
||||
},
|
||||
after: function() {
|
||||
assertAttributes(doc.querySelector("#node27"), {
|
||||
id: "node27",
|
||||
class: '" " and \' \''
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Add an attribute value without closing \"",
|
||||
enteredText: 'style="display: block;',
|
||||
|
@ -687,6 +687,7 @@ ResponsiveUI.prototype = {
|
||||
this.stack.removeAttribute("notransition");
|
||||
}
|
||||
this.ignoreY = false;
|
||||
this.ignoreX = false;
|
||||
this.isResizing = false;
|
||||
},
|
||||
|
||||
|
@ -42,7 +42,7 @@ function simpleInherit(aInspector, aRuleView)
|
||||
styleNode.parentNode.removeChild(styleNode);
|
||||
|
||||
emptyInherit();
|
||||
}).then(null, console.error);
|
||||
});
|
||||
}
|
||||
|
||||
function emptyInherit()
|
||||
@ -68,7 +68,7 @@ function emptyInherit()
|
||||
styleNode.parentNode.removeChild(styleNode);
|
||||
|
||||
elementStyleInherit();
|
||||
}).then(null, console.error);
|
||||
});
|
||||
}
|
||||
|
||||
function elementStyleInherit()
|
||||
@ -92,7 +92,7 @@ function elementStyleInherit()
|
||||
is(inheritProp.name, "color", "color should have been inherited.");
|
||||
|
||||
finishTest();
|
||||
}).then(null, console.error);
|
||||
});
|
||||
}
|
||||
|
||||
function finishTest()
|
||||
|
@ -37,7 +37,7 @@ function SI_inspectNode()
|
||||
is(span, computedView.viewedElement.rawNode(),
|
||||
"style inspector node matches the selected node");
|
||||
SI_toggleDefaultStyles();
|
||||
}).then(null, (err) => console.error(err));
|
||||
});
|
||||
}
|
||||
|
||||
function SI_toggleDefaultStyles()
|
||||
|
@ -60,7 +60,7 @@
|
||||
<!ENTITY btnPageJS.accesskey "J">
|
||||
<!ENTITY btnPageSecurity.label "Security">
|
||||
<!ENTITY btnPageSecurity.tooltip "Log security errors and warnings">
|
||||
<!ENTITY btnPageSecurity.accesskey "S">
|
||||
<!ENTITY btnPageSecurity.accesskey "u">
|
||||
|
||||
<!-- LOCALIZATION NOTE (btnPageLogging): This is used as the text of the
|
||||
- the toolbar. It shows or hides messages that the web developer inserted on
|
||||
|
@ -9,12 +9,6 @@
|
||||
|
||||
.newattr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Give some padding to focusable elements to match the editor input
|
||||
* that will replace them. */
|
||||
span[tabindex] {
|
||||
display: inline-block;
|
||||
padding: 1px 0;
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,32 @@ MOZ_CONFIG_LOG_TRAP
|
||||
|
||||
dnl Disable the trap when running sub-configures.
|
||||
define([_MOZ_AC_OUTPUT_SUBDIRS], defn([AC_OUTPUT_SUBDIRS]))
|
||||
define([MOZ_SUBCONFIGURE_WRAP],
|
||||
[ _CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
case "$host" in
|
||||
*-mingw*)
|
||||
_CONFIG_SHELL=$(cd $(dirname $_CONFIG_SHELL); pwd -W)/$(basename $_CONFIG_SHELL)
|
||||
if test ! -e "$_CONFIG_SHELL" -a -e "${_CONFIG_SHELL}.exe"; then
|
||||
_CONFIG_SHELL="${_CONFIG_SHELL}.exe"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -d "$1"; then
|
||||
(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py dump "$_CONFIG_SHELL")
|
||||
fi
|
||||
$2
|
||||
(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py adjust)
|
||||
])
|
||||
|
||||
define([AC_OUTPUT_SUBDIRS],
|
||||
[trap '' EXIT
|
||||
_MOZ_AC_OUTPUT_SUBDIRS($1)
|
||||
for moz_config_dir in $1; do
|
||||
MOZ_SUBCONFIGURE_WRAP([$moz_config_dir],[
|
||||
_MOZ_AC_OUTPUT_SUBDIRS($moz_config_dir)
|
||||
])
|
||||
done
|
||||
|
||||
MOZ_CONFIG_LOG_TRAP
|
||||
])
|
||||
|
||||
|
124
build/subconfigure.py
Normal file
124
build/subconfigure.py
Normal file
@ -0,0 +1,124 @@
|
||||
# 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/.
|
||||
|
||||
# This script is used to capture the content of config.status-generated
|
||||
# files and subsequently restore their timestamp if they haven't changed.
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import pickle
|
||||
|
||||
class File(object):
|
||||
def __init__(self, path):
|
||||
self._path = path
|
||||
self._content = open(path, 'rb').read()
|
||||
stat = os.stat(path)
|
||||
self._times = (stat.st_atime, stat.st_mtime)
|
||||
|
||||
def update_time(self):
|
||||
'''If the file hasn't changed since the instance was created,
|
||||
restore its old modification time.'''
|
||||
if not os.path.exists(self._path):
|
||||
return
|
||||
if open(self._path, 'rb').read() == self._content:
|
||||
os.utime(self._path, self._times)
|
||||
|
||||
|
||||
# As defined in the various sub-configures in the tree
|
||||
PRECIOUS_VARS = set([
|
||||
'build_alias',
|
||||
'host_alias',
|
||||
'target_alias',
|
||||
'CC',
|
||||
'CFLAGS',
|
||||
'LDFLAGS',
|
||||
'LIBS',
|
||||
'CPPFLAGS',
|
||||
'CPP',
|
||||
'CCC',
|
||||
'CXXFLAGS',
|
||||
'CXX',
|
||||
'CCASFLAGS',
|
||||
'CCAS',
|
||||
])
|
||||
|
||||
|
||||
# Autoconf, in some of the sub-configures used in the tree, likes to error
|
||||
# out when "precious" variables change in value. The solution it gives to
|
||||
# straighten things is to either run make distclean or remove config.cache.
|
||||
# There's no reason not to do the latter automatically instead of failing,
|
||||
# doing the cleanup (which, on buildbots means a full clobber), and
|
||||
# restarting from scratch.
|
||||
def maybe_clear_cache():
|
||||
comment = re.compile(r'^\s+#')
|
||||
cache = {}
|
||||
with open('config.cache') as f:
|
||||
for line in f.readlines():
|
||||
if not comment.match(line) and '=' in line:
|
||||
key, value = line.split('=', 1)
|
||||
cache[key] = value
|
||||
for precious in PRECIOUS_VARS:
|
||||
entry = 'ac_cv_env_%s_value' % precious
|
||||
if entry in cache and (not precious in os.environ or os.environ[precious] != cache[entry]):
|
||||
os.remove('config.cache')
|
||||
return
|
||||
|
||||
|
||||
def dump(dump_file, shell):
|
||||
if os.path.exists('config.cache'):
|
||||
maybe_clear_cache()
|
||||
if not os.path.exists('config.status'):
|
||||
if os.path.exists(dump_file):
|
||||
os.remove(dump_file)
|
||||
return
|
||||
|
||||
config_files = [File('config.status')]
|
||||
|
||||
# Scan the config.status output for information about configuration files
|
||||
# it generates.
|
||||
config_status_output = subprocess.check_output(
|
||||
[shell, '-c', './config.status --help'],
|
||||
stderr=subprocess.STDOUT).splitlines()
|
||||
state = None
|
||||
for line in config_status_output:
|
||||
if line.startswith('Configuration') and line.endswith(':'):
|
||||
state = 'config'
|
||||
elif not line.startswith(' '):
|
||||
state = None
|
||||
elif state == 'config':
|
||||
for f in (couple.split(':')[0] for couple in line.split()):
|
||||
if os.path.isfile(f):
|
||||
config_files.append(File(f))
|
||||
|
||||
with open(dump_file, 'wb') as f:
|
||||
pickle.dump(config_files, f)
|
||||
|
||||
|
||||
def adjust(dump_file):
|
||||
if not os.path.exists(dump_file):
|
||||
return
|
||||
|
||||
config_files = []
|
||||
|
||||
try:
|
||||
with open(dump_file, 'rb') as f:
|
||||
config_files = pickle.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for f in config_files:
|
||||
f.update_time()
|
||||
|
||||
os.remove(dump_file)
|
||||
|
||||
|
||||
CONFIG_DUMP = 'config_files.pkl'
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[1] == 'dump':
|
||||
dump(CONFIG_DUMP, sys.argv[2])
|
||||
elif sys.argv[1] == 'adjust':
|
||||
adjust(CONFIG_DUMP)
|
@ -24,10 +24,12 @@ $(call BUILDSTATUS,SUBTIER_FINISH precompile $(1))
|
||||
|
||||
endef
|
||||
|
||||
export::
|
||||
$(call BUILDSTATUS,SUBTIERS IPDL WebIDL XPIDL XPIDLParser)
|
||||
default::
|
||||
$(call BUILDSTATUS,TIER_START precompile IPDL WebIDL XPIDL)
|
||||
+$(MAKE) export
|
||||
$(call BUILDSTATUS,TIER_FINISH precompile)
|
||||
|
||||
export:: ipdl webidl xpidl-parser xpidl
|
||||
export:: ipdl webidl xpidl
|
||||
|
||||
ipdl:
|
||||
$(call make_subtier_dir,IPDL,$(DEPTH)/ipc/ipdl,ipdl)
|
||||
@ -35,9 +37,9 @@ ipdl:
|
||||
webidl:
|
||||
$(call make_subtier_dir,WebIDL,$(DEPTH)/dom/bindings,webidl)
|
||||
|
||||
xpidl-parser:
|
||||
$(call make_subtier_dir,XPIDLParser,$(DEPTH)/xpcom/idl-parser,xpidl-parser)
|
||||
|
||||
xpidl: xpidl-parser
|
||||
xpidl:
|
||||
$(call BUILDSTATUS,SUBTIER_START precompile XPIDL)
|
||||
+$(MAKE) -C $(DEPTH)/xpcom/idl-parser xpidl-parser
|
||||
$(call py_action,process_install_manifest,$(DIST)/idl $(DEPTH)/_build_manifests/install/dist_idl)
|
||||
$(call make_subtier_dir,XPIDL,$(DEPTH)/config/makefiles/xpidl,xpidl)
|
||||
+$(MAKE) -C $(DEPTH)/config/makefiles/xpidl xpidl
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH precompile XPIDL)
|
||||
|
@ -12,9 +12,9 @@ PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
export_tier_%:
|
||||
$(addprefix export_tier_,$(TIERS)): export_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,export,$(dir)))
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,export,$(dir),export))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
|
@ -12,9 +12,9 @@ PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
libs_tier_%:
|
||||
$(addprefix libs_tier_,$(TIERS)): libs_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,libs,$(dir)))
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,libs,$(dir),libs))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
@ -43,7 +43,7 @@ GARBAGE += $(foreach lib,$(LIBRARY),$(EXPORT_LIBRARY)/$(lib))
|
||||
endif
|
||||
endif # EXPORT_LIBRARY
|
||||
|
||||
libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
|
||||
libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS)
|
||||
ifndef NO_DIST_INSTALL
|
||||
ifdef SHARED_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
@ -118,16 +118,6 @@ HOST_LIBRARY_DEST ?= $(DIST)/host/lib
|
||||
INSTALL_TARGETS += HOST_LIBRARY
|
||||
endif
|
||||
|
||||
ifdef JAVA_LIBRARY
|
||||
JAVA_LIBRARY_FILES = $(JAVA_LIBRARY)
|
||||
ifdef IS_COMPONENT
|
||||
JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)/components
|
||||
else
|
||||
JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)
|
||||
endif
|
||||
INSTALL_TARGETS += JAVA_LIBRARY
|
||||
endif
|
||||
|
||||
endif # !NO_DIST_INSTALL
|
||||
|
||||
# EOF
|
||||
|
@ -12,9 +12,9 @@ PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
tools_tier_%:
|
||||
$(addprefix tools_tier_,$(TIERS)): tools_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,tools,$(dir)))
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,tools,$(dir),tools))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
|
123
config/rules.mk
123
config/rules.mk
@ -30,6 +30,7 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
|
||||
TEST_DIRS \
|
||||
TIERS \
|
||||
TOOL_DIRS \
|
||||
XPCSHELL_TESTS \
|
||||
XPIDL_MODULE \
|
||||
$(NULL)
|
||||
|
||||
@ -303,10 +304,6 @@ LIBRARY := $(NULL)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef JAVA_LIBRARY_NAME
|
||||
JAVA_LIBRARY := $(JAVA_LIBRARY_NAME).jar
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifndef GNU_CC
|
||||
|
||||
@ -433,8 +430,9 @@ UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-de
|
||||
endif
|
||||
|
||||
ifdef MACH
|
||||
BUILDSTATUS=@echo BUILDSTATUS $1
|
||||
BUILDSTATUS=@echo "BUILDSTATUS $1"
|
||||
endif
|
||||
|
||||
# Static directories are largely independent of our build system. But, they
|
||||
# could share the same build mechanism (like moz.build files). We need to
|
||||
# prevent leaking of our backend state to these independent build systems. This
|
||||
@ -447,9 +445,9 @@ define SUBMAKE # $(call SUBMAKE,target,directory,static)
|
||||
endef # The extra line is important here! don't delete it
|
||||
|
||||
define TIER_DIR_SUBMAKE
|
||||
$(call BUILDSTATUS,TIERDIR_START $(2))
|
||||
$(call SUBMAKE,$(1),$(2),$(3))
|
||||
$(call BUILDSTATUS,TIERDIR_FINISH $(2))
|
||||
$(call BUILDSTATUS,TIERDIR_START $(1) $(2) $(3))
|
||||
$(call SUBMAKE,$(4),$(3),$(5))
|
||||
$(call BUILDSTATUS,TIERDIR_FINISH $(1) $(2) $(3))
|
||||
|
||||
endef # Ths empty line is important.
|
||||
|
||||
@ -707,7 +705,7 @@ alldep::
|
||||
endif # TIERS
|
||||
endif # SUPPRESS_DEFAULT_RULES
|
||||
|
||||
ifeq ($(filter s,$(MAKEFLAGS)),)
|
||||
ifeq ($(findstring s,$(filter-out --%, $(MAKEFLAGS))),)
|
||||
ECHO := echo
|
||||
QUIET :=
|
||||
else
|
||||
@ -716,32 +714,38 @@ QUIET := -q
|
||||
endif
|
||||
|
||||
# This function is called and evaluated to produce the rule to build the
|
||||
# specified tier. Each tier begins by building the "static" directories.
|
||||
# The BUILDSTATUS echo commands are used to faciliate easier parsing
|
||||
# of build output. Build drivers are encouraged to filter these lines
|
||||
# from the user.
|
||||
# specified tier.
|
||||
#
|
||||
# Tiers are traditionally composed of directories that are invoked either
|
||||
# once (so-called "static" directories) or 3 times with the export, libs, and
|
||||
# tools sub-tiers.
|
||||
#
|
||||
# If the TIER_$(tier)_CUSTOM variable is defined, then these traditional
|
||||
# tier rules are ignored and each directory in the tier is executed via a
|
||||
# sub-make invocation (make -C).
|
||||
define CREATE_TIER_RULE
|
||||
tier_$(1)::
|
||||
$(call BUILDSTATUS,TIER_START $(1))
|
||||
$(call BUILDSTATUS,SUBTIERS $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools))
|
||||
$(call BUILDSTATUS,STATICDIRS $$($$@_staticdirs))
|
||||
$(call BUILDSTATUS,DIRS $$($$@_dirs))
|
||||
ifdef TIER_$(1)_CUSTOM
|
||||
$$(foreach dir,$$($$@_dirs),$$(call SUBMAKE,,$$(dir)))
|
||||
else
|
||||
$(call BUILDSTATUS,TIER_START $(1) $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools))
|
||||
ifneq (,$(tier_$(1)_staticdirs))
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) static)
|
||||
$$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1))
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) static $$($$@_staticdirs))
|
||||
$$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,$(1),static,$$(dir),,1))
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) static)
|
||||
endif
|
||||
ifneq (,$(tier_$(1)_dirs))
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) export)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) export $$($$@_dirs))
|
||||
$$(MAKE) export_$$@
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) export)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) libs)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) libs $$($$@_dirs))
|
||||
$$(MAKE) libs_$$@
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) libs)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) tools)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) tools $$($$@_dirs))
|
||||
$$(MAKE) tools_$$@
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) tools)
|
||||
$(call BUILDSTATUS TIER_FINISH $(1))
|
||||
endif
|
||||
$(call BUILDSTATUS,TIER_FINISH $(1))
|
||||
endif
|
||||
endef
|
||||
|
||||
@ -1136,15 +1140,15 @@ $(COBJS):
|
||||
# DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
|
||||
# 'moc' only knows about #defines it gets on the command line (-D...), not in
|
||||
# included headers like mozilla-config.h
|
||||
moc_%.cpp: %.h
|
||||
$(filter moc_%.cpp,$(CPPSRCS)): moc_%.cpp: %.h
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
|
||||
|
||||
moc_%.cc: %.cc
|
||||
$(filter moc_%.cc,$(CPPSRCS)): moc_%.cc: %.cc
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
|
||||
|
||||
qrc_%.cpp: %.qrc
|
||||
$(filter qrc_%.cpp,$(CPPSRCS)): qrc_%.cpp: %.qrc
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(RCC) -name $* $< $(OUTOPTION)$@
|
||||
|
||||
@ -1175,35 +1179,35 @@ $(CMOBJS):
|
||||
@$(MAKE_DEPS_AUTO_CC)
|
||||
$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.s,$(CPPSRCS:%.cpp=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.s,$(CPPSRCS:%.cc=%.s)): %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.s: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.s,$(CSRCS:%.c=%.s)): %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CC) -S $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CPPSRCS:%.cpp=%.i)): %.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CPPSRCS:%.cc=%.i)): %.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.i: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CSRCS:%.c=%.i)): %.i: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CC) -C -E $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CMMSRCS:%.mm=%.i)): %.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.res: %.rc
|
||||
$(RESFILE): %.res: %.rc
|
||||
$(REPORT_BUILD)
|
||||
@echo Creating Resource file: $@
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
@ -1216,21 +1220,11 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
# Cancel these implicit rules
|
||||
#
|
||||
%: %,v
|
||||
# Cancel GNU make built-in implicit rules
|
||||
ifndef .PYMAKE
|
||||
MAKEFLAGS += -r
|
||||
endif
|
||||
|
||||
%: RCS/%,v
|
||||
|
||||
%: RCS/%
|
||||
|
||||
%: s.%
|
||||
|
||||
%: SCCS/s.%
|
||||
|
||||
###############################################################################
|
||||
# Java rules
|
||||
###############################################################################
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
SEP := ;
|
||||
else
|
||||
@ -1255,40 +1249,13 @@ else
|
||||
normalizepath = $(1)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Java rules
|
||||
###############################################################################
|
||||
ifneq (,$(value JAVAFILES)$(value RESFILES))
|
||||
include $(topsrcdir)/config/makefiles/java-build.mk
|
||||
endif
|
||||
|
||||
_srcdir = $(call normalizepath,$(srcdir))
|
||||
ifdef JAVA_SOURCEPATH
|
||||
SP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_SOURCEPATH))))
|
||||
_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)$(SEP)$(SP)"
|
||||
else
|
||||
_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)"
|
||||
endif
|
||||
|
||||
ifdef JAVA_CLASSPATH
|
||||
CP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_CLASSPATH))))
|
||||
_JAVA_CLASSPATH = ".$(SEP)$(CP)"
|
||||
else
|
||||
_JAVA_CLASSPATH = .
|
||||
endif
|
||||
|
||||
_JAVA_DIR = _java
|
||||
$(_JAVA_DIR)::
|
||||
$(NSINSTALL) -D $@
|
||||
|
||||
$(_JAVA_DIR)/%.class: %.java $(GLOBAL_DEPS) $(_JAVA_DIR)
|
||||
$(REPORT_BUILD)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -classpath $(_JAVA_CLASSPATH) \
|
||||
-sourcepath $(_JAVA_SOURCEPATH) -d $(_JAVA_DIR) $(_VPATH_SRCS)
|
||||
|
||||
$(JAVA_LIBRARY): $(addprefix $(_JAVA_DIR)/,$(JAVA_SRCS:.java=.class)) $(GLOBAL_DEPS)
|
||||
$(REPORT_BUILD)
|
||||
$(JAR) cf $@ -C $(_JAVA_DIR) .
|
||||
|
||||
GARBAGE_DIRS += $(_JAVA_DIR)
|
||||
|
||||
###############################################################################
|
||||
# Update Files Managed by Build Backend
|
||||
###############################################################################
|
||||
|
@ -170,6 +170,7 @@ WebGLContext::WebGLContext()
|
||||
mGLMaxVertexUniformVectors = 0;
|
||||
mGLMaxColorAttachments = 1;
|
||||
mGLMaxDrawBuffers = 1;
|
||||
mGLMaxTransformFeedbackSeparateAttribs = 0;
|
||||
|
||||
// See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
|
||||
mPixelStorePackAlignment = 4;
|
||||
@ -235,6 +236,7 @@ WebGLContext::DestroyResourcesAndContext()
|
||||
mBound2DTextures.Clear();
|
||||
mBoundCubeMapTextures.Clear();
|
||||
mBoundArrayBuffer = nullptr;
|
||||
mBoundTransformFeedbackBuffer = nullptr;
|
||||
mCurrentProgram = nullptr;
|
||||
mBoundFramebuffer = nullptr;
|
||||
mActiveOcclusionQuery = nullptr;
|
||||
|
@ -322,7 +322,6 @@ public:
|
||||
void AttachShader(WebGLProgram* program, WebGLShader* shader);
|
||||
void BindAttribLocation(WebGLProgram* program, WebGLuint location,
|
||||
const nsAString& name);
|
||||
void BindBuffer(WebGLenum target, WebGLBuffer* buf);
|
||||
void BindFramebuffer(WebGLenum target, WebGLFramebuffer* wfb);
|
||||
void BindRenderbuffer(WebGLenum target, WebGLRenderbuffer* wrb);
|
||||
void BindTexture(WebGLenum target, WebGLTexture *tex);
|
||||
@ -338,16 +337,6 @@ public:
|
||||
void BlendFunc(WebGLenum sfactor, WebGLenum dfactor);
|
||||
void BlendFuncSeparate(WebGLenum srcRGB, WebGLenum dstRGB,
|
||||
WebGLenum srcAlpha, WebGLenum dstAlpha);
|
||||
void BufferData(WebGLenum target, WebGLsizeiptr size, WebGLenum usage);
|
||||
void BufferData(WebGLenum target, const dom::ArrayBufferView &data,
|
||||
WebGLenum usage);
|
||||
void BufferData(WebGLenum target,
|
||||
const Nullable<dom::ArrayBuffer> &maybeData,
|
||||
WebGLenum usage);
|
||||
void BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
const dom::ArrayBufferView &data);
|
||||
void BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
const Nullable<dom::ArrayBuffer> &maybeData);
|
||||
WebGLenum CheckFramebufferStatus(WebGLenum target);
|
||||
void Clear(WebGLbitfield mask);
|
||||
void ClearColor(WebGLclampf r, WebGLclampf g, WebGLclampf b, WebGLclampf a);
|
||||
@ -370,7 +359,6 @@ public:
|
||||
void CopyTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
|
||||
WebGLint yoffset, WebGLint x, WebGLint y,
|
||||
WebGLsizei width, WebGLsizei height);
|
||||
already_AddRefed<WebGLBuffer> CreateBuffer();
|
||||
already_AddRefed<WebGLFramebuffer> CreateFramebuffer();
|
||||
already_AddRefed<WebGLProgram> CreateProgram();
|
||||
already_AddRefed<WebGLRenderbuffer> CreateRenderbuffer();
|
||||
@ -378,7 +366,6 @@ public:
|
||||
already_AddRefed<WebGLShader> CreateShader(WebGLenum type);
|
||||
already_AddRefed<WebGLVertexArray> CreateVertexArray();
|
||||
void CullFace(WebGLenum face);
|
||||
void DeleteBuffer(WebGLBuffer *buf);
|
||||
void DeleteFramebuffer(WebGLFramebuffer *fbuf);
|
||||
void DeleteProgram(WebGLProgram *prog);
|
||||
void DeleteRenderbuffer(WebGLRenderbuffer *rbuf);
|
||||
@ -459,7 +446,6 @@ public:
|
||||
already_AddRefed<WebGLUniformLocation>
|
||||
GetUniformLocation(WebGLProgram *prog, const nsAString& name);
|
||||
void Hint(WebGLenum target, WebGLenum mode);
|
||||
bool IsBuffer(WebGLBuffer *buffer);
|
||||
bool IsFramebuffer(WebGLFramebuffer *fb);
|
||||
bool IsProgram(WebGLProgram *prog);
|
||||
bool IsRenderbuffer(WebGLRenderbuffer *rb);
|
||||
@ -754,12 +740,46 @@ private:
|
||||
bool ValidateTargetParameter(WebGLenum target, const char* infos);
|
||||
WebGLRefPtr<WebGLQuery>& GetActiveQueryByTarget(WebGLenum target);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Buffer Objects (WebGLContextBuffers.cpp)
|
||||
public:
|
||||
void BindBuffer(WebGLenum target, WebGLBuffer* buf);
|
||||
void BindBufferBase(WebGLenum target, WebGLuint index, WebGLBuffer* buffer);
|
||||
void BindBufferRange(WebGLenum target, WebGLuint index, WebGLBuffer* buffer,
|
||||
WebGLintptr offset, WebGLsizeiptr size);
|
||||
void BufferData(WebGLenum target, WebGLsizeiptr size, WebGLenum usage);
|
||||
void BufferData(WebGLenum target, const dom::ArrayBufferView &data,
|
||||
WebGLenum usage);
|
||||
void BufferData(WebGLenum target,
|
||||
const Nullable<dom::ArrayBuffer> &maybeData,
|
||||
WebGLenum usage);
|
||||
void BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
const dom::ArrayBufferView &data);
|
||||
void BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
const Nullable<dom::ArrayBuffer> &maybeData);
|
||||
already_AddRefed<WebGLBuffer> CreateBuffer();
|
||||
void DeleteBuffer(WebGLBuffer *buf);
|
||||
bool IsBuffer(WebGLBuffer *buffer);
|
||||
|
||||
private:
|
||||
// ARRAY_BUFFER slot
|
||||
WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
|
||||
|
||||
// TRANSFORM_FEEDBACK_BUFFER slot
|
||||
WebGLRefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer;
|
||||
|
||||
// these two functions emit INVALID_ENUM for invalid `target`.
|
||||
WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTarget(GLenum target, const char* infos);
|
||||
WebGLRefPtr<WebGLBuffer>* GetBufferSlotByTargetIndexed(GLenum target, GLuint index, const char* infos);
|
||||
bool ValidateBufferUsageEnum(WebGLenum target, const char* infos);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// State and State Requests (WebGLContextState.cpp)
|
||||
public:
|
||||
void Disable(WebGLenum cap);
|
||||
void Enable(WebGLenum cap);
|
||||
JS::Value GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv);
|
||||
JS::Value GetParameterIndexed(JSContext* cx, WebGLenum pname, WebGLuint index);
|
||||
bool IsEnabled(WebGLenum cap);
|
||||
|
||||
private:
|
||||
@ -916,6 +936,7 @@ protected:
|
||||
int32_t mGLMaxVertexUniformVectors;
|
||||
int32_t mGLMaxColorAttachments;
|
||||
int32_t mGLMaxDrawBuffers;
|
||||
uint32_t mGLMaxTransformFeedbackSeparateAttribs;
|
||||
|
||||
// Represents current status, or state, of the context. That is, is it lost
|
||||
// or stable and what part of the context lost process are we currently at.
|
||||
@ -979,7 +1000,6 @@ protected:
|
||||
bool ValidateComparisonEnum(WebGLenum target, const char *info);
|
||||
bool ValidateStencilOpEnum(WebGLenum action, const char *info);
|
||||
bool ValidateFaceEnum(WebGLenum face, const char *info);
|
||||
bool ValidateBufferUsageEnum(WebGLenum target, const char *info);
|
||||
bool ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
|
||||
uint32_t *texelSize, const char *info);
|
||||
bool ValidateDrawModeEnum(WebGLenum mode, const char *info);
|
||||
@ -1110,8 +1130,6 @@ protected:
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
|
||||
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer> mBoundArrayBuffer;
|
||||
|
||||
WebGLRefPtr<WebGLProgram> mCurrentProgram;
|
||||
|
||||
uint32_t mMaxFramebufferColorAttachments;
|
||||
|
432
content/canvas/src/WebGLContextBuffers.cpp
Normal file
432
content/canvas/src/WebGLContextBuffers.cpp
Normal file
@ -0,0 +1,432 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 "WebGLContext.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLVertexArray.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
void
|
||||
WebGLContext::BindBuffer(WebGLenum target, WebGLBuffer *buffer)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindBuffer", buffer))
|
||||
return;
|
||||
|
||||
// silently ignore a deleted buffer
|
||||
if (buffer && buffer->IsDeleted())
|
||||
return;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bindBuffer");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
if (!buffer->Target()) {
|
||||
buffer->SetTarget(target);
|
||||
buffer->SetHasEverBeenBound(true);
|
||||
} else if (target != buffer->Target()) {
|
||||
return ErrorInvalidOperation("bindBuffer: buffer already bound to a different target");
|
||||
}
|
||||
}
|
||||
|
||||
*bufferSlot = buffer;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fBindBuffer(target, buffer ? buffer->GLName() : 0);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindBufferBase(WebGLenum target, WebGLuint index, WebGLBuffer* buffer)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindBufferBase", buffer))
|
||||
return;
|
||||
|
||||
// silently ignore a deleted buffer
|
||||
if (buffer && buffer->IsDeleted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
if (!buffer->Target()) {
|
||||
buffer->SetTarget(target);
|
||||
buffer->SetHasEverBeenBound(true);
|
||||
} else if (target != buffer->Target()) {
|
||||
return ErrorInvalidOperation("bindBuffer: buffer already bound to a different target");
|
||||
}
|
||||
}
|
||||
|
||||
*bufferSlot = buffer;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fBindBufferBase(target, index, buffer ? buffer->GLName() : 0);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindBufferRange(WebGLenum target, WebGLuint index, WebGLBuffer* buffer,
|
||||
WebGLintptr offset, WebGLsizeiptr size)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindBufferRange", buffer))
|
||||
return;
|
||||
|
||||
// silently ignore a deleted buffer
|
||||
if (buffer && buffer->IsDeleted())
|
||||
return;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTargetIndexed(target, index, "bindBufferBase");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
if (!buffer->Target()) {
|
||||
buffer->SetTarget(target);
|
||||
buffer->SetHasEverBeenBound(true);
|
||||
} else if (target != buffer->Target()) {
|
||||
return ErrorInvalidOperation("bindBuffer: buffer already bound to a different target");
|
||||
}
|
||||
}
|
||||
|
||||
*bufferSlot = buffer;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fBindBufferRange(target, index, buffer ? buffer->GLName() : 0, offset, size);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferData(WebGLenum target, WebGLsizeiptr size,
|
||||
WebGLenum usage)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bufferData");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (size < 0)
|
||||
return ErrorInvalidValue("bufferData: negative size");
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return;
|
||||
|
||||
WebGLBuffer* boundBuffer = bufferSlot->get();
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
void* zeroBuffer = calloc(size, 1);
|
||||
if (!zeroBuffer)
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
|
||||
MakeContextCurrent();
|
||||
InvalidateBufferFetching();
|
||||
|
||||
GLenum error = CheckedBufferData(target, size, zeroBuffer, usage);
|
||||
free(zeroBuffer);
|
||||
|
||||
if (error) {
|
||||
GenerateWarning("bufferData generated error %s", ErrorName(error));
|
||||
return;
|
||||
}
|
||||
|
||||
boundBuffer->SetByteLength(size);
|
||||
if (!boundBuffer->ElementArrayCacheBufferData(nullptr, size)) {
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferData(WebGLenum target,
|
||||
const Nullable<ArrayBuffer> &maybeData,
|
||||
WebGLenum usage)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (maybeData.IsNull()) {
|
||||
// see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
|
||||
return ErrorInvalidValue("bufferData: null object passed");
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bufferData");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ArrayBuffer& data = maybeData.Value();
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return;
|
||||
|
||||
WebGLBuffer* boundBuffer = bufferSlot->get();
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
MakeContextCurrent();
|
||||
InvalidateBufferFetching();
|
||||
|
||||
GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);
|
||||
|
||||
if (error) {
|
||||
GenerateWarning("bufferData generated error %s", ErrorName(error));
|
||||
return;
|
||||
}
|
||||
|
||||
boundBuffer->SetByteLength(data.Length());
|
||||
if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length())) {
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferData(WebGLenum target, const ArrayBufferView& data,
|
||||
WebGLenum usage)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bufferSubData");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return;
|
||||
|
||||
WebGLBuffer* boundBuffer = bufferSlot->get();
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
InvalidateBufferFetching();
|
||||
MakeContextCurrent();
|
||||
|
||||
GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);
|
||||
if (error) {
|
||||
GenerateWarning("bufferData generated error %s", ErrorName(error));
|
||||
return;
|
||||
}
|
||||
|
||||
boundBuffer->SetByteLength(data.Length());
|
||||
if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length())) {
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
|
||||
const Nullable<ArrayBuffer> &maybeData)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (maybeData.IsNull()) {
|
||||
// see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
|
||||
return;
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bufferSubData");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ArrayBuffer& data = maybeData.Value();
|
||||
|
||||
if (byteOffset < 0)
|
||||
return ErrorInvalidValue("bufferSubData: negative offset");
|
||||
|
||||
WebGLBuffer* boundBuffer = bufferSlot->get();
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.Length();
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
return ErrorInvalidValue("bufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
|
||||
checked_neededByteLength.value(), boundBuffer->ByteLength());
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), data.Length());
|
||||
|
||||
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
const ArrayBufferView& data)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>* bufferSlot = GetBufferSlotByTarget(target, "bufferSubData");
|
||||
|
||||
if (!bufferSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (byteOffset < 0)
|
||||
return ErrorInvalidValue("bufferSubData: negative offset");
|
||||
|
||||
WebGLBuffer* boundBuffer = bufferSlot->get();
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferSubData: no buffer bound!");
|
||||
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.Length();
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
return ErrorInvalidValue("bufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
|
||||
checked_neededByteLength.value(), boundBuffer->ByteLength());
|
||||
|
||||
boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), data.Length());
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLBuffer>
|
||||
WebGLContext::CreateBuffer()
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return nullptr;
|
||||
|
||||
nsRefPtr<WebGLBuffer> globj = new WebGLBuffer(this);
|
||||
return globj.forget();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DeleteBuffer(WebGLBuffer *buffer)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("deleteBuffer", buffer))
|
||||
return;
|
||||
|
||||
if (!buffer || buffer->IsDeleted())
|
||||
return;
|
||||
|
||||
if (mBoundArrayBuffer == buffer) {
|
||||
BindBuffer(LOCAL_GL_ARRAY_BUFFER,
|
||||
static_cast<WebGLBuffer*>(nullptr));
|
||||
}
|
||||
|
||||
if (mBoundVertexArray->mBoundElementArrayBuffer == buffer) {
|
||||
BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
|
||||
static_cast<WebGLBuffer*>(nullptr));
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
|
||||
if (mBoundVertexArray->mAttribBuffers[i].buf == buffer)
|
||||
mBoundVertexArray->mAttribBuffers[i].buf = nullptr;
|
||||
}
|
||||
|
||||
buffer->RequestDelete();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsBuffer(WebGLBuffer *buffer)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return false;
|
||||
|
||||
return ValidateObjectAllowDeleted("isBuffer", buffer) &&
|
||||
!buffer->IsDeleted() &&
|
||||
buffer->HasEverBeenBound();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateBufferUsageEnum(WebGLenum target, const char *infos)
|
||||
{
|
||||
switch (target) {
|
||||
case LOCAL_GL_STREAM_DRAW:
|
||||
case LOCAL_GL_STATIC_DRAW:
|
||||
case LOCAL_GL_DYNAMIC_DRAW:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInvalidEnumInfo(infos, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>*
|
||||
WebGLContext::GetBufferSlotByTarget(GLenum target, const char* infos)
|
||||
{
|
||||
switch (target) {
|
||||
case LOCAL_GL_ARRAY_BUFFER:
|
||||
return &mBoundArrayBuffer;
|
||||
|
||||
case LOCAL_GL_ELEMENT_ARRAY_BUFFER:
|
||||
return &mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
|
||||
if (!IsWebGL2()) {
|
||||
break;
|
||||
}
|
||||
return &mBoundTransformFeedbackBuffer;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInvalidEnum("%s: target: invalid enum value 0x%x", infos, target);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WebGLRefPtr<WebGLBuffer>*
|
||||
WebGLContext::GetBufferSlotByTargetIndexed(GLenum target, GLuint index, const char* infos)
|
||||
{
|
||||
switch (target) {
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER:
|
||||
if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
|
||||
ErrorInvalidValue("%s: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", infos, index);
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr; // See bug 903594
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInvalidEnum("%s: target: invalid enum value 0x%x", infos, target);
|
||||
return nullptr;
|
||||
}
|
@ -127,47 +127,6 @@ WebGLContext::BindAttribLocation(WebGLProgram *prog, WebGLuint location,
|
||||
gl->fBindAttribLocation(progname, location, mappedName.get());
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindBuffer(WebGLenum target, WebGLBuffer *buf)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindBuffer", buf))
|
||||
return;
|
||||
|
||||
WebGLuint bufname = buf ? buf->GLName() : 0;
|
||||
|
||||
// silently ignore a deleted buffer
|
||||
if (buf && buf->IsDeleted())
|
||||
return;
|
||||
|
||||
if (target != LOCAL_GL_ARRAY_BUFFER &&
|
||||
target != LOCAL_GL_ELEMENT_ARRAY_BUFFER)
|
||||
{
|
||||
return ErrorInvalidEnumInfo("bindBuffer: target", target);
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
if ((buf->Target() != LOCAL_GL_NONE) && (target != buf->Target()))
|
||||
return ErrorInvalidOperation("bindBuffer: buffer already bound to a different target");
|
||||
buf->SetTarget(target);
|
||||
buf->SetHasEverBeenBound(true);
|
||||
}
|
||||
|
||||
// we really want to do this AFTER all the validation is done, otherwise our bookkeeping could get confused.
|
||||
// see bug 656752
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
mBoundArrayBuffer = buf;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
mBoundVertexArray->mBoundElementArrayBuffer = buf;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fBindBuffer(target, bufname);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindFramebuffer(WebGLenum target, WebGLFramebuffer *wfb)
|
||||
{
|
||||
@ -352,220 +311,6 @@ GLenum WebGLContext::CheckedBufferData(GLenum target,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferData(WebGLenum target, WebGLsizeiptr size,
|
||||
WebGLenum usage)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
WebGLBuffer *boundBuffer = nullptr;
|
||||
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferData: target", target);
|
||||
}
|
||||
|
||||
if (size < 0)
|
||||
return ErrorInvalidValue("bufferData: negative size");
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return;
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
void* zeroBuffer = calloc(size, 1);
|
||||
if (!zeroBuffer)
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
|
||||
MakeContextCurrent();
|
||||
InvalidateBufferFetching();
|
||||
|
||||
GLenum error = CheckedBufferData(target, size, zeroBuffer, usage);
|
||||
free(zeroBuffer);
|
||||
|
||||
if (error) {
|
||||
GenerateWarning("bufferData generated error %s", ErrorName(error));
|
||||
return;
|
||||
}
|
||||
|
||||
boundBuffer->SetByteLength(size);
|
||||
if (!boundBuffer->ElementArrayCacheBufferData(nullptr, size)) {
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferData(WebGLenum target,
|
||||
const Nullable<ArrayBuffer> &maybeData,
|
||||
WebGLenum usage)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (maybeData.IsNull()) {
|
||||
// see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
|
||||
return ErrorInvalidValue("bufferData: null object passed");
|
||||
}
|
||||
|
||||
const ArrayBuffer& data = maybeData.Value();
|
||||
|
||||
WebGLBuffer *boundBuffer = nullptr;
|
||||
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferData: target", target);
|
||||
}
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return;
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
MakeContextCurrent();
|
||||
InvalidateBufferFetching();
|
||||
|
||||
GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);
|
||||
|
||||
if (error) {
|
||||
GenerateWarning("bufferData generated error %s", ErrorName(error));
|
||||
return;
|
||||
}
|
||||
|
||||
boundBuffer->SetByteLength(data.Length());
|
||||
if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length())) {
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferData(WebGLenum target, const ArrayBufferView& data,
|
||||
WebGLenum usage)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
WebGLBuffer *boundBuffer = nullptr;
|
||||
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferData: target", target);
|
||||
}
|
||||
|
||||
if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
|
||||
return;
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
InvalidateBufferFetching();
|
||||
MakeContextCurrent();
|
||||
|
||||
GLenum error = CheckedBufferData(target, data.Length(), data.Data(), usage);
|
||||
if (error) {
|
||||
GenerateWarning("bufferData generated error %s", ErrorName(error));
|
||||
return;
|
||||
}
|
||||
|
||||
boundBuffer->SetByteLength(data.Length());
|
||||
if (!boundBuffer->ElementArrayCacheBufferData(data.Data(), data.Length())) {
|
||||
return ErrorOutOfMemory("bufferData: out of memory");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferSubData(GLenum target, WebGLsizeiptr byteOffset,
|
||||
const Nullable<ArrayBuffer> &maybeData)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (maybeData.IsNull()) {
|
||||
// see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
|
||||
return;
|
||||
}
|
||||
|
||||
const ArrayBuffer& data = maybeData.Value();
|
||||
|
||||
WebGLBuffer *boundBuffer = nullptr;
|
||||
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferSubData: target", target);
|
||||
}
|
||||
|
||||
if (byteOffset < 0)
|
||||
return ErrorInvalidValue("bufferSubData: negative offset");
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferData: no buffer bound!");
|
||||
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.Length();
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
return ErrorInvalidValue("bufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
|
||||
checked_neededByteLength.value(), boundBuffer->ByteLength());
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), data.Length());
|
||||
|
||||
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BufferSubData(WebGLenum target, WebGLsizeiptr byteOffset,
|
||||
const ArrayBufferView& data)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
WebGLBuffer *boundBuffer = nullptr;
|
||||
|
||||
if (target == LOCAL_GL_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundArrayBuffer;
|
||||
} else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
|
||||
boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
|
||||
} else {
|
||||
return ErrorInvalidEnumInfo("bufferSubData: target", target);
|
||||
}
|
||||
|
||||
if (byteOffset < 0)
|
||||
return ErrorInvalidValue("bufferSubData: negative offset");
|
||||
|
||||
if (!boundBuffer)
|
||||
return ErrorInvalidOperation("bufferSubData: no buffer bound!");
|
||||
|
||||
CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + data.Length();
|
||||
if (!checked_neededByteLength.isValid())
|
||||
return ErrorInvalidValue("bufferSubData: integer overflow computing the needed byte length");
|
||||
|
||||
if (checked_neededByteLength.value() > boundBuffer->ByteLength())
|
||||
return ErrorInvalidValue("bufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
|
||||
checked_neededByteLength.value(), boundBuffer->ByteLength());
|
||||
|
||||
boundBuffer->ElementArrayCacheBufferSubData(byteOffset, data.Data(), data.Length());
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fBufferSubData(target, byteOffset, data.Length(), data.Data());
|
||||
}
|
||||
|
||||
WebGLenum
|
||||
WebGLContext::CheckFramebufferStatus(WebGLenum target)
|
||||
{
|
||||
@ -944,34 +689,6 @@ WebGLContext::CullFace(WebGLenum face)
|
||||
gl->fCullFace(face);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DeleteBuffer(WebGLBuffer *buf)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("deleteBuffer", buf))
|
||||
return;
|
||||
|
||||
if (!buf || buf->IsDeleted())
|
||||
return;
|
||||
|
||||
if (mBoundArrayBuffer == buf)
|
||||
BindBuffer(LOCAL_GL_ARRAY_BUFFER,
|
||||
static_cast<WebGLBuffer*>(nullptr));
|
||||
|
||||
if (mBoundVertexArray->mBoundElementArrayBuffer == buf)
|
||||
BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
|
||||
static_cast<WebGLBuffer*>(nullptr));
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
|
||||
if (mBoundVertexArray->mAttribBuffers[i].buf == buf)
|
||||
mBoundVertexArray->mAttribBuffers[i].buf = nullptr;
|
||||
}
|
||||
|
||||
buf->RequestDelete();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::DeleteFramebuffer(WebGLFramebuffer* fbuf)
|
||||
{
|
||||
@ -1731,15 +1448,6 @@ WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname)
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLBuffer>
|
||||
WebGLContext::CreateBuffer()
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return nullptr;
|
||||
nsRefPtr<WebGLBuffer> globj = new WebGLBuffer(this);
|
||||
return globj.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebGLTexture>
|
||||
WebGLContext::CreateTexture()
|
||||
{
|
||||
@ -2205,17 +1913,6 @@ WebGLContext::Hint(WebGLenum target, WebGLenum mode)
|
||||
gl->fHint(target, mode);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsBuffer(WebGLBuffer *buffer)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return false;
|
||||
|
||||
return ValidateObjectAllowDeleted("isBuffer", buffer) &&
|
||||
!buffer->IsDeleted() &&
|
||||
buffer->HasEverBeenBound();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsFramebuffer(WebGLFramebuffer *fb)
|
||||
{
|
||||
|
@ -302,6 +302,13 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
|
||||
}
|
||||
return JS::ObjectOrNullValue(obj);
|
||||
}
|
||||
case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
|
||||
{
|
||||
if (!IsWebGL2()) {
|
||||
break;
|
||||
}
|
||||
return JS::Int32Value(mGLMaxTransformFeedbackSeparateAttribs);
|
||||
}
|
||||
|
||||
// unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
|
||||
// javascript integer values. We just return them as doubles and javascript doesn't care.
|
||||
@ -435,6 +442,14 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
|
||||
return WebGLObjectAsJSValue(cx, mBoundArrayBuffer.get(), rv);
|
||||
}
|
||||
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
|
||||
{
|
||||
if (!IsWebGL2()) {
|
||||
break;
|
||||
}
|
||||
return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv);
|
||||
}
|
||||
|
||||
case LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING:
|
||||
{
|
||||
return WebGLObjectAsJSValue(cx, mBoundVertexArray->mBoundElementArrayBuffer.get(), rv);
|
||||
@ -472,6 +487,32 @@ WebGLContext::GetParameter(JSContext* cx, WebGLenum pname, ErrorResult& rv)
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
JS::Value
|
||||
WebGLContext::GetParameterIndexed(JSContext* cx, WebGLenum pname, WebGLuint index)
|
||||
{
|
||||
if (!IsContextStable())
|
||||
return JS::NullValue();
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
switch (pname) {
|
||||
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
|
||||
{
|
||||
if (index >= mGLMaxTransformFeedbackSeparateAttribs) {
|
||||
ErrorInvalidValue("getParameterIndexed: index should be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", index);
|
||||
return JS::NullValue();
|
||||
}
|
||||
return JS::NullValue(); // See bug 903594
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ErrorInvalidEnumInfo("getParameterIndexed: parameter", pname);
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::IsEnabled(WebGLenum cap)
|
||||
{
|
||||
|
@ -223,19 +223,6 @@ bool WebGLContext::ValidateFaceEnum(WebGLenum face, const char *info)
|
||||
}
|
||||
}
|
||||
|
||||
bool WebGLContext::ValidateBufferUsageEnum(WebGLenum target, const char *info)
|
||||
{
|
||||
switch (target) {
|
||||
case LOCAL_GL_STREAM_DRAW:
|
||||
case LOCAL_GL_STATIC_DRAW:
|
||||
case LOCAL_GL_DYNAMIC_DRAW:
|
||||
return true;
|
||||
default:
|
||||
ErrorInvalidEnumInfo(info, target);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WebGLContext::ValidateDrawModeEnum(WebGLenum mode, const char *info)
|
||||
{
|
||||
switch (mode) {
|
||||
@ -820,6 +807,7 @@ WebGLContext::InitAndValidateGL()
|
||||
mBoundCubeMapTextures.Clear();
|
||||
|
||||
mBoundArrayBuffer = nullptr;
|
||||
mBoundTransformFeedbackBuffer = nullptr;
|
||||
mCurrentProgram = nullptr;
|
||||
|
||||
mBoundFramebuffer = nullptr;
|
||||
@ -919,10 +907,14 @@ WebGLContext::InitAndValidateGL()
|
||||
default:
|
||||
GenerateWarning("GL error 0x%x occurred during WebGL context initialization!", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsWebGL2()) {
|
||||
gl->GetUIntegerv(LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &mGLMaxTransformFeedbackSeparateAttribs);
|
||||
}
|
||||
|
||||
// Always 1 for GLES2
|
||||
mMaxFramebufferColorAttachments = 1;
|
||||
|
||||
|
@ -32,6 +32,7 @@ if CONFIG['MOZ_WEBGL']:
|
||||
'WebGL2Context.cpp',
|
||||
'WebGLContext.cpp',
|
||||
'WebGLContextAsyncQueries.cpp',
|
||||
'WebGLContextBuffers.cpp',
|
||||
'WebGLContextGL.cpp',
|
||||
'WebGLContextUtils.cpp',
|
||||
'WebGLContextReporter.cpp',
|
||||
|
@ -10,10 +10,11 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(TextTrack,
|
||||
mParent,
|
||||
mCueList,
|
||||
mActiveCueList)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_3(TextTrack,
|
||||
nsDOMEventTargetHelper,
|
||||
mParent,
|
||||
mCueList,
|
||||
mActiveCueList)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(TextTrack, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(TextTrack, nsDOMEventTargetHelper)
|
||||
|
@ -26,8 +26,7 @@ class TextTrack MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TextTrack,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrack, nsDOMEventTargetHelper)
|
||||
|
||||
TextTrack(nsISupports* aParent);
|
||||
TextTrack(nsISupports* aParent,
|
||||
|
@ -17,11 +17,12 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_4(TextTrackCue,
|
||||
mDocument,
|
||||
mTrack,
|
||||
mTrackElement,
|
||||
mDisplayState)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_4(TextTrackCue,
|
||||
nsDOMEventTargetHelper,
|
||||
mDocument,
|
||||
mTrack,
|
||||
mTrackElement,
|
||||
mDisplayState)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(TextTrackCue, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(TextTrackCue, nsDOMEventTargetHelper)
|
||||
|
@ -26,8 +26,7 @@ class TextTrackCue MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TextTrackCue,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrackCue, nsDOMEventTargetHelper)
|
||||
|
||||
// TextTrackCue WebIDL
|
||||
// See bug 868509 about splitting out the WebVTT-specific interfaces.
|
||||
|
@ -9,7 +9,10 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(TextTrackList, mGlobal, mTextTracks)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(TextTrackList,
|
||||
nsDOMEventTargetHelper,
|
||||
mGlobal,
|
||||
mTextTracks)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(TextTrackList, nsDOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(TextTrackList, nsDOMEventTargetHelper)
|
||||
|
@ -20,8 +20,7 @@ class TextTrackList MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(TextTrackList,
|
||||
nsDOMEventTargetHelper)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrackList, nsDOMEventTargetHelper)
|
||||
|
||||
TextTrackList(nsISupports* aGlobal);
|
||||
|
||||
|
@ -43,8 +43,7 @@ if CONFIG['MOZ_OMX_DECODER']:
|
||||
PARALLEL_DIRS += ['omx']
|
||||
PARALLEL_DIRS += ['omx/mediaresourcemanager']
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH']:
|
||||
PARALLEL_DIRS += ['webspeech']
|
||||
PARALLEL_DIRS += ['webspeech']
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
|
@ -145,6 +145,7 @@ MOCHITEST_FILES = \
|
||||
test_VideoPlaybackQuality_disabled.html \
|
||||
test_webvtt_disabled.html \
|
||||
test_playback_rate_playpause.html \
|
||||
test_bug895305.html \
|
||||
$(NULL)
|
||||
|
||||
# Disabled on Windows for frequent intermittent failures
|
||||
|
43
content/media/test/test_bug895305.html
Normal file
43
content/media/test/test_bug895305.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=895305
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=905320
|
||||
-->
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>Regression test for bug 895305 and 905320 - TextTrack* leaks</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
|
||||
function() {
|
||||
var audio = document.createElement("audio");
|
||||
// Check leaking on TextTrackList objects.
|
||||
window.ttl = audio.textTracks;
|
||||
ttl.addEventListener("click", function(){}, false);
|
||||
|
||||
// Check leaking on TextTrackCue objects.
|
||||
window.ttc = new TextTrackCue(3, 4, "Test.");
|
||||
ttc.addEventListener("click", function() {}, false);
|
||||
|
||||
// Check leaking on TextTrack objects.
|
||||
audio.addTextTrack("subtitles", "label", "en-CA");
|
||||
ttl[0].addEventListener("click", function() {}, false);
|
||||
|
||||
ok(true); // Need to have at least one assertion for Mochitest to be happy.
|
||||
SimpleTest.finish();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -3,4 +3,7 @@
|
||||
# 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/.
|
||||
|
||||
PARALLEL_DIRS = ['recognition', 'synth']
|
||||
PARALLEL_DIRS = ['synth']
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH']:
|
||||
PARALLEL_DIRS += ['recognition']
|
||||
|
@ -3,39 +3,40 @@
|
||||
# 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/.
|
||||
|
||||
MODULE = 'content'
|
||||
if CONFIG['MOZ_WEBSPEECH']:
|
||||
MODULE = 'content'
|
||||
|
||||
TEST_DIRS += ['test', 'ipc/test']
|
||||
TEST_DIRS += ['test', 'ipc/test']
|
||||
|
||||
XPIDL_MODULE = 'dom_webspeechsynth'
|
||||
XPIDL_MODULE = 'dom_webspeechsynth'
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMSpeechSynthesisEvent.idl',
|
||||
'nsISpeechService.idl',
|
||||
'nsISynthVoiceRegistry.idl'
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMSpeechSynthesisEvent.idl',
|
||||
'nsISpeechService.idl',
|
||||
'nsISynthVoiceRegistry.idl'
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'EnableSpeechSynthesisCheck.h',
|
||||
'SpeechSynthesis.h',
|
||||
'SpeechSynthesisUtterance.h',
|
||||
'SpeechSynthesisVoice.h',
|
||||
'ipc/SpeechSynthesisChild.h',
|
||||
'ipc/SpeechSynthesisParent.h',
|
||||
'nsSpeechTask.h',
|
||||
'nsSynthVoiceRegistry.h',
|
||||
]
|
||||
EXPORTS.mozilla.dom += [
|
||||
'EnableSpeechSynthesisCheck.h',
|
||||
'SpeechSynthesis.h',
|
||||
'SpeechSynthesisUtterance.h',
|
||||
'SpeechSynthesisVoice.h',
|
||||
'ipc/SpeechSynthesisChild.h',
|
||||
'ipc/SpeechSynthesisParent.h',
|
||||
'nsSpeechTask.h',
|
||||
'nsSynthVoiceRegistry.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'EnableSpeechSynthesisCheck.cpp',
|
||||
'SpeechSynthesis.cpp',
|
||||
'SpeechSynthesisChild.cpp',
|
||||
'SpeechSynthesisParent.cpp',
|
||||
'SpeechSynthesisUtterance.cpp',
|
||||
'SpeechSynthesisVoice.cpp',
|
||||
'nsSpeechTask.cpp',
|
||||
'nsSynthVoiceRegistry.cpp',
|
||||
]
|
||||
CPP_SOURCES += [
|
||||
'EnableSpeechSynthesisCheck.cpp',
|
||||
'SpeechSynthesis.cpp',
|
||||
'SpeechSynthesisChild.cpp',
|
||||
'SpeechSynthesisParent.cpp',
|
||||
'SpeechSynthesisUtterance.cpp',
|
||||
'SpeechSynthesisVoice.cpp',
|
||||
'nsSpeechTask.cpp',
|
||||
'nsSynthVoiceRegistry.cpp',
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'ipc/PSpeechSynthesis.ipdl',
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIObjectFrame.h"
|
||||
#include "nsBindingManager.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
|
@ -613,4 +613,47 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_11(_class, \
|
||||
_field1, \
|
||||
_field2, \
|
||||
_field3, \
|
||||
_field4, \
|
||||
_field5, \
|
||||
_field6, \
|
||||
_field7, \
|
||||
_field8, \
|
||||
_field9, \
|
||||
_field10, \
|
||||
_field11) \
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field1) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field2) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field3) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field4) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field5) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field6) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field7) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field8) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field9) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field10) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(_field11) \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field1) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field2) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field3) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field4) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field5) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field6) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field7) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field8) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field9) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field10) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(_field11) \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(_class)
|
||||
|
||||
#endif /* nsWrapperCache_h___ */
|
||||
|
@ -82,7 +82,9 @@ IndexedDBParent::~IndexedDBParent()
|
||||
void
|
||||
IndexedDBParent::Disconnect()
|
||||
{
|
||||
MOZ_ASSERT(!mDisconnected);
|
||||
if (mDisconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
mDisconnected = true;
|
||||
|
||||
|
@ -28,8 +28,11 @@ NoFilesSelected=No files selected.
|
||||
# %S will be a number greater or equal to 2.
|
||||
XFilesSelected=%S files selected.
|
||||
ColorPicker=Choose a color
|
||||
# LOCALIZATION NOTE (AndXMoreFiles): this string is shown at the end of the
|
||||
# tooltip text for <input type='file' multiple> when there are more than 21
|
||||
# files selected (when we will only list the first 20, plus an "and X more"
|
||||
# line). %S will be the number of files minus 20.
|
||||
AndXMoreFiles=and %S more
|
||||
# LOCALIZATION NOTE (AndNMoreFiles): Semi-colon list of plural forms.
|
||||
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# This string is shown at the end of the tooltip text for <input type='file'
|
||||
# multiple> when there are more than 21 files selected (when we will only list
|
||||
# the first 20, plus an "and X more" line). #1 represents the number of files
|
||||
# minus 20 and will always be a number equal to or greater than 2. So the
|
||||
# singular case will never be used.
|
||||
AndNMoreFiles=and one more;and #1 more
|
||||
|
@ -2018,9 +2018,19 @@ MmsService.prototype = {
|
||||
null,
|
||||
DELIVERY_STATUS_PENDING,
|
||||
null,
|
||||
this.retrieveMessage(url,
|
||||
responseNotify.bind(this),
|
||||
aDomMessage));
|
||||
(function (rv) {
|
||||
let success = Components.isSuccessCode(rv);
|
||||
if (!success) {
|
||||
if (DEBUG) debug("Could not change the delivery status: MMS " +
|
||||
domMessage.id + ", error code " + rv);
|
||||
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
this.retrieveMessage(url,
|
||||
responseNotify.bind(this),
|
||||
aDomMessage);
|
||||
}).bind(this));
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
|
@ -57,6 +57,7 @@ using mozilla::DefaultXDisplay;
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
|
||||
#include "nsContentCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
|
@ -3232,6 +3232,8 @@ RadioInterface.prototype = {
|
||||
function RILNetworkInterface(radioInterface, apnSetting) {
|
||||
this.radioInterface = radioInterface;
|
||||
this.apnSetting = apnSetting;
|
||||
|
||||
this.connectedTypes = [];
|
||||
}
|
||||
|
||||
RILNetworkInterface.prototype = {
|
||||
@ -3402,12 +3404,12 @@ RILNetworkInterface.prototype = {
|
||||
registeredAsDataCallCallback: false,
|
||||
registeredAsNetworkInterface: false,
|
||||
connecting: false,
|
||||
apnSetting: {},
|
||||
apnSetting: null,
|
||||
|
||||
// APN failed connections. Retry counter
|
||||
apnRetryCounter: 0,
|
||||
|
||||
connectedTypes: [],
|
||||
connectedTypes: null,
|
||||
|
||||
inConnectedTypes: function inConnectedTypes(type) {
|
||||
return this.connectedTypes.indexOf(type) != -1;
|
||||
|
@ -70,7 +70,20 @@ interface WebGL2RenderingContext : WebGLRenderingContext {
|
||||
void vertexAttribDivisor(GLuint index, GLuint divisor);
|
||||
|
||||
/* transform feedback */
|
||||
const GLenum RASTERIZER_DISCARD = 0x8C89;
|
||||
const GLenum RASTERIZER_DISCARD = 0x8C89;
|
||||
const GLenum TRANSFORM_FEEDBACK_BUFFER = 0x8C8E;
|
||||
const GLenum TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F;
|
||||
const GLenum TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84;
|
||||
const GLenum TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85;
|
||||
const GLenum MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B;
|
||||
|
||||
/* buffer objects */
|
||||
void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer);
|
||||
void bindBufferRange(GLenum target, GLuint index, WebGLBuffer? buffer,
|
||||
GLintptr offset, GLsizeiptr size);
|
||||
|
||||
/* state requests */
|
||||
any getParameterIndexed(GLenum pname, GLuint index);
|
||||
|
||||
|
||||
void beginQuery(GLenum target, WebGLQuery? queryObject);
|
||||
|
@ -164,7 +164,11 @@ var WifiManager = (function() {
|
||||
|
||||
var driverLoaded = false;
|
||||
|
||||
manager.getDriverLoaded = function() { return driverLoaded; }
|
||||
manager.checkDriverState = function(expectState) {
|
||||
if (!unloadDriverEnabled)
|
||||
return true;
|
||||
return (expectState === driverLoaded);
|
||||
}
|
||||
|
||||
function loadDriver(callback) {
|
||||
if (driverLoaded) {
|
||||
@ -2843,7 +2847,7 @@ WifiWorker.prototype = {
|
||||
|
||||
// First, notify all of the requests that were trying to make this change.
|
||||
let state = this._stateRequests[0].enabled;
|
||||
let driverLoaded = WifiManager.getDriverLoaded();
|
||||
let driverReady = WifiManager.checkDriverState(newState);
|
||||
|
||||
// It is callback function's responsibility to handle the pending request.
|
||||
// So we just return here.
|
||||
@ -2857,7 +2861,7 @@ WifiWorker.prototype = {
|
||||
// were racing somehow) so don't notify.
|
||||
// For newState is false(disable), we expect driverLoaded is false(driver unloaded)
|
||||
// to proceed, and vice versa.
|
||||
if (!success || (newState === driverLoaded && state === newState)) {
|
||||
if (!success || (driverReady && state === newState)) {
|
||||
do {
|
||||
if (!("callback" in this._stateRequests[0])) {
|
||||
this._stateRequests.shift();
|
||||
@ -2873,8 +2877,8 @@ WifiWorker.prototype = {
|
||||
let self = this;
|
||||
let callback = null;
|
||||
this._callbackTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
if (newState === driverLoaded) {
|
||||
// Driver status is as same as new state, proceed next request.
|
||||
if (driverReady) {
|
||||
// Driver is ready for next request.
|
||||
callback = function(timer) {
|
||||
if ("callback" in self._stateRequests[0]) {
|
||||
self._stateRequests[0].callback.call(self, self._stateRequests[0].enabled);
|
||||
@ -2885,7 +2889,7 @@ WifiWorker.prototype = {
|
||||
timer = null;
|
||||
};
|
||||
} else {
|
||||
// Driver status is not as same as new state, wait driver.
|
||||
// Wait driver until it's ready.
|
||||
callback = function(timer) {
|
||||
self._notifyAfterStateChange(success, newState);
|
||||
timer = null;
|
||||
|
@ -654,6 +654,95 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(XXX_transform_feedback)) {
|
||||
SymLoadStruct transformFeedbackSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fBindBufferBase,
|
||||
{ "BindBufferBase",
|
||||
"BindBufferBaseEXT",
|
||||
"BindBufferBaseNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ (PRFuncPtr*) &mSymbols.fBindBufferRange,
|
||||
{ "BindBufferRange",
|
||||
"BindBufferRangeEXT",
|
||||
"BindBufferRangeNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ (PRFuncPtr*) &mSymbols.fBeginTransformFeedback,
|
||||
{ "BeginTransformFeedback",
|
||||
"BeginTransformFeedbackEXT",
|
||||
"BeginTransformFeedbackNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ (PRFuncPtr*) &mSymbols.fEndTransformFeedback,
|
||||
{ "EndTransformFeedback",
|
||||
"EndTransformFeedbackEXT",
|
||||
"EndTransformFeedbackNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings,
|
||||
{ "TransformFeedbackVaryings",
|
||||
"TransformFeedbackVaryingsEXT",
|
||||
"TransformFeedbackVaryingsNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying,
|
||||
{ "GetTransformFeedbackVarying",
|
||||
"GetTransformFeedbackVaryingEXT",
|
||||
"GetTransformFeedbackVaryingNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ (PRFuncPtr*) &mSymbols.fGetIntegeri_v,
|
||||
{ "GetIntegeri_v",
|
||||
"GetIntegerIndexedvEXT",
|
||||
"GetIntegerIndexedvNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ nullptr, { nullptr } },
|
||||
};
|
||||
|
||||
if (!LoadSymbols(transformFeedbackSymbols, trygl, prefix)) {
|
||||
NS_ERROR("GL supports transform feedback without supplying its functions.");
|
||||
|
||||
MarkExtensionGroupUnsupported(XXX_transform_feedback);
|
||||
MarkExtensionGroupUnsupported(XXX_bind_buffer_offset);
|
||||
mSymbols.fBindBufferBase = nullptr;
|
||||
mSymbols.fBindBufferRange = nullptr;
|
||||
mSymbols.fBeginTransformFeedback = nullptr;
|
||||
mSymbols.fEndTransformFeedback = nullptr;
|
||||
mSymbols.fTransformFeedbackVaryings = nullptr;
|
||||
mSymbols.fGetTransformFeedbackVarying = nullptr;
|
||||
mSymbols.fGetIntegeri_v = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(XXX_bind_buffer_offset)) {
|
||||
SymLoadStruct bindBufferOffsetSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fBindBufferOffset,
|
||||
{ "BindBufferOffset",
|
||||
"BindBufferOffsetEXT",
|
||||
"BindBufferOffsetNV",
|
||||
nullptr
|
||||
}
|
||||
},
|
||||
{ nullptr, { nullptr } },
|
||||
};
|
||||
|
||||
if (!LoadSymbols(bindBufferOffsetSymbols, trygl, prefix)) {
|
||||
NS_ERROR("GL supports BindBufferOffset without supplying its function.");
|
||||
|
||||
MarkExtensionGroupUnsupported(XXX_bind_buffer_offset);
|
||||
mSymbols.fBindBufferOffset = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsExtensionSupported(XXX_query_objects)) {
|
||||
SymLoadStruct queryObjectsSymbols[] = {
|
||||
{ (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", "BeginQueryEXT", nullptr } },
|
||||
|
@ -474,6 +474,7 @@ public:
|
||||
* This enum should be sorted by name.
|
||||
*/
|
||||
enum GLExtensionGroup {
|
||||
XXX_bind_buffer_offset,
|
||||
XXX_depth_texture,
|
||||
XXX_draw_buffers,
|
||||
XXX_draw_instanced,
|
||||
@ -2034,6 +2035,18 @@ public:
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Package XXX_bind_buffer_offset
|
||||
public:
|
||||
void fBindBufferOffset(GLenum target, GLuint index, GLuint buffer, GLintptr offset)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fBindBufferOffset);
|
||||
mSymbols.fBindBufferOffset(target, index, buffer, offset);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Package XXX_draw_buffers
|
||||
public:
|
||||
@ -2187,6 +2200,66 @@ public:
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Package XXX_transform_feedback
|
||||
public:
|
||||
void fBindBufferBase(GLenum target, GLuint index, GLuint buffer)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fBindBufferBase);
|
||||
mSymbols.fBindBufferBase(target, index, buffer);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fBindBufferRange);
|
||||
mSymbols.fBindBufferRange(target, index, buffer, offset, size);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fBeginTransformFeedback(GLenum primitiveMode)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fBeginTransformFeedback);
|
||||
mSymbols.fBeginTransformFeedback(primitiveMode);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fEndTransformFeedback()
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fEndTransformFeedback);
|
||||
mSymbols.fEndTransformFeedback();
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fTransformFeedbackVaryings);
|
||||
mSymbols.fTransformFeedbackVaryings(program, count, varyings, bufferMode);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fGetTransformFeedbackVarying);
|
||||
mSymbols.fGetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
void fGetIntegeri_v(GLenum param, GLuint index, GLint* values)
|
||||
{
|
||||
BEFORE_GL_CALL;
|
||||
ASSERT_SYMBOL_PRESENT(fGetIntegeri_v);
|
||||
mSymbols.fGetIntegeri_v(param, index, values);
|
||||
AFTER_GL_CALL;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Package XXX_vertex_array_object
|
||||
public:
|
||||
|
@ -27,6 +27,16 @@ struct ExtensionGroupInfo
|
||||
};
|
||||
|
||||
static const ExtensionGroupInfo sExtensionGroupInfoArr[] = {
|
||||
{
|
||||
"XXX_bind_buffer_offset",
|
||||
0, // OpenGL version
|
||||
0, // OpenGL ES version
|
||||
{
|
||||
GLContext::EXT_transform_feedback,
|
||||
GLContext::NV_transform_feedback,
|
||||
GLContext::Extensions_End
|
||||
}
|
||||
},
|
||||
{
|
||||
"XXX_depth_texture",
|
||||
200, // OpenGL version
|
||||
|
@ -263,6 +263,7 @@ GLXLibrary::EnsureInitialized(LibType libType)
|
||||
}
|
||||
|
||||
mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
|
||||
mIsNVIDIA = serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
|
||||
mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
|
||||
|
||||
mInitialized = true;
|
||||
@ -367,7 +368,10 @@ GLXLibrary::CreatePixmap(gfxASurface* aSurface)
|
||||
// again).
|
||||
//
|
||||
// This checks that the depth matches in one of the two ways.
|
||||
if (depth != format->depth && depth != format->depth - alphaSize) {
|
||||
// NVIDIA now forces format->depth == depth so only the first way
|
||||
// is checked for NVIDIA
|
||||
if (depth != format->depth &&
|
||||
(mIsNVIDIA || depth != format->depth - alphaSize) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,29 @@ struct GLContextSymbols
|
||||
// ARB_instanced_array
|
||||
typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISOR) (GLuint index, GLuint divisor);
|
||||
PFNGLVERTEXATTRIBDIVISOR fVertexAttribDivisor;
|
||||
|
||||
// EXT_transform_feedback / OpenGL (ES) 3.0
|
||||
typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASE) (GLenum target, GLuint index, GLuint buffer);
|
||||
PFNGLBINDBUFFERBASE fBindBufferBase;
|
||||
typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGE) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
|
||||
PFNGLBINDBUFFERRANGE fBindBufferRange;
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACK) (GLenum primitiveMode);
|
||||
PFNGLBEGINTRANSFORMFEEDBACK fBeginTransformFeedback;
|
||||
typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACK) (void);
|
||||
PFNGLENDTRANSFORMFEEDBACK fEndTransformFeedback;
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGS) (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode);
|
||||
PFNGLTRANSFORMFEEDBACKVARYINGS fTransformFeedbackVaryings;
|
||||
typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYING) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
|
||||
PFNGLGETTRANSFORMFEEDBACKVARYING fGetTransformFeedbackVarying;
|
||||
|
||||
typedef void (GLAPIENTRY * PFNGLGETINTEGERI_V) (GLenum param, GLuint index, GLint* values);
|
||||
PFNGLGETINTEGERI_V fGetIntegeri_v;
|
||||
|
||||
// EXT_transform_feedback only
|
||||
typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSET) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
|
||||
PFNGLBINDBUFFEROFFSET fBindBufferOffset;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class GLXLibrary
|
||||
public:
|
||||
GLXLibrary() : mInitialized(false), mTriedInitializing(false),
|
||||
mUseTextureFromPixmap(false), mDebug(false),
|
||||
mHasRobustness(false), mIsATI(false),
|
||||
mHasRobustness(false), mIsATI(false), mIsNVIDIA(false),
|
||||
mClientIsMesa(false), mGLXMajorVersion(0),
|
||||
mGLXMinorVersion(0), mLibType(OPENGL_LIB),
|
||||
mOGLLibrary(nullptr) {}
|
||||
@ -202,6 +202,7 @@ private:
|
||||
bool mDebug;
|
||||
bool mHasRobustness;
|
||||
bool mIsATI;
|
||||
bool mIsNVIDIA;
|
||||
bool mClientIsMesa;
|
||||
int mGLXMajorVersion;
|
||||
int mGLXMinorVersion;
|
||||
|
@ -343,6 +343,7 @@ Decoder::PostFrameStop(FrameBlender::FrameAlpha aFrameAlpha /* = FrameBlender::k
|
||||
mCurrentFrame->SetFrameDisposalMethod(aDisposalMethod);
|
||||
mCurrentFrame->SetTimeout(aTimeout);
|
||||
mCurrentFrame->SetBlendMethod(aBlendMethod);
|
||||
mCurrentFrame->ImageUpdated(mCurrentFrame->GetRect());
|
||||
|
||||
// Flush any invalidations before we finish the frame
|
||||
FlushInvalidations();
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsReadLine.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define CONVERTER_BUFFER_SIZE 8192
|
||||
@ -39,11 +40,10 @@ nsConverterInputStream::Init(nsIInputStream* aStream,
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// set up our buffers
|
||||
rv = NS_NewByteBuffer(getter_AddRefs(mByteData), nullptr, aBufferSize);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = NS_NewUnicharBuffer(getter_AddRefs(mUnicharData), nullptr, aBufferSize);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!mByteData.SetCapacity(aBufferSize) ||
|
||||
!mUnicharData.SetCapacity(aBufferSize)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mInput = aStream;
|
||||
mReplacementChar = aReplacementChar;
|
||||
@ -62,8 +62,8 @@ nsConverterInputStream::Close()
|
||||
mLineBuffer = nullptr;
|
||||
mInput = nullptr;
|
||||
mConverter = nullptr;
|
||||
mByteData = nullptr;
|
||||
mUnicharData = nullptr;
|
||||
mByteData.Clear();
|
||||
mUnicharData.Clear();
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -85,7 +85,7 @@ nsConverterInputStream::Read(PRUnichar* aBuf,
|
||||
if (readCount > aCount) {
|
||||
readCount = aCount;
|
||||
}
|
||||
memcpy(aBuf, mUnicharData->GetBuffer() + mUnicharDataOffset,
|
||||
memcpy(aBuf, mUnicharData.Elements() + mUnicharDataOffset,
|
||||
readCount * sizeof(PRUnichar));
|
||||
mUnicharDataOffset += readCount;
|
||||
*aReadCount = readCount;
|
||||
@ -117,7 +117,7 @@ nsConverterInputStream::ReadSegments(nsWriteUnicharSegmentFun aWriter,
|
||||
|
||||
while (bytesToWrite) {
|
||||
rv = aWriter(this, aClosure,
|
||||
mUnicharData->GetBuffer() + mUnicharDataOffset,
|
||||
mUnicharData.Elements() + mUnicharDataOffset,
|
||||
totalBytesWritten, bytesToWrite, &bytesWritten);
|
||||
if (NS_FAILED(rv)) {
|
||||
// don't propagate errors to the caller
|
||||
@ -152,8 +152,7 @@ nsConverterInputStream::ReadString(uint32_t aCount, nsAString& aString,
|
||||
if (readCount > aCount) {
|
||||
readCount = aCount;
|
||||
}
|
||||
const PRUnichar* buf = reinterpret_cast<const PRUnichar*>(mUnicharData->GetBuffer() +
|
||||
mUnicharDataOffset);
|
||||
const PRUnichar* buf = mUnicharData.Elements() + mUnicharDataOffset;
|
||||
aString.Assign(buf, readCount);
|
||||
mUnicharDataOffset += readCount;
|
||||
*aReadCount = readCount;
|
||||
@ -182,32 +181,27 @@ nsConverterInputStream::Fill(nsresult * aErrorCode)
|
||||
// to n+1 unicode chars. Thus we need to keep track of the leftover
|
||||
// bytes as we convert.
|
||||
|
||||
int32_t nb = mByteData->Fill(aErrorCode, mInput, mLeftOverBytes);
|
||||
#if defined(DEBUG_bzbarsky) && 0
|
||||
for (unsigned int foo = 0; foo < mByteData->GetLength(); ++foo) {
|
||||
fprintf(stderr, "%c", mByteData->GetBuffer()[foo]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
if (nb <= 0 && mLeftOverBytes == 0) {
|
||||
uint32_t nb;
|
||||
*aErrorCode = NS_FillArray(mByteData, mInput, mLeftOverBytes, &nb);
|
||||
if (nb == 0 && mLeftOverBytes == 0) {
|
||||
// No more data
|
||||
*aErrorCode = NS_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_ASSERTION(uint32_t(nb) + mLeftOverBytes == mByteData->GetLength(),
|
||||
NS_ASSERTION(uint32_t(nb) + mLeftOverBytes == mByteData.Length(),
|
||||
"mByteData is lying to us somewhere");
|
||||
|
||||
|
||||
// Now convert as much of the byte buffer to unicode as possible
|
||||
mUnicharDataOffset = 0;
|
||||
mUnicharDataLength = 0;
|
||||
uint32_t srcConsumed = 0;
|
||||
do {
|
||||
int32_t srcLen = mByteData->GetLength() - srcConsumed;
|
||||
int32_t dstLen = mUnicharData->GetBufferSize() - mUnicharDataLength;
|
||||
*aErrorCode = mConverter->Convert(mByteData->GetBuffer()+srcConsumed,
|
||||
int32_t srcLen = mByteData.Length() - srcConsumed;
|
||||
int32_t dstLen = mUnicharData.Capacity() - mUnicharDataLength;
|
||||
*aErrorCode = mConverter->Convert(mByteData.Elements()+srcConsumed,
|
||||
&srcLen,
|
||||
mUnicharData->GetBuffer()+mUnicharDataLength,
|
||||
mUnicharData.Elements()+mUnicharDataLength,
|
||||
&dstLen);
|
||||
mUnicharDataLength += dstLen;
|
||||
// XXX if srcLen is negative, we want to drop the _first_ byte in
|
||||
@ -215,23 +209,23 @@ nsConverterInputStream::Fill(nsresult * aErrorCode)
|
||||
// possible right now -- see bug 160784
|
||||
srcConsumed += srcLen;
|
||||
if (NS_FAILED(*aErrorCode) && mReplacementChar) {
|
||||
NS_ASSERTION(0 < mUnicharData->GetBufferSize() - mUnicharDataLength,
|
||||
NS_ASSERTION(0 < mUnicharData.Capacity() - mUnicharDataLength,
|
||||
"Decoder returned an error but filled the output buffer! "
|
||||
"Should not happen.");
|
||||
mUnicharData->GetBuffer()[mUnicharDataLength++] = mReplacementChar;
|
||||
mUnicharData.Elements()[mUnicharDataLength++] = mReplacementChar;
|
||||
++srcConsumed;
|
||||
// XXX this is needed to make sure we don't underrun our buffer;
|
||||
// bug 160784 again
|
||||
srcConsumed = std::max<uint32_t>(srcConsumed, 0);
|
||||
mConverter->Reset();
|
||||
}
|
||||
NS_ASSERTION(srcConsumed <= mByteData->GetLength(),
|
||||
NS_ASSERTION(srcConsumed <= mByteData.Length(),
|
||||
"Whoa. The converter should have returned NS_OK_UDEC_MOREINPUT before this point!");
|
||||
} while (mReplacementChar &&
|
||||
NS_FAILED(*aErrorCode) &&
|
||||
uint32_t(mUnicharData->GetBufferSize()) > mUnicharDataLength);
|
||||
mUnicharData.Capacity() > mUnicharDataLength);
|
||||
|
||||
mLeftOverBytes = mByteData->GetLength() - srcConsumed;
|
||||
mLeftOverBytes = mByteData.Length() - srcConsumed;
|
||||
|
||||
return mUnicharDataLength;
|
||||
}
|
||||
|
@ -7,12 +7,10 @@
|
||||
#include "nsIConverterInputStream.h"
|
||||
#include "nsIUnicharLineInputStream.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
#include "nsIByteBuffer.h"
|
||||
#include "nsIUnicharBuffer.h"
|
||||
#include "nsReadLine.h"
|
||||
|
||||
#define NS_CONVERTERINPUTSTREAM_CONTRACTID "@mozilla.org/intl/converter-input-stream;1"
|
||||
@ -49,8 +47,8 @@ class nsConverterInputStream : public nsIConverterInputStream,
|
||||
uint32_t Fill(nsresult *aErrorCode);
|
||||
|
||||
nsCOMPtr<nsIUnicodeDecoder> mConverter;
|
||||
nsCOMPtr<nsIByteBuffer> mByteData;
|
||||
nsCOMPtr<nsIUnicharBuffer> mUnicharData;
|
||||
FallibleTArray<char> mByteData;
|
||||
FallibleTArray<PRUnichar> mUnicharData;
|
||||
nsCOMPtr<nsIInputStream> mInput;
|
||||
|
||||
nsresult mLastErrorCode;
|
||||
|
@ -19,9 +19,32 @@ MOZ_CONFIG_LOG_TRAP
|
||||
|
||||
dnl Disable the trap when running sub-configures.
|
||||
define([_MOZ_AC_OUTPUT_SUBDIRS], defn([AC_OUTPUT_SUBDIRS]))
|
||||
define([MOZ_SUBCONFIGURE_WRAP],
|
||||
[ _CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
case "$host" in
|
||||
*-mingw*)
|
||||
_CONFIG_SHELL=$(cd $(dirname $_CONFIG_SHELL); pwd -W)/$(basename $_CONFIG_SHELL)
|
||||
if test ! -e "$_CONFIG_SHELL" -a -e "${_CONFIG_SHELL}.exe"; then
|
||||
_CONFIG_SHELL="${_CONFIG_SHELL}.exe"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -d "$1"; then
|
||||
(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py dump "$_CONFIG_SHELL")
|
||||
fi
|
||||
$2
|
||||
(cd "$1"; $PYTHON $_topsrcdir/build/subconfigure.py adjust)
|
||||
])
|
||||
|
||||
define([AC_OUTPUT_SUBDIRS],
|
||||
[trap '' EXIT
|
||||
_MOZ_AC_OUTPUT_SUBDIRS($1)
|
||||
for moz_config_dir in $1; do
|
||||
MOZ_SUBCONFIGURE_WRAP([$moz_config_dir],[
|
||||
_MOZ_AC_OUTPUT_SUBDIRS($moz_config_dir)
|
||||
])
|
||||
done
|
||||
|
||||
MOZ_CONFIG_LOG_TRAP
|
||||
])
|
||||
|
||||
|
124
js/src/build/subconfigure.py
Normal file
124
js/src/build/subconfigure.py
Normal file
@ -0,0 +1,124 @@
|
||||
# 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/.
|
||||
|
||||
# This script is used to capture the content of config.status-generated
|
||||
# files and subsequently restore their timestamp if they haven't changed.
|
||||
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import pickle
|
||||
|
||||
class File(object):
|
||||
def __init__(self, path):
|
||||
self._path = path
|
||||
self._content = open(path, 'rb').read()
|
||||
stat = os.stat(path)
|
||||
self._times = (stat.st_atime, stat.st_mtime)
|
||||
|
||||
def update_time(self):
|
||||
'''If the file hasn't changed since the instance was created,
|
||||
restore its old modification time.'''
|
||||
if not os.path.exists(self._path):
|
||||
return
|
||||
if open(self._path, 'rb').read() == self._content:
|
||||
os.utime(self._path, self._times)
|
||||
|
||||
|
||||
# As defined in the various sub-configures in the tree
|
||||
PRECIOUS_VARS = set([
|
||||
'build_alias',
|
||||
'host_alias',
|
||||
'target_alias',
|
||||
'CC',
|
||||
'CFLAGS',
|
||||
'LDFLAGS',
|
||||
'LIBS',
|
||||
'CPPFLAGS',
|
||||
'CPP',
|
||||
'CCC',
|
||||
'CXXFLAGS',
|
||||
'CXX',
|
||||
'CCASFLAGS',
|
||||
'CCAS',
|
||||
])
|
||||
|
||||
|
||||
# Autoconf, in some of the sub-configures used in the tree, likes to error
|
||||
# out when "precious" variables change in value. The solution it gives to
|
||||
# straighten things is to either run make distclean or remove config.cache.
|
||||
# There's no reason not to do the latter automatically instead of failing,
|
||||
# doing the cleanup (which, on buildbots means a full clobber), and
|
||||
# restarting from scratch.
|
||||
def maybe_clear_cache():
|
||||
comment = re.compile(r'^\s+#')
|
||||
cache = {}
|
||||
with open('config.cache') as f:
|
||||
for line in f.readlines():
|
||||
if not comment.match(line) and '=' in line:
|
||||
key, value = line.split('=', 1)
|
||||
cache[key] = value
|
||||
for precious in PRECIOUS_VARS:
|
||||
entry = 'ac_cv_env_%s_value' % precious
|
||||
if entry in cache and (not precious in os.environ or os.environ[precious] != cache[entry]):
|
||||
os.remove('config.cache')
|
||||
return
|
||||
|
||||
|
||||
def dump(dump_file, shell):
|
||||
if os.path.exists('config.cache'):
|
||||
maybe_clear_cache()
|
||||
if not os.path.exists('config.status'):
|
||||
if os.path.exists(dump_file):
|
||||
os.remove(dump_file)
|
||||
return
|
||||
|
||||
config_files = [File('config.status')]
|
||||
|
||||
# Scan the config.status output for information about configuration files
|
||||
# it generates.
|
||||
config_status_output = subprocess.check_output(
|
||||
[shell, '-c', './config.status --help'],
|
||||
stderr=subprocess.STDOUT).splitlines()
|
||||
state = None
|
||||
for line in config_status_output:
|
||||
if line.startswith('Configuration') and line.endswith(':'):
|
||||
state = 'config'
|
||||
elif not line.startswith(' '):
|
||||
state = None
|
||||
elif state == 'config':
|
||||
for f in (couple.split(':')[0] for couple in line.split()):
|
||||
if os.path.isfile(f):
|
||||
config_files.append(File(f))
|
||||
|
||||
with open(dump_file, 'wb') as f:
|
||||
pickle.dump(config_files, f)
|
||||
|
||||
|
||||
def adjust(dump_file):
|
||||
if not os.path.exists(dump_file):
|
||||
return
|
||||
|
||||
config_files = []
|
||||
|
||||
try:
|
||||
with open(dump_file, 'rb') as f:
|
||||
config_files = pickle.load(f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
for f in config_files:
|
||||
f.update_time()
|
||||
|
||||
os.remove(dump_file)
|
||||
|
||||
|
||||
CONFIG_DUMP = 'config_files.pkl'
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.argv[1] == 'dump':
|
||||
dump(CONFIG_DUMP, sys.argv[2])
|
||||
elif sys.argv[1] == 'adjust':
|
||||
adjust(CONFIG_DUMP)
|
@ -12,9 +12,9 @@ PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
export_tier_%:
|
||||
$(addprefix export_tier_,$(TIERS)): export_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,export,$(dir)))
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,export,$(dir),export))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
|
@ -12,9 +12,9 @@ PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
libs_tier_%:
|
||||
$(addprefix libs_tier_,$(TIERS)): libs_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,libs,$(dir)))
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,libs,$(dir),libs))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
@ -43,7 +43,7 @@ GARBAGE += $(foreach lib,$(LIBRARY),$(EXPORT_LIBRARY)/$(lib))
|
||||
endif
|
||||
endif # EXPORT_LIBRARY
|
||||
|
||||
libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
|
||||
libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS)
|
||||
ifndef NO_DIST_INSTALL
|
||||
ifdef SHARED_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
@ -118,16 +118,6 @@ HOST_LIBRARY_DEST ?= $(DIST)/host/lib
|
||||
INSTALL_TARGETS += HOST_LIBRARY
|
||||
endif
|
||||
|
||||
ifdef JAVA_LIBRARY
|
||||
JAVA_LIBRARY_FILES = $(JAVA_LIBRARY)
|
||||
ifdef IS_COMPONENT
|
||||
JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)/components
|
||||
else
|
||||
JAVA_LIBRARY_DEST ?= $(FINAL_TARGET)
|
||||
endif
|
||||
INSTALL_TARGETS += JAVA_LIBRARY
|
||||
endif
|
||||
|
||||
endif # !NO_DIST_INSTALL
|
||||
|
||||
# EOF
|
||||
|
@ -12,9 +12,9 @@ PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
|
||||
###############
|
||||
## TIER targets
|
||||
###############
|
||||
tools_tier_%:
|
||||
$(addprefix tools_tier_,$(TIERS)): tools_tier_%:
|
||||
@$(ECHO) "$@"
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,tools,$(dir)))
|
||||
$(foreach dir,$(tier_$*_dirs),$(call TIER_DIR_SUBMAKE,$*,tools,$(dir),tools))
|
||||
|
||||
#################
|
||||
## Common targets
|
||||
|
@ -30,6 +30,7 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
|
||||
TEST_DIRS \
|
||||
TIERS \
|
||||
TOOL_DIRS \
|
||||
XPCSHELL_TESTS \
|
||||
XPIDL_MODULE \
|
||||
$(NULL)
|
||||
|
||||
@ -303,10 +304,6 @@ LIBRARY := $(NULL)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef JAVA_LIBRARY_NAME
|
||||
JAVA_LIBRARY := $(JAVA_LIBRARY_NAME).jar
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
ifndef GNU_CC
|
||||
|
||||
@ -433,8 +430,9 @@ UPDATE_TITLE = printf "\033]0;%s in %s\007" $(1) $(shell $(BUILD_TOOLS)/print-de
|
||||
endif
|
||||
|
||||
ifdef MACH
|
||||
BUILDSTATUS=@echo BUILDSTATUS $1
|
||||
BUILDSTATUS=@echo "BUILDSTATUS $1"
|
||||
endif
|
||||
|
||||
# Static directories are largely independent of our build system. But, they
|
||||
# could share the same build mechanism (like moz.build files). We need to
|
||||
# prevent leaking of our backend state to these independent build systems. This
|
||||
@ -447,9 +445,9 @@ define SUBMAKE # $(call SUBMAKE,target,directory,static)
|
||||
endef # The extra line is important here! don't delete it
|
||||
|
||||
define TIER_DIR_SUBMAKE
|
||||
$(call BUILDSTATUS,TIERDIR_START $(2))
|
||||
$(call SUBMAKE,$(1),$(2),$(3))
|
||||
$(call BUILDSTATUS,TIERDIR_FINISH $(2))
|
||||
$(call BUILDSTATUS,TIERDIR_START $(1) $(2) $(3))
|
||||
$(call SUBMAKE,$(4),$(3),$(5))
|
||||
$(call BUILDSTATUS,TIERDIR_FINISH $(1) $(2) $(3))
|
||||
|
||||
endef # Ths empty line is important.
|
||||
|
||||
@ -707,7 +705,7 @@ alldep::
|
||||
endif # TIERS
|
||||
endif # SUPPRESS_DEFAULT_RULES
|
||||
|
||||
ifeq ($(filter s,$(MAKEFLAGS)),)
|
||||
ifeq ($(findstring s,$(filter-out --%, $(MAKEFLAGS))),)
|
||||
ECHO := echo
|
||||
QUIET :=
|
||||
else
|
||||
@ -716,32 +714,38 @@ QUIET := -q
|
||||
endif
|
||||
|
||||
# This function is called and evaluated to produce the rule to build the
|
||||
# specified tier. Each tier begins by building the "static" directories.
|
||||
# The BUILDSTATUS echo commands are used to faciliate easier parsing
|
||||
# of build output. Build drivers are encouraged to filter these lines
|
||||
# from the user.
|
||||
# specified tier.
|
||||
#
|
||||
# Tiers are traditionally composed of directories that are invoked either
|
||||
# once (so-called "static" directories) or 3 times with the export, libs, and
|
||||
# tools sub-tiers.
|
||||
#
|
||||
# If the TIER_$(tier)_CUSTOM variable is defined, then these traditional
|
||||
# tier rules are ignored and each directory in the tier is executed via a
|
||||
# sub-make invocation (make -C).
|
||||
define CREATE_TIER_RULE
|
||||
tier_$(1)::
|
||||
$(call BUILDSTATUS,TIER_START $(1))
|
||||
$(call BUILDSTATUS,SUBTIERS $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools))
|
||||
$(call BUILDSTATUS,STATICDIRS $$($$@_staticdirs))
|
||||
$(call BUILDSTATUS,DIRS $$($$@_dirs))
|
||||
ifdef TIER_$(1)_CUSTOM
|
||||
$$(foreach dir,$$($$@_dirs),$$(call SUBMAKE,,$$(dir)))
|
||||
else
|
||||
$(call BUILDSTATUS,TIER_START $(1) $(if $(tier_$(1)_staticdirs),static )$(if $(tier_$(1)_dirs),export libs tools))
|
||||
ifneq (,$(tier_$(1)_staticdirs))
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) static)
|
||||
$$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,,$$(dir),1))
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) static $$($$@_staticdirs))
|
||||
$$(foreach dir,$$($$@_staticdirs),$$(call TIER_DIR_SUBMAKE,$(1),static,$$(dir),,1))
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) static)
|
||||
endif
|
||||
ifneq (,$(tier_$(1)_dirs))
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) export)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) export $$($$@_dirs))
|
||||
$$(MAKE) export_$$@
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) export)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) libs)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) libs $$($$@_dirs))
|
||||
$$(MAKE) libs_$$@
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) libs)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) tools)
|
||||
$(call BUILDSTATUS,SUBTIER_START $(1) tools $$($$@_dirs))
|
||||
$$(MAKE) tools_$$@
|
||||
$(call BUILDSTATUS,SUBTIER_FINISH $(1) tools)
|
||||
$(call BUILDSTATUS TIER_FINISH $(1))
|
||||
endif
|
||||
$(call BUILDSTATUS,TIER_FINISH $(1))
|
||||
endif
|
||||
endef
|
||||
|
||||
@ -1136,15 +1140,15 @@ $(COBJS):
|
||||
# DEFINES and ACDEFINES are needed here to enable conditional compilation of Q_OBJECTs:
|
||||
# 'moc' only knows about #defines it gets on the command line (-D...), not in
|
||||
# included headers like mozilla-config.h
|
||||
moc_%.cpp: %.h
|
||||
$(filter moc_%.cpp,$(CPPSRCS)): moc_%.cpp: %.h
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $< $(OUTOPTION)$@
|
||||
|
||||
moc_%.cc: %.cc
|
||||
$(filter moc_%.cc,$(CPPSRCS)): moc_%.cc: %.cc
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(MOC) $(DEFINES) $(ACDEFINES) $(_VPATH_SRCS:.cc=.h) $(OUTOPTION)$@
|
||||
|
||||
qrc_%.cpp: %.qrc
|
||||
$(filter qrc_%.cpp,$(CPPSRCS)): qrc_%.cpp: %.qrc
|
||||
$(REPORT_BUILD)
|
||||
$(ELOG) $(RCC) -name $* $< $(OUTOPTION)$@
|
||||
|
||||
@ -1175,35 +1179,35 @@ $(CMOBJS):
|
||||
@$(MAKE_DEPS_AUTO_CC)
|
||||
$(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.s,$(CPPSRCS:%.cpp=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.s,$(CPPSRCS:%.cc=%.s)): %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -S $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.s: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.s,$(CSRCS:%.c=%.s)): %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CC) -S $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
|
||||
|
||||
%.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CPPSRCS:%.cpp=%.i)): %.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CPPSRCS:%.cc=%.i)): %.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -C -E $(COMPILE_CXXFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.i: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CSRCS:%.c=%.i)): %.i: %.c $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CC) -C -E $(COMPILE_CFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(filter %.i,$(CMMSRCS:%.mm=%.i)): %.i: %.mm $(call mkdir_deps,$(MDDEPDIR))
|
||||
$(REPORT_BUILD)
|
||||
$(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS) > $*.i
|
||||
|
||||
%.res: %.rc
|
||||
$(RESFILE): %.res: %.rc
|
||||
$(REPORT_BUILD)
|
||||
@echo Creating Resource file: $@
|
||||
ifeq ($(OS_ARCH),OS2)
|
||||
@ -1216,21 +1220,11 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
# Cancel these implicit rules
|
||||
#
|
||||
%: %,v
|
||||
# Cancel GNU make built-in implicit rules
|
||||
ifndef .PYMAKE
|
||||
MAKEFLAGS += -r
|
||||
endif
|
||||
|
||||
%: RCS/%,v
|
||||
|
||||
%: RCS/%
|
||||
|
||||
%: s.%
|
||||
|
||||
%: SCCS/s.%
|
||||
|
||||
###############################################################################
|
||||
# Java rules
|
||||
###############################################################################
|
||||
ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
|
||||
SEP := ;
|
||||
else
|
||||
@ -1255,40 +1249,13 @@ else
|
||||
normalizepath = $(1)
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Java rules
|
||||
###############################################################################
|
||||
ifneq (,$(value JAVAFILES)$(value RESFILES))
|
||||
include $(topsrcdir)/config/makefiles/java-build.mk
|
||||
endif
|
||||
|
||||
_srcdir = $(call normalizepath,$(srcdir))
|
||||
ifdef JAVA_SOURCEPATH
|
||||
SP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_SOURCEPATH))))
|
||||
_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)$(SEP)$(SP)"
|
||||
else
|
||||
_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)"
|
||||
endif
|
||||
|
||||
ifdef JAVA_CLASSPATH
|
||||
CP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_CLASSPATH))))
|
||||
_JAVA_CLASSPATH = ".$(SEP)$(CP)"
|
||||
else
|
||||
_JAVA_CLASSPATH = .
|
||||
endif
|
||||
|
||||
_JAVA_DIR = _java
|
||||
$(_JAVA_DIR)::
|
||||
$(NSINSTALL) -D $@
|
||||
|
||||
$(_JAVA_DIR)/%.class: %.java $(GLOBAL_DEPS) $(_JAVA_DIR)
|
||||
$(REPORT_BUILD)
|
||||
$(JAVAC) $(JAVAC_FLAGS) -classpath $(_JAVA_CLASSPATH) \
|
||||
-sourcepath $(_JAVA_SOURCEPATH) -d $(_JAVA_DIR) $(_VPATH_SRCS)
|
||||
|
||||
$(JAVA_LIBRARY): $(addprefix $(_JAVA_DIR)/,$(JAVA_SRCS:.java=.class)) $(GLOBAL_DEPS)
|
||||
$(REPORT_BUILD)
|
||||
$(JAR) cf $@ -C $(_JAVA_DIR) .
|
||||
|
||||
GARBAGE_DIRS += $(_JAVA_DIR)
|
||||
|
||||
###############################################################################
|
||||
# Update Files Managed by Build Backend
|
||||
###############################################################################
|
||||
|
@ -4361,7 +4361,8 @@ if test -n "$ENABLE_INTL_API" ; then
|
||||
|
||||
abs_srcdir=`(cd $srcdir; pwd)`
|
||||
mkdir -p $_objdir/intl/icu
|
||||
(cd $_objdir/intl/icu; \
|
||||
(cd $_objdir/intl/icu
|
||||
MOZ_SUBCONFIGURE_WRAP([.],[
|
||||
CC="$CC" CXX="$CXX" \
|
||||
CFLAGS="$ICU_CFLAGS" CPPFLAGS="$ICU_CPPFLAGS" CXXFLAGS="$ICU_CXXFLAGS" \
|
||||
$SHELL $abs_srcdir/../../intl/icu/source/runConfigureICU \
|
||||
@ -4370,6 +4371,7 @@ if test -n "$ENABLE_INTL_API" ; then
|
||||
$ICU_LINK_OPTS \
|
||||
--enable-extras=no --enable-icuio=no --enable-layout=no \
|
||||
--enable-tests=no --enable-samples=no || exit 1
|
||||
])
|
||||
) || exit 1
|
||||
fi
|
||||
|
||||
|
22
js/src/jit-test/tests/asm.js/testBug907085.js
Normal file
22
js/src/jit-test/tests/asm.js/testBug907085.js
Normal file
@ -0,0 +1,22 @@
|
||||
try {
|
||||
s.e
|
||||
} catch (e) {}
|
||||
o = o = s2 = /x/
|
||||
for (let e in []);
|
||||
x = s2
|
||||
schedulegc(21)
|
||||
eval("x.e=x.t")
|
||||
try {
|
||||
(function() {
|
||||
this.eval("\
|
||||
(function(stdlib,fgn,heap) {\
|
||||
\"use asm\";\
|
||||
var Vie = new stdlib.Float64Array(heap);\
|
||||
var Iew = new stdlib.Int8Array(heap);\
|
||||
function f(){\
|
||||
ent\
|
||||
}\
|
||||
})()\
|
||||
")
|
||||
})()
|
||||
} catch (e) {}
|
10
js/src/jit-test/tests/ion/bug905989.js
Normal file
10
js/src/jit-test/tests/ion/bug905989.js
Normal file
@ -0,0 +1,10 @@
|
||||
function TestCase(n, d, e, a) {};
|
||||
function reportCompare() {
|
||||
new TestCase();
|
||||
}
|
||||
reportCompare();
|
||||
TestCase = ParallelArray;
|
||||
try {
|
||||
reportCompare();
|
||||
} catch(exc1) {}
|
||||
reportCompare();
|
15
js/src/jit-test/tests/ion/bug906284.js
Normal file
15
js/src/jit-test/tests/ion/bug906284.js
Normal file
@ -0,0 +1,15 @@
|
||||
"use strict"
|
||||
function f() {
|
||||
h = {}
|
||||
}
|
||||
var c = 0;
|
||||
for (var i=0; i<3; i++) {
|
||||
try {
|
||||
new f();
|
||||
assertEq(0, 1);
|
||||
} catch(e) {
|
||||
c++;
|
||||
assertEq(e.message.contains("undeclared variable"), true);
|
||||
}
|
||||
}
|
||||
assertEq(c, 3);
|
@ -892,7 +892,7 @@ ion::ToggleBaselineSPS(JSRuntime *runtime, bool enable)
|
||||
}
|
||||
|
||||
static void
|
||||
MarkActiveBaselineScripts(JSContext *cx, const JitActivationIterator &activation)
|
||||
MarkActiveBaselineScripts(JSRuntime *rt, const JitActivationIterator &activation)
|
||||
{
|
||||
for (ion::IonFrameIterator iter(activation); !iter.done(); ++iter) {
|
||||
switch (iter.type()) {
|
||||
@ -903,7 +903,7 @@ MarkActiveBaselineScripts(JSContext *cx, const JitActivationIterator &activation
|
||||
// Keep the baseline script around, since bailouts from the ion
|
||||
// jitcode might need to re-enter into the baseline jitcode.
|
||||
iter.script()->baselineScript()->setActive();
|
||||
for (InlineFrameIterator inlineIter(cx, &iter); inlineIter.more(); ++inlineIter)
|
||||
for (InlineFrameIterator inlineIter(rt, &iter); inlineIter.more(); ++inlineIter)
|
||||
inlineIter.script()->baselineScript()->setActive();
|
||||
break;
|
||||
}
|
||||
@ -915,19 +915,9 @@ MarkActiveBaselineScripts(JSContext *cx, const JitActivationIterator &activation
|
||||
void
|
||||
ion::MarkActiveBaselineScripts(Zone *zone)
|
||||
{
|
||||
// First check if there is a JitActivation on the stack, so that there
|
||||
// must be a valid IonContext.
|
||||
JitActivationIterator iter(zone->runtimeFromMainThread());
|
||||
if (iter.done())
|
||||
return;
|
||||
|
||||
// If baseline is disabled, there are no baseline scripts on the stack.
|
||||
JSContext *cx = GetIonContext()->cx;
|
||||
if (!ion::IsBaselineEnabled(cx))
|
||||
return;
|
||||
|
||||
for (; !iter.done(); ++iter) {
|
||||
JSRuntime *rt = zone->runtimeFromMainThread();
|
||||
for (JitActivationIterator iter(rt); !iter.done(); ++iter) {
|
||||
if (iter.activation()->compartment()->zone() == zone)
|
||||
MarkActiveBaselineScripts(cx, iter);
|
||||
MarkActiveBaselineScripts(rt, iter);
|
||||
}
|
||||
}
|
||||
|
@ -6171,7 +6171,7 @@ CodeGenerator::visitBindNameIC(OutOfLineUpdateCache *ool, BindNameIC *ic)
|
||||
}
|
||||
|
||||
typedef bool (*SetPropertyFn)(JSContext *, HandleObject,
|
||||
HandlePropertyName, const HandleValue, bool, int);
|
||||
HandlePropertyName, const HandleValue, bool, jsbytecode *);
|
||||
static const VMFunction SetPropertyInfo =
|
||||
FunctionInfo<SetPropertyFn>(SetProperty);
|
||||
|
||||
@ -6181,9 +6181,8 @@ CodeGenerator::visitCallSetProperty(LCallSetProperty *ins)
|
||||
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LCallSetProperty::Value));
|
||||
|
||||
const Register objReg = ToRegister(ins->getOperand(0));
|
||||
JSOp op = JSOp(*ins->mir()->resumePoint()->pc());
|
||||
|
||||
pushArg(Imm32(op));
|
||||
pushArg(ImmWord(ins->mir()->resumePoint()->pc()));
|
||||
pushArg(Imm32(ins->mir()->strict()));
|
||||
|
||||
pushArg(value);
|
||||
@ -6217,11 +6216,8 @@ CodeGenerator::visitSetPropertyCacheV(LSetPropertyCacheV *ins)
|
||||
RegisterSet liveRegs = ins->safepoint()->liveRegs();
|
||||
Register objReg = ToRegister(ins->getOperand(0));
|
||||
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetPropertyCacheV::Value));
|
||||
jsbytecode *pc = ins->mir()->resumePoint()->pc();
|
||||
bool isSetName = JSOp(*pc) == JSOP_SETNAME || JSOp(*pc) == JSOP_SETGNAME;
|
||||
|
||||
SetPropertyIC cache(liveRegs, objReg, ins->mir()->name(), value,
|
||||
isSetName, ins->mir()->strict());
|
||||
SetPropertyIC cache(liveRegs, objReg, ins->mir()->name(), value, ins->mir()->strict());
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
|
||||
@ -6231,16 +6227,13 @@ CodeGenerator::visitSetPropertyCacheT(LSetPropertyCacheT *ins)
|
||||
RegisterSet liveRegs = ins->safepoint()->liveRegs();
|
||||
Register objReg = ToRegister(ins->getOperand(0));
|
||||
ConstantOrRegister value;
|
||||
jsbytecode *pc = ins->mir()->resumePoint()->pc();
|
||||
bool isSetName = JSOp(*pc) == JSOP_SETNAME || JSOp(*pc) == JSOP_SETGNAME;
|
||||
|
||||
if (ins->getOperand(1)->isConstant())
|
||||
value = ConstantOrRegister(*ins->getOperand(1)->toConstant());
|
||||
else
|
||||
value = TypedOrValueRegister(ins->valueType(), ToAnyRegister(ins->getOperand(1)));
|
||||
|
||||
SetPropertyIC cache(liveRegs, objReg, ins->mir()->name(), value,
|
||||
isSetName, ins->mir()->strict());
|
||||
SetPropertyIC cache(liveRegs, objReg, ins->mir()->name(), value, ins->mir()->strict());
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
|
||||
|
@ -159,10 +159,8 @@ IonBuilder::getSingleCallTarget(types::StackTypeSet *calleeTypes)
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
|
||||
AutoObjectVector &targets,
|
||||
uint32_t maxTargets,
|
||||
bool *gotLambda)
|
||||
IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes, bool constructing,
|
||||
AutoObjectVector &targets, uint32_t maxTargets, bool *gotLambda)
|
||||
{
|
||||
JS_ASSERT(targets.length() == 0);
|
||||
JS_ASSERT(gotLambda);
|
||||
@ -183,18 +181,13 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
|
||||
return false;
|
||||
for(unsigned i = 0; i < objCount; i++) {
|
||||
JSObject *obj = calleeTypes->getSingleObject(i);
|
||||
JSFunction *fun;
|
||||
if (obj) {
|
||||
if (!obj->is<JSFunction>()) {
|
||||
targets.clear();
|
||||
return true;
|
||||
}
|
||||
if (obj->as<JSFunction>().isInterpreted() &&
|
||||
!obj->as<JSFunction>().getOrCreateScript(cx))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DebugOnly<bool> appendOk = targets.append(obj);
|
||||
JS_ASSERT(appendOk);
|
||||
fun = &obj->as<JSFunction>();
|
||||
} else {
|
||||
types::TypeObject *typeObj = calleeTypes->getTypeObject(i);
|
||||
JS_ASSERT(typeObj);
|
||||
@ -202,13 +195,24 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
|
||||
targets.clear();
|
||||
return true;
|
||||
}
|
||||
if (!typeObj->interpretedFunction->getOrCreateScript(cx))
|
||||
return false;
|
||||
DebugOnly<bool> appendOk = targets.append(typeObj->interpretedFunction);
|
||||
JS_ASSERT(appendOk);
|
||||
|
||||
fun = typeObj->interpretedFunction;
|
||||
*gotLambda = true;
|
||||
}
|
||||
|
||||
if (fun->isInterpreted() && !fun->getOrCreateScript(cx))
|
||||
return false;
|
||||
|
||||
// Don't optimize if we're constructing and the callee is not a
|
||||
// constructor, so that CallKnown does not have to handle this case
|
||||
// (it should always throw).
|
||||
if (constructing && !fun->isInterpretedConstructor() && !fun->isNativeConstructor()) {
|
||||
targets.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
DebugOnly<bool> appendOk = targets.append(fun);
|
||||
JS_ASSERT(appendOk);
|
||||
}
|
||||
|
||||
// For now, only inline "singleton" lambda calls
|
||||
@ -4947,7 +4951,7 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
|
||||
bool gotLambda = false;
|
||||
types::StackTypeSet *calleeTypes = current->peek(calleeDepth)->resultTypeSet();
|
||||
if (calleeTypes) {
|
||||
if (!getPolyCallTargets(calleeTypes, originals, 4, &gotLambda))
|
||||
if (!getPolyCallTargets(calleeTypes, constructing, originals, 4, &gotLambda))
|
||||
return false;
|
||||
}
|
||||
JS_ASSERT_IF(gotLambda, originals.length() <= 1);
|
||||
@ -4983,16 +4987,9 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
|
||||
|
||||
// No inline, just make the call.
|
||||
RootedFunction target(cx, NULL);
|
||||
if (targets.length() == 1) {
|
||||
if (targets.length() == 1)
|
||||
target = &targets[0]->as<JSFunction>();
|
||||
|
||||
// Don't optimize if we're constructing and the callee is not an
|
||||
// interpreted constructor, so that CallKnown does not have to
|
||||
// handle this case (it should always throw).
|
||||
if (constructing && !target->isInterpretedConstructor())
|
||||
target = NULL;
|
||||
}
|
||||
|
||||
return makeCall(target, callInfo, hasClones);
|
||||
}
|
||||
|
||||
@ -5266,7 +5263,8 @@ IonBuilder::makeCall(HandleFunction target, CallInfo &callInfo, bool cloneAtCall
|
||||
{
|
||||
// Constructor calls to non-constructors should throw. We don't want to use
|
||||
// CallKnown in this case.
|
||||
JS_ASSERT_IF(callInfo.constructing() && target, target->isInterpretedConstructor());
|
||||
JS_ASSERT_IF(callInfo.constructing() && target,
|
||||
target->isInterpretedConstructor() || target->isNativeConstructor());
|
||||
|
||||
MCall *call = makeCallHelper(target, callInfo, cloneAtCallsite);
|
||||
if (!call)
|
||||
|
@ -225,10 +225,8 @@ class IonBuilder : public MIRGenerator
|
||||
}
|
||||
|
||||
JSFunction *getSingleCallTarget(types::StackTypeSet *calleeTypes);
|
||||
bool getPolyCallTargets(types::StackTypeSet *calleeTypes,
|
||||
AutoObjectVector &targets,
|
||||
uint32_t maxTargets,
|
||||
bool *gotLambda);
|
||||
bool getPolyCallTargets(types::StackTypeSet *calleeTypes, bool constructing,
|
||||
AutoObjectVector &targets, uint32_t maxTargets, bool *gotLambda);
|
||||
bool canInlineTarget(JSFunction *target, bool constructing);
|
||||
|
||||
void popCfgStack();
|
||||
|
@ -397,9 +397,9 @@ IonCache::linkAndAttachStub(JSContext *cx, MacroAssembler &masm, StubAttacher &a
|
||||
|
||||
attachStub(masm, attacher, code);
|
||||
|
||||
if (pc) {
|
||||
if (pc_) {
|
||||
IonSpew(IonSpew_InlineCaches, "Cache %p(%s:%d/%d) generated %s %s stub at %p",
|
||||
this, script->filename(), script->lineno, pc - script->code,
|
||||
this, script_->filename(), script_->lineno, pc_ - script_->code,
|
||||
attachKind, CacheName(kind()), code->raw());
|
||||
} else {
|
||||
IonSpew(IonSpew_InlineCaches, "Cache %p generated %s %s stub at %p",
|
||||
@ -2287,7 +2287,7 @@ SetPropertyIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
|
||||
RootedShape oldShape(cx, obj->lastProperty());
|
||||
|
||||
// Set/Add the property on the object, the inlined cache are setup for the next execution.
|
||||
if (!SetProperty(cx, obj, name, value, cache.strict(), cache.isSetName()))
|
||||
if (!SetProperty(cx, obj, name, value, cache.strict(), cache.pc()))
|
||||
return false;
|
||||
|
||||
// The property did not exist before, now we can try to inline the property add.
|
||||
|
@ -165,8 +165,8 @@ class IonCache
|
||||
CodeLocationLabel fallbackLabel_;
|
||||
|
||||
// Location of this operation, NULL for idempotent caches.
|
||||
JSScript *script;
|
||||
jsbytecode *pc;
|
||||
JSScript *script_;
|
||||
jsbytecode *pc_;
|
||||
|
||||
private:
|
||||
static const size_t MAX_STUBS;
|
||||
@ -184,8 +184,8 @@ class IonCache
|
||||
disabled_(false),
|
||||
stubCount_(0),
|
||||
fallbackLabel_(),
|
||||
script(NULL),
|
||||
pc(NULL)
|
||||
script_(NULL),
|
||||
pc_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -256,20 +256,25 @@ class IonCache
|
||||
}
|
||||
void setIdempotent() {
|
||||
JS_ASSERT(!idempotent_);
|
||||
JS_ASSERT(!script);
|
||||
JS_ASSERT(!pc);
|
||||
JS_ASSERT(!script_);
|
||||
JS_ASSERT(!pc_);
|
||||
idempotent_ = true;
|
||||
}
|
||||
|
||||
void setScriptedLocation(JSScript *script, jsbytecode *pc) {
|
||||
JS_ASSERT(!idempotent_);
|
||||
this->script = script;
|
||||
this->pc = pc;
|
||||
script_ = script;
|
||||
pc_ = pc;
|
||||
}
|
||||
|
||||
void getScriptedLocation(MutableHandleScript pscript, jsbytecode **ppc) const {
|
||||
pscript.set(script);
|
||||
*ppc = pc;
|
||||
pscript.set(script_);
|
||||
*ppc = pc_;
|
||||
}
|
||||
|
||||
jsbytecode *pc() const {
|
||||
JS_ASSERT(pc_);
|
||||
return pc_;
|
||||
}
|
||||
};
|
||||
|
||||
@ -605,17 +610,15 @@ class SetPropertyIC : public RepatchIonCache
|
||||
Register object_;
|
||||
PropertyName *name_;
|
||||
ConstantOrRegister value_;
|
||||
bool isSetName_;
|
||||
bool strict_;
|
||||
|
||||
public:
|
||||
SetPropertyIC(RegisterSet liveRegs, Register object, PropertyName *name,
|
||||
ConstantOrRegister value, bool isSetName, bool strict)
|
||||
ConstantOrRegister value, bool strict)
|
||||
: liveRegs_(liveRegs),
|
||||
object_(object),
|
||||
name_(name),
|
||||
value_(value),
|
||||
isSetName_(isSetName),
|
||||
strict_(strict)
|
||||
{
|
||||
}
|
||||
@ -631,9 +634,6 @@ class SetPropertyIC : public RepatchIonCache
|
||||
ConstantOrRegister value() const {
|
||||
return value_;
|
||||
}
|
||||
bool isSetName() const {
|
||||
return isSetName_;
|
||||
}
|
||||
bool strict() const {
|
||||
return strict_;
|
||||
}
|
||||
@ -778,7 +778,7 @@ class SetElementIC : public RepatchIonCache
|
||||
return object_;
|
||||
}
|
||||
Register tempToUnboxIndex() const {
|
||||
return temp_;
|
||||
return tempToUnboxIndex_;
|
||||
}
|
||||
Register temp() const {
|
||||
return temp_;
|
||||
|
@ -339,6 +339,13 @@ class InlineFrameIteratorMaybeGC
|
||||
resetOn(iter);
|
||||
}
|
||||
|
||||
InlineFrameIteratorMaybeGC(JSRuntime *rt, const IonFrameIterator *iter)
|
||||
: callee_(rt),
|
||||
script_(rt)
|
||||
{
|
||||
resetOn(iter);
|
||||
}
|
||||
|
||||
InlineFrameIteratorMaybeGC(JSContext *cx, const IonBailoutIterator *iter);
|
||||
|
||||
InlineFrameIteratorMaybeGC(JSContext *cx, const InlineFrameIteratorMaybeGC *iter)
|
||||
|
@ -514,13 +514,19 @@ ion::PropagateAbortPar(JSScript *outermostScript, JSScript *currentScript)
|
||||
}
|
||||
|
||||
void
|
||||
ion::CallToUncompiledScriptPar(JSFunction *func)
|
||||
ion::CallToUncompiledScriptPar(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(InParallelSection());
|
||||
|
||||
#ifdef DEBUG
|
||||
static const int max_bound_function_unrolling = 5;
|
||||
|
||||
if (!obj->is<JSFunction>()) {
|
||||
Spew(SpewBailouts, "Call to non-function");
|
||||
return;
|
||||
}
|
||||
|
||||
JSFunction *func = &obj->as<JSFunction>();
|
||||
if (func->hasScript()) {
|
||||
JSScript *script = func->nonLazyScript();
|
||||
Spew(SpewBailouts, "Call to uncompiled script: %p:%s:%d",
|
||||
|
@ -83,7 +83,7 @@ void TraceLIR(uint32_t bblock, uint32_t lir, uint32_t execModeInt,
|
||||
const char *lirOpName, const char *mirOpName,
|
||||
JSScript *script, jsbytecode *pc);
|
||||
|
||||
void CallToUncompiledScriptPar(JSFunction *func);
|
||||
void CallToUncompiledScriptPar(JSObject *obj);
|
||||
|
||||
} // namespace ion
|
||||
} // namespace js
|
||||
|
@ -397,12 +397,14 @@ StringFromCharCode(JSContext *cx, int32_t code)
|
||||
|
||||
bool
|
||||
SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
|
||||
bool strict, int jsop)
|
||||
bool strict, jsbytecode *pc)
|
||||
{
|
||||
RootedValue v(cx, value);
|
||||
RootedId id(cx, NameToId(name));
|
||||
|
||||
if (jsop == JSOP_SETALIASEDVAR) {
|
||||
JSOp op = JSOp(*pc);
|
||||
|
||||
if (op == JSOP_SETALIASEDVAR) {
|
||||
// Aliased var assigns ignore readonly attributes on the property, as
|
||||
// required for initializing 'const' closure variables.
|
||||
Shape *shape = obj->nativeLookup(cx, name);
|
||||
@ -412,7 +414,7 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
|
||||
}
|
||||
|
||||
if (JS_LIKELY(!obj->getOps()->setProperty)) {
|
||||
unsigned defineHow = (jsop == JSOP_SETNAME || jsop == JSOP_SETGNAME) ? DNP_UNQUALIFIED : 0;
|
||||
unsigned defineHow = (op == JSOP_SETNAME || op == JSOP_SETGNAME) ? DNP_UNQUALIFIED : 0;
|
||||
return baseops::SetPropertyHelper(cx, obj, obj, id, defineHow, &v, strict);
|
||||
}
|
||||
|
||||
|
@ -614,7 +614,7 @@ bool CharCodeAt(JSContext *cx, HandleString str, int32_t index, uint32_t *code);
|
||||
JSFlatString *StringFromCharCode(JSContext *cx, int32_t code);
|
||||
|
||||
bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
|
||||
bool strict, int jsop);
|
||||
bool strict, jsbytecode *pc);
|
||||
|
||||
bool InterruptCheck(JSContext *cx);
|
||||
|
||||
|
@ -635,7 +635,7 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
code = ssd->data;
|
||||
if (natoms != 0) {
|
||||
script->natoms = natoms;
|
||||
script->atoms = ssd->atoms(length, nsrcnotes);
|
||||
script->atoms = ssd->atoms();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1516,15 +1516,26 @@ js::SharedScriptData::new_(ExclusiveContext *cx, uint32_t codeLength,
|
||||
uint32_t baseLength = codeLength + srcnotesLength;
|
||||
uint32_t padding = sizeof(JSAtom *) - baseLength % sizeof(JSAtom *);
|
||||
uint32_t length = baseLength + padding + sizeof(JSAtom *) * natoms;
|
||||
JS_ASSERT(length % sizeof(JSAtom *) == 0);
|
||||
|
||||
SharedScriptData *entry = (SharedScriptData *)cx->malloc_(length +
|
||||
offsetof(SharedScriptData, data));
|
||||
|
||||
if (!entry)
|
||||
return NULL;
|
||||
entry->marked = false;
|
||||
entry->length = length;
|
||||
entry->natoms = natoms;
|
||||
entry->marked = false;
|
||||
memset(entry->data + baseLength, 0, padding);
|
||||
|
||||
/*
|
||||
* Call constructors to initialize the storage that will be accessed as a
|
||||
* HeapPtrAtom array via atoms().
|
||||
*/
|
||||
HeapPtrAtom *atoms = entry->atoms();
|
||||
for (unsigned i = 0; i < natoms; ++i)
|
||||
new (&atoms[i]) HeapPtrAtom();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -1572,7 +1583,7 @@ SaveSharedScriptData(ExclusiveContext *cx, Handle<JSScript *> script, SharedScri
|
||||
#endif
|
||||
|
||||
script->code = ssd->data;
|
||||
script->atoms = ssd->atoms(script->length, nsrcnotes);
|
||||
script->atoms = ssd->atoms();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1916,7 +1927,7 @@ JSScript::fullyInitFromEmitter(ExclusiveContext *cx, HandleScript script, Byteco
|
||||
PodCopy<jsbytecode>(code + prologLength, bce->code().begin(), mainLength);
|
||||
if (!FinishTakingSrcNotes(cx, bce, (jssrcnote *)(code + script->length)))
|
||||
return false;
|
||||
InitAtomMap(bce->atomIndices.getMap(), ssd->atoms(script->length, nsrcnotes));
|
||||
InitAtomMap(bce->atomIndices.getMap(), ssd->atoms());
|
||||
|
||||
if (!SaveSharedScriptData(cx, script, ssd, nsrcnotes))
|
||||
return false;
|
||||
@ -2794,7 +2805,7 @@ JSScript::markChildren(JSTracer *trc)
|
||||
if (IS_GC_MARKING_TRACER(trc)) {
|
||||
compartment()->mark();
|
||||
|
||||
if (code)
|
||||
if (code || natoms)
|
||||
MarkScriptData(trc->runtime, code);
|
||||
}
|
||||
|
||||
|
@ -1385,22 +1385,27 @@ CallDestroyScriptHook(FreeOp *fop, JSScript *script);
|
||||
|
||||
struct SharedScriptData
|
||||
{
|
||||
bool marked;
|
||||
uint32_t length;
|
||||
uint32_t natoms;
|
||||
bool marked;
|
||||
jsbytecode data[1];
|
||||
|
||||
static SharedScriptData *new_(ExclusiveContext *cx, uint32_t codeLength,
|
||||
uint32_t srcnotesLength, uint32_t natoms);
|
||||
|
||||
HeapPtrAtom *atoms(uint32_t codeLength, uint32_t srcnotesLength) {
|
||||
uint32_t length = codeLength + srcnotesLength;
|
||||
return reinterpret_cast<HeapPtrAtom *>(data + length + sizeof(JSAtom *) -
|
||||
length % sizeof(JSAtom *));
|
||||
HeapPtrAtom *atoms() {
|
||||
if (!natoms)
|
||||
return NULL;
|
||||
return reinterpret_cast<HeapPtrAtom *>(data + length - sizeof(JSAtom *) * natoms);
|
||||
}
|
||||
|
||||
static SharedScriptData *fromBytecode(const jsbytecode *bytecode) {
|
||||
return (SharedScriptData *)(bytecode - offsetof(SharedScriptData, data));
|
||||
}
|
||||
|
||||
private:
|
||||
SharedScriptData() MOZ_DELETE;
|
||||
SharedScriptData(const SharedScriptData&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
struct ScriptBytecodeHasher
|
||||
|
@ -346,7 +346,7 @@ function jsTestDriverBrowserInit()
|
||||
{
|
||||
properties.version = '1.7';
|
||||
}
|
||||
else if (properties.test.match(/^js1_8|^ecma_6/))
|
||||
else if (properties.test.match(/^js1_8/))
|
||||
{
|
||||
properties.version = '1.8';
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ var cosh_data = [
|
||||
[1875817529344, 28.953212876533797]
|
||||
];
|
||||
|
||||
for (let [x, y] of cosh_data)
|
||||
for (var [x, y] of cosh_data)
|
||||
assertNear(Math.acosh(x), y);
|
||||
|
||||
for (var i = 0; i <= 100; i++) {
|
||||
|
@ -282,7 +282,7 @@ var sinh_data = [
|
||||
[1581915832320, 28.78280496108106]
|
||||
];
|
||||
|
||||
for (let [x, y] of sinh_data)
|
||||
for (var [x, y] of sinh_data)
|
||||
assertNear(Math.asinh(x), y);
|
||||
|
||||
for (var i = 0; i <= 80; i++) {
|
||||
|
@ -269,7 +269,7 @@ var tanh_data = [
|
||||
[1e-10, 1e-10],
|
||||
];
|
||||
|
||||
for (let [x, y] of tanh_data)
|
||||
for (var [x, y] of tanh_data)
|
||||
assertNear(Math.atanh(x), y);
|
||||
|
||||
assertNear(Math.atanh(+3 / 5), +Math.log(2));
|
||||
|
@ -11,7 +11,7 @@ var cbrt_data = [
|
||||
[ Math.SQRT2, 1.1224620483093728 ]
|
||||
];
|
||||
|
||||
for (let [x, y] of cbrt_data)
|
||||
for (var [x, y] of cbrt_data)
|
||||
assertNear(Math.cbrt(x), y);
|
||||
|
||||
reportCompare(0, 0, "ok");
|
||||
|
@ -269,7 +269,7 @@ var cosh_data = [
|
||||
[28.953212876533797, 1875817529343.9976],
|
||||
];
|
||||
|
||||
for (let [x, y] of cosh_data)
|
||||
for (var [x, y] of cosh_data)
|
||||
assertNear(Math.cosh(x), y);
|
||||
|
||||
reportCompare(0, 0, "ok");
|
||||
|
@ -18,7 +18,7 @@ var expm1_data = [
|
||||
[ 0.0000031404608812881633, 0.0000031404658125405988 ]
|
||||
];
|
||||
|
||||
for (let [x, y] of expm1_data)
|
||||
for (var [x, y] of expm1_data)
|
||||
assertNear(Math.expm1(x), y);
|
||||
|
||||
reportCompare(0, 0, "ok");
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
// If any argument is +∞, the result is +∞.
|
||||
// If any argument is −∞, the result is +∞.
|
||||
for (let inf of [Infinity, -Infinity]) {
|
||||
for (var inf of [Infinity, -Infinity]) {
|
||||
assertEq(Math.hypot(inf, 0), Infinity);
|
||||
assertEq(Math.hypot(0, inf), Infinity);
|
||||
assertEq(Math.hypot(inf, inf), Infinity);
|
||||
|
@ -14,7 +14,7 @@ var log1p_data = [
|
||||
[ 0.011404608812881634, 0.011340066517988035 ],
|
||||
];
|
||||
|
||||
for (let [x, y] of log1p_data)
|
||||
for (var [x, y] of log1p_data)
|
||||
assertNear(Math.log1p(x), y);
|
||||
|
||||
reportCompare(0, 0, "ok");
|
||||
|
@ -289,7 +289,7 @@ var sinh_data = [
|
||||
[28.78280496108106, 1581915832319.9973]
|
||||
];
|
||||
|
||||
for (let [x, y] of sinh_data)
|
||||
for (var [x, y] of sinh_data)
|
||||
assertNear(Math.sinh(x), y);
|
||||
|
||||
reportCompare(0, 0, "ok");
|
||||
|
@ -271,7 +271,7 @@ var tanh_data = [
|
||||
[1e-10, 1e-10],
|
||||
];
|
||||
|
||||
for (let [x, y] of tanh_data)
|
||||
for (var [x, y] of tanh_data)
|
||||
assertNear(Math.tanh(y), x);
|
||||
|
||||
reportCompare(0, 0, "ok");
|
||||
|
@ -1,12 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
// explicitly turn on js185
|
||||
if (typeof version != 'undefined')
|
||||
{
|
||||
version(185);
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
|
@ -12,9 +12,6 @@
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "Layers.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "nsRenderingContext.h"
|
||||
#include "MaskLayerImageCache.h"
|
||||
@ -23,19 +20,11 @@
|
||||
#include "LayerTreeInvalidation.h"
|
||||
#include "nsSVGIntegrationUtils.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
|
||||
#include "nsAnimationManager.h"
|
||||
#include "nsTransitionManager.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
//#define DEBUG_DISPLAY_ITEM_DATA
|
||||
#endif
|
||||
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user