Merge m-c to fig.

This commit is contained in:
Ryan VanderMeulen 2013-08-20 16:33:28 -04:00
commit 988f90b952
218 changed files with 3431 additions and 2315 deletions

View File

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

View File

@ -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);
},

View File

@ -1,4 +1,4 @@
{
"revision": "f98ec5e292dffd144f0a6520cc18ff5cb7762d09",
"revision": "dbaee540a7d23d271e62e7da80d7db226be8860b",
"repo_path": "/integration/gaia-central"
}

View File

@ -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);

View File

@ -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"]

View File

@ -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) {

View File

@ -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");
});
}

View File

@ -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";

View File

@ -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;
}
}

View File

@ -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.");
};
}

View File

@ -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();
};
}

View File

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

View File

@ -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&quot;l'u&quot;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, "&quot;");
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;

View File

@ -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 &quot; and single &apos;"></div>
</body>
</html>

View File

@ -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 &quot; and single '\"", "Value contains &quot;");
value = value.replace(/Double/, "&quot;").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;',

View File

@ -687,6 +687,7 @@ ResponsiveUI.prototype = {
this.stack.removeAttribute("notransition");
}
this.ignoreY = false;
this.ignoreX = false;
this.isResizing = false;
},

View File

@ -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()

View File

@ -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()

View File

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

View File

@ -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;
}

View File

@ -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
View 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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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;
}

View File

@ -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)
{

View File

@ -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)
{

View File

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

View File

@ -32,6 +32,7 @@ if CONFIG['MOZ_WEBGL']:
'WebGL2Context.cpp',
'WebGLContext.cpp',
'WebGLContextAsyncQueries.cpp',
'WebGLContextBuffers.cpp',
'WebGLContextGL.cpp',
'WebGLContextUtils.cpp',
'WebGLContextReporter.cpp',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);

View File

@ -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']

View File

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

View 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>

View File

@ -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']

View File

@ -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',

View File

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

View File

@ -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___ */

View File

@ -82,7 +82,9 @@ IndexedDBParent::~IndexedDBParent()
void
IndexedDBParent::Disconnect()
{
MOZ_ASSERT(!mDisconnected);
if (mDisconnected) {
return;
}
mDisconnected = true;

View File

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

View File

@ -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));
},

View File

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

View File

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

View File

@ -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);

View File

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

View File

@ -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 } },

View File

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

View File

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

View File

@ -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;
}

View File

@ -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;
};
}

View File

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

View File

@ -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();

View File

@ -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;
}

View File

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

View File

@ -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
])

View 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)

View File

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

View File

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

View File

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

View File

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

View File

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

View 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) {}

View File

@ -0,0 +1,10 @@
function TestCase(n, d, e, a) {};
function reportCompare() {
new TestCase();
}
reportCompare();
TestCase = ParallelArray;
try {
reportCompare();
} catch(exc1) {}
reportCompare();

View 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);

View File

@ -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);
}
}

View File

@ -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));
}

View File

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

View File

@ -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();

View File

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

View File

@ -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_;

View File

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

View File

@ -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",

View File

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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

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

View File

@ -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';
}

View File

@ -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++) {

View File

@ -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++) {

View File

@ -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));

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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);

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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);
}

View File

@ -7,7 +7,6 @@
#include "gfxContext.h"
#include "nsPresContext.h"
#include "nsDisplayList.h"
#include "nsCSSRendering.h"
#include "nsLayoutUtils.h"

View File

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