зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
e59d6747c1
|
@ -1343,8 +1343,10 @@ pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/
|
|||
// endpoint to send newtab click and view pings
|
||||
pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v3/links/");
|
||||
|
||||
// activates the remote-hosted newtab page
|
||||
#ifndef RELEASE_BUILD
|
||||
// if true, it activates the remote-hosted newtab page
|
||||
pref("browser.newtabpage.remote", false);
|
||||
#endif
|
||||
|
||||
// Enable the DOM fullscreen API.
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
@ -1666,4 +1668,4 @@ pref("toolkit.pageThumbs.minHeight", 190);
|
|||
#ifdef NIGHTLY_BUILD
|
||||
// Enable speech synthesis, only Nightly for now
|
||||
pref("media.webspeech.synth.enabled", true);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/NotificationDB.jsm");
|
||||
Cu.import("resource:///modules/RecentWindow.jsm");
|
||||
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
|
||||
"resource://gre/modules/Preferences.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
|
||||
|
@ -34,8 +33,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "GMPInstallManager",
|
|||
"resource://gre/modules/GMPInstallManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
|
||||
"resource://gre/modules/NewTabUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
|
||||
"resource:///modules/RemoteNewTabUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
|
||||
"resource:///modules/ContentSearch.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
|
||||
|
@ -3564,11 +3561,8 @@ const BrowserSearch = {
|
|||
if (!aSearchBar || document.activeElement != aSearchBar.textbox.inputField) {
|
||||
let url = gBrowser.currentURI.spec.toLowerCase();
|
||||
let mm = gBrowser.selectedBrowser.messageManager;
|
||||
let newTabRemoted = Services.prefs.getBoolPref("browser.newtabpage.remote");
|
||||
if (url === "about:home" ||
|
||||
(url === "about:newtab" &&
|
||||
((!newTabRemoted && NewTabUtils.allPages.enabled) ||
|
||||
(newTabRemoted && RemoteNewTabUtils.allPages.enabled)))) {
|
||||
(url === "about:newtab" && NewTabUtils.allPages.enabled)) {
|
||||
ContentSearch.focusInput(mm);
|
||||
} else {
|
||||
openUILinkIn("about:home", "current");
|
||||
|
|
|
@ -90,9 +90,11 @@ static RedirEntry kRedirMap[] = {
|
|||
nsIAboutModule::ENABLE_INDEXED_DB },
|
||||
{ "newtab", "chrome://browser/content/newtab/newTab.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#ifndef RELEASE_BUILD
|
||||
{ "remote-newtab", "chrome://browser/content/remote-newtab/newTab.xhtml",
|
||||
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
{ "preferences", "chrome://browser/content/preferences/in-content/preferences.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
|
||||
|
|
|
@ -4,17 +4,18 @@
|
|||
# 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/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
|
||||
if not CONFIG['RELEASE_BUILD']:
|
||||
BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'tests/xpcshell/xpcshell.ini',
|
||||
]
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'tests/xpcshell/xpcshell.ini',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'NewTabPrefsProvider.jsm',
|
||||
'NewTabURL.jsm',
|
||||
'PlacesProvider.jsm',
|
||||
'RemoteAboutNewTab.jsm',
|
||||
'RemoteNewTabLocation.jsm',
|
||||
'RemoteNewTabUtils.jsm',
|
||||
]
|
||||
EXTRA_JS_MODULES += [
|
||||
'NewTabPrefsProvider.jsm',
|
||||
'NewTabURL.jsm',
|
||||
'PlacesProvider.jsm',
|
||||
'RemoteAboutNewTab.jsm',
|
||||
'RemoteNewTabLocation.jsm',
|
||||
'RemoteNewTabUtils.jsm',
|
||||
]
|
||||
|
|
|
@ -14,6 +14,9 @@ const POLARIS_ENABLED = "browser.polaris.enabled";
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
|
||||
"resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
|
||||
"resource:///modules/AboutHome.jsm");
|
||||
|
||||
|
@ -26,14 +29,16 @@ XPCOMUtils.defineLazyModuleGetter(this, "DirectoryLinksProvider",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
|
||||
"resource://gre/modules/NewTabUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteAboutNewTab",
|
||||
"resource:///modules/RemoteAboutNewTab.jsm");
|
||||
if(!AppConstants.RELEASE_BUILD) {
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteAboutNewTab",
|
||||
"resource:///modules/RemoteAboutNewTab.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
|
||||
"resource:///modules/RemoteNewTabUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
|
||||
"resource:///modules/RemoteNewTabUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
|
||||
"resource:///modules/NewTabPrefsProvider.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
|
||||
"resource:///modules/NewTabPrefsProvider.jsm");
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UITour",
|
||||
"resource:///modules/UITour.jsm");
|
||||
|
@ -181,9 +186,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "ExtensionManagement",
|
||||
"resource://gre/modules/ExtensionManagement.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
|
||||
"resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils",
|
||||
"@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils");
|
||||
|
||||
|
@ -849,10 +851,12 @@ BrowserGlue.prototype = {
|
|||
NewTabUtils.links.addProvider(DirectoryLinksProvider);
|
||||
AboutNewTab.init();
|
||||
|
||||
RemoteNewTabUtils.init();
|
||||
RemoteNewTabUtils.links.addProvider(DirectoryLinksProvider);
|
||||
RemoteAboutNewTab.init();
|
||||
NewTabPrefsProvider.prefs.init();
|
||||
if(!AppConstants.RELEASE_BUILD) {
|
||||
RemoteNewTabUtils.init();
|
||||
RemoteNewTabUtils.links.addProvider(DirectoryLinksProvider);
|
||||
RemoteAboutNewTab.init();
|
||||
NewTabPrefsProvider.prefs.init();
|
||||
}
|
||||
|
||||
SessionStore.init();
|
||||
BrowserUITelemetry.init();
|
||||
|
@ -1173,8 +1177,10 @@ BrowserGlue.prototype = {
|
|||
CustomizationTabPreloader.uninit();
|
||||
WebappManager.uninit();
|
||||
|
||||
RemoteAboutNewTab.uninit();
|
||||
NewTabPrefsProvider.prefs.uninit();
|
||||
if (!AppConstants.RELEASE_BUILD) {
|
||||
RemoteAboutNewTab.uninit();
|
||||
NewTabPrefsProvider.prefs.uninit();
|
||||
}
|
||||
AboutNewTab.uninit();
|
||||
#ifdef NIGHTLY_BUILD
|
||||
if (Services.prefs.getBoolPref("dom.identity.enabled")) {
|
||||
|
@ -2585,9 +2591,11 @@ AboutNewTabService.prototype = {
|
|||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutNewTabService]),
|
||||
|
||||
get newTabURL() {
|
||||
if (Services.prefs.getBoolPref("browser.newtabpage.remote")) {
|
||||
|
||||
if (!AppConstants.RELEASE_BUILD && Services.prefs.getBoolPref("browser.newtabpage.remote")) {
|
||||
return "about:remote-newtab";
|
||||
}
|
||||
|
||||
return this._newTabURL;
|
||||
},
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm")
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||
"resource://gre/modules/NetUtil.jsm");
|
||||
|
@ -31,8 +32,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
|
|||
XPCOMUtils.defineLazyServiceGetter(this, "eTLD",
|
||||
"@mozilla.org/network/effective-tld-service;1",
|
||||
"nsIEffectiveTLDService");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
|
||||
"resource:///modules/RemoteNewTabUtils.jsm");
|
||||
|
||||
// ensure remote new tab doesn't go beyond aurora
|
||||
if (!AppConstants.RELEASE_BUILD) {
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "RemoteNewTabUtils",
|
||||
"resource:///modules/RemoteNewTabUtils.jsm");
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gTextDecoder", () => {
|
||||
return new TextDecoder();
|
||||
});
|
||||
|
@ -760,8 +766,12 @@ var DirectoryLinksProvider = {
|
|||
|
||||
NewTabUtils.placesProvider.addObserver(this);
|
||||
NewTabUtils.links.addObserver(this);
|
||||
RemoteNewTabUtils.placesProvider.addObserver(this);
|
||||
RemoteNewTabUtils.links.addObserver(this);
|
||||
|
||||
// ensure remote new tab doesn't go beyond aurora
|
||||
if (!AppConstants.RELEASE_BUILD) {
|
||||
RemoteNewTabUtils.placesProvider.addObserver(this);
|
||||
RemoteNewTabUtils.links.addObserver(this);
|
||||
}
|
||||
|
||||
return Task.spawn(function() {
|
||||
// get the last modified time of the links file if it exists
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
uint64_t Root() const { return mDominatorTree.root().identifier(); }
|
||||
};
|
||||
|
||||
} // namespace devtools
|
||||
|
|
|
@ -117,6 +117,13 @@ function saveNewHeapSnapshot(opts = { runtime: true }) {
|
|||
return filePath;
|
||||
}
|
||||
|
||||
function readHeapSnapshot(filePath) {
|
||||
const snapshot = ChromeUtils.readHeapSnapshot(filePath);
|
||||
ok(snapshot, "Should have read a heap snapshot back from " + filePath);
|
||||
ok(snapshot instanceof HeapSnapshot, "snapshot should be an instance of HeapSnapshot");
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a heap snapshot to the file with the given name in the current
|
||||
* directory, read it back as a HeapSnapshot instance, and then take a census of
|
||||
|
@ -138,18 +145,40 @@ function saveNewHeapSnapshot(opts = { runtime: true }) {
|
|||
*/
|
||||
function saveHeapSnapshotAndTakeCensus(dbg=null, censusOptions=undefined) {
|
||||
const snapshotOptions = dbg ? { debugger: dbg } : { runtime: true };
|
||||
const filePath = ChromeUtils.saveHeapSnapshot(snapshotOptions);
|
||||
ok(filePath, "Should get a file path to save the core dump to.");
|
||||
ok(true, "Should have saved a heap snapshot to " + filePath);
|
||||
|
||||
const snapshot = ChromeUtils.readHeapSnapshot(filePath);
|
||||
ok(snapshot, "Should have read a heap snapshot back from " + filePath);
|
||||
ok(snapshot instanceof HeapSnapshot, "snapshot should be an instance of HeapSnapshot");
|
||||
const filePath = saveNewHeapSnapshot(snapshotOptions);
|
||||
const snapshot = readHeapSnapshot(filePath);
|
||||
|
||||
equal(typeof snapshot.takeCensus, "function", "snapshot should have a takeCensus method");
|
||||
|
||||
return snapshot.takeCensus(censusOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a heap snapshot to disk, read it back as a HeapSnapshot instance, and
|
||||
* then compute its dominator tree.
|
||||
*
|
||||
* @param {Debugger|null} dbg
|
||||
* If a Debugger object is given, only serialize the subgraph covered by
|
||||
* the Debugger's debuggees. If null, serialize the whole heap graph.
|
||||
*
|
||||
* @returns {DominatorTree}
|
||||
*/
|
||||
function saveHeapSnapshotAndComputeDominatorTree(dbg = null) {
|
||||
const snapshotOptions = dbg ? { debugger: dbg } : { runtime: true };
|
||||
const filePath = saveNewHeapSnapshot(snapshotOptions);
|
||||
const snapshot = readHeapSnapshot(filePath);
|
||||
|
||||
equal(typeof snapshot.computeDominatorTree, "function",
|
||||
"snapshot should have a `computeDominatorTree` method");
|
||||
|
||||
const dominatorTree = snapshot.computeDominatorTree();
|
||||
|
||||
ok(dominatorTree, "Should be able to compute a dominator tree");
|
||||
ok(dominatorTree instanceof DominatorTree, "Should be an instance of DominatorTree");
|
||||
|
||||
return dominatorTree;
|
||||
}
|
||||
|
||||
function isSavedFrame(obj) {
|
||||
return Object.prototype.toString.call(obj) === "[object SavedFrame]";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that we can get the root of dominator trees.
|
||||
|
||||
function run_test() {
|
||||
const dominatorTree = saveHeapSnapshotAndComputeDominatorTree();
|
||||
equal(typeof dominatorTree.root, "number", "root should be a number");
|
||||
equal(Math.floor(dominatorTree.root), dominatorTree.root, "root should be an integer");
|
||||
ok(dominatorTree.root >= 0, "root should be positive");
|
||||
ok(dominatorTree.root <= Math.pow(2, 48), "root should be less than or equal to 2^48");
|
||||
do_test_finished();
|
||||
}
|
|
@ -30,6 +30,7 @@ support-files =
|
|||
[test_census-tree-node-08.js]
|
||||
[test_DominatorTree_01.js]
|
||||
[test_DominatorTree_02.js]
|
||||
[test_DominatorTree_03.js]
|
||||
[test_HeapAnalyses_getCreationTime_01.js]
|
||||
[test_HeapAnalyses_readHeapSnapshot_01.js]
|
||||
[test_HeapAnalyses_takeCensusDiff_01.js]
|
||||
|
|
|
@ -1450,7 +1450,7 @@ addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
|
|||
});
|
||||
|
||||
// Run the tests.
|
||||
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
runAllAsyncTests().then(function() {
|
||||
|
|
|
@ -935,15 +935,15 @@ PerformanceBase::TranslateTime(DOMHighResTimeStamp aTime,
|
|||
}
|
||||
otherCreationTimeStamp = performance->CreationTimeStamp();
|
||||
} else if (aTimeSource.IsWorker()) {
|
||||
otherCreationTimeStamp = aTimeSource.GetAsWorker().NowBaseTimeStamp();
|
||||
otherCreationTimeStamp = aTimeSource.GetAsWorker().CreationTimeStamp();
|
||||
} else if (aTimeSource.IsSharedWorker()) {
|
||||
SharedWorker& sharedWorker = aTimeSource.GetAsSharedWorker();
|
||||
WorkerPrivate* workerPrivate = sharedWorker.GetWorkerPrivate();
|
||||
otherCreationTimeStamp = workerPrivate->NowBaseTimeStamp();
|
||||
otherCreationTimeStamp = workerPrivate->CreationTimeStamp();
|
||||
} else if (aTimeSource.IsServiceWorker()) {
|
||||
ServiceWorker& serviceWorker = aTimeSource.GetAsServiceWorker();
|
||||
WorkerPrivate* workerPrivate = serviceWorker.GetWorkerPrivate();
|
||||
otherCreationTimeStamp = workerPrivate->NowBaseTimeStamp();
|
||||
otherCreationTimeStamp = workerPrivate->CreationTimeStamp();
|
||||
} else {
|
||||
MOZ_CRASH("This should not be possible.");
|
||||
}
|
||||
|
|
|
@ -127,23 +127,6 @@ function testHasRun() {
|
|||
}
|
||||
}
|
||||
|
||||
function createFileWithData(fileData) {
|
||||
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"].getService(SpecialPowers.Ci.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
testFile.append("fileAPItestfile2-" + fileNum);
|
||||
fileNum++;
|
||||
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
|
||||
var fileList = document.getElementById('fileList');
|
||||
SpecialPowers.wrap(fileList).value = testFile.path;
|
||||
|
||||
return fileList.files[0];
|
||||
}
|
||||
|
||||
function gc() {
|
||||
window.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIDOMWindowUtils)
|
||||
|
|
|
@ -742,7 +742,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183
|
|||
[test_encodeToStringWithMaxLength.html]
|
||||
[test_fileapi.html]
|
||||
[test_fileapi_slice.html]
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 775227
|
||||
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 775227
|
||||
[test_getElementById.html]
|
||||
[test_html_colors_quirks.html]
|
||||
[test_html_colors_standards.html]
|
||||
|
|
|
@ -54,31 +54,6 @@ cx.fill();
|
|||
cx.closePath();
|
||||
|
||||
|
||||
var fileData =
|
||||
atob(cx.canvas.toDataURL("image/png").substring("data:text/png;base64,".length + 1));
|
||||
var memFile = cx.canvas.mozGetAsFile("image/png");
|
||||
var fileFile = createFileWithData(fileData);
|
||||
var size = fileData.length;
|
||||
|
||||
// This might fail if we dramatically improve the png encoder. If that happens
|
||||
// please increase the complexity or size of the image generated above to ensure
|
||||
// that we're testing with files that are large enough.
|
||||
ok(size > 65536, "test data sufficiently large");
|
||||
|
||||
|
||||
// Test that basic properties work
|
||||
testSlice(memFile, size, "image/png", fileData, "memFile");
|
||||
testSlice(fileFile, size, "", fileData, "fileFile");
|
||||
|
||||
|
||||
// Try loading directly from slice into an image
|
||||
var testBinaryData = "";
|
||||
for (var i = 0; i < 256; i++) {
|
||||
testBinaryData += String.fromCharCode(i);
|
||||
}
|
||||
while (testBinaryData.length < 20000) {
|
||||
testBinaryData += testBinaryData;
|
||||
}
|
||||
function imageLoadHandler(event) {
|
||||
var origcanvas = $("canvas");
|
||||
var testcanvas = $("testcanvas");
|
||||
|
@ -100,37 +75,93 @@ function imageLoadHandler(event) {
|
|||
testHasRun();
|
||||
}
|
||||
|
||||
// image in the middle
|
||||
var imgfile = createFileWithData(testBinaryData + fileData + testBinaryData);
|
||||
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
var fileData =
|
||||
atob(cx.canvas.toDataURL("image/png").substring("data:text/png;base64,".length + 1));
|
||||
var size = fileData.length;
|
||||
var testBinaryData = "";
|
||||
|
||||
// image at start
|
||||
var imgfile = createFileWithData(fileData + testBinaryData);
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(0, size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
// This might fail if we dramatically improve the png encoder. If that happens
|
||||
// please increase the complexity or size of the image generated above to ensure
|
||||
// that we're testing with files that are large enough.
|
||||
ok(size > 65536, "test data sufficiently large");
|
||||
|
||||
// image at end
|
||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
SpecialPowers.createFiles([{name: "basicTestFile", data: fileData}],
|
||||
basicTest);
|
||||
|
||||
function basicTest(files) {
|
||||
var fileFile = files[0];
|
||||
|
||||
// Test that basic properties work
|
||||
var memFile = cx.canvas.mozGetAsFile("image/png");
|
||||
testSlice(memFile, size, "image/png", fileData, "memFile");
|
||||
testSlice(fileFile, size, "", fileData, "fileFile");
|
||||
|
||||
// Try loading directly from slice into an image
|
||||
for (var i = 0; i < 256; i++) {
|
||||
testBinaryData += String.fromCharCode(i);
|
||||
}
|
||||
while (testBinaryData.length < 20000) {
|
||||
testBinaryData += testBinaryData;
|
||||
}
|
||||
|
||||
// image in the middle
|
||||
SpecialPowers.createFiles([{name: "middleTestFile",
|
||||
data: testBinaryData + fileData + testBinaryData}],
|
||||
imageMiddleTest);
|
||||
}
|
||||
|
||||
function imageMiddleTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length * 2, "correct file size (middle)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
|
||||
// image at start
|
||||
SpecialPowers.createFiles([{name: "startTestFile",
|
||||
data: fileData + testBinaryData}],
|
||||
imageStartTest);
|
||||
}
|
||||
|
||||
function imageStartTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (start)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(0, size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
|
||||
// image at end
|
||||
SpecialPowers.createFiles([{name: "endTestFile",
|
||||
data: testBinaryData + fileData}],
|
||||
imageEndTest);
|
||||
}
|
||||
|
||||
function imageEndTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
|
||||
// image past end
|
||||
SpecialPowers.createFiles([{name: "pastEndTestFile",
|
||||
data: testBinaryData + fileData}],
|
||||
imagePastEndTest);
|
||||
}
|
||||
|
||||
function imagePastEndTest(files) {
|
||||
var imgfile = files[0];
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size + 1000));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
}
|
||||
|
||||
// image past end
|
||||
var imgfile = createFileWithData(testBinaryData + fileData);
|
||||
is(imgfile.size, size + testBinaryData.length, "correct file size (past end)");
|
||||
var img = new Image;
|
||||
img.src = URL.createObjectURL(imgfile.slice(testBinaryData.length, testBinaryData.length + size + 1000));
|
||||
img.onload = imageLoadHandler;
|
||||
expectedTestCount++;
|
||||
</script>
|
||||
</pre>
|
||||
</body> </html>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -43,7 +43,7 @@ function testWorker() {
|
|||
var w = new Worker('empty_worker.js');
|
||||
var a = performance.translateTime(0, w);
|
||||
// bug 1226147
|
||||
todo (a >= now, "Time has been translated from a Worker that started loading later than we did");
|
||||
ok (a >= now, "Time has been translated from a Worker that started loading later than we did");
|
||||
next();
|
||||
}
|
||||
|
||||
|
|
|
@ -495,6 +495,7 @@ DOMInterfaces = {
|
|||
'ExtendableEvent': {
|
||||
'headerFile': 'mozilla/dom/ServiceWorkerEvents.h',
|
||||
'nativeType': 'mozilla::dom::workers::ExtendableEvent',
|
||||
'implicitJSContext': [ 'waitUntil' ],
|
||||
},
|
||||
|
||||
'ExtendableMessageEvent': {
|
||||
|
|
|
@ -2281,7 +2281,9 @@ public:
|
|||
}
|
||||
|
||||
// unref stored DBusMessages before clearing the hashtable
|
||||
sPairingReqTable->EnumerateRead(UnrefDBusMessage, nullptr);
|
||||
for (auto iter = sPairingReqTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
dbus_message_unref(iter.UserData());
|
||||
}
|
||||
sPairingReqTable->Clear();
|
||||
|
||||
sIsPairing = 0;
|
||||
|
@ -2299,14 +2301,6 @@ public:
|
|||
BT_WARNING("Failed to dispatch to BT thread!");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static PLDHashOperator
|
||||
UnrefDBusMessage(const BluetoothAddress& key, DBusMessage* value, void* arg)
|
||||
{
|
||||
dbus_message_unref(value);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
};
|
||||
|
||||
class StopBluetoothRunnable final : public nsRunnable
|
||||
|
|
|
@ -1118,7 +1118,7 @@ Event::TimeStamp() const
|
|||
MOZ_ASSERT(workerPrivate);
|
||||
|
||||
TimeDuration duration =
|
||||
mEvent->timeStamp - workerPrivate->NowBaseTimeStamp();
|
||||
mEvent->timeStamp - workerPrivate->CreationTimeStamp();
|
||||
return duration.ToMilliseconds();
|
||||
}
|
||||
|
||||
|
|
|
@ -74,8 +74,9 @@ function testWorkerEvents() {
|
|||
var worker = new Worker(window.URL.createObjectURL(blob));
|
||||
worker.onmessage = function(evt) {
|
||||
var timeAfterEvent = window.performance.now();
|
||||
ok(evt.data > timeBeforeEvent &&
|
||||
evt.data < timeAfterEvent,
|
||||
var time = window.performance.translateTime(evt.data, worker);
|
||||
ok(time >= timeBeforeEvent &&
|
||||
time <= timeAfterEvent,
|
||||
"Event timestamp in dedicated worker (" + evt.data +
|
||||
") is in expected range: (" +
|
||||
timeBeforeEvent + ", " + timeAfterEvent + ")");
|
||||
|
|
|
@ -404,7 +404,7 @@ nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect)
|
|||
|
||||
// Subtract the parent border unless it uses border-box sizing.
|
||||
if (parent &&
|
||||
parent->StylePosition()->mBoxSizing != NS_STYLE_BOX_SIZING_BORDER) {
|
||||
parent->StylePosition()->mBoxSizing != StyleBoxSizing::Border) {
|
||||
const nsStyleBorder* border = parent->StyleBorder();
|
||||
origin.x -= border->GetComputedBorderWidth(NS_SIDE_LEFT);
|
||||
origin.y -= border->GetComputedBorderWidth(NS_SIDE_TOP);
|
||||
|
|
|
@ -50,14 +50,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=388794
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var pendingLoads = 0;
|
||||
|
||||
/* Use regex due to rounding error in Fennec with C++APZ enabled */
|
||||
var hrefs = {
|
||||
test1: "data:text/html,?testImage.x=0&testImage.y=0",
|
||||
test2: "data:text/html,?x=0&y=0",
|
||||
test3: "data:text/html,?testImage.x=0&testImage.y=0",
|
||||
test4: "data:text/html,?x=0&y=0",
|
||||
test5: "data:text/html,?testImage.x=5&testImage.y=5",
|
||||
test6: "data:text/html,?x=5&y=5",
|
||||
test1: /data:text\/html,\?testImage\.x=0&testImage\.y=0/,
|
||||
test2: /data:text\/html,\?x=0&y=0/,
|
||||
test3: /data:text\/html,\?testImage\.x=0&testImage\.y=0/,
|
||||
test4: /data:text\/html,\?x=0&y=0/,
|
||||
test5: /data:text\/html,\?testImage\.x=[4-6]&testImage\.y=[4-6]/,
|
||||
test6: /data:text\/html,\?x=[4-6]&y=[4-6]/,
|
||||
};
|
||||
|
||||
function submitForm(idNum) {
|
||||
|
@ -91,8 +91,8 @@ addLoadEvent(function() {
|
|||
});
|
||||
|
||||
function frameLoaded(frame) {
|
||||
is(frame.contentWindow.location.href, hrefs[frame.name],
|
||||
"Unexpected href for frame " + frame.name);
|
||||
ok(hrefs[frame.name].test(frame.contentWindow.location.href),
|
||||
"Unexpected href for frame " + frame.name, "expected to match: " + hrefs[frame.name].toString() + " got: " + frame.contentWindow.location.href);
|
||||
if (--pendingLoads == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
|
|
@ -93,7 +93,9 @@ public:
|
|||
if (mozilla::IsInfinite<double>(aValue)) {
|
||||
return FromInfinity();
|
||||
}
|
||||
double val = aValue * USECS_PER_S;
|
||||
// Due to internal double representation, this
|
||||
// operation is not commutative, do not attempt to simplify.
|
||||
double val = (aValue + .0000005) * USECS_PER_S;
|
||||
if (val >= double(INT64_MAX)) {
|
||||
return FromMicroseconds(INT64_MAX);
|
||||
} else if (val <= double(INT64_MIN)) {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "TimeUnits.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
TEST(TimeUnit, Rounding)
|
||||
{
|
||||
int64_t usecs = 66261715;
|
||||
double seconds = media::TimeUnit::FromMicroseconds(usecs).ToSeconds();
|
||||
EXPECT_EQ(media::TimeUnit::FromSeconds(seconds).ToMicroseconds(), usecs);
|
||||
|
||||
seconds = 4.169470;
|
||||
usecs = 4169470;
|
||||
EXPECT_EQ(media::TimeUnit::FromSeconds(seconds).ToMicroseconds(), usecs);
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
@ -263,18 +264,6 @@ MessagePortService::ClosePort(MessagePortParent* aParent)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PLDHashOperator
|
||||
MessagePortService::CloseAllDebugCheck(const nsID& aID,
|
||||
MessagePortServiceData* aData,
|
||||
void* aPtr)
|
||||
{
|
||||
nsID* id = static_cast<nsID*>(aPtr);
|
||||
MOZ_ASSERT(!id->Equals(aID));
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
MessagePortService::CloseAll(const nsID& aUUID, bool aForced)
|
||||
{
|
||||
|
@ -319,7 +308,9 @@ MessagePortService::CloseAll(const nsID& aUUID, bool aForced)
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
mPorts.EnumerateRead(CloseAllDebugCheck, const_cast<nsID*>(&aUUID));
|
||||
for (auto iter = mPorts.Iter(); !iter.Done(); iter.Next()) {
|
||||
MOZ_ASSERT(!aUUID.Equals(iter.Key()));
|
||||
}
|
||||
#endif
|
||||
|
||||
MaybeShutdown();
|
||||
|
|
|
@ -151,19 +151,6 @@ DOMStorageCache::Persist(const DOMStorage* aStorage) const
|
|||
!aStorage->IsPrivate();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
PLDHashOperator
|
||||
CloneSetData(const nsAString& aKey, const nsString aValue, void* aArg)
|
||||
{
|
||||
DOMStorageCache::Data* target = static_cast<DOMStorageCache::Data*>(aArg);
|
||||
target->mKeys.Put(aKey, aValue);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DOMStorageCache::Data&
|
||||
DOMStorageCache::DataSet(const DOMStorage* aStorage)
|
||||
{
|
||||
|
@ -178,7 +165,9 @@ DOMStorageCache::DataSet(const DOMStorage* aStorage)
|
|||
Data& defaultSet = mData[kDefaultSet];
|
||||
Data& sessionSet = mData[kSessionSet];
|
||||
|
||||
defaultSet.mKeys.EnumerateRead(CloneSetData, &sessionSet);
|
||||
for (auto iter = defaultSet.mKeys.Iter(); !iter.Done(); iter.Next()) {
|
||||
sessionSet.mKeys.Put(iter.Key(), iter.UserData());
|
||||
}
|
||||
|
||||
mSessionOnlyDataSetActive = true;
|
||||
|
||||
|
@ -363,36 +352,6 @@ DOMStorageCache::GetLength(const DOMStorage* aStorage, uint32_t* aRetval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class IndexFinderData
|
||||
{
|
||||
public:
|
||||
IndexFinderData(uint32_t aIndex, nsAString& aRetval)
|
||||
: mIndex(aIndex), mKey(aRetval)
|
||||
{
|
||||
mKey.SetIsVoid(true);
|
||||
}
|
||||
|
||||
uint32_t mIndex;
|
||||
nsAString& mKey;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
FindKeyOrder(const nsAString& aKey, const nsString aValue, void* aArg)
|
||||
{
|
||||
IndexFinderData* data = static_cast<IndexFinderData*>(aArg);
|
||||
|
||||
if (data->mIndex--) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
data->mKey = aKey;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
nsresult
|
||||
DOMStorageCache::GetKey(const DOMStorage* aStorage, uint32_t aIndex, nsAString& aRetval)
|
||||
{
|
||||
|
@ -407,24 +366,18 @@ DOMStorageCache::GetKey(const DOMStorage* aStorage, uint32_t aIndex, nsAString&
|
|||
}
|
||||
}
|
||||
|
||||
IndexFinderData data(aIndex, aRetval);
|
||||
DataSet(aStorage).mKeys.EnumerateRead(FindKeyOrder, &data);
|
||||
aRetval.SetIsVoid(true);
|
||||
for (auto iter = DataSet(aStorage).mKeys.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (aIndex == 0) {
|
||||
aRetval = iter.Key();
|
||||
break;
|
||||
}
|
||||
aIndex--;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static PLDHashOperator
|
||||
KeysArrayBuilder(const nsAString& aKey, const nsString aValue, void* aArg)
|
||||
{
|
||||
nsTArray<nsString>* keys = static_cast<nsTArray<nsString>* >(aArg);
|
||||
|
||||
keys->AppendElement(aKey);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
DOMStorageCache::GetKeys(const DOMStorage* aStorage, nsTArray<nsString>& aKeys)
|
||||
{
|
||||
|
@ -436,7 +389,9 @@ DOMStorageCache::GetKeys(const DOMStorage* aStorage, nsTArray<nsString>& aKeys)
|
|||
return;
|
||||
}
|
||||
|
||||
DataSet(aStorage).mKeys.EnumerateRead(KeysArrayBuilder, &aKeys);
|
||||
for (auto iter = DataSet(aStorage).mKeys.Iter(); !iter.Done(); iter.Next()) {
|
||||
aKeys.AppendElement(iter.Key());
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -598,7 +553,9 @@ DOMStorageCache::CloneFrom(const DOMStorageCache* aThat)
|
|||
mSessionOnlyDataSetActive = aThat->mSessionOnlyDataSetActive;
|
||||
|
||||
for (uint32_t i = 0; i < kDataSetCount; ++i) {
|
||||
aThat->mData[i].mKeys.EnumerateRead(CloneSetData, &mData[i]);
|
||||
for (auto it = aThat->mData[i].mKeys.ConstIter(); !it.Done(); it.Next()) {
|
||||
mData[i].mKeys.Put(it.Key(), it.UserData());
|
||||
}
|
||||
ProcessUsageDelta(i, aThat->mData[i].mOriginQuotaUsage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1253,40 +1253,25 @@ DOMStorageDBThread::PendingOperations::Finalize(nsresult aRv)
|
|||
|
||||
namespace {
|
||||
|
||||
class FindPendingOperationForScopeData
|
||||
bool
|
||||
FindPendingClearForScope(const nsACString& aScope,
|
||||
DOMStorageDBThread::DBOperation* aPendingOperation)
|
||||
{
|
||||
public:
|
||||
explicit FindPendingOperationForScopeData(const nsACString& aScope) : mScope(aScope), mFound(false) {}
|
||||
nsCString mScope;
|
||||
bool mFound;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
FindPendingClearForScope(const nsACString& aMapping,
|
||||
DOMStorageDBThread::DBOperation* aPendingOperation,
|
||||
void* aArg)
|
||||
{
|
||||
FindPendingOperationForScopeData* data =
|
||||
static_cast<FindPendingOperationForScopeData*>(aArg);
|
||||
|
||||
if (aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opClearAll) {
|
||||
data->mFound = true;
|
||||
return PL_DHASH_STOP;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opClear &&
|
||||
data->mScope == aPendingOperation->Scope()) {
|
||||
data->mFound = true;
|
||||
return PL_DHASH_STOP;
|
||||
aScope == aPendingOperation->Scope()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opClearMatchingScope &&
|
||||
StringBeginsWith(data->mScope, aPendingOperation->Scope())) {
|
||||
data->mFound = true;
|
||||
return PL_DHASH_STOP;
|
||||
StringBeginsWith(aScope, aPendingOperation->Scope())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1296,17 +1281,14 @@ DOMStorageDBThread::PendingOperations::IsScopeClearPending(const nsACString& aSc
|
|||
{
|
||||
// Called under the lock
|
||||
|
||||
FindPendingOperationForScopeData data(aScope);
|
||||
mClears.EnumerateRead(FindPendingClearForScope, &data);
|
||||
if (data.mFound) {
|
||||
return true;
|
||||
for (auto iter = mClears.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (FindPendingClearForScope(aScope, iter.UserData())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mExecList.Length(); ++i) {
|
||||
DOMStorageDBThread::DBOperation* task = mExecList[i];
|
||||
FindPendingClearForScope(EmptyCString(), task, &data);
|
||||
|
||||
if (data.mFound) {
|
||||
if (FindPendingClearForScope(aScope, mExecList[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1316,23 +1298,18 @@ DOMStorageDBThread::PendingOperations::IsScopeClearPending(const nsACString& aSc
|
|||
|
||||
namespace {
|
||||
|
||||
PLDHashOperator
|
||||
FindPendingUpdateForScope(const nsACString& aMapping,
|
||||
DOMStorageDBThread::DBOperation* aPendingOperation,
|
||||
void* aArg)
|
||||
bool
|
||||
FindPendingUpdateForScope(const nsACString& aScope,
|
||||
DOMStorageDBThread::DBOperation* aPendingOperation)
|
||||
{
|
||||
FindPendingOperationForScopeData* data =
|
||||
static_cast<FindPendingOperationForScopeData*>(aArg);
|
||||
|
||||
if ((aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opAddItem ||
|
||||
aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opUpdateItem ||
|
||||
aPendingOperation->Type() == DOMStorageDBThread::DBOperation::opRemoveItem) &&
|
||||
data->mScope == aPendingOperation->Scope()) {
|
||||
data->mFound = true;
|
||||
return PL_DHASH_STOP;
|
||||
aScope == aPendingOperation->Scope()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1342,17 +1319,14 @@ DOMStorageDBThread::PendingOperations::IsScopeUpdatePending(const nsACString& aS
|
|||
{
|
||||
// Called under the lock
|
||||
|
||||
FindPendingOperationForScopeData data(aScope);
|
||||
mUpdates.EnumerateRead(FindPendingUpdateForScope, &data);
|
||||
if (data.mFound) {
|
||||
return true;
|
||||
for (auto iter = mUpdates.Iter(); !iter.Done(); iter.Next()) {
|
||||
if (FindPendingUpdateForScope(aScope, iter.UserData())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mExecList.Length(); ++i) {
|
||||
DOMStorageDBThread::DBOperation* task = mExecList[i];
|
||||
FindPendingUpdateForScope(EmptyCString(), task, &data);
|
||||
|
||||
if (data.mFound) {
|
||||
if (FindPendingUpdateForScope(aScope, mExecList[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
typedef unsigned long long NodeId;
|
||||
|
||||
/**
|
||||
* In a directed graph with a root node `R`, a node `A` is said to "dominate" a
|
||||
* node `B` iff every path from `R` to `B` contains `A`. A node `A` is said to
|
||||
|
@ -37,5 +39,10 @@
|
|||
*/
|
||||
[ChromeOnly, Exposed=(Window,System,Worker)]
|
||||
interface DominatorTree {
|
||||
|
||||
/**
|
||||
* The `NodeId` for the root of the dominator tree. This is a "meta-root" in
|
||||
* that it has an edge to each GC root in the heap snapshot this dominator
|
||||
* tree was created from.
|
||||
*/
|
||||
readonly attribute NodeId root;
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
* W3C liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" };
|
||||
enum SessionType { "temporary", "persistent" };
|
||||
|
||||
[Pref="media.eme.apiVisible"]
|
||||
|
|
|
@ -32,13 +32,8 @@ DOMHighResTimeStamp
|
|||
Performance::Now() const
|
||||
{
|
||||
TimeDuration duration =
|
||||
TimeStamp::Now() - mWorkerPrivate->NowBaseTimeStamp();
|
||||
double nowTime = duration.ToMilliseconds();
|
||||
// Round down to the nearest 5us, because if the timer is too accurate people
|
||||
// can do nasty timing attacks with it. See similar code in the non-worker
|
||||
// Performance implementation.
|
||||
const double maxResolutionMs = 0.005;
|
||||
return floor(nowTime / maxResolutionMs) * maxResolutionMs;
|
||||
TimeStamp::Now() - mWorkerPrivate->CreationTimeStamp();
|
||||
return RoundTime(duration.ToMilliseconds());
|
||||
}
|
||||
|
||||
// To be removed once bug 1124165 lands
|
||||
|
@ -57,7 +52,7 @@ Performance::GetPerformanceTimingFromString(const nsAString& aProperty)
|
|||
}
|
||||
|
||||
if (aProperty.EqualsLiteral("navigationStart")) {
|
||||
return mWorkerPrivate->NowBaseTimeHighRes();
|
||||
return mWorkerPrivate->CreationTime();
|
||||
}
|
||||
|
||||
MOZ_CRASH("IsPerformanceTimingAttribute and GetPerformanceTimingFromString are out of sync");
|
||||
|
@ -82,13 +77,13 @@ Performance::InsertUserEntry(PerformanceEntry* aEntry)
|
|||
TimeStamp
|
||||
Performance::CreationTimeStamp() const
|
||||
{
|
||||
return mWorkerPrivate->NowBaseTimeStamp();
|
||||
return mWorkerPrivate->CreationTimeStamp();
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp
|
||||
Performance::CreationTime() const
|
||||
{
|
||||
return mWorkerPrivate->NowBaseTimeHighRes();
|
||||
return mWorkerPrivate->CreationTime();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -697,7 +697,9 @@ FetchEvent::RespondWith(JSContext* aCx, Promise& aArg, ErrorResult& aRv)
|
|||
spec, line, column);
|
||||
aArg.AppendNativeHandler(handler);
|
||||
|
||||
WaitUntil(aArg, aRv);
|
||||
// Append directly to the lifecycle promises array. Don't call WaitUntil()
|
||||
// because that will lead to double-reporting any errors.
|
||||
mPromises.AppendElement(&aArg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -739,6 +741,94 @@ FetchEvent::ReportCanceled()
|
|||
NS_LITERAL_CSTRING("InterceptionCanceledWithURL"), &requestURL);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class WaitUntilHandler final : public PromiseNativeHandler
|
||||
{
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
const nsCString mScope;
|
||||
nsCString mSourceSpec;
|
||||
uint32_t mLine;
|
||||
uint32_t mColumn;
|
||||
nsString mRejectValue;
|
||||
|
||||
~WaitUntilHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
WaitUntilHandler(WorkerPrivate* aWorkerPrivate, JSContext* aCx)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
, mScope(mWorkerPrivate->WorkerName())
|
||||
, mLine(0)
|
||||
, mColumn(0)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// Save the location of the waitUntil() call itself as a fallback
|
||||
// in case the rejection value does not contain any location info.
|
||||
nsJSUtils::GetCallingLocation(aCx, mSourceSpec, &mLine, &mColumn);
|
||||
}
|
||||
|
||||
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||
{
|
||||
// do nothing, we are only here to report errors
|
||||
}
|
||||
|
||||
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
nsCString spec;
|
||||
uint32_t line = 0;
|
||||
uint32_t column = 0;
|
||||
ExtractErrorValues(aCx, aValue, spec, &line, &column, mRejectValue);
|
||||
|
||||
// only use the extracted location if we found one
|
||||
if (!spec.IsEmpty()) {
|
||||
mSourceSpec = spec;
|
||||
mLine = line;
|
||||
mColumn = column;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &WaitUntilHandler::ReportOnMainThread);
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
|
||||
NS_DispatchToMainThread(runnable.forget())));
|
||||
}
|
||||
|
||||
void
|
||||
ReportOnMainThread()
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
|
||||
// TODO: Make the error message a localized string. (bug 1222720)
|
||||
nsString message;
|
||||
message.AppendLiteral("Service worker event waitUntil() was passed a "
|
||||
"promise that rejected with '");
|
||||
message.Append(mRejectValue);
|
||||
message.AppendLiteral("'.");
|
||||
|
||||
// Note, there is a corner case where this won't report to the window
|
||||
// that triggered the error. Consider a navigation fetch event that
|
||||
// rejects waitUntil() without holding respondWith() open. In this case
|
||||
// there is no controlling document yet, the window did call .register()
|
||||
// because there is no documeny yet, and the navigation is no longer
|
||||
// being intercepted.
|
||||
|
||||
swm->ReportToAllClients(mScope, message, NS_ConvertUTF8toUTF16(mSourceSpec),
|
||||
EmptyString(), mLine, mColumn,
|
||||
nsIScriptError::errorFlag);
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS0(WaitUntilHandler)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(FetchEvent, ExtendableEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(FetchEvent, ExtendableEvent)
|
||||
|
||||
|
@ -753,7 +843,7 @@ ExtendableEvent::ExtendableEvent(EventTarget* aOwner)
|
|||
}
|
||||
|
||||
void
|
||||
ExtendableEvent::WaitUntil(Promise& aPromise, ErrorResult& aRv)
|
||||
ExtendableEvent::WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
|
@ -762,6 +852,12 @@ ExtendableEvent::WaitUntil(Promise& aPromise, ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
|
||||
// Append our handler to each waitUntil promise separately so we
|
||||
// can record the location in script where waitUntil was called.
|
||||
RefPtr<WaitUntilHandler> handler =
|
||||
new WaitUntilHandler(GetCurrentThreadWorkerPrivate(), aCx);
|
||||
aPromise.AppendNativeHandler(handler);
|
||||
|
||||
mPromises.AppendElement(&aPromise);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,9 @@ public:
|
|||
|
||||
class ExtendableEvent : public Event
|
||||
{
|
||||
protected:
|
||||
nsTArray<RefPtr<Promise>> mPromises;
|
||||
|
||||
protected:
|
||||
explicit ExtendableEvent(mozilla::dom::EventTarget* aOwner);
|
||||
~ExtendableEvent() {}
|
||||
|
||||
|
@ -90,7 +90,7 @@ public:
|
|||
}
|
||||
|
||||
void
|
||||
WaitUntil(Promise& aPromise, ErrorResult& aRv);
|
||||
WaitUntil(JSContext* aCx, Promise& aPromise, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
GetPromise();
|
||||
|
|
|
@ -945,10 +945,10 @@ public:
|
|||
mRegistration = swm->GetRegistration(mPrincipal, mScope);
|
||||
|
||||
if (mRegistration) {
|
||||
mRegistration->mPendingUninstall = false;
|
||||
RefPtr<ServiceWorkerInfo> newest = mRegistration->Newest();
|
||||
if (newest && mScriptSpec.Equals(newest->ScriptSpec()) &&
|
||||
mScriptSpec.Equals(mRegistration->mScriptSpec)) {
|
||||
mRegistration->mPendingUninstall = false;
|
||||
swm->StoreRegistration(mPrincipal, mRegistration);
|
||||
Succeed();
|
||||
|
||||
|
|
|
@ -406,21 +406,10 @@ public:
|
|||
NS_RUNTIMEABORT("Failed to dispatch life cycle event handler.");
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> obj(aCx, workerPrivate->GlobalScope()->GetWrapper());
|
||||
JS::ExposeValueToActiveJS(aValue);
|
||||
|
||||
js::ErrorReport report(aCx);
|
||||
if (NS_WARN_IF(!report.init(aCx, aValue))) {
|
||||
JS_ClearPendingException(aCx);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
xpcReport->Init(report.report(), report.message(),
|
||||
/* aIsChrome = */ false, workerPrivate->WindowID());
|
||||
|
||||
RefPtr<AsyncErrorReporter> aer = new AsyncErrorReporter(xpcReport);
|
||||
NS_DispatchToMainThread(aer);
|
||||
// Note, all WaitUntil() rejections are reported to client consoles
|
||||
// by the WaitUntilHandler in ServiceWorkerEvents. This ensures that
|
||||
// errors in non-lifecycle events like FetchEvent and PushEvent are
|
||||
// reported properly.
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2192,24 +2192,11 @@ WorkerPrivateParent<Derived>::WorkerPrivateParent(
|
|||
aParent->CopyJSSettings(mJSSettings);
|
||||
|
||||
MOZ_ASSERT(IsDedicatedWorker());
|
||||
mNowBaseTimeStamp = aParent->NowBaseTimeStamp();
|
||||
mNowBaseTimeHighRes = aParent->NowBaseTimeHighRes();
|
||||
}
|
||||
else {
|
||||
AssertIsOnMainThread();
|
||||
|
||||
RuntimeService::GetDefaultJSSettings(mJSSettings);
|
||||
|
||||
if (IsDedicatedWorker() && mLoadInfo.mWindow &&
|
||||
mLoadInfo.mWindow->GetPerformance()) {
|
||||
mNowBaseTimeStamp = mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
|
||||
GetNavigationStartTimeStamp();
|
||||
mNowBaseTimeHighRes = mLoadInfo.mWindow->GetPerformance()->GetDOMTiming()->
|
||||
GetNavigationStartHighRes();
|
||||
} else {
|
||||
mNowBaseTimeStamp = CreationTimeStamp();
|
||||
mNowBaseTimeHighRes = CreationTimeHighRes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,8 +191,6 @@ private:
|
|||
WorkerType mWorkerType;
|
||||
TimeStamp mCreationTimeStamp;
|
||||
DOMHighResTimeStamp mCreationTimeHighRes;
|
||||
TimeStamp mNowBaseTimeStamp;
|
||||
DOMHighResTimeStamp mNowBaseTimeHighRes;
|
||||
|
||||
protected:
|
||||
// The worker is owned by its thread, which is represented here. This is set
|
||||
|
@ -549,21 +547,11 @@ public:
|
|||
return mCreationTimeStamp;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp CreationTimeHighRes() const
|
||||
DOMHighResTimeStamp CreationTime() const
|
||||
{
|
||||
return mCreationTimeHighRes;
|
||||
}
|
||||
|
||||
TimeStamp NowBaseTimeStamp() const
|
||||
{
|
||||
return mNowBaseTimeStamp;
|
||||
}
|
||||
|
||||
DOMHighResTimeStamp NowBaseTimeHighRes() const
|
||||
{
|
||||
return mNowBaseTimeHighRes;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
GetPrincipal() const
|
||||
{
|
||||
|
|
|
@ -472,6 +472,9 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
|||
}
|
||||
|
||||
srView = static_cast<SourceSurfaceD2DTarget*>(aSurface)->GetSRView();
|
||||
if (!srView) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureViews();
|
||||
|
||||
|
@ -759,6 +762,11 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
|||
|
||||
mDevice->Draw(4, 0);
|
||||
|
||||
srView = static_cast<SourceSurfaceD2DTarget*>(aSurface)->GetSRView();
|
||||
if (!srView) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((aDest.x / mSize.width) * 2.0f),
|
||||
1.0f - (aDest.y / mSize.height * 2.0f),
|
||||
|
|
|
@ -230,30 +230,15 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
|||
aEndAngle = oldStart;
|
||||
}
|
||||
|
||||
const Float kSmallRadius = 0.007f;
|
||||
Float midAngle = 0;
|
||||
bool smallFullCircle = false;
|
||||
|
||||
// XXX - Workaround for now, D2D does not appear to do the desired thing when
|
||||
// the angle sweeps a complete circle.
|
||||
bool fullCircle = false;
|
||||
if (aEndAngle - aStartAngle >= 2 * M_PI) {
|
||||
if (aRadius > kSmallRadius) {
|
||||
aEndAngle = Float(aStartAngle + M_PI * 1.9999);
|
||||
}
|
||||
else {
|
||||
smallFullCircle = true;
|
||||
midAngle = Float(aStartAngle + M_PI);
|
||||
aEndAngle = Float(aStartAngle + 2 * M_PI);
|
||||
}
|
||||
fullCircle = true;
|
||||
aEndAngle = Float(aStartAngle + M_PI * 1.9999);
|
||||
} else if (aStartAngle - aEndAngle >= 2 * M_PI) {
|
||||
if (aRadius > kSmallRadius) {
|
||||
aStartAngle = Float(aEndAngle + M_PI * 1.9999);
|
||||
}
|
||||
else {
|
||||
smallFullCircle = true;
|
||||
midAngle = Float(aEndAngle + M_PI);
|
||||
aStartAngle = Float(aEndAngle + 2 * M_PI);
|
||||
}
|
||||
fullCircle = true;
|
||||
aStartAngle = Float(aEndAngle + M_PI * 1.9999);
|
||||
}
|
||||
|
||||
Point startPoint;
|
||||
|
@ -275,7 +260,12 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
|||
aAntiClockwise ? D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE :
|
||||
D2D1_SWEEP_DIRECTION_CLOCKWISE;
|
||||
|
||||
if (!smallFullCircle) {
|
||||
// if startPoint and endPoint of our circle are too close there are D2D issues
|
||||
// with drawing the circle as a single arc
|
||||
const Float kEpsilon = 1e-5f;
|
||||
if (!fullCircle ||
|
||||
(std::abs(startPoint.x - endPoint.x) +
|
||||
std::abs(startPoint.y - endPoint.y) > kEpsilon)) {
|
||||
|
||||
if (aAntiClockwise) {
|
||||
if (aStartAngle - aEndAngle > M_PI) {
|
||||
|
@ -294,7 +284,10 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
|||
arcSize));
|
||||
}
|
||||
else {
|
||||
// draw small circles as two half-circles
|
||||
// our first workaround attempt didn't work, so instead draw the circle as
|
||||
// two half-circles
|
||||
Float midAngle = aEndAngle > aStartAngle ?
|
||||
Float(aStartAngle + M_PI) : Float(aEndAngle + M_PI);
|
||||
Point midPoint;
|
||||
midPoint.x = aOrigin.x + aRadius * cosf(midAngle);
|
||||
midPoint.y = aOrigin.y + aRadius * sinf(midAngle);
|
||||
|
@ -305,7 +298,9 @@ PathBuilderD2D::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
|||
direction,
|
||||
arcSize));
|
||||
|
||||
mSink->AddArc(D2D1::ArcSegment(D2DPoint(endPoint),
|
||||
// if the adjusted endPoint computed above is used here and endPoint !=
|
||||
// startPoint then this half of the circle won't render...
|
||||
mSink->AddArc(D2D1::ArcSegment(D2DPoint(startPoint),
|
||||
D2D1::SizeF(aRadius, aRadius),
|
||||
0.0f,
|
||||
direction,
|
||||
|
|
|
@ -96,6 +96,11 @@ SourceSurfaceD2DTarget::GetSRView()
|
|||
return mSRView;
|
||||
}
|
||||
|
||||
if (!Factory::GetDirect3D10Device()) {
|
||||
gfxCriticalError() << "Invalid D3D10 device in D2D target surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HRESULT hr = Factory::GetDirect3D10Device()->CreateShaderResourceView(mTexture, nullptr, getter_AddRefs(mSRView));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
@ -40,15 +40,8 @@ RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1,
|
|||
static GLfloat
|
||||
WrapTexCoord(GLfloat v)
|
||||
{
|
||||
// fmodf gives negative results for negative numbers;
|
||||
// that is, fmodf(0.75, 1.0) == 0.75, but
|
||||
// fmodf(-0.75, 1.0) == -0.75. For the negative case,
|
||||
// the result we need is 0.25, so we add 1.0f.
|
||||
if (v < 0.0f) {
|
||||
return 1.0f + fmodf(v, 1.0f);
|
||||
}
|
||||
|
||||
return fmodf(v, 1.0f);
|
||||
// This should return values in range [0, 1.0)
|
||||
return v - floorf(v);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -200,15 +200,8 @@ Compositor::FillRect(const gfx::Rect& aRect, const gfx::Color& aColor,
|
|||
static float
|
||||
WrapTexCoord(float v)
|
||||
{
|
||||
// fmodf gives negative results for negative numbers;
|
||||
// that is, fmodf(0.75, 1.0) == 0.75, but
|
||||
// fmodf(-0.75, 1.0) == -0.75. For the negative case,
|
||||
// the result we need is 0.25, so we add 1.0f.
|
||||
if (v < 0.0f) {
|
||||
return 1.0f + fmodf(v, 1.0f);
|
||||
}
|
||||
|
||||
return fmodf(v, 1.0f);
|
||||
// This should return values in range [0, 1.0)
|
||||
return v - floorf(v);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -1220,14 +1220,16 @@ APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
|
|||
}
|
||||
if (node && aConstraints) {
|
||||
ForEachNode(node.get(),
|
||||
[&aConstraints, this](HitTestingTreeNode* aNode)
|
||||
[&aConstraints, &node, this](HitTestingTreeNode* aNode)
|
||||
{
|
||||
if (AsyncPanZoomController* childApzc = aNode->GetApzc()) {
|
||||
// We can have subtrees with their own zoom constraints or separate layers
|
||||
// id - leave these alone.
|
||||
if (childApzc->HasNoParentWithSameLayersId() ||
|
||||
this->mZoomConstraints.find(childApzc->GetGuid()) != this->mZoomConstraints.end()) {
|
||||
return TraversalFlag::Skip;
|
||||
if (aNode != node) {
|
||||
if (AsyncPanZoomController* childApzc = aNode->GetApzc()) {
|
||||
// We can have subtrees with their own zoom constraints or separate layers
|
||||
// id - leave these alone.
|
||||
if (childApzc->HasNoParentWithSameLayersId() ||
|
||||
this->mZoomConstraints.find(childApzc->GetGuid()) != this->mZoomConstraints.end()) {
|
||||
return TraversalFlag::Skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aNode->IsPrimaryHolder()) {
|
||||
|
|
|
@ -168,7 +168,10 @@ ContainerRenderVR(ContainerT* aContainer,
|
|||
if (!aContainer->mVRRenderTargetSet || aContainer->mVRRenderTargetSet->size != surfaceRect.Size()) {
|
||||
aContainer->mVRRenderTargetSet = vrRendering->CreateRenderTargetSet(compositor, surfaceRect.Size());
|
||||
}
|
||||
|
||||
if (!aContainer->mVRRenderTargetSet) {
|
||||
NS_WARNING("CreateRenderTargetSet failed");
|
||||
return;
|
||||
}
|
||||
surface = aContainer->mVRRenderTargetSet->GetNextRenderTarget();
|
||||
if (!surface) {
|
||||
NS_WARNING("GetNextRenderTarget failed");
|
||||
|
|
|
@ -370,6 +370,9 @@ TextureClientD3D11::Unlock()
|
|||
|
||||
if (NS_IsMainThread() && mReadbackSink && mTexture10) {
|
||||
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
mTexture10->GetDesc(&desc);
|
||||
|
@ -588,6 +591,9 @@ TextureClientD3D11::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlag
|
|||
}
|
||||
} else {
|
||||
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
if (!device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CD3D10_TEXTURE2D_DESC newDesc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
aSize.width, aSize.height, 1, 1,
|
||||
|
@ -1235,6 +1241,9 @@ SyncObjectD3D11::FinalizeFrame()
|
|||
|
||||
if (!mD3D10Texture && mD3D10SyncedTextures.size()) {
|
||||
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
|
||||
hr = device->OpenSharedResource(mHandle, __uuidof(ID3D10Texture2D), (void**)(ID3D10Texture2D**)getter_AddRefs(mD3D10Texture));
|
||||
|
||||
|
@ -1305,6 +1314,9 @@ SyncObjectD3D11::FinalizeFrame()
|
|||
box.back = box.bottom = box.right = 1;
|
||||
|
||||
ID3D10Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device();
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto iter = mD3D10SyncedTextures.begin(); iter != mD3D10SyncedTextures.end(); iter++) {
|
||||
device->CopySubresourceRegion(mD3D10Texture, 0, 0, 0, 0, *iter, 0, &box);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%" height="100%">
|
||||
|
||||
<title>Testcase for small radius circle with large center coordinates</title>
|
||||
<!--From https://bugzilla.mozilla.org/show_bug.cgi?id=1131264 -->
|
||||
|
||||
<rect width="100%" height="100%" fill="lime"/>
|
||||
|
||||
<circle r="5" cx="40" cy="40" fill="red" />
|
||||
<circle r="1" cx="10004" cy="10004" fill="lime"
|
||||
transform="scale(10 10) translate(-10000 -10000)"/>
|
||||
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 557 B |
|
@ -6,3 +6,4 @@ skip-if(!asyncPan) == 1086723.html 1086723-ref.html
|
|||
== 853889-1.html 853889-1-ref.html
|
||||
skip-if(Android) == 1143303-1.svg pass.svg
|
||||
fuzzy(100,30) == 1149923.html 1149923-ref.html # use fuzzy due to few distorted pixels caused by border-radius
|
||||
== 1131264-1.svg pass.svg
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
#include <gdk/gdk.h>
|
||||
#include "gfxPlatformGtk.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -400,6 +401,21 @@ gfxFontconfigFontEntry::~gfxFontconfigFontEntry()
|
|||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
PatternHasLang(const FcPattern *aPattern, const FcChar8 *aLang)
|
||||
{
|
||||
FcLangSet *langset;
|
||||
|
||||
if (FcPatternGetLangSet(aPattern, FC_LANG, 0, &langset) != FcResultMatch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FcLangSetHasLang(langset, aLang) != FcLangDifferentLang) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFontconfigFontEntry::SupportsLangGroup(nsIAtom *aLangGroup) const
|
||||
{
|
||||
|
@ -415,16 +431,7 @@ gfxFontconfigFontEntry::SupportsLangGroup(nsIAtom *aLangGroup) const
|
|||
}
|
||||
|
||||
// is lang included in the underlying pattern?
|
||||
FcLangSet *langset;
|
||||
if (FcPatternGetLangSet(mFontPattern, FC_LANG, 0, &langset) != FcResultMatch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FcLangSetHasLang(langset, (FcChar8 *)fcLang.get()) != FcLangDifferentLang) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return PatternHasLang(mFontPattern, ToFcChar8Ptr(fcLang.get()));
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1551,7 +1558,7 @@ gfxFcPlatformFontList::AddGenericFonts(mozilla::FontFamilyType aGenericType,
|
|||
void
|
||||
gfxFcPlatformFontList::ClearLangGroupPrefFonts()
|
||||
{
|
||||
mGenericMappings.Clear();
|
||||
ClearGenericMappings();
|
||||
gfxPlatformFontList::ClearLangGroupPrefFonts();
|
||||
mAlwaysUseFontconfigGenerics = PrefFontListsUseOnlyGenerics();
|
||||
}
|
||||
|
@ -1596,9 +1603,6 @@ gfxFcPlatformFontList::GetFTLibrary()
|
|||
return sCairoFTLibrary;
|
||||
}
|
||||
|
||||
// a given generic will map to at most this many families
|
||||
const uint32_t kMaxGenericFamilies = 3;
|
||||
|
||||
gfxPlatformFontList::PrefFontList*
|
||||
gfxFcPlatformFontList::FindGenericFamilies(const nsAString& aGeneric,
|
||||
nsIAtom* aLanguage)
|
||||
|
@ -1651,6 +1655,8 @@ gfxFcPlatformFontList::FindGenericFamilies(const nsAString& aGeneric,
|
|||
|
||||
// -- select the fonts to be used for the generic
|
||||
prefFonts = new PrefFontList; // can be empty but in practice won't happen
|
||||
uint32_t limit = gfxPlatformGtk::GetPlatform()->MaxGenericSubstitions();
|
||||
bool foundFontWithLang = false;
|
||||
for (int i = 0; i < faces->nfont; i++) {
|
||||
FcPattern* font = faces->fonts[i];
|
||||
FcChar8* mappedGeneric = nullptr;
|
||||
|
@ -1668,14 +1674,25 @@ gfxFcPlatformFontList::FindGenericFamilies(const nsAString& aGeneric,
|
|||
gfxFontFamily* genericFamily =
|
||||
gfxPlatformFontList::FindFamily(mappedGenericName);
|
||||
if (genericFamily && !prefFonts->Contains(genericFamily)) {
|
||||
//printf("generic %s ==> %s\n", genericLang.get(), (const char*)mappedGeneric);
|
||||
prefFonts->AppendElement(genericFamily);
|
||||
if (prefFonts->Length() >= kMaxGenericFamilies) {
|
||||
bool foundLang = !fcLang.IsEmpty() &&
|
||||
PatternHasLang(font, ToFcChar8Ptr(fcLang.get()));
|
||||
foundFontWithLang = foundFontWithLang || foundLang;
|
||||
// stop at the first family for which the lang matches (or
|
||||
// when there is no lang)
|
||||
if (fcLang.IsEmpty() ||
|
||||
prefFonts->Length() >= limit || foundLang) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if no font in the list matches the lang, trim all but the first one
|
||||
if (!prefFonts->IsEmpty() && !foundFontWithLang) {
|
||||
prefFonts->TruncateLength(1);
|
||||
}
|
||||
|
||||
mGenericMappings.Put(genericLang, prefFonts);
|
||||
return prefFonts;
|
||||
}
|
||||
|
|
|
@ -239,6 +239,11 @@ public:
|
|||
|
||||
void ClearLangGroupPrefFonts() override;
|
||||
|
||||
// clear out cached generic-lang ==> family-list mappings
|
||||
void ClearGenericMappings() {
|
||||
mGenericMappings.Clear();
|
||||
}
|
||||
|
||||
void GetSampleLangForGroup(nsIAtom* aLanguage, nsACString& aLangStr);
|
||||
|
||||
static FT_Library GetFTLibrary();
|
||||
|
|
|
@ -1772,8 +1772,8 @@ gfxPlatform::GetBidiNumeralOption()
|
|||
return mBidiNumeralOption;
|
||||
}
|
||||
|
||||
static void
|
||||
FlushFontAndWordCaches()
|
||||
/* static */ void
|
||||
gfxPlatform::FlushFontAndWordCaches()
|
||||
{
|
||||
gfxFontCache *fontCache = gfxFontCache::GetCache();
|
||||
if (fontCache) {
|
||||
|
|
|
@ -514,6 +514,9 @@ public:
|
|||
|
||||
int32_t GetBidiNumeralOption();
|
||||
|
||||
static void
|
||||
FlushFontAndWordCaches();
|
||||
|
||||
/**
|
||||
* Returns a 1x1 surface that can be used to create graphics contexts
|
||||
* for measuring text etc as if they will be rendered to the screen
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
#define GDK_PIXMAP_SIZE_MAX 32767
|
||||
|
||||
#define GFX_PREF_MAX_GENERIC_SUBSTITUTIONS "gfx.font_rendering.fontconfig.max_generic_substitutions"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::unicode;
|
||||
|
@ -72,6 +74,8 @@ gfxPlatformGtk::gfxPlatformGtk()
|
|||
sFontconfigUtils = gfxFontconfigUtils::GetFontconfigUtils();
|
||||
}
|
||||
|
||||
mMaxGenericSubstitutions = UNINITIALIZED_VALUE;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
sUseXRender = (GDK_IS_X11_DISPLAY(gdk_display_get_default())) ?
|
||||
mozilla::Preferences::GetBool("gfx.xrender.enabled") : false;
|
||||
|
@ -364,6 +368,35 @@ gfxPlatformGtk::GetOffscreenFormat()
|
|||
return gfxImageFormat::RGB24;
|
||||
}
|
||||
|
||||
void gfxPlatformGtk::FontsPrefsChanged(const char *aPref)
|
||||
{
|
||||
// only checking for generic substitions, pass other changes up
|
||||
if (strcmp(GFX_PREF_MAX_GENERIC_SUBSTITUTIONS, aPref)) {
|
||||
gfxPlatform::FontsPrefsChanged(aPref);
|
||||
return;
|
||||
}
|
||||
|
||||
mMaxGenericSubstitutions = UNINITIALIZED_VALUE;
|
||||
if (sUseFcFontList) {
|
||||
gfxFcPlatformFontList* pfl = gfxFcPlatformFontList::PlatformFontList();
|
||||
pfl->ClearGenericMappings();
|
||||
FlushFontAndWordCaches();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gfxPlatformGtk::MaxGenericSubstitions()
|
||||
{
|
||||
if (mMaxGenericSubstitutions == UNINITIALIZED_VALUE) {
|
||||
mMaxGenericSubstitutions =
|
||||
Preferences::GetInt(GFX_PREF_MAX_GENERIC_SUBSTITUTIONS, 3);
|
||||
if (mMaxGenericSubstitutions < 0) {
|
||||
mMaxGenericSubstitutions = 3;
|
||||
}
|
||||
}
|
||||
|
||||
return uint32_t(mMaxGenericSubstitutions);
|
||||
}
|
||||
|
||||
void
|
||||
gfxPlatformGtk::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
|
||||
{
|
||||
|
|
|
@ -126,9 +126,16 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
void FontsPrefsChanged(const char *aPref) override;
|
||||
|
||||
// maximum number of fonts to substitute for a generic
|
||||
uint32_t MaxGenericSubstitions();
|
||||
|
||||
protected:
|
||||
static gfxFontconfigUtils *sFontconfigUtils;
|
||||
|
||||
int8_t mMaxGenericSubstitutions;
|
||||
|
||||
private:
|
||||
virtual void GetPlatformCMSOutputProfile(void *&mem,
|
||||
size_t &size) override;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef gc_HashTable_h
|
||||
#define gc_HashTable_h
|
||||
#ifndef GCHashTable_h
|
||||
#define GCHashTable_h
|
||||
|
||||
#include "js/HashTable.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
@ -18,36 +18,48 @@ template <typename Key, typename Value>
|
|||
struct DefaultMapGCPolicy {
|
||||
using KeyPolicy = DefaultGCPolicy<Key>;
|
||||
using ValuePolicy = DefaultGCPolicy<Value>;
|
||||
|
||||
static bool needsSweep(Key* key, Value* value) {
|
||||
return KeyPolicy::needsSweep(key) || ValuePolicy::needsSweep(value);
|
||||
}
|
||||
};
|
||||
|
||||
// A TraceableHashMap is a HashMap with an additional trace method that knows
|
||||
// how to visit all keys and values in the table. HashMaps that contain GC
|
||||
// pointers that must be traced to be kept alive will generally want to use
|
||||
// this TraceableHashMap specializeation in lieu of HashMap.
|
||||
// A GCHashMap is a GC-aware HashMap, meaning that it has additional trace and
|
||||
// sweep methods that know how to visit all keys and values in the table.
|
||||
// HashMaps that contain GC pointers will generally want to use this GCHashMap
|
||||
// specialization in lieu of HashMap, either because those pointers must be
|
||||
// traced to be kept alive -- in which case, KeyPolicy and/or ValuePolicy
|
||||
// should do the appropriate tracing -- or because those pointers are weak and
|
||||
// must be swept during a GC -- in which case needsSweep should be set
|
||||
// appropriately.
|
||||
//
|
||||
// Most types of GC pointers as keys and values can be traced with no extra
|
||||
// infrastructure. For structs and non-gc-pointer members, ensure that there
|
||||
// is a specialization of DefaultGCPolicy<T> with an appropriate trace method
|
||||
// available to handle the custom type. Generic helpers can be found in
|
||||
// js/public/TracingAPI.h.
|
||||
// infrastructure. For structs, the DefaultGCPolicy<T> will call a trace()
|
||||
// method on the struct. For other structs and non-gc-pointer members, ensure
|
||||
// that there is a specialization of DefaultGCPolicy<T> with an appropriate
|
||||
// trace() static method available to handle the custom type. Generic helpers
|
||||
// can be found in js/public/TracingAPI.h.
|
||||
//
|
||||
// Note that this HashMap only knows *how* to trace and sweep (and the tracing
|
||||
// can handle keys that move), but it does not itself cause tracing or sweeping
|
||||
// to be invoked. For tracing, it must be used with Rooted or PersistentRooted,
|
||||
// or barriered and traced manually. For sweeping, currently it requires an
|
||||
// explicit call to <map>.sweep().
|
||||
//
|
||||
// Note that although this HashMap's trace will deal correctly with moved keys,
|
||||
// it does not itself know when to barrier or trace keys. To function properly
|
||||
// it must either be used with Rooted, or barriered and traced manually.
|
||||
template <typename Key,
|
||||
typename Value,
|
||||
typename HashPolicy = DefaultHasher<Key>,
|
||||
typename AllocPolicy = TempAllocPolicy,
|
||||
typename GCPolicy = DefaultMapGCPolicy<Key, Value>>
|
||||
class TraceableHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>,
|
||||
public JS::Traceable
|
||||
class GCHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>,
|
||||
public JS::Traceable
|
||||
{
|
||||
using Base = HashMap<Key, Value, HashPolicy, AllocPolicy>;
|
||||
|
||||
public:
|
||||
explicit TraceableHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {}
|
||||
explicit GCHashMap(AllocPolicy a = AllocPolicy()) : Base(a) {}
|
||||
|
||||
static void trace(TraceableHashMap* map, JSTracer* trc) { map->trace(trc); }
|
||||
static void trace(GCHashMap* map, JSTracer* trc) { map->trace(trc); }
|
||||
void trace(JSTracer* trc) {
|
||||
if (!this->initialized())
|
||||
return;
|
||||
|
@ -60,23 +72,33 @@ class TraceableHashMap : public HashMap<Key, Value, HashPolicy, AllocPolicy>,
|
|||
}
|
||||
}
|
||||
|
||||
// TraceableHashMap is movable
|
||||
TraceableHashMap(TraceableHashMap&& rhs) : Base(mozilla::Forward<TraceableHashMap>(rhs)) {}
|
||||
void operator=(TraceableHashMap&& rhs) {
|
||||
void sweep() {
|
||||
if (!this->initialized())
|
||||
return;
|
||||
|
||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
|
||||
if (GCPolicy::needsSweep(&e.front().mutableKey(), &e.front().value()))
|
||||
e.removeFront();
|
||||
}
|
||||
}
|
||||
|
||||
// GCHashMap is movable
|
||||
GCHashMap(GCHashMap&& rhs) : Base(mozilla::Forward<GCHashMap>(rhs)) {}
|
||||
void operator=(GCHashMap&& rhs) {
|
||||
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
|
||||
Base::operator=(mozilla::Forward<TraceableHashMap>(rhs));
|
||||
Base::operator=(mozilla::Forward<GCHashMap>(rhs));
|
||||
}
|
||||
|
||||
private:
|
||||
// TraceableHashMap is not copyable or assignable
|
||||
TraceableHashMap(const TraceableHashMap& hm) = delete;
|
||||
TraceableHashMap& operator=(const TraceableHashMap& hm) = delete;
|
||||
// GCHashMap is not copyable or assignable
|
||||
GCHashMap(const GCHashMap& hm) = delete;
|
||||
GCHashMap& operator=(const GCHashMap& hm) = delete;
|
||||
};
|
||||
|
||||
template <typename Outer, typename... Args>
|
||||
class TraceableHashMapOperations
|
||||
class GCHashMapOperations
|
||||
{
|
||||
using Map = TraceableHashMap<Args...>;
|
||||
using Map = GCHashMap<Args...>;
|
||||
using Lookup = typename Map::Lookup;
|
||||
using Ptr = typename Map::Ptr;
|
||||
using AddPtr = typename Map::AddPtr;
|
||||
|
@ -98,10 +120,10 @@ class TraceableHashMapOperations
|
|||
};
|
||||
|
||||
template <typename Outer, typename... Args>
|
||||
class MutableTraceableHashMapOperations
|
||||
: public TraceableHashMapOperations<Outer, Args...>
|
||||
class MutableGCHashMapOperations
|
||||
: public GCHashMapOperations<Outer, Args...>
|
||||
{
|
||||
using Map = TraceableHashMap<Args...>;
|
||||
using Map = GCHashMap<Args...>;
|
||||
using Lookup = typename Map::Lookup;
|
||||
using Ptr = typename Map::Ptr;
|
||||
using AddPtr = typename Map::AddPtr;
|
||||
|
@ -145,24 +167,22 @@ class MutableTraceableHashMapOperations
|
|||
};
|
||||
|
||||
template <typename A, typename B, typename C, typename D, typename E>
|
||||
class RootedBase<TraceableHashMap<A,B,C,D,E>>
|
||||
: public MutableTraceableHashMapOperations<JS::Rooted<TraceableHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
||||
class RootedBase<GCHashMap<A,B,C,D,E>>
|
||||
: public MutableGCHashMapOperations<JS::Rooted<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
||||
{};
|
||||
|
||||
template <typename A, typename B, typename C, typename D, typename E>
|
||||
class MutableHandleBase<TraceableHashMap<A,B,C,D,E>>
|
||||
: public MutableTraceableHashMapOperations<JS::MutableHandle<TraceableHashMap<A,B,C,D,E>>,
|
||||
A,B,C,D,E>
|
||||
class MutableHandleBase<GCHashMap<A,B,C,D,E>>
|
||||
: public MutableGCHashMapOperations<JS::MutableHandle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
||||
{};
|
||||
|
||||
template <typename A, typename B, typename C, typename D, typename E>
|
||||
class HandleBase<TraceableHashMap<A,B,C,D,E>>
|
||||
: public TraceableHashMapOperations<JS::Handle<TraceableHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
||||
class HandleBase<GCHashMap<A,B,C,D,E>>
|
||||
: public GCHashMapOperations<JS::Handle<GCHashMap<A,B,C,D,E>>, A,B,C,D,E>
|
||||
{};
|
||||
|
||||
// A TraceableHashSet is a HashSet with an additional trace method that knows
|
||||
// how to visit all set elements. HashSets that contain GC pointers that must
|
||||
// be traced to be kept alive will generally want to use this TraceableHashSet
|
||||
// A GCHashSet is a HashSet with an additional trace method that knows
|
||||
// be traced to be kept alive will generally want to use this GCHashSet
|
||||
// specializeation in lieu of HashSet.
|
||||
//
|
||||
// Most types of GC pointers can be traced with no extra infrastructure. For
|
||||
|
@ -178,15 +198,15 @@ template <typename T,
|
|||
typename HashPolicy = DefaultHasher<T>,
|
||||
typename AllocPolicy = TempAllocPolicy,
|
||||
typename GCPolicy = DefaultGCPolicy<T>>
|
||||
class TraceableHashSet : public HashSet<T, HashPolicy, AllocPolicy>,
|
||||
public JS::Traceable
|
||||
class GCHashSet : public HashSet<T, HashPolicy, AllocPolicy>,
|
||||
public JS::Traceable
|
||||
{
|
||||
using Base = HashSet<T, HashPolicy, AllocPolicy>;
|
||||
|
||||
public:
|
||||
explicit TraceableHashSet(AllocPolicy a = AllocPolicy()) : Base(a) {}
|
||||
explicit GCHashSet(AllocPolicy a = AllocPolicy()) : Base(a) {}
|
||||
|
||||
static void trace(TraceableHashSet* set, JSTracer* trc) { set->trace(trc); }
|
||||
static void trace(GCHashSet* set, JSTracer* trc) { set->trace(trc); }
|
||||
void trace(JSTracer* trc) {
|
||||
if (!this->initialized())
|
||||
return;
|
||||
|
@ -198,23 +218,32 @@ class TraceableHashSet : public HashSet<T, HashPolicy, AllocPolicy>,
|
|||
}
|
||||
}
|
||||
|
||||
// TraceableHashSet is movable
|
||||
TraceableHashSet(TraceableHashSet&& rhs) : Base(mozilla::Forward<TraceableHashSet>(rhs)) {}
|
||||
void operator=(TraceableHashSet&& rhs) {
|
||||
void sweep() {
|
||||
if (!this->initialized())
|
||||
return;
|
||||
for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
|
||||
if (GCPolicy::needsSweep(&e.mutableFront()))
|
||||
e.removeFront();
|
||||
}
|
||||
}
|
||||
|
||||
// GCHashSet is movable
|
||||
GCHashSet(GCHashSet&& rhs) : Base(mozilla::Forward<GCHashSet>(rhs)) {}
|
||||
void operator=(GCHashSet&& rhs) {
|
||||
MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
|
||||
Base::operator=(mozilla::Forward<TraceableHashSet>(rhs));
|
||||
Base::operator=(mozilla::Forward<GCHashSet>(rhs));
|
||||
}
|
||||
|
||||
private:
|
||||
// TraceableHashSet is not copyable or assignable
|
||||
TraceableHashSet(const TraceableHashSet& hs) = delete;
|
||||
TraceableHashSet& operator=(const TraceableHashSet& hs) = delete;
|
||||
// GCHashSet is not copyable or assignable
|
||||
GCHashSet(const GCHashSet& hs) = delete;
|
||||
GCHashSet& operator=(const GCHashSet& hs) = delete;
|
||||
};
|
||||
|
||||
template <typename Outer, typename... Args>
|
||||
class TraceableHashSetOperations
|
||||
class GCHashSetOperations
|
||||
{
|
||||
using Set = TraceableHashSet<Args...>;
|
||||
using Set = GCHashSet<Args...>;
|
||||
using Lookup = typename Set::Lookup;
|
||||
using Ptr = typename Set::Ptr;
|
||||
using AddPtr = typename Set::AddPtr;
|
||||
|
@ -236,10 +265,10 @@ class TraceableHashSetOperations
|
|||
};
|
||||
|
||||
template <typename Outer, typename... Args>
|
||||
class MutableTraceableHashSetOperations
|
||||
: public TraceableHashSetOperations<Outer, Args...>
|
||||
class MutableGCHashSetOperations
|
||||
: public GCHashSetOperations<Outer, Args...>
|
||||
{
|
||||
using Set = TraceableHashSet<Args...>;
|
||||
using Set = GCHashSet<Args...>;
|
||||
using Lookup = typename Set::Lookup;
|
||||
using Ptr = typename Set::Ptr;
|
||||
using AddPtr = typename Set::AddPtr;
|
||||
|
@ -281,44 +310,42 @@ class MutableTraceableHashSetOperations
|
|||
};
|
||||
|
||||
template <typename T, typename HP, typename AP, typename GP>
|
||||
class RootedBase<TraceableHashSet<T, HP, AP, GP>>
|
||||
: public MutableTraceableHashSetOperations<JS::Rooted<TraceableHashSet<T, HP, AP, GP>>,
|
||||
T, HP, AP, GP>
|
||||
class RootedBase<GCHashSet<T, HP, AP, GP>>
|
||||
: public MutableGCHashSetOperations<JS::Rooted<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
|
||||
{
|
||||
using Set = TraceableHashSet<T, HP, AP, GP>;
|
||||
using Set = GCHashSet<T, HP, AP, GP>;
|
||||
|
||||
friend class TraceableHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
|
||||
friend class GCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
|
||||
const Set& extract() const { return *static_cast<const JS::Rooted<Set>*>(this)->address(); }
|
||||
|
||||
friend class MutableTraceableHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
|
||||
friend class MutableGCHashSetOperations<JS::Rooted<Set>, T, HP, AP, GP>;
|
||||
Set& extract() { return *static_cast<JS::Rooted<Set>*>(this)->address(); }
|
||||
};
|
||||
|
||||
template <typename T, typename HP, typename AP, typename GP>
|
||||
class MutableHandleBase<TraceableHashSet<T, HP, AP, GP>>
|
||||
: public MutableTraceableHashSetOperations<JS::MutableHandle<TraceableHashSet<T, HP, AP, GP>>,
|
||||
T, HP, AP, GP>
|
||||
class MutableHandleBase<GCHashSet<T, HP, AP, GP>>
|
||||
: public MutableGCHashSetOperations<JS::MutableHandle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
|
||||
{
|
||||
using Set = TraceableHashSet<T, HP, AP, GP>;
|
||||
using Set = GCHashSet<T, HP, AP, GP>;
|
||||
|
||||
friend class TraceableHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
|
||||
friend class GCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
|
||||
const Set& extract() const {
|
||||
return *static_cast<const JS::MutableHandle<Set>*>(this)->address();
|
||||
}
|
||||
|
||||
friend class MutableTraceableHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
|
||||
friend class MutableGCHashSetOperations<JS::MutableHandle<Set>, T, HP, AP, GP>;
|
||||
Set& extract() { return *static_cast<JS::MutableHandle<Set>*>(this)->address(); }
|
||||
};
|
||||
|
||||
template <typename T, typename HP, typename AP, typename GP>
|
||||
class HandleBase<TraceableHashSet<T, HP, AP, GP>>
|
||||
: public TraceableHashSetOperations<JS::Handle<TraceableHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
|
||||
class HandleBase<GCHashSet<T, HP, AP, GP>>
|
||||
: public GCHashSetOperations<JS::Handle<GCHashSet<T, HP, AP, GP>>, T, HP, AP, GP>
|
||||
{
|
||||
using Set = TraceableHashSet<T, HP, AP, GP>;
|
||||
friend class TraceableHashSetOperations<JS::Handle<Set>, T, HP, AP, GP>;
|
||||
using Set = GCHashSet<T, HP, AP, GP>;
|
||||
friend class GCHashSetOperations<JS::Handle<Set>, T, HP, AP, GP>;
|
||||
const Set& extract() const { return *static_cast<const JS::Handle<Set>*>(this)->address(); }
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* gc_HashTable_h */
|
||||
#endif /* GCHashTable_h */
|
|
@ -374,12 +374,17 @@ struct StructGCPolicy {
|
|||
// trace method.
|
||||
t->trace(trc);
|
||||
}
|
||||
|
||||
static bool needsSweep(T* t) {
|
||||
return t->needsSweep();
|
||||
}
|
||||
};
|
||||
|
||||
// This policy ignores any GC interaction, e.g. for non-GC types.
|
||||
template <typename T>
|
||||
struct IgnoreGCPolicy {
|
||||
static void trace(JSTracer* trc, uint32_t* id, const char* name) {}
|
||||
static void trace(JSTracer* trc, T* t, const char* name) {}
|
||||
static bool needsSweep(T* v) { return false; }
|
||||
};
|
||||
|
||||
// The default policy when no other more specific policy fits (e.g. for a
|
||||
|
|
|
@ -69,19 +69,227 @@ namespace ubi {
|
|||
class JS_PUBLIC_API(DominatorTree)
|
||||
{
|
||||
private:
|
||||
// Type aliases.
|
||||
// Types.
|
||||
|
||||
using NodeSet = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
|
||||
using NodeSetPtr = mozilla::UniquePtr<NodeSet, JS::DeletePolicy<NodeSet>>;
|
||||
using PredecessorSets = js::HashMap<Node, NodeSetPtr, js::DefaultHasher<Node>,
|
||||
js::SystemAllocPolicy>;
|
||||
using NodeToIndexMap = js::HashMap<Node, uint32_t, js::DefaultHasher<Node>,
|
||||
js::SystemAllocPolicy>;
|
||||
class DominatedSets;
|
||||
|
||||
public:
|
||||
class DominatedSetRange;
|
||||
|
||||
/**
|
||||
* A pointer to an immediately dominated node.
|
||||
*
|
||||
* Don't use this type directly; it is no safer than regular pointers. This
|
||||
* is only for use indirectly with range-based for loops and
|
||||
* `DominatedSetRange`.
|
||||
*
|
||||
* @see JS::ubi::DominatorTree::getDominatedSet
|
||||
*/
|
||||
class DominatedNodePtr
|
||||
{
|
||||
friend class DominatedSetRange;
|
||||
|
||||
const mozilla::Vector<Node>& postOrder;
|
||||
const uint32_t* ptr;
|
||||
|
||||
DominatedNodePtr(const mozilla::Vector<Node>& postOrder, const uint32_t* ptr)
|
||||
: postOrder(postOrder)
|
||||
, ptr(ptr)
|
||||
{ }
|
||||
|
||||
public:
|
||||
bool operator!=(const DominatedNodePtr& rhs) const { return ptr != rhs.ptr; }
|
||||
void operator++() { ptr++; }
|
||||
const Node& operator*() const { return postOrder[*ptr]; }
|
||||
};
|
||||
|
||||
/**
|
||||
* A range of immediately dominated `JS::ubi::Node`s for use with
|
||||
* range-based for loops.
|
||||
*
|
||||
* @see JS::ubi::DominatorTree::getDominatedSet
|
||||
*/
|
||||
class DominatedSetRange
|
||||
{
|
||||
friend class DominatedSets;
|
||||
|
||||
const mozilla::Vector<Node>& postOrder;
|
||||
const uint32_t* beginPtr;
|
||||
const uint32_t* endPtr;
|
||||
|
||||
DominatedSetRange(mozilla::Vector<Node>& postOrder, const uint32_t* begin, const uint32_t* end)
|
||||
: postOrder(postOrder)
|
||||
, beginPtr(begin)
|
||||
, endPtr(end)
|
||||
{
|
||||
MOZ_ASSERT(begin <= end);
|
||||
}
|
||||
|
||||
public:
|
||||
DominatedNodePtr begin() const {
|
||||
MOZ_ASSERT(beginPtr <= endPtr);
|
||||
return DominatedNodePtr(postOrder, beginPtr);
|
||||
}
|
||||
|
||||
DominatedNodePtr end() const {
|
||||
return DominatedNodePtr(postOrder, endPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely skip ahead `n` dominators in the range, in O(1) time.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* mozilla::Maybe<DominatedSetRange> range = myDominatorTree.getDominatedSet(myNode);
|
||||
* if (range.isNothing()) {
|
||||
* // Handle unknown nodes however you see fit...
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* // Don't care about the first ten, for whatever reason.
|
||||
* range->skip(10);
|
||||
* for (const JS::ubi::Node& dominatedNode : *range) {
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
void skip(size_t n) {
|
||||
beginPtr += n;
|
||||
if (beginPtr > endPtr)
|
||||
beginPtr = endPtr;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/**
|
||||
* The set of all dominated sets in a dominator tree.
|
||||
*
|
||||
* Internally stores the sets in a contiguous array, with a side table of
|
||||
* indices into that contiguous array to denote the start index of each
|
||||
* individual set.
|
||||
*/
|
||||
class DominatedSets
|
||||
{
|
||||
mozilla::Vector<uint32_t> dominated;
|
||||
mozilla::Vector<uint32_t> indices;
|
||||
|
||||
DominatedSets(mozilla::Vector<uint32_t>&& dominated, mozilla::Vector<uint32_t>&& indices)
|
||||
: dominated(mozilla::Move(dominated))
|
||||
, indices(mozilla::Move(indices))
|
||||
{ }
|
||||
|
||||
public:
|
||||
// DominatedSets is not copy-able.
|
||||
DominatedSets(const DominatedSets& rhs) = delete;
|
||||
DominatedSets& operator=(const DominatedSets& rhs) = delete;
|
||||
|
||||
// DominatedSets is move-able.
|
||||
DominatedSets(DominatedSets&& rhs)
|
||||
: dominated(mozilla::Move(rhs.dominated))
|
||||
, indices(mozilla::Move(rhs.indices))
|
||||
{
|
||||
MOZ_ASSERT(this != &rhs, "self-move not allowed");
|
||||
}
|
||||
DominatedSets& operator=(DominatedSets&& rhs) {
|
||||
this->~DominatedSets();
|
||||
new (this) DominatedSets(mozilla::Move(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the DominatedSets given the mapping of a node index to its
|
||||
* immediate dominator. Returns `Some` on success, `Nothing` on OOM
|
||||
* failure.
|
||||
*/
|
||||
static mozilla::Maybe<DominatedSets> Create(const mozilla::Vector<uint32_t>& doms) {
|
||||
auto length = doms.length();
|
||||
MOZ_ASSERT(length < UINT32_MAX);
|
||||
|
||||
// Create a vector `dominated` holding a flattened set of buckets of
|
||||
// immediately dominated children nodes, with a lookup table
|
||||
// `indices` mapping from each node to the beginning of its bucket.
|
||||
//
|
||||
// This has three phases:
|
||||
//
|
||||
// 1. Iterate over the full set of nodes and count up the size of
|
||||
// each bucket. These bucket sizes are temporarily stored in the
|
||||
// `indices` vector.
|
||||
//
|
||||
// 2. Convert the `indices` vector to store the cumulative sum of
|
||||
// the sizes of all buckets before each index, resulting in a
|
||||
// mapping from node index to one past the end of that node's
|
||||
// bucket.
|
||||
//
|
||||
// 3. Iterate over the full set of nodes again, filling in bucket
|
||||
// entries from the end of the bucket's range to its
|
||||
// beginning. This decrements each index as a bucket entry is
|
||||
// filled in. After having filled in all of a bucket's entries,
|
||||
// the index points to the start of the bucket.
|
||||
|
||||
mozilla::Vector<uint32_t> dominated;
|
||||
mozilla::Vector<uint32_t> indices;
|
||||
if (!dominated.growBy(length) || !indices.growBy(length))
|
||||
return mozilla::Nothing();
|
||||
|
||||
// 1
|
||||
memset(indices.begin(), 0, length * sizeof(uint32_t));
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
indices[doms[i]]++;
|
||||
|
||||
// 2
|
||||
uint32_t sumOfSizes = 0;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
sumOfSizes += indices[i];
|
||||
MOZ_ASSERT(sumOfSizes <= length);
|
||||
indices[i] = sumOfSizes;
|
||||
}
|
||||
|
||||
// 3
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
auto idxOfDom = doms[i];
|
||||
indices[idxOfDom]--;
|
||||
dominated[indices[idxOfDom]] = i;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Assert that our buckets are non-overlapping and don't run off the
|
||||
// end of the vector.
|
||||
uint32_t lastIndex = 0;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
MOZ_ASSERT(indices[i] >= lastIndex);
|
||||
MOZ_ASSERT(indices[i] < length);
|
||||
lastIndex = indices[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
return mozilla::Some(DominatedSets(mozilla::Move(dominated), mozilla::Move(indices)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of nodes immediately dominated by the node at
|
||||
* `postOrder[nodeIndex]`.
|
||||
*/
|
||||
DominatedSetRange dominatedSet(mozilla::Vector<Node>& postOrder, uint32_t nodeIndex) const {
|
||||
MOZ_ASSERT(postOrder.length() == indices.length());
|
||||
MOZ_ASSERT(nodeIndex < indices.length());
|
||||
auto end = nodeIndex == indices.length() - 1
|
||||
? dominated.end()
|
||||
: &dominated[indices[nodeIndex + 1]];
|
||||
return DominatedSetRange(postOrder, &dominated[indices[nodeIndex]], end);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// Data members.
|
||||
mozilla::Vector<Node> postOrder;
|
||||
NodeToIndexMap nodeToPostOrderIndex;
|
||||
mozilla::Vector<uint32_t> doms;
|
||||
DominatedSets dominatedSets;
|
||||
|
||||
private:
|
||||
// We use `UNDEFINED` as a sentinel value in the `doms` vector to signal
|
||||
|
@ -90,10 +298,11 @@ class JS_PUBLIC_API(DominatorTree)
|
|||
static const uint32_t UNDEFINED = UINT32_MAX;
|
||||
|
||||
DominatorTree(mozilla::Vector<Node>&& postOrder, NodeToIndexMap&& nodeToPostOrderIndex,
|
||||
mozilla::Vector<uint32_t>&& doms)
|
||||
mozilla::Vector<uint32_t>&& doms, DominatedSets&& dominatedSets)
|
||||
: postOrder(mozilla::Move(postOrder))
|
||||
, nodeToPostOrderIndex(mozilla::Move(nodeToPostOrderIndex))
|
||||
, doms(mozilla::Move(doms))
|
||||
, dominatedSets(mozilla::Move(dominatedSets))
|
||||
{ }
|
||||
|
||||
static uint32_t intersect(mozilla::Vector<uint32_t>& doms, uint32_t finger1, uint32_t finger2) {
|
||||
|
@ -218,6 +427,7 @@ class JS_PUBLIC_API(DominatorTree)
|
|||
: postOrder(mozilla::Move(rhs.postOrder))
|
||||
, nodeToPostOrderIndex(mozilla::Move(rhs.nodeToPostOrderIndex))
|
||||
, doms(mozilla::Move(rhs.doms))
|
||||
, dominatedSets(mozilla::Move(rhs.dominatedSets))
|
||||
{
|
||||
MOZ_ASSERT(this != &rhs, "self-move is not allowed");
|
||||
}
|
||||
|
@ -326,9 +536,21 @@ class JS_PUBLIC_API(DominatorTree)
|
|||
}
|
||||
}
|
||||
|
||||
auto maybeDominatedSets = DominatedSets::Create(doms);
|
||||
if (maybeDominatedSets.isNothing())
|
||||
return mozilla::Nothing();
|
||||
|
||||
return mozilla::Some(DominatorTree(mozilla::Move(postOrder),
|
||||
mozilla::Move(nodeToPostOrderIndex),
|
||||
mozilla::Move(doms)));
|
||||
mozilla::Move(doms),
|
||||
mozilla::Move(*maybeDominatedSets)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root node for this dominator tree.
|
||||
*/
|
||||
const Node& root() const {
|
||||
return postOrder[postOrder.length() - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -346,6 +568,33 @@ class JS_PUBLIC_API(DominatorTree)
|
|||
MOZ_ASSERT(idx < postOrder.length());
|
||||
return postOrder[doms[idx]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of nodes immediately dominated by the given `node`. If `node`
|
||||
* is not a member of this dominator tree, return `Nothing`.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* mozilla::Maybe<DominatedSetRange> range = myDominatorTree.getDominatedSet(myNode);
|
||||
* if (range.isNothing()) {
|
||||
* // Handle unknown node however you see fit...
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* for (const JS::ubi::Node& dominatedNode : *range) {
|
||||
* // Do something with each immediately dominated node...
|
||||
* }
|
||||
*/
|
||||
mozilla::Maybe<DominatedSetRange> getDominatedSet(const Node& node) {
|
||||
assertSanity();
|
||||
auto ptr = nodeToPostOrderIndex.lookup(node);
|
||||
if (!ptr)
|
||||
return mozilla::Nothing();
|
||||
|
||||
auto idx = ptr->value();
|
||||
MOZ_ASSERT(idx < postOrder.length());
|
||||
return mozilla::Some(dominatedSets.dominatedSet(postOrder, idx));
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace ubi
|
||||
|
|
|
@ -1918,7 +1918,7 @@ EmitExtractLane(FunctionCompiler& f, AsmType type, MDefinition** def)
|
|||
}
|
||||
|
||||
static AsmType
|
||||
AsmSimdTypeToScalarType(AsmType simd)
|
||||
AsmSimdTypeToLaneType(AsmType simd)
|
||||
{
|
||||
switch (simd) {
|
||||
case AsmType::Int32x4: return AsmType::Int32;
|
||||
|
@ -1952,7 +1952,7 @@ EmitSimdReplaceLane(FunctionCompiler& f, AsmType simdType, MDefinition** def)
|
|||
}
|
||||
|
||||
MDefinition* scalar;
|
||||
if (!EmitExpr(f, AsmSimdTypeToScalarType(simdType), &scalar))
|
||||
if (!EmitExpr(f, AsmSimdTypeToLaneType(simdType), &scalar))
|
||||
return false;
|
||||
*def = f.insertElementSimd(vector, scalar, lane, MIRTypeFromAsmType(simdType));
|
||||
return true;
|
||||
|
@ -2055,7 +2055,7 @@ static bool
|
|||
EmitSimdSplat(FunctionCompiler& f, AsmType type, MDefinition** def)
|
||||
{
|
||||
MDefinition* in;
|
||||
if (!EmitExpr(f, AsmSimdTypeToScalarType(type), &in))
|
||||
if (!EmitExpr(f, AsmSimdTypeToLaneType(type), &in))
|
||||
return false;
|
||||
*def = f.splatSimd(in, MIRTypeFromAsmType(type));
|
||||
return true;
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#define ATTR_NONCONFIGURABLE 0x10
|
||||
#define ATTR_NONWRITABLE 0x20
|
||||
|
||||
// The extended slot in which the self-hosted name for self-hosted builtins is
|
||||
// stored.
|
||||
#define LAZY_FUNCTION_NAME_SLOT 0
|
||||
|
||||
// Stores the private WeakMap slot used for WeakSets
|
||||
#define WEAKSET_MAP_SLOT 0
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
// Assertions, defined here instead of in the header above to make `assert`
|
||||
// invisible to C++.
|
||||
#ifdef DEBUG
|
||||
#define assert(b, info) if (!(b)) AssertionFailed(info)
|
||||
#define assert(b, info) if (!(b)) AssertionFailed(__FILE__ + ":" + __LINE__ + ": " + info)
|
||||
#else
|
||||
#define assert(b, info) // Elided assertion.
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "prlink.h"
|
||||
|
||||
#include "ctypes/typedefs.h"
|
||||
#include "js/TraceableHashTable.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/String.h"
|
||||
|
||||
|
@ -283,8 +283,7 @@ struct FieldHashPolicy : DefaultHasher<JSFlatString*>
|
|||
}
|
||||
};
|
||||
|
||||
typedef TraceableHashMap<JSFlatString*, FieldInfo, FieldHashPolicy, SystemAllocPolicy>
|
||||
FieldInfoHash;
|
||||
using FieldInfoHash = GCHashMap<JSFlatString*, FieldInfo, FieldHashPolicy, SystemAllocPolicy>;
|
||||
|
||||
void
|
||||
TraceFieldInfoHash(JSTracer* trc, FieldInfoHash* fields);
|
||||
|
|
|
@ -462,6 +462,46 @@ template<typename T>
|
|||
void
|
||||
CheckTracedThing(JSTracer* trc, T thing);
|
||||
|
||||
// Define a default Policy for all pointer types. This may fail to link if this
|
||||
// policy gets used on a non-GC typed pointer by accident.
|
||||
template <typename T>
|
||||
struct DefaultGCPolicy<T*>
|
||||
{
|
||||
static void trace(JSTracer* trc, T** t, const char* name) {
|
||||
// If linking is failing here, it likely means that you need to define
|
||||
// or use a non-default GC policy for your non-gc-pointer type.
|
||||
TraceManuallyBarrieredEdge(trc, t, name);
|
||||
}
|
||||
|
||||
static bool needsSweep(T** t) {
|
||||
return gc::IsAboutToBeFinalizedUnbarriered(t);
|
||||
}
|
||||
};
|
||||
|
||||
// RelocatablePtr is only defined for GC pointer types, so this default policy
|
||||
// should work in all cases.
|
||||
template <typename T>
|
||||
struct DefaultGCPolicy<RelocatablePtr<T*>>
|
||||
{
|
||||
static void trace(JSTracer* trc, RelocatablePtr<T*> t, const char* name) {
|
||||
TraceEdge(trc, t, name);
|
||||
}
|
||||
static bool needsSweep(RelocatablePtr<T*>* thingp) {
|
||||
return gc::IsAboutToBeFinalizedUnbarriered(thingp);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct DefaultGCPolicy<ReadBarriered<T>>
|
||||
{
|
||||
static void trace(JSTracer* trc, ReadBarriered<T> t, const char* name) {
|
||||
TraceEdge(trc, t, name);
|
||||
}
|
||||
static bool needsSweep(ReadBarriered<T>* thingp) {
|
||||
return gc::IsAboutToBeFinalized(thingp);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* gc_Marking_h */
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/TraceableHashTable.h"
|
||||
#include "js/GCHashTable.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -137,29 +137,6 @@ void
|
|||
TraceCycleCollectorChildren(JS::CallbackTracer* trc, ObjectGroup* group);
|
||||
|
||||
} // namespace gc
|
||||
|
||||
// Define a default Policy for all pointer types. This may fail to link if this
|
||||
// policy gets used on a non-GC typed pointer by accident.
|
||||
template <typename T>
|
||||
struct DefaultGCPolicy<T*>
|
||||
{
|
||||
static void trace(JSTracer* trc, T** t, const char* name) {
|
||||
// If linking is failing here, it likely means that you need to define
|
||||
// or use a non-default GC policy for your non-gc-pointer type.
|
||||
TraceManuallyBarrieredEdge(trc, t, name);
|
||||
}
|
||||
};
|
||||
|
||||
// RelocatablePtr is only defined for GC pointer types, so this default policy
|
||||
// should work in all cases.
|
||||
template <typename T>
|
||||
struct DefaultGCPolicy<RelocatablePtr<T*>>
|
||||
{
|
||||
static void trace(JSTracer* trc, RelocatablePtr<T*> t, const char* name) {
|
||||
TraceEdge(trc, t, name);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* js_Tracer_h */
|
||||
|
|
|
@ -644,8 +644,10 @@ ScalarTypeToLength(Scalar::Type type)
|
|||
MOZ_CRASH("unexpected SIMD kind");
|
||||
}
|
||||
|
||||
// Get the type of the individual lanes in a SIMD type.
|
||||
// For example, Int32x4 -> Int32, FLoat32x4 -> Float32 etc.
|
||||
static inline MIRType
|
||||
SimdTypeToScalarType(MIRType type)
|
||||
SimdTypeToLaneType(MIRType type)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
static_assert(MIRType_Last <= ELEMENT_TYPE_MASK,
|
||||
|
|
|
@ -23,15 +23,15 @@
|
|||
// Call into cross-jitted code by following the ABI of the simulated architecture.
|
||||
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7) \
|
||||
(js::jit::Simulator::Current()->call( \
|
||||
JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 8, p0, p1, p2, p3, p4, p5, p6, p7) & 0xffffffff)
|
||||
JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 8, p0, p1, p2, p3, p4, p5, p6, p7))
|
||||
|
||||
#define CALL_GENERATED_1(entry, p0) \
|
||||
(js::jit::Simulator::Current()->call( \
|
||||
JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 1, p0) & 0xffffffff)
|
||||
JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 1, p0))
|
||||
|
||||
#define CALL_GENERATED_2(entry, p0, p1) \
|
||||
(js::jit::Simulator::Current()->call( \
|
||||
JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 2, p0, p1) & 0xffffffff)
|
||||
JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 2, p0, p1))
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -3234,13 +3234,13 @@ IonBuilder::inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* descr)
|
|||
// containing the coercion of 'undefined' to the right type.
|
||||
MConstant* defVal = nullptr;
|
||||
if (callInfo.argc() < SimdTypeToLength(simdType)) {
|
||||
MIRType scalarType = SimdTypeToScalarType(simdType);
|
||||
if (scalarType == MIRType_Int32) {
|
||||
MIRType laneType = SimdTypeToLaneType(simdType);
|
||||
if (laneType == MIRType_Int32) {
|
||||
defVal = constant(Int32Value(0));
|
||||
} else {
|
||||
MOZ_ASSERT(IsFloatingPointType(scalarType));
|
||||
MOZ_ASSERT(IsFloatingPointType(laneType));
|
||||
defVal = constant(DoubleNaNValue());
|
||||
defVal->setResultType(scalarType);
|
||||
defVal->setResultType(laneType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3369,9 +3369,9 @@ IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdTypeD
|
|||
|
||||
// See comment in inlineBinarySimd
|
||||
MIRType vecType = SimdTypeDescrToMIRType(type);
|
||||
MIRType scalarType = SimdTypeToScalarType(vecType);
|
||||
MIRType laneType = SimdTypeToLaneType(vecType);
|
||||
MSimdExtractElement* ins = MSimdExtractElement::New(alloc(), callInfo.getArg(0),
|
||||
vecType, scalarType, SimdLane(lane));
|
||||
vecType, laneType, SimdLane(lane));
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
@ -3473,8 +3473,10 @@ IonBuilder::inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdTypeDescr
|
|||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
// Get the typed array element type corresponding to the lanes in a SIMD vector type.
|
||||
// This only applies to SIMD types that can be loaded and stored to a typed array.
|
||||
static Scalar::Type
|
||||
SimdTypeToScalarType(SimdTypeDescr::Type type)
|
||||
SimdTypeToArrayElementType(SimdTypeDescr::Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SimdTypeDescr::Float32x4: return Scalar::Float32x4;
|
||||
|
@ -3538,7 +3540,7 @@ IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdTypeDescr::T
|
|||
if (!checkInlineSimd(callInfo, native, type, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
Scalar::Type simdType = SimdTypeToScalarType(type);
|
||||
Scalar::Type simdType = SimdTypeToArrayElementType(type);
|
||||
|
||||
MDefinition* index = nullptr;
|
||||
MInstruction* elements = nullptr;
|
||||
|
@ -3561,7 +3563,7 @@ IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, SimdTypeDescr::
|
|||
if (!checkInlineSimd(callInfo, native, type, 3, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
Scalar::Type simdType = SimdTypeToScalarType(type);
|
||||
Scalar::Type simdType = SimdTypeToArrayElementType(type);
|
||||
|
||||
MDefinition* index = nullptr;
|
||||
MInstruction* elements = nullptr;
|
||||
|
|
|
@ -906,13 +906,13 @@ MConstant::canProduceFloat32() const
|
|||
MDefinition*
|
||||
MSimdValueX4::foldsTo(TempAllocator& alloc)
|
||||
{
|
||||
DebugOnly<MIRType> scalarType = SimdTypeToScalarType(type());
|
||||
DebugOnly<MIRType> laneType = SimdTypeToLaneType(type());
|
||||
bool allConstants = true;
|
||||
bool allSame = true;
|
||||
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
MDefinition* op = getOperand(i);
|
||||
MOZ_ASSERT(op->type() == scalarType);
|
||||
MOZ_ASSERT(op->type() == laneType);
|
||||
if (!op->isConstantValue())
|
||||
allConstants = false;
|
||||
if (i > 0 && op != getOperand(i - 1))
|
||||
|
@ -952,11 +952,11 @@ MSimdValueX4::foldsTo(TempAllocator& alloc)
|
|||
MDefinition*
|
||||
MSimdSplatX4::foldsTo(TempAllocator& alloc)
|
||||
{
|
||||
DebugOnly<MIRType> scalarType = SimdTypeToScalarType(type());
|
||||
DebugOnly<MIRType> laneType = SimdTypeToLaneType(type());
|
||||
MDefinition* op = getOperand(0);
|
||||
if (!op->isConstantValue())
|
||||
return this;
|
||||
MOZ_ASSERT(op->type() == scalarType);
|
||||
MOZ_ASSERT(op->type() == laneType);
|
||||
|
||||
SimdConstant cst;
|
||||
switch (type()) {
|
||||
|
|
|
@ -1401,16 +1401,16 @@ class MSimdValueX4
|
|||
static MSimdValueX4* NewAsmJS(TempAllocator& alloc, MIRType type, MDefinition* x,
|
||||
MDefinition* y, MDefinition* z, MDefinition* w)
|
||||
{
|
||||
mozilla::DebugOnly<MIRType> scalarType = SimdTypeToScalarType(type);
|
||||
MOZ_ASSERT(scalarType == x->type());
|
||||
MOZ_ASSERT(scalarType == y->type());
|
||||
MOZ_ASSERT(scalarType == z->type());
|
||||
MOZ_ASSERT(scalarType == w->type());
|
||||
mozilla::DebugOnly<MIRType> laneType = SimdTypeToLaneType(type);
|
||||
MOZ_ASSERT(laneType == x->type());
|
||||
MOZ_ASSERT(laneType == y->type());
|
||||
MOZ_ASSERT(laneType == z->type());
|
||||
MOZ_ASSERT(laneType == w->type());
|
||||
return MSimdValueX4::New(alloc, type, x, y, z, w);
|
||||
}
|
||||
|
||||
bool canConsumeFloat32(MUse* use) const override {
|
||||
return SimdTypeToScalarType(type()) == MIRType_Float32;
|
||||
return SimdTypeToLaneType(type()) == MIRType_Float32;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
|
@ -1445,7 +1445,7 @@ class MSimdSplatX4
|
|||
|
||||
static MSimdSplatX4* NewAsmJS(TempAllocator& alloc, MDefinition* v, MIRType type)
|
||||
{
|
||||
MOZ_ASSERT(SimdTypeToScalarType(type) == v->type());
|
||||
MOZ_ASSERT(SimdTypeToLaneType(type) == v->type());
|
||||
return new(alloc) MSimdSplatX4(type, v);
|
||||
}
|
||||
|
||||
|
@ -1455,7 +1455,7 @@ class MSimdSplatX4
|
|||
}
|
||||
|
||||
bool canConsumeFloat32(MUse* use) const override {
|
||||
return SimdTypeToScalarType(type()) == MIRType_Float32;
|
||||
return SimdTypeToLaneType(type()) == MIRType_Float32;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
|
@ -1596,17 +1596,17 @@ class MSimdExtractElement
|
|||
protected:
|
||||
SimdLane lane_;
|
||||
|
||||
MSimdExtractElement(MDefinition* obj, MIRType vecType, MIRType scalarType, SimdLane lane)
|
||||
MSimdExtractElement(MDefinition* obj, MIRType vecType, MIRType laneType, SimdLane lane)
|
||||
: MUnaryInstruction(obj), lane_(lane)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(vecType));
|
||||
MOZ_ASSERT(uint32_t(lane) < SimdTypeToLength(vecType));
|
||||
MOZ_ASSERT(!IsSimdType(scalarType));
|
||||
MOZ_ASSERT(SimdTypeToScalarType(vecType) == scalarType);
|
||||
MOZ_ASSERT(!IsSimdType(laneType));
|
||||
MOZ_ASSERT(SimdTypeToLaneType(vecType) == laneType);
|
||||
|
||||
setMovable();
|
||||
specialization_ = vecType;
|
||||
setResultType(scalarType);
|
||||
setResultType(laneType);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -1665,7 +1665,7 @@ class MSimdInsertElement
|
|||
MIRType type, SimdLane lane)
|
||||
{
|
||||
MOZ_ASSERT(vec->type() == type);
|
||||
MOZ_ASSERT(SimdTypeToScalarType(type) == val->type());
|
||||
MOZ_ASSERT(SimdTypeToLaneType(type) == val->type());
|
||||
return new(alloc) MSimdInsertElement(vec, val, type, lane);
|
||||
}
|
||||
|
||||
|
@ -1696,7 +1696,7 @@ class MSimdInsertElement
|
|||
}
|
||||
|
||||
bool canConsumeFloat32(MUse* use) const override {
|
||||
return use == getUseFor(1) && SimdTypeToScalarType(type()) == MIRType_Float32;
|
||||
return use == getUseFor(1) && SimdTypeToLaneType(type()) == MIRType_Float32;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
|
|
|
@ -567,17 +567,17 @@ bool
|
|||
SimdScalarPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(ins->type()));
|
||||
MIRType scalarType = SimdTypeToScalarType(ins->type());
|
||||
MIRType laneType = SimdTypeToLaneType(ins->type());
|
||||
|
||||
MDefinition* in = ins->getOperand(Op);
|
||||
if (in->type() == scalarType)
|
||||
if (in->type() == laneType)
|
||||
return true;
|
||||
|
||||
MInstruction* replace;
|
||||
if (scalarType == MIRType_Int32) {
|
||||
if (laneType == MIRType_Int32) {
|
||||
replace = MTruncateToInt32::New(alloc, in);
|
||||
} else {
|
||||
MOZ_ASSERT(scalarType == MIRType_Float32);
|
||||
MOZ_ASSERT(laneType == MIRType_Float32);
|
||||
replace = MToFloat32::New(alloc, in);
|
||||
}
|
||||
|
||||
|
|
|
@ -4597,7 +4597,7 @@ Simulator::callInternal(uint8_t* entry)
|
|||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
int32_t
|
||||
Simulator::call(uint8_t* entry, int argument_count, ...)
|
||||
{
|
||||
va_list parameters;
|
||||
|
@ -4634,7 +4634,7 @@ Simulator::call(uint8_t* entry, int argument_count, ...)
|
|||
MOZ_ASSERT(entry_stack == get_register(sp));
|
||||
set_register(sp, original_stack);
|
||||
|
||||
int64_t result = (int64_t(get_register(r1)) << 32) | get_register(r0);
|
||||
int32_t result = get_register(r0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ class Simulator
|
|||
void execute();
|
||||
|
||||
// Sets up the simulator state and grabs the result on return.
|
||||
int64_t call(uint8_t* entry, int argument_count, ...);
|
||||
int32_t call(uint8_t* entry, int argument_count, ...);
|
||||
|
||||
// Debugger input.
|
||||
void setLastDebuggerInput(char* input);
|
||||
|
|
|
@ -3426,7 +3426,7 @@ Simulator::callInternal(uint8_t* entry)
|
|||
setRegister(fp, fp_val);
|
||||
}
|
||||
|
||||
int64_t
|
||||
int32_t
|
||||
Simulator::call(uint8_t* entry, int argument_count, ...)
|
||||
{
|
||||
va_list parameters;
|
||||
|
@ -3462,7 +3462,7 @@ Simulator::call(uint8_t* entry, int argument_count, ...)
|
|||
MOZ_ASSERT(entry_stack == getRegister(sp));
|
||||
setRegister(sp, original_stack);
|
||||
|
||||
int64_t result = (int64_t(getRegister(v1)) << 32) | getRegister(v0);
|
||||
int32_t result = getRegister(v0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ class Simulator {
|
|||
void execute();
|
||||
|
||||
// Sets up the simulator state and grabs the result on return.
|
||||
int64_t call(uint8_t* entry, int argument_count, ...);
|
||||
int32_t call(uint8_t* entry, int argument_count, ...);
|
||||
|
||||
// Push an address onto the JS stack.
|
||||
uintptr_t pushAddress(uintptr_t address);
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ds/TraceableFifo.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TraceableHashTable.h"
|
||||
#include "js/TraceableVector.h"
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
@ -122,7 +122,7 @@ BEGIN_TEST(testGCRootedStaticStructInternalStackStorageAugmented)
|
|||
}
|
||||
END_TEST(testGCRootedStaticStructInternalStackStorageAugmented)
|
||||
|
||||
using MyHashMap = js::TraceableHashMap<js::Shape*, JSObject*>;
|
||||
using MyHashMap = js::GCHashMap<js::Shape*, JSObject*>;
|
||||
|
||||
BEGIN_TEST(testGCRootedHashMap)
|
||||
{
|
||||
|
|
|
@ -519,58 +519,68 @@ BEGIN_TEST(test_JS_ubi_DominatorTree)
|
|||
// graph when computing the dominator tree.
|
||||
FakeNode m('m');
|
||||
CHECK(tree.getImmediateDominator(&m) == JS::ubi::Node());
|
||||
CHECK(tree.getDominatedSet(&m).isNothing());
|
||||
|
||||
fprintf(stderr, "r's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&r).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&r) == JS::ubi::Node(&r));
|
||||
struct {
|
||||
FakeNode& dominated;
|
||||
FakeNode& dominator;
|
||||
} domination[] = {
|
||||
{r, r},
|
||||
{a, r},
|
||||
{b, r},
|
||||
{c, r},
|
||||
{d, r},
|
||||
{e, r},
|
||||
{f, c},
|
||||
{g, c},
|
||||
{h, r},
|
||||
{i, r},
|
||||
{j, g},
|
||||
{k, r},
|
||||
{l, d}
|
||||
};
|
||||
|
||||
fprintf(stderr, "a's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&a).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&a) == JS::ubi::Node(&r));
|
||||
for (auto& relation : domination) {
|
||||
// Test immediate dominator.
|
||||
fprintf(stderr,
|
||||
"%c's immediate dominator is %c\n",
|
||||
relation.dominated.name,
|
||||
tree.getImmediateDominator(&relation.dominator).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&relation.dominated) == JS::ubi::Node(&relation.dominator));
|
||||
|
||||
fprintf(stderr, "b's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&b).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&b) == JS::ubi::Node(&r));
|
||||
// Test the dominated set. Build up the expected dominated set based on
|
||||
// the set of nodes immediately dominated by this one in `domination`,
|
||||
// then iterate over the actual dominated set and check against the
|
||||
// expected set.
|
||||
|
||||
fprintf(stderr, "c's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&c).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&c) == JS::ubi::Node(&r));
|
||||
auto& node = relation.dominated;
|
||||
fprintf(stderr, "Checking %c's dominated set:\n", node.name);
|
||||
|
||||
fprintf(stderr, "d's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&d).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&d) == JS::ubi::Node(&r));
|
||||
js::HashSet<char> expectedDominatedSet(cx);
|
||||
CHECK(expectedDominatedSet.init());
|
||||
for (auto& rel : domination) {
|
||||
if (&rel.dominator == &node) {
|
||||
fprintf(stderr, " Expecting %c\n", rel.dominated.name);
|
||||
CHECK(expectedDominatedSet.putNew(rel.dominated.name));
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "e's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&e).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&e) == JS::ubi::Node(&r));
|
||||
auto maybeActualDominatedSet = tree.getDominatedSet(&node);
|
||||
CHECK(maybeActualDominatedSet.isSome());
|
||||
auto& actualDominatedSet = *maybeActualDominatedSet;
|
||||
|
||||
fprintf(stderr, "f's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&f).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&f) == JS::ubi::Node(&c));
|
||||
for (const auto& dominated : actualDominatedSet) {
|
||||
fprintf(stderr, " Found %c\n", dominated.as<FakeNode>()->name);
|
||||
CHECK(expectedDominatedSet.has(dominated.as<FakeNode>()->name));
|
||||
expectedDominatedSet.remove(dominated.as<FakeNode>()->name);
|
||||
}
|
||||
|
||||
fprintf(stderr, "g's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&g).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&g) == JS::ubi::Node(&c));
|
||||
// Ensure we found them all and aren't still expecting nodes we never
|
||||
// got.
|
||||
CHECK(expectedDominatedSet.count() == 0);
|
||||
|
||||
fprintf(stderr, "h's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&h).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&h) == JS::ubi::Node(&r));
|
||||
|
||||
fprintf(stderr, "i's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&i).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&i) == JS::ubi::Node(&r));
|
||||
|
||||
fprintf(stderr, "j's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&j).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&j) == JS::ubi::Node(&g));
|
||||
|
||||
fprintf(stderr, "k's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&k).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&k) == JS::ubi::Node(&r));
|
||||
|
||||
fprintf(stderr, "l's immediate dominator is %c\n",
|
||||
tree.getImmediateDominator(&l).as<FakeNode>()->name);
|
||||
CHECK(tree.getImmediateDominator(&l) == JS::ubi::Node(&d));
|
||||
fprintf(stderr, "Done checking %c's dominated set.\n\n", node.name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2090,7 +2090,6 @@ DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue val
|
|||
{
|
||||
RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : nullptr);
|
||||
if (getter && !(attrs & JSPROP_GETTER)) {
|
||||
RootedObject global(cx, (JSObject*) &obj->global());
|
||||
JSFunction* getobj = NewNativeFunction(cx, (Native) getter, 0, atom);
|
||||
if (!getobj)
|
||||
return false;
|
||||
|
@ -2104,7 +2103,6 @@ DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue val
|
|||
if (setter && !(attrs & JSPROP_SETTER)) {
|
||||
// Root just the getter, since the setter is not yet a JSObject.
|
||||
AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, nullptr);
|
||||
RootedObject global(cx, (JSObject*) &obj->global());
|
||||
JSFunction* setobj = NewNativeFunction(cx, (Native) setter, 1, atom);
|
||||
if (!setobj)
|
||||
return false;
|
||||
|
@ -3453,8 +3451,13 @@ IsFunctionCloneable(HandleFunction fun)
|
|||
if (IsStaticGlobalLexicalScope(scope))
|
||||
return true;
|
||||
|
||||
// 'eval' and non-syntactic scopes are always scoped immediately under
|
||||
// a non-extensible lexical scope.
|
||||
// If the script already deals with non-syntactic scopes, we can clone
|
||||
// it.
|
||||
if (scope->is<StaticNonSyntacticScopeObjects>())
|
||||
return true;
|
||||
|
||||
// 'eval' scopes are always scoped immediately under a non-extensible
|
||||
// lexical scope.
|
||||
if (scope->is<StaticBlockObject>()) {
|
||||
StaticBlockObject& block = scope->as<StaticBlockObject>();
|
||||
if (block.needsClone())
|
||||
|
@ -3466,11 +3469,6 @@ IsFunctionCloneable(HandleFunction fun)
|
|||
// under the global, we can clone it.
|
||||
if (enclosing->is<StaticEvalObject>())
|
||||
return !enclosing->as<StaticEvalObject>().isNonGlobal();
|
||||
|
||||
// If the script already deals with a non-syntactic scope, we can
|
||||
// clone it.
|
||||
if (enclosing->is<StaticNonSyntacticScopeObjects>())
|
||||
return true;
|
||||
}
|
||||
|
||||
// Any other enclosing static scope (e.g., function, block) cannot be
|
||||
|
@ -3536,7 +3534,16 @@ CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject dynamicScop
|
|||
return CloneFunctionReuseScript(cx, fun, dynamicScope, fun->getAllocKind());
|
||||
}
|
||||
|
||||
return CloneFunctionAndScript(cx, fun, dynamicScope, staticScope, fun->getAllocKind());
|
||||
JSFunction* clone = CloneFunctionAndScript(cx, fun, dynamicScope, staticScope,
|
||||
fun->getAllocKind());
|
||||
|
||||
#ifdef DEBUG
|
||||
// The cloned function should itself be cloneable.
|
||||
RootedFunction cloneRoot(cx, clone);
|
||||
MOZ_ASSERT_IF(cloneRoot, IsFunctionCloneable(cloneRoot));
|
||||
#endif
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
namespace JS {
|
||||
|
|
|
@ -1461,7 +1461,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
|
|||
|
||||
/* Lazily cloned self-hosted script. */
|
||||
MOZ_ASSERT(fun->isSelfHostedBuiltin());
|
||||
RootedAtom funAtom(cx, &fun->getExtendedSlot(0).toString()->asAtom());
|
||||
RootedAtom funAtom(cx, &fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->asAtom());
|
||||
if (!funAtom)
|
||||
return false;
|
||||
Rooted<PropertyName*> funName(cx, funAtom->asPropertyName());
|
||||
|
@ -1507,7 +1507,7 @@ JSFunction::maybeRelazify(JSRuntime* rt)
|
|||
} else {
|
||||
MOZ_ASSERT(isSelfHostedBuiltin());
|
||||
MOZ_ASSERT(isExtended());
|
||||
MOZ_ASSERT(getExtendedSlot(0).toString()->isAtom());
|
||||
MOZ_ASSERT(getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString()->isAtom());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ class StringifyContext
|
|||
: sb(sb),
|
||||
gap(gap),
|
||||
replacer(cx, replacer),
|
||||
stack(cx, TraceableHashSet<JSObject*, MovableCellHasher<JSObject*>>(cx)),
|
||||
stack(cx, GCHashSet<JSObject*, MovableCellHasher<JSObject*>>(cx)),
|
||||
propertyList(propertyList),
|
||||
depth(0)
|
||||
{}
|
||||
|
@ -148,7 +148,7 @@ class StringifyContext
|
|||
StringBuffer& sb;
|
||||
const StringBuffer& gap;
|
||||
RootedObject replacer;
|
||||
Rooted<TraceableHashSet<JSObject*, MovableCellHasher<JSObject*>>> stack;
|
||||
Rooted<GCHashSet<JSObject*, MovableCellHasher<JSObject*>>> stack;
|
||||
const AutoIdVector& propertyList;
|
||||
uint32_t depth;
|
||||
};
|
||||
|
@ -324,7 +324,7 @@ class CycleDetector
|
|||
}
|
||||
|
||||
private:
|
||||
MutableHandle<TraceableHashSet<JSObject*, MovableCellHasher<JSObject*>>> stack;
|
||||
MutableHandle<GCHashSet<JSObject*, MovableCellHasher<JSObject*>>> stack;
|
||||
HandleObject obj_;
|
||||
};
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ EXPORTS.js += [
|
|||
'../public/Date.h',
|
||||
'../public/Debug.h',
|
||||
'../public/GCAPI.h',
|
||||
'../public/GCHashTable.h',
|
||||
'../public/HashTable.h',
|
||||
'../public/HeapAPI.h',
|
||||
'../public/Id.h',
|
||||
|
@ -125,7 +126,6 @@ EXPORTS.js += [
|
|||
'../public/RootingAPI.h',
|
||||
'../public/SliceBudget.h',
|
||||
'../public/StructuredClone.h',
|
||||
'../public/TraceableHashTable.h',
|
||||
'../public/TraceableVector.h',
|
||||
'../public/TraceKind.h',
|
||||
'../public/TracingAPI.h',
|
||||
|
|
|
@ -667,7 +667,7 @@ GlobalObject::getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global,
|
|||
if (!fun)
|
||||
return false;
|
||||
fun->setIsSelfHostedBuiltin();
|
||||
fun->setExtendedSlot(0, StringValue(selfHostedName));
|
||||
fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
|
||||
funVal.setObject(*fun);
|
||||
|
||||
return GlobalObject::addIntrinsicValue(cx, global, selfHostedName, funVal);
|
||||
|
|
|
@ -2027,7 +2027,7 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
|
|||
// different thread than the clone target. In theory, these objects are all
|
||||
// tenured and will not be compacted; however, we simply avoid the issue
|
||||
// altogether by skipping the cycle-detection when off the main thread.
|
||||
Maybe<AutoCycleDetector> detect;
|
||||
mozilla::Maybe<AutoCycleDetector> detect;
|
||||
if (js::CurrentThreadCanAccessZone(selfHostedObject->zoneFromAnyThread())) {
|
||||
detect.emplace(cx, selfHostedObject);
|
||||
if (!detect->init())
|
||||
|
@ -2195,7 +2195,8 @@ js::SelfHostedFunction(JSContext* cx, HandlePropertyName propName)
|
|||
bool
|
||||
js::IsSelfHostedFunctionWithName(JSFunction* fun, JSAtom* name)
|
||||
{
|
||||
return fun->isSelfHostedBuiltin() && fun->getExtendedSlot(0).toString() == name;
|
||||
return fun->isSelfHostedBuiltin() &&
|
||||
fun->getExtendedSlot(LAZY_FUNCTION_NAME_SLOT).toString() == name;
|
||||
}
|
||||
|
||||
static_assert(JSString::MAX_LENGTH <= INT32_MAX,
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#include "builtin/MapObject.h"
|
||||
#include "js/Date.h"
|
||||
#include "js/TraceableHashTable.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "vm/SavedFrame.h"
|
||||
#include "vm/SharedArrayObject.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
|
@ -342,7 +342,7 @@ struct JSStructuredCloneWriter {
|
|||
// The "memory" list described in the HTML5 internal structured cloning algorithm.
|
||||
// memory is a superset of objs; items are never removed from Memory
|
||||
// until a serialization operation is finished
|
||||
using CloneMemory = TraceableHashMap<JSObject*, uint32_t, MovableCellHasher<JSObject*>>;
|
||||
using CloneMemory = GCHashMap<JSObject*, uint32_t, MovableCellHasher<JSObject*>>;
|
||||
Rooted<CloneMemory> memory;
|
||||
|
||||
// The user defined callbacks that will be used for cloning.
|
||||
|
|
|
@ -133,7 +133,7 @@ TraceLoggerThread::init()
|
|||
{
|
||||
if (!pointerMap.init())
|
||||
return false;
|
||||
if (!extraTextId.init())
|
||||
if (!textIdPayloads.init())
|
||||
return false;
|
||||
if (!events.init())
|
||||
return false;
|
||||
|
@ -187,8 +187,8 @@ TraceLoggerThread::~TraceLoggerThread()
|
|||
graph = nullptr;
|
||||
}
|
||||
|
||||
if (extraTextId.initialized()) {
|
||||
for (TextIdHashMap::Range r = extraTextId.all(); !r.empty(); r.popFront())
|
||||
if (textIdPayloads.initialized()) {
|
||||
for (TextIdHashMap::Range r = textIdPayloads.all(); !r.empty(); r.popFront())
|
||||
js_delete(r.front().value());
|
||||
}
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ TraceLoggerThread::eventText(uint32_t id)
|
|||
if (id < TraceLogger_Last)
|
||||
return TLTextIdString(static_cast<TraceLoggerTextId>(id));
|
||||
|
||||
TextIdHashMap::Ptr p = extraTextId.lookup(id);
|
||||
TextIdHashMap::Ptr p = textIdPayloads.lookup(id);
|
||||
MOZ_ASSERT(p);
|
||||
|
||||
return p->value()->string();
|
||||
|
@ -351,13 +351,13 @@ TraceLoggerThread::extractScriptDetails(uint32_t textId, const char** filename,
|
|||
TraceLoggerEventPayload*
|
||||
TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId textId)
|
||||
{
|
||||
TextIdHashMap::AddPtr p = extraTextId.lookupForAdd(textId);
|
||||
TextIdHashMap::AddPtr p = textIdPayloads.lookupForAdd(textId);
|
||||
if (p)
|
||||
return p->value();
|
||||
|
||||
TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, (char*)nullptr);
|
||||
|
||||
if (!extraTextId.add(p, textId, payload))
|
||||
if (!textIdPayloads.add(p, textId, payload))
|
||||
return nullptr;
|
||||
|
||||
return payload;
|
||||
|
@ -379,7 +379,7 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text)
|
|||
MOZ_ASSERT(ret == len);
|
||||
MOZ_ASSERT(strlen(str) == len);
|
||||
|
||||
uint32_t textId = extraTextId.count() + TraceLogger_Last;
|
||||
uint32_t textId = nextTextId;
|
||||
|
||||
TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, str);
|
||||
if (!payload) {
|
||||
|
@ -387,7 +387,7 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!extraTextId.putNew(textId, payload)) {
|
||||
if (!textIdPayloads.putNew(textId, payload)) {
|
||||
js_delete(payload);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -398,6 +398,8 @@ TraceLoggerThread::getOrCreateEventPayload(const char* text)
|
|||
if (graph.get())
|
||||
graph->addTextId(textId, str);
|
||||
|
||||
nextTextId++;
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
|
@ -438,14 +440,14 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f
|
|||
MOZ_ASSERT(ret == len);
|
||||
MOZ_ASSERT(strlen(str) == len);
|
||||
|
||||
uint32_t textId = extraTextId.count() + TraceLogger_Last;
|
||||
uint32_t textId = nextTextId;
|
||||
TraceLoggerEventPayload* payload = js_new<TraceLoggerEventPayload>(textId, str);
|
||||
if (!payload) {
|
||||
js_free(str);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!extraTextId.putNew(textId, payload)) {
|
||||
if (!textIdPayloads.putNew(textId, payload)) {
|
||||
js_delete(payload);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -456,6 +458,8 @@ TraceLoggerThread::getOrCreateEventPayload(TraceLoggerTextId type, const char* f
|
|||
if (graph.get())
|
||||
graph->addTextId(textId, str);
|
||||
|
||||
nextTextId++;
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
|
@ -566,7 +570,7 @@ TraceLoggerThread::log(uint32_t id)
|
|||
}
|
||||
|
||||
// Free all TextEvents that have no uses anymore.
|
||||
for (TextIdHashMap::Enum e(extraTextId); !e.empty(); e.popFront()) {
|
||||
for (TextIdHashMap::Enum e(textIdPayloads); !e.empty(); e.popFront()) {
|
||||
if (e.front().value()->uses() == 0) {
|
||||
js_delete(e.front().value());
|
||||
e.removeFront();
|
||||
|
|
|
@ -166,7 +166,8 @@ class TraceLoggerThread
|
|||
mozilla::UniquePtr<TraceLoggerGraph> graph;
|
||||
|
||||
PointerHashMap pointerMap;
|
||||
TextIdHashMap extraTextId;
|
||||
TextIdHashMap textIdPayloads;
|
||||
uint32_t nextTextId;
|
||||
|
||||
ContinuousSpace<EventEntry> events;
|
||||
|
||||
|
@ -181,6 +182,7 @@ class TraceLoggerThread
|
|||
: enabled(0),
|
||||
failed(false),
|
||||
graph(),
|
||||
nextTextId(TraceLogger_Last),
|
||||
iteration_(0),
|
||||
top(nullptr)
|
||||
{ }
|
||||
|
|
|
@ -205,11 +205,11 @@ GridEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
|
|||
// OK -- now, stomp on or restore the "grid" entries in kDisplayKTable,
|
||||
// depending on whether the grid pref is enabled vs. disabled.
|
||||
if (sIndexOfGridInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfGridInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfGridInDisplayTable].mKeyword =
|
||||
isGridEnabled ? eCSSKeyword_grid : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfInlineGridInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfInlineGridInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfInlineGridInDisplayTable].mKeyword =
|
||||
isGridEnabled ? eCSSKeyword_inline_grid : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
@ -265,23 +265,23 @@ RubyEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
|
|||
// OK -- now, stomp on or restore the "ruby" entries in kDisplayKTable,
|
||||
// depending on whether the ruby pref is enabled vs. disabled.
|
||||
if (sIndexOfRubyInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyInDisplayTable].mKeyword =
|
||||
isRubyEnabled ? eCSSKeyword_ruby : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyBaseInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyBaseInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyBaseInDisplayTable].mKeyword =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_base : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyBaseContainerInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyBaseContainerInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyBaseContainerInDisplayTable].mKeyword =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_base_container : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyTextInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyTextInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyTextInDisplayTable].mKeyword =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_text : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
if (sIndexOfRubyTextContainerInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyTextContainerInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfRubyTextContainerInDisplayTable].mKeyword =
|
||||
isRubyEnabled ? eCSSKeyword_ruby_text_container : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ StickyEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
|
|||
|
||||
// OK -- now, stomp on or restore the "sticky" entry in kPositionKTable,
|
||||
// depending on whether the sticky pref is enabled vs. disabled.
|
||||
nsCSSProps::kPositionKTable[sIndexOfStickyInPositionTable] =
|
||||
nsCSSProps::kPositionKTable[sIndexOfStickyInPositionTable].mKeyword =
|
||||
isStickyEnabled ? eCSSKeyword_sticky : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -344,7 +344,7 @@ DisplayContentsEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
|
|||
// OK -- now, stomp on or restore the "contents" entry in kDisplayKTable,
|
||||
// depending on whether the pref is enabled vs. disabled.
|
||||
if (sIndexOfContentsInDisplayTable >= 0) {
|
||||
nsCSSProps::kDisplayKTable[sIndexOfContentsInDisplayTable] =
|
||||
nsCSSProps::kDisplayKTable[sIndexOfContentsInDisplayTable].mKeyword =
|
||||
isDisplayContentsEnabled ? eCSSKeyword_contents : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
@ -379,10 +379,10 @@ TextAlignTrueEnabledPrefChangeCallback(const char* aPrefName, void* aClosure)
|
|||
// OK -- now, stomp on or restore the "true" entry in the keyword tables,
|
||||
// depending on whether the pref is enabled vs. disabled.
|
||||
MOZ_ASSERT(sIndexOfTrueInTextAlignTable >= 0);
|
||||
nsCSSProps::kTextAlignKTable[sIndexOfTrueInTextAlignTable] =
|
||||
nsCSSProps::kTextAlignKTable[sIndexOfTrueInTextAlignTable].mKeyword =
|
||||
isTextAlignTrueEnabled ? eCSSKeyword_true : eCSSKeyword_UNKNOWN;
|
||||
MOZ_ASSERT(sIndexOfTrueInTextAlignLastTable >= 0);
|
||||
nsCSSProps::kTextAlignLastKTable[sIndexOfTrueInTextAlignLastTable] =
|
||||
nsCSSProps::kTextAlignLastKTable[sIndexOfTrueInTextAlignLastTable].mKeyword =
|
||||
isTextAlignTrueEnabled ? eCSSKeyword_true : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -428,16 +428,16 @@ FloatLogicalValuesEnabledPrefChangeCallback(const char* aPrefName,
|
|||
// OK -- now, stomp on or restore the logical entries in the keyword tables,
|
||||
// depending on whether the pref is enabled vs. disabled.
|
||||
MOZ_ASSERT(sIndexOfInlineStartInFloatTable >= 0);
|
||||
nsCSSProps::kFloatKTable[sIndexOfInlineStartInFloatTable] =
|
||||
nsCSSProps::kFloatKTable[sIndexOfInlineStartInFloatTable].mKeyword =
|
||||
isFloatLogicalValuesEnabled ? eCSSKeyword_inline_start : eCSSKeyword_UNKNOWN;
|
||||
MOZ_ASSERT(sIndexOfInlineEndInFloatTable >= 0);
|
||||
nsCSSProps::kFloatKTable[sIndexOfInlineEndInFloatTable] =
|
||||
nsCSSProps::kFloatKTable[sIndexOfInlineEndInFloatTable].mKeyword =
|
||||
isFloatLogicalValuesEnabled ? eCSSKeyword_inline_end : eCSSKeyword_UNKNOWN;
|
||||
MOZ_ASSERT(sIndexOfInlineStartInClearTable >= 0);
|
||||
nsCSSProps::kClearKTable[sIndexOfInlineStartInClearTable] =
|
||||
nsCSSProps::kClearKTable[sIndexOfInlineStartInClearTable].mKeyword =
|
||||
isFloatLogicalValuesEnabled ? eCSSKeyword_inline_start : eCSSKeyword_UNKNOWN;
|
||||
MOZ_ASSERT(sIndexOfInlineEndInClearTable >= 0);
|
||||
nsCSSProps::kClearKTable[sIndexOfInlineEndInClearTable] =
|
||||
nsCSSProps::kClearKTable[sIndexOfInlineEndInClearTable].mKeyword =
|
||||
isFloatLogicalValuesEnabled ? eCSSKeyword_inline_end : eCSSKeyword_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -4507,7 +4507,7 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
|
|||
nsIFrame* aFrame,
|
||||
const nsIFrame::IntrinsicISizeOffsetData& aOffsets,
|
||||
nsLayoutUtils::IntrinsicISizeType aType,
|
||||
uint8_t aBoxSizing,
|
||||
StyleBoxSizing aBoxSizing,
|
||||
nscoord aContentSize,
|
||||
nscoord aContentMinSize,
|
||||
const nsStyleCoord& aStyleSize,
|
||||
|
@ -4528,7 +4528,7 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
|
|||
coordOutsideSize += aOffsets.hPadding;
|
||||
pctOutsideSize += aOffsets.hPctPadding;
|
||||
|
||||
if (aBoxSizing == NS_STYLE_BOX_SIZING_PADDING) {
|
||||
if (aBoxSizing == StyleBoxSizing::Padding) {
|
||||
min += coordOutsideSize;
|
||||
result = NSCoordSaturatingAdd(result, coordOutsideSize);
|
||||
pctTotal += pctOutsideSize;
|
||||
|
@ -4540,7 +4540,7 @@ AddIntrinsicSizeOffset(nsRenderingContext* aRenderingContext,
|
|||
|
||||
coordOutsideSize += aOffsets.hBorder;
|
||||
|
||||
if (aBoxSizing == NS_STYLE_BOX_SIZING_BORDER) {
|
||||
if (aBoxSizing == StyleBoxSizing::Border) {
|
||||
min += coordOutsideSize;
|
||||
result = NSCoordSaturatingAdd(result, coordOutsideSize);
|
||||
pctTotal += pctOutsideSize;
|
||||
|
@ -4668,7 +4668,7 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
|
|||
// so we work in the parent's writing mode; but if aFrame is orthogonal to
|
||||
// its parent, we'll need to look at its BSize instead of min/pref-ISize.
|
||||
const nsStylePosition* stylePos = aFrame->StylePosition();
|
||||
uint8_t boxSizing = stylePos->mBoxSizing;
|
||||
StyleBoxSizing boxSizing = stylePos->mBoxSizing;
|
||||
|
||||
const nsStyleCoord& styleMinISize =
|
||||
horizontalAxis ? stylePos->mMinWidth : stylePos->mMinHeight;
|
||||
|
@ -4725,7 +4725,7 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
|
|||
// widths just like auto.
|
||||
// For -moz-max-content and -moz-min-content, we handle them like
|
||||
// specified widths, but ignore box-sizing.
|
||||
boxSizing = NS_STYLE_BOX_SIZING_CONTENT;
|
||||
boxSizing = StyleBoxSizing::Content;
|
||||
} else if (!styleISize.ConvertsToLength() &&
|
||||
!(haveFixedMinISize && haveFixedMaxISize && maxISize <= minISize)) {
|
||||
#ifdef DEBUG_INTRINSIC_WIDTH
|
||||
|
@ -4787,14 +4787,14 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
|
|||
|
||||
nscoord bSizeTakenByBoxSizing = 0;
|
||||
switch (boxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER: {
|
||||
case StyleBoxSizing::Border: {
|
||||
const nsStyleBorder* styleBorder = aFrame->StyleBorder();
|
||||
bSizeTakenByBoxSizing +=
|
||||
horizontalAxis ? styleBorder->GetComputedBorder().TopBottom()
|
||||
: styleBorder->GetComputedBorder().LeftRight();
|
||||
// fall through
|
||||
}
|
||||
case NS_STYLE_BOX_SIZING_PADDING: {
|
||||
case StyleBoxSizing::Padding: {
|
||||
if (!(aFlags & IGNORE_PADDING)) {
|
||||
const nsStyleSides& stylePadding =
|
||||
aFrame->StylePadding()->mPadding;
|
||||
|
@ -4814,7 +4814,7 @@ nsLayoutUtils::IntrinsicForAxis(PhysicalAxis aAxis,
|
|||
}
|
||||
// fall through
|
||||
}
|
||||
case NS_STYLE_BOX_SIZING_CONTENT:
|
||||
case StyleBoxSizing::Content:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -5191,11 +5191,15 @@ nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(WritingMode aWM,
|
|||
|
||||
LogicalSize boxSizingAdjust(aWM);
|
||||
switch (stylePos->mBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
case StyleBoxSizing::Border:
|
||||
boxSizingAdjust += aBorder;
|
||||
// fall through
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
case StyleBoxSizing::Padding:
|
||||
boxSizingAdjust += aPadding;
|
||||
// fall through
|
||||
case StyleBoxSizing::Content:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
nscoord boxSizingToMarginEdgeISize =
|
||||
aMargin.ISize(aWM) + aBorder.ISize(aWM) + aPadding.ISize(aWM) -
|
||||
|
|
|
@ -693,6 +693,9 @@ nsBlockFrame::GetMinISize(nsRenderingContext *aRenderingContext)
|
|||
curFrame->LazyMarkLinesDirty();
|
||||
}
|
||||
|
||||
if (RenumberLists(PresContext())) {
|
||||
AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
}
|
||||
if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION)
|
||||
ResolveBidi();
|
||||
InlineMinISizeData data;
|
||||
|
@ -778,6 +781,9 @@ nsBlockFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
|
|||
curFrame->LazyMarkLinesDirty();
|
||||
}
|
||||
|
||||
if (RenumberLists(PresContext())) {
|
||||
AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
}
|
||||
if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION)
|
||||
ResolveBidi();
|
||||
InlinePrefISizeData data;
|
||||
|
|
|
@ -4304,11 +4304,15 @@ nsFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
|||
const nsStylePosition *stylePos = StylePosition();
|
||||
|
||||
switch (stylePos->mBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
case StyleBoxSizing::Border:
|
||||
boxSizingAdjust += aBorder;
|
||||
// fall through
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
case StyleBoxSizing::Padding:
|
||||
boxSizingAdjust += aPadding;
|
||||
// fall through
|
||||
case StyleBoxSizing::Content:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
nscoord boxSizingToMarginEdgeISize =
|
||||
aMargin.ISize(aWM) + aBorder.ISize(aWM) + aPadding.ISize(aWM) -
|
||||
|
|
|
@ -251,19 +251,22 @@ nsCSSOffsetState::ComputeISizeValue(nscoord aContainingBlockISize,
|
|||
|
||||
nscoord
|
||||
nsCSSOffsetState::ComputeISizeValue(nscoord aContainingBlockISize,
|
||||
uint8_t aBoxSizing,
|
||||
StyleBoxSizing aBoxSizing,
|
||||
const nsStyleCoord& aCoord)
|
||||
{
|
||||
WritingMode wm = GetWritingMode();
|
||||
nscoord inside = 0, outside = ComputedLogicalBorderPadding().IStartEnd(wm) +
|
||||
ComputedLogicalMargin().IStartEnd(wm);
|
||||
switch (aBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
case StyleBoxSizing::Border:
|
||||
inside = ComputedLogicalBorderPadding().IStartEnd(wm);
|
||||
break;
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
case StyleBoxSizing::Padding:
|
||||
inside = ComputedLogicalPadding().IStartEnd(wm);
|
||||
break;
|
||||
case StyleBoxSizing::Content:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
outside -= inside;
|
||||
|
||||
|
@ -273,18 +276,21 @@ nsCSSOffsetState::ComputeISizeValue(nscoord aContainingBlockISize,
|
|||
|
||||
nscoord
|
||||
nsCSSOffsetState::ComputeBSizeValue(nscoord aContainingBlockBSize,
|
||||
uint8_t aBoxSizing,
|
||||
StyleBoxSizing aBoxSizing,
|
||||
const nsStyleCoord& aCoord)
|
||||
{
|
||||
WritingMode wm = GetWritingMode();
|
||||
nscoord inside = 0;
|
||||
switch (aBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
case StyleBoxSizing::Border:
|
||||
inside = ComputedLogicalBorderPadding().BStartEnd(wm);
|
||||
break;
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
case StyleBoxSizing::Padding:
|
||||
inside = ComputedLogicalPadding().BStartEnd(wm);
|
||||
break;
|
||||
case StyleBoxSizing::Content:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
return nsLayoutUtils::ComputeBSizeValue(aContainingBlockBSize,
|
||||
inside, aCoord);
|
||||
|
@ -1133,11 +1139,15 @@ nsHTMLReflowState::CalculateBorderPaddingMargin(
|
|||
nscoord outside = paddingStartEnd + borderStartEnd + marginStartEnd;
|
||||
nscoord inside = 0;
|
||||
switch (mStylePosition->mBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
case StyleBoxSizing::Border:
|
||||
inside += borderStartEnd;
|
||||
// fall through
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
case StyleBoxSizing::Padding:
|
||||
inside += paddingStartEnd;
|
||||
// fall through
|
||||
case StyleBoxSizing::Content:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
outside -= inside;
|
||||
*aInsideBoxSizing = inside;
|
||||
|
@ -1456,8 +1466,8 @@ nsHTMLReflowState::CalculateHypotheticalPosition
|
|||
// We need to compute it. It's important we do this, because if it's
|
||||
// percentage-based this computed value may be different from the
|
||||
// computed value calculated using the absolute containing block height.
|
||||
boxBSize = ComputeBSizeValue(blockContentSize.BSize(wm),
|
||||
insideBoxSizing, styleBSize) +
|
||||
boxBSize = nsLayoutUtils::ComputeBSizeValue(blockContentSize.BSize(wm),
|
||||
insideBoxSizing, styleBSize) +
|
||||
insideBoxSizing + outsideBoxSizing;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,11 +250,11 @@ protected:
|
|||
// same as previous, but using mComputedBorderPadding, mComputedPadding,
|
||||
// and mComputedMargin
|
||||
nscoord ComputeISizeValue(nscoord aContainingBlockISize,
|
||||
uint8_t aBoxSizing,
|
||||
mozilla::StyleBoxSizing aBoxSizing,
|
||||
const nsStyleCoord& aCoord);
|
||||
|
||||
nscoord ComputeBSizeValue(nscoord aContainingBlockBSize,
|
||||
uint8_t aBoxSizing,
|
||||
mozilla::StyleBoxSizing aBoxSizing,
|
||||
const nsStyleCoord& aCoord);
|
||||
};
|
||||
|
||||
|
|
|
@ -577,17 +577,13 @@ static void GetKeywordsForProperty(const nsCSSProperty aProperty,
|
|||
// Shorthand props have no keywords.
|
||||
return;
|
||||
}
|
||||
const nsCSSProps::KTableValue *keywordTable =
|
||||
const nsCSSProps::KTableEntry* keywordTable =
|
||||
nsCSSProps::kKeywordTableTable[aProperty];
|
||||
if (keywordTable) {
|
||||
size_t i = 0;
|
||||
while (nsCSSKeyword(keywordTable[i]) != eCSSKeyword_UNKNOWN) {
|
||||
nsCSSKeyword word = nsCSSKeyword(keywordTable[i]);
|
||||
for (size_t i = 0; keywordTable[i].mKeyword != eCSSKeyword_UNKNOWN; ++i) {
|
||||
nsCSSKeyword word = keywordTable[i].mKeyword;
|
||||
InsertNoDuplicates(aArray,
|
||||
NS_ConvertASCIItoUTF16(nsCSSKeywords::GetStringValue(word)));
|
||||
// Increment counter by 2, because in this table every second
|
||||
// element is a nsCSSKeyword.
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -548,7 +548,7 @@ RenderFrameParent::SetTargetAPZC(uint64_t aInputBlockId,
|
|||
= &APZCTreeManager::SetTargetAPZC;
|
||||
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
|
||||
GetApzcTreeManager(), setTargetApzcFunc,
|
||||
aInputBlockId, nsTArray<ScrollableLayerGuid>(aTargets)));
|
||||
aInputBlockId, aTargets));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -559,7 +559,7 @@ RenderFrameParent::SetAllowedTouchBehavior(uint64_t aInputBlockId,
|
|||
if (GetApzcTreeManager()) {
|
||||
APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
|
||||
GetApzcTreeManager(), &APZCTreeManager::SetAllowedTouchBehavior,
|
||||
aInputBlockId, nsTArray<TouchBehaviorFlags>(aFlags)));
|
||||
aInputBlockId, aFlags));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ skip-if(B2G||Mulet) fails-if(Android) random-if(gtkWidget) == src-list-local-ps.
|
|||
random-if(!cocoaWidget) == helveticaneue-ultra.html helveticaneue-ultra-ref.html
|
||||
|
||||
HTTP(..) == order-1.html order-1-ref.html
|
||||
pref(layout.css.unicode-range.enabled,true) random-if(gtkWidget) HTTP(..) == order-2.html order-2-ref.html # enable new linux font backend, bug 1180560
|
||||
pref(layout.css.unicode-range.enabled,true) random-if(gtkWidget) HTTP(..) == order-3.html order-3-ref.html # enable new linux font backend, bug 1180560
|
||||
pref(layout.css.unicode-range.enabled,true) HTTP(..) == order-2.html order-2-ref.html
|
||||
pref(layout.css.unicode-range.enabled,true) HTTP(..) == order-3.html order-3-ref.html
|
||||
HTTP(..) == multiple-in-family-1.html multiple-in-family-1-ref.html
|
||||
HTTP(..) == multiple-in-family-1b.html multiple-in-family-1-ref.html
|
||||
HTTP(..) != multiple-in-family-1.html multiple-in-family-1-notref.html
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Bug 994418</title>
|
||||
</head>
|
||||
<body>
|
||||
MMMCMXCIX. sometext
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Bug 994418</title>
|
||||
<style>
|
||||
ol {
|
||||
display: inline-block;
|
||||
list-style: upper-roman inside;
|
||||
padding: 0; margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ol start="3999"><li></ol>sometext
|
||||
</body>
|
||||
</html>
|
|
@ -8,3 +8,4 @@ asserts(1) == ol-reversed-1b.html ol-reversed-1-ref.html # bug 478135
|
|||
== bullet-space-1.html bullet-space-1-ref.html
|
||||
== bullet-space-2.html bullet-space-2-ref.html
|
||||
== bullet-intrinsic-isize-1.html bullet-intrinsic-isize-1-ref.html
|
||||
== bullet-intrinsic-isize-2.html bullet-intrinsic-isize-2-ref.html
|
||||
|
|
|
@ -30,4 +30,19 @@
|
|||
<circle cx="250" cy="205" r="11" fill="lime"/>
|
||||
<circle cx="206" cy="225" r="11" fill="lime"/>
|
||||
|
||||
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1131264 -->
|
||||
<!-- small circles take a different code path -->
|
||||
|
||||
<!-- Test circle element dashes cover two red circles -->
|
||||
<circle cx="125" cy="325" r="8" fill="red"/>
|
||||
<circle cx="50" cy="380" r="8" fill="red"/>
|
||||
<circle cx="0" cy="0" r=".0008" fill="none" stroke="lime" stroke-width=".0003" stroke-dasharray=".0005 .0005 .0005 100"
|
||||
transform="translate(50, 300) scale(1e5, 1e5)"/>
|
||||
|
||||
<!-- Sanity test to check that two circles cover circle element dashes (i.e. that the previous check didn't pass because the stroke was solid) -->
|
||||
<circle cx="0" cy="0" r=".0008" fill="none" stroke="red" stroke-width=".0001" stroke-dasharray=".0001 .0005 .0001 100"
|
||||
transform="translate(180, 300) scale(1e5, 1e5)"/>
|
||||
<circle cx="260" cy="305" r="11" fill="lime"/>
|
||||
<circle cx="235" cy="358" r="11" fill="lime"/>
|
||||
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 1.6 KiB После Ширина: | Высота: | Размер: 2.5 KiB |
|
@ -18,7 +18,7 @@
|
|||
|
||||
*/
|
||||
#define CSS_KEY(_name,_id) eCSSKeyword_##_id,
|
||||
enum nsCSSKeyword {
|
||||
enum nsCSSKeyword : int16_t {
|
||||
eCSSKeyword_UNKNOWN = -1,
|
||||
#include "nsCSSKeywordList.h"
|
||||
eCSSKeyword_COUNT
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
using namespace mozilla;
|
||||
|
||||
typedef nsCSSProps::KTableValue KTableValue;
|
||||
typedef nsCSSProps::KTableEntry KTableEntry;
|
||||
|
||||
// pref-backed bool values (hooked up in nsCSSParser::Startup)
|
||||
static bool sOpentypeSVGEnabled;
|
||||
|
@ -791,7 +791,7 @@ protected:
|
|||
// property (like "display") for which we emulate a vendor-prefixed value
|
||||
// (like "-webkit-box").
|
||||
nsCSSKeyword LookupKeywordPrefixAware(nsAString& aKeywordStr,
|
||||
const KTableValue aKeywordTable[]);
|
||||
const KTableEntry aKeywordTable[]);
|
||||
|
||||
bool ShouldUseUnprefixingService() const;
|
||||
bool ParsePropertyWithUnprefixingService(const nsAString& aPropertyName,
|
||||
|
@ -964,7 +964,7 @@ protected:
|
|||
|
||||
// parsing 'align/justify-items/self' from the css-align spec
|
||||
bool ParseAlignJustifyPosition(nsCSSValue& aResult,
|
||||
const KTableValue aTable[]);
|
||||
const KTableEntry aTable[]);
|
||||
bool ParseJustifyItems();
|
||||
bool ParseAlignItemsSelfJustifySelf(nsCSSProperty aPropID);
|
||||
// parsing 'align/justify-content' from the css-align spec
|
||||
|
@ -984,7 +984,7 @@ protected:
|
|||
bool MergeBitmaskValue(int32_t aNewValue, const int32_t aMasks[],
|
||||
int32_t& aMergedValue);
|
||||
bool ParseBitmaskValues(nsCSSValue& aValue,
|
||||
const KTableValue aKeywordTable[],
|
||||
const KTableEntry aKeywordTable[],
|
||||
const int32_t aMasks[]);
|
||||
bool ParseFontVariantEastAsian(nsCSSValue& aValue);
|
||||
bool ParseFontVariantLigatures(nsCSSValue& aValue);
|
||||
|
@ -1008,7 +1008,7 @@ protected:
|
|||
bool ParsePadding();
|
||||
bool ParseQuotes();
|
||||
bool ParseTextAlign(nsCSSValue& aValue,
|
||||
const KTableValue aTable[]);
|
||||
const KTableEntry aTable[]);
|
||||
bool ParseTextAlign(nsCSSValue& aValue);
|
||||
bool ParseTextAlignLast(nsCSSValue& aValue);
|
||||
bool ParseTextDecoration();
|
||||
|
@ -1119,28 +1119,28 @@ protected:
|
|||
bool ParseColorOpacity(uint8_t& aOpacity);
|
||||
bool ParseColorOpacity(float& aOpacity);
|
||||
bool ParseEnum(nsCSSValue& aValue,
|
||||
const KTableValue aKeywordTable[]);
|
||||
const KTableEntry aKeywordTable[]);
|
||||
|
||||
// Variant parsing methods
|
||||
CSSParseResult ParseVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[]);
|
||||
const KTableEntry aKeywordTable[]);
|
||||
CSSParseResult ParseVariantWithRestrictions(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[],
|
||||
const KTableEntry aKeywordTable[],
|
||||
uint32_t aRestrictions);
|
||||
CSSParseResult ParseNonNegativeVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[]);
|
||||
const KTableEntry aKeywordTable[]);
|
||||
CSSParseResult ParseOneOrLargerVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[]);
|
||||
const KTableEntry aKeywordTable[]);
|
||||
|
||||
// Variant parsing methods that are guaranteed to UngetToken any token
|
||||
// consumed on failure
|
||||
bool ParseSingleTokenVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
MOZ_ASSERT(!(aVariantMask & VARIANT_MULTIPLE_TOKENS),
|
||||
"use ParseVariant for variants in VARIANT_MULTIPLE_TOKENS");
|
||||
|
@ -1151,7 +1151,7 @@ protected:
|
|||
bool ParseSingleTokenVariantWithRestrictions(
|
||||
nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[],
|
||||
const KTableEntry aKeywordTable[],
|
||||
uint32_t aRestrictions)
|
||||
{
|
||||
MOZ_ASSERT(!(aVariantMask & VARIANT_MULTIPLE_TOKENS),
|
||||
|
@ -1165,7 +1165,7 @@ protected:
|
|||
}
|
||||
bool ParseSingleTokenNonNegativeVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
MOZ_ASSERT(!(aVariantMask & VARIANT_MULTIPLE_TOKENS),
|
||||
"use ParseNonNegativeVariant for variants in "
|
||||
|
@ -1177,7 +1177,7 @@ protected:
|
|||
}
|
||||
bool ParseSingleTokenOneOrLargerVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
MOZ_ASSERT(!(aVariantMask & VARIANT_MULTIPLE_TOKENS),
|
||||
"use ParseOneOrLargerVariant for variants in "
|
||||
|
@ -1209,12 +1209,12 @@ protected:
|
|||
// that ends with a eCSSKeyword_UNKNOWN marker.
|
||||
//
|
||||
// |aPropertyKTable| can be used if some of the keywords to exclude
|
||||
// also appear in an existing nsCSSProps::KTableValue,
|
||||
// also appear in an existing nsCSSProps::KTableEntry,
|
||||
// to avoid duplicating them.
|
||||
bool ParseCustomIdent(nsCSSValue& aValue,
|
||||
const nsAutoString& aIdentValue,
|
||||
const nsCSSKeyword aExcludedKeywords[] = nullptr,
|
||||
const nsCSSProps::KTableValue aPropertyKTable[] = nullptr);
|
||||
const nsCSSProps::KTableEntry aPropertyKTable[] = nullptr);
|
||||
bool ParseCounter(nsCSSValue& aValue);
|
||||
bool ParseAttr(nsCSSValue& aValue);
|
||||
bool ParseSymbols(nsCSSValue& aValue);
|
||||
|
@ -6807,7 +6807,7 @@ CSSParserImpl::ParseTreePseudoElement(nsAtomList **aPseudoElementArgs)
|
|||
|
||||
nsCSSKeyword
|
||||
CSSParserImpl::LookupKeywordPrefixAware(nsAString& aKeywordStr,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(aKeywordStr);
|
||||
|
||||
|
@ -7219,7 +7219,7 @@ static const nsCSSProperty kColumnRuleIDs[] = {
|
|||
|
||||
bool
|
||||
CSSParserImpl::ParseEnum(nsCSSValue& aValue,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
nsSubstring* ident = NextIdent();
|
||||
if (nullptr == ident) {
|
||||
|
@ -7364,7 +7364,7 @@ CSSParserImpl::TranslateDimension(nsCSSValue& aValue,
|
|||
CSSParseResult
|
||||
CSSParserImpl::ParseVariantWithRestrictions(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[],
|
||||
const KTableEntry aKeywordTable[],
|
||||
uint32_t aRestrictions)
|
||||
{
|
||||
switch (aRestrictions) {
|
||||
|
@ -7386,7 +7386,7 @@ CSSParserImpl::ParseVariantWithRestrictions(nsCSSValue& aValue,
|
|||
CSSParseResult
|
||||
CSSParserImpl::ParseNonNegativeVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
// The variant mask must only contain non-numeric variants or the ones
|
||||
// that we specifically handle.
|
||||
|
@ -7428,7 +7428,7 @@ CSSParserImpl::ParseNonNegativeVariant(nsCSSValue& aValue,
|
|||
CSSParseResult
|
||||
CSSParserImpl::ParseOneOrLargerVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
// The variant mask must only contain non-numeric variants or the ones
|
||||
// that we specifically handle.
|
||||
|
@ -7458,7 +7458,7 @@ CSSParserImpl::ParseOneOrLargerVariant(nsCSSValue& aValue,
|
|||
CSSParseResult
|
||||
CSSParserImpl::ParseVariant(nsCSSValue& aValue,
|
||||
int32_t aVariantMask,
|
||||
const KTableValue aKeywordTable[])
|
||||
const KTableEntry aKeywordTable[])
|
||||
{
|
||||
NS_ASSERTION(!(mHashlessColorQuirk && (aVariantMask & VARIANT_COLOR)) ||
|
||||
!(aVariantMask & VARIANT_NUMBER),
|
||||
|
@ -7764,7 +7764,7 @@ bool
|
|||
CSSParserImpl::ParseCustomIdent(nsCSSValue& aValue,
|
||||
const nsAutoString& aIdentValue,
|
||||
const nsCSSKeyword aExcludedKeywords[],
|
||||
const nsCSSProps::KTableValue aPropertyKTable[])
|
||||
const nsCSSProps::KTableEntry aPropertyKTable[])
|
||||
{
|
||||
nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(aIdentValue);
|
||||
if (keyword == eCSSKeyword_UNKNOWN) {
|
||||
|
@ -9459,7 +9459,7 @@ CSSParserImpl::ParseGridGap()
|
|||
// $aTable is for <content-position> or <self-position>
|
||||
bool
|
||||
CSSParserImpl::ParseAlignJustifyPosition(nsCSSValue& aResult,
|
||||
const KTableValue aTable[])
|
||||
const KTableEntry aTable[])
|
||||
{
|
||||
nsCSSValue pos, overflowPos;
|
||||
int32_t value = 0;
|
||||
|
@ -10804,7 +10804,7 @@ CSSParserImpl::ParseBoxProperty(nsCSSValue& aValue,
|
|||
return CSSParseResult::NotFound;
|
||||
}
|
||||
|
||||
const KTableValue* kwtable = nsCSSProps::kKeywordTableTable[aPropID];
|
||||
const KTableEntry* kwtable = nsCSSProps::kKeywordTableTable[aPropID];
|
||||
uint32_t restrictions = nsCSSProps::ValueRestrictions(aPropID);
|
||||
|
||||
return ParseVariantWithRestrictions(aValue, variant, kwtable, restrictions);
|
||||
|
@ -10910,7 +10910,7 @@ CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
|
|||
return CSSParseResult::NotFound;
|
||||
}
|
||||
|
||||
const KTableValue* kwtable = nsCSSProps::kKeywordTableTable[aPropID];
|
||||
const KTableEntry* kwtable = nsCSSProps::kKeywordTableTable[aPropID];
|
||||
uint32_t restrictions = nsCSSProps::ValueRestrictions(aPropID);
|
||||
return ParseVariantWithRestrictions(aValue, variant, kwtable, restrictions);
|
||||
}
|
||||
|
@ -12539,27 +12539,28 @@ CSSParserImpl::ParseContent()
|
|||
{
|
||||
// We need to divide the 'content' keywords into two classes for
|
||||
// ParseVariant's sake, so we can't just use nsCSSProps::kContentKTable.
|
||||
static const KTableValue kContentListKWs[] = {
|
||||
eCSSKeyword_open_quote, NS_STYLE_CONTENT_OPEN_QUOTE,
|
||||
eCSSKeyword_close_quote, NS_STYLE_CONTENT_CLOSE_QUOTE,
|
||||
eCSSKeyword_no_open_quote, NS_STYLE_CONTENT_NO_OPEN_QUOTE,
|
||||
eCSSKeyword_no_close_quote, NS_STYLE_CONTENT_NO_CLOSE_QUOTE,
|
||||
eCSSKeyword_UNKNOWN,-1
|
||||
static const KTableEntry kContentListKWs[] = {
|
||||
{ eCSSKeyword_open_quote, NS_STYLE_CONTENT_OPEN_QUOTE },
|
||||
{ eCSSKeyword_close_quote, NS_STYLE_CONTENT_CLOSE_QUOTE },
|
||||
{ eCSSKeyword_no_open_quote, NS_STYLE_CONTENT_NO_OPEN_QUOTE },
|
||||
{ eCSSKeyword_no_close_quote, NS_STYLE_CONTENT_NO_CLOSE_QUOTE },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
static const KTableValue kContentSolitaryKWs[] = {
|
||||
eCSSKeyword__moz_alt_content, NS_STYLE_CONTENT_ALT_CONTENT,
|
||||
eCSSKeyword_UNKNOWN,-1
|
||||
static const KTableEntry kContentSolitaryKWs[] = {
|
||||
{ eCSSKeyword__moz_alt_content, NS_STYLE_CONTENT_ALT_CONTENT },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
// Verify that these two lists add up to the size of
|
||||
// nsCSSProps::kContentKTable.
|
||||
MOZ_ASSERT(nsCSSProps::kContentKTable[
|
||||
ArrayLength(kContentListKWs) +
|
||||
ArrayLength(kContentSolitaryKWs) - 4] == eCSSKeyword_UNKNOWN &&
|
||||
ArrayLength(kContentSolitaryKWs) - 2].mKeyword ==
|
||||
eCSSKeyword_UNKNOWN &&
|
||||
nsCSSProps::kContentKTable[
|
||||
ArrayLength(kContentListKWs) +
|
||||
ArrayLength(kContentSolitaryKWs) - 3] == -1,
|
||||
ArrayLength(kContentSolitaryKWs) - 2].mValue == -1,
|
||||
"content keyword tables out of sync");
|
||||
|
||||
nsCSSValue value;
|
||||
|
@ -13031,7 +13032,7 @@ CSSParserImpl::MergeBitmaskValue(int32_t aNewValue,
|
|||
|
||||
bool
|
||||
CSSParserImpl::ParseBitmaskValues(nsCSSValue& aValue,
|
||||
const KTableValue aKeywordTable[],
|
||||
const KTableEntry aKeywordTable[],
|
||||
const int32_t aMasks[])
|
||||
{
|
||||
// Parse at least one keyword
|
||||
|
@ -14009,7 +14010,7 @@ CSSParserImpl::ParseTextDecoration()
|
|||
}
|
||||
|
||||
bool
|
||||
CSSParserImpl::ParseTextAlign(nsCSSValue& aValue, const KTableValue aTable[])
|
||||
CSSParserImpl::ParseTextAlign(nsCSSValue& aValue, const KTableEntry aTable[])
|
||||
{
|
||||
if (ParseSingleTokenVariant(aValue, VARIANT_INHERIT, nullptr)) {
|
||||
// 'inherit', 'initial' and 'unset' must be alone
|
||||
|
@ -15688,16 +15689,16 @@ CSSParserImpl::ParsePaintOrder()
|
|||
((1 << NS_STYLE_PAINT_ORDER_BITWIDTH) > NS_STYLE_PAINT_ORDER_LAST_VALUE,
|
||||
"bitfield width insufficient for paint-order constants");
|
||||
|
||||
static const KTableValue kPaintOrderKTable[] = {
|
||||
eCSSKeyword_normal, NS_STYLE_PAINT_ORDER_NORMAL,
|
||||
eCSSKeyword_fill, NS_STYLE_PAINT_ORDER_FILL,
|
||||
eCSSKeyword_stroke, NS_STYLE_PAINT_ORDER_STROKE,
|
||||
eCSSKeyword_markers, NS_STYLE_PAINT_ORDER_MARKERS,
|
||||
eCSSKeyword_UNKNOWN,-1
|
||||
static const KTableEntry kPaintOrderKTable[] = {
|
||||
{ eCSSKeyword_normal, NS_STYLE_PAINT_ORDER_NORMAL },
|
||||
{ eCSSKeyword_fill, NS_STYLE_PAINT_ORDER_FILL },
|
||||
{ eCSSKeyword_stroke, NS_STYLE_PAINT_ORDER_STROKE },
|
||||
{ eCSSKeyword_markers, NS_STYLE_PAINT_ORDER_MARKERS },
|
||||
{ eCSSKeyword_UNKNOWN, -1 }
|
||||
};
|
||||
|
||||
static_assert(MOZ_ARRAY_LENGTH(kPaintOrderKTable) ==
|
||||
2 * (NS_STYLE_PAINT_ORDER_LAST_VALUE + 2),
|
||||
NS_STYLE_PAINT_ORDER_LAST_VALUE + 2,
|
||||
"missing paint-order values in kPaintOrderKTable");
|
||||
|
||||
nsCSSValue value;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -307,7 +307,10 @@ enum nsStyleAnimType {
|
|||
|
||||
class nsCSSProps {
|
||||
public:
|
||||
typedef int16_t KTableValue;
|
||||
struct KTableEntry {
|
||||
nsCSSKeyword mKeyword;
|
||||
int16_t mValue;
|
||||
};
|
||||
|
||||
static void AddRefTable(void);
|
||||
static void ReleaseTable(void);
|
||||
|
@ -387,22 +390,22 @@ public:
|
|||
// otherwise, returns -1.
|
||||
// NOTE: Generally, clients should call FindKeyword() instead of this method.
|
||||
static int32_t FindIndexOfKeyword(nsCSSKeyword aKeyword,
|
||||
const KTableValue aTable[]);
|
||||
const KTableEntry aTable[]);
|
||||
|
||||
// Find |aKeyword| in |aTable|, if found set |aValue| to its corresponding value.
|
||||
// If not found, return false and do not set |aValue|.
|
||||
static bool FindKeyword(nsCSSKeyword aKeyword, const KTableValue aTable[],
|
||||
static bool FindKeyword(nsCSSKeyword aKeyword, const KTableEntry aTable[],
|
||||
int32_t& aValue);
|
||||
// Return the first keyword in |aTable| that has the corresponding value |aValue|.
|
||||
// Return |eCSSKeyword_UNKNOWN| if not found.
|
||||
static nsCSSKeyword ValueToKeywordEnum(int32_t aValue,
|
||||
const KTableValue aTable[]);
|
||||
const KTableEntry aTable[]);
|
||||
// Ditto but as a string, return "" when not found.
|
||||
static const nsAFlatCString& ValueToKeyword(int32_t aValue,
|
||||
const KTableValue aTable[]);
|
||||
const KTableEntry aTable[]);
|
||||
|
||||
static const nsStyleStructID kSIDTable[eCSSProperty_COUNT_no_shorthands];
|
||||
static const KTableValue* const kKeywordTableTable[eCSSProperty_COUNT_no_shorthands];
|
||||
static const KTableEntry* const kKeywordTableTable[eCSSProperty_COUNT_no_shorthands];
|
||||
static const nsStyleAnimType kAnimTypeTable[eCSSProperty_COUNT_no_shorthands];
|
||||
static const ptrdiff_t
|
||||
kStyleStructOffsetTable[eCSSProperty_COUNT_no_shorthands];
|
||||
|
@ -627,180 +630,180 @@ public:
|
|||
if (nsCSSProps::IsEnabled(*it_, (nsCSSProps::EnabledState) es_))
|
||||
|
||||
// Keyword/Enum value tables
|
||||
static const KTableValue kAnimationDirectionKTable[];
|
||||
static const KTableValue kAnimationFillModeKTable[];
|
||||
static const KTableValue kAnimationIterationCountKTable[];
|
||||
static const KTableValue kAnimationPlayStateKTable[];
|
||||
static const KTableValue kAnimationTimingFunctionKTable[];
|
||||
static const KTableValue kAppearanceKTable[];
|
||||
static const KTableValue kAzimuthKTable[];
|
||||
static const KTableValue kBackfaceVisibilityKTable[];
|
||||
static const KTableValue kTransformStyleKTable[];
|
||||
static const KTableValue kBackgroundAttachmentKTable[];
|
||||
static const KTableValue kBackgroundOriginKTable[];
|
||||
static const KTableValue kBackgroundPositionKTable[];
|
||||
static const KTableValue kBackgroundRepeatKTable[];
|
||||
static const KTableValue kBackgroundRepeatPartKTable[];
|
||||
static const KTableValue kBackgroundSizeKTable[];
|
||||
static const KTableValue kBlendModeKTable[];
|
||||
static const KTableValue kBorderCollapseKTable[];
|
||||
static const KTableValue kBorderColorKTable[];
|
||||
static const KTableValue kBorderImageRepeatKTable[];
|
||||
static const KTableValue kBorderImageSliceKTable[];
|
||||
static const KTableValue kBorderStyleKTable[];
|
||||
static const KTableValue kBorderWidthKTable[];
|
||||
static const KTableValue kBoxAlignKTable[];
|
||||
static const KTableValue kBoxDecorationBreakKTable[];
|
||||
static const KTableValue kBoxDirectionKTable[];
|
||||
static const KTableValue kBoxOrientKTable[];
|
||||
static const KTableValue kBoxPackKTable[];
|
||||
static const KTableValue kClipShapeSizingKTable[];
|
||||
static const KTableValue kCounterRangeKTable[];
|
||||
static const KTableValue kCounterSpeakAsKTable[];
|
||||
static const KTableValue kCounterSymbolsSystemKTable[];
|
||||
static const KTableValue kCounterSystemKTable[];
|
||||
static const KTableValue kDominantBaselineKTable[];
|
||||
static const KTableValue kShapeRadiusKTable[];
|
||||
static const KTableValue kFillRuleKTable[];
|
||||
static const KTableValue kFilterFunctionKTable[];
|
||||
static const KTableValue kImageRenderingKTable[];
|
||||
static const KTableValue kShapeRenderingKTable[];
|
||||
static const KTableValue kStrokeLinecapKTable[];
|
||||
static const KTableValue kStrokeLinejoinKTable[];
|
||||
static const KTableValue kStrokeContextValueKTable[];
|
||||
static const KTableValue kVectorEffectKTable[];
|
||||
static const KTableValue kTextAnchorKTable[];
|
||||
static const KTableValue kTextRenderingKTable[];
|
||||
static const KTableValue kColorInterpolationKTable[];
|
||||
static const KTableValue kColumnFillKTable[];
|
||||
static const KTableValue kBoxPropSourceKTable[];
|
||||
static const KTableValue kBoxShadowTypeKTable[];
|
||||
static const KTableValue kBoxSizingKTable[];
|
||||
static const KTableValue kCaptionSideKTable[];
|
||||
static const KTableEntry kAnimationDirectionKTable[];
|
||||
static const KTableEntry kAnimationFillModeKTable[];
|
||||
static const KTableEntry kAnimationIterationCountKTable[];
|
||||
static const KTableEntry kAnimationPlayStateKTable[];
|
||||
static const KTableEntry kAnimationTimingFunctionKTable[];
|
||||
static const KTableEntry kAppearanceKTable[];
|
||||
static const KTableEntry kAzimuthKTable[];
|
||||
static const KTableEntry kBackfaceVisibilityKTable[];
|
||||
static const KTableEntry kTransformStyleKTable[];
|
||||
static const KTableEntry kBackgroundAttachmentKTable[];
|
||||
static const KTableEntry kBackgroundOriginKTable[];
|
||||
static const KTableEntry kBackgroundPositionKTable[];
|
||||
static const KTableEntry kBackgroundRepeatKTable[];
|
||||
static const KTableEntry kBackgroundRepeatPartKTable[];
|
||||
static const KTableEntry kBackgroundSizeKTable[];
|
||||
static const KTableEntry kBlendModeKTable[];
|
||||
static const KTableEntry kBorderCollapseKTable[];
|
||||
static const KTableEntry kBorderColorKTable[];
|
||||
static const KTableEntry kBorderImageRepeatKTable[];
|
||||
static const KTableEntry kBorderImageSliceKTable[];
|
||||
static const KTableEntry kBorderStyleKTable[];
|
||||
static const KTableEntry kBorderWidthKTable[];
|
||||
static const KTableEntry kBoxAlignKTable[];
|
||||
static const KTableEntry kBoxDecorationBreakKTable[];
|
||||
static const KTableEntry kBoxDirectionKTable[];
|
||||
static const KTableEntry kBoxOrientKTable[];
|
||||
static const KTableEntry kBoxPackKTable[];
|
||||
static const KTableEntry kClipShapeSizingKTable[];
|
||||
static const KTableEntry kCounterRangeKTable[];
|
||||
static const KTableEntry kCounterSpeakAsKTable[];
|
||||
static const KTableEntry kCounterSymbolsSystemKTable[];
|
||||
static const KTableEntry kCounterSystemKTable[];
|
||||
static const KTableEntry kDominantBaselineKTable[];
|
||||
static const KTableEntry kShapeRadiusKTable[];
|
||||
static const KTableEntry kFillRuleKTable[];
|
||||
static const KTableEntry kFilterFunctionKTable[];
|
||||
static const KTableEntry kImageRenderingKTable[];
|
||||
static const KTableEntry kShapeRenderingKTable[];
|
||||
static const KTableEntry kStrokeLinecapKTable[];
|
||||
static const KTableEntry kStrokeLinejoinKTable[];
|
||||
static const KTableEntry kStrokeContextValueKTable[];
|
||||
static const KTableEntry kVectorEffectKTable[];
|
||||
static const KTableEntry kTextAnchorKTable[];
|
||||
static const KTableEntry kTextRenderingKTable[];
|
||||
static const KTableEntry kColorInterpolationKTable[];
|
||||
static const KTableEntry kColumnFillKTable[];
|
||||
static const KTableEntry kBoxPropSourceKTable[];
|
||||
static const KTableEntry kBoxShadowTypeKTable[];
|
||||
static const KTableEntry kBoxSizingKTable[];
|
||||
static const KTableEntry kCaptionSideKTable[];
|
||||
// Not const because we modify its entries when the pref
|
||||
// "layout.css.float-logical-values.enabled" changes:
|
||||
static KTableValue kClearKTable[];
|
||||
static const KTableValue kColorKTable[];
|
||||
static const KTableValue kContentKTable[];
|
||||
static const KTableValue kControlCharacterVisibilityKTable[];
|
||||
static const KTableValue kCursorKTable[];
|
||||
static const KTableValue kDirectionKTable[];
|
||||
static KTableEntry kClearKTable[];
|
||||
static const KTableEntry kColorKTable[];
|
||||
static const KTableEntry kContentKTable[];
|
||||
static const KTableEntry kControlCharacterVisibilityKTable[];
|
||||
static const KTableEntry kCursorKTable[];
|
||||
static const KTableEntry kDirectionKTable[];
|
||||
// Not const because we modify its entries when various
|
||||
// "layout.css.*.enabled" prefs changes:
|
||||
static KTableValue kDisplayKTable[];
|
||||
static const KTableValue kElevationKTable[];
|
||||
static const KTableValue kEmptyCellsKTable[];
|
||||
static KTableEntry kDisplayKTable[];
|
||||
static const KTableEntry kElevationKTable[];
|
||||
static const KTableEntry kEmptyCellsKTable[];
|
||||
// -- tables for the align-/justify-content/items/self properties --
|
||||
static const KTableValue kAlignAllKeywords[];
|
||||
static const KTableValue kAlignOverflowPosition[]; // <overflow-position>
|
||||
static const KTableValue kAlignSelfPosition[]; // <self-position>
|
||||
static const KTableValue kAlignLegacy[]; // 'legacy'
|
||||
static const KTableValue kAlignLegacyPosition[]; // 'left/right/center'
|
||||
static const KTableValue kAlignAutoStretchBaseline[]; // 'auto/stretch/baseline/last-baseline'
|
||||
static const KTableValue kAlignAutoBaseline[]; // 'auto/baseline/last-baseline'
|
||||
static const KTableValue kAlignContentDistribution[]; // <content-distribution>
|
||||
static const KTableValue kAlignContentPosition[]; // <content-position>
|
||||
static const KTableValue kAlignSelfKTable[];
|
||||
static const KTableValue kJustifyContentKTable[];
|
||||
static const KTableEntry kAlignAllKeywords[];
|
||||
static const KTableEntry kAlignOverflowPosition[]; // <overflow-position>
|
||||
static const KTableEntry kAlignSelfPosition[]; // <self-position>
|
||||
static const KTableEntry kAlignLegacy[]; // 'legacy'
|
||||
static const KTableEntry kAlignLegacyPosition[]; // 'left/right/center'
|
||||
static const KTableEntry kAlignAutoStretchBaseline[]; // 'auto/stretch/baseline/last-baseline'
|
||||
static const KTableEntry kAlignAutoBaseline[]; // 'auto/baseline/last-baseline'
|
||||
static const KTableEntry kAlignContentDistribution[]; // <content-distribution>
|
||||
static const KTableEntry kAlignContentPosition[]; // <content-position>
|
||||
static const KTableEntry kAlignSelfKTable[];
|
||||
static const KTableEntry kJustifyContentKTable[];
|
||||
// ------------------------------------------------------------------
|
||||
static const KTableValue kFlexDirectionKTable[];
|
||||
static const KTableValue kFlexWrapKTable[];
|
||||
static const KTableEntry kFlexDirectionKTable[];
|
||||
static const KTableEntry kFlexWrapKTable[];
|
||||
// Not const because we modify its entries when the pref
|
||||
// "layout.css.float-logical-values.enabled" changes:
|
||||
static KTableValue kFloatKTable[];
|
||||
static const KTableValue kFloatEdgeKTable[];
|
||||
static const KTableValue kFontKTable[];
|
||||
static const KTableValue kFontKerningKTable[];
|
||||
static const KTableValue kFontSizeKTable[];
|
||||
static const KTableValue kFontSmoothingKTable[];
|
||||
static const KTableValue kFontStretchKTable[];
|
||||
static const KTableValue kFontStyleKTable[];
|
||||
static const KTableValue kFontSynthesisKTable[];
|
||||
static const KTableValue kFontVariantKTable[];
|
||||
static const KTableValue kFontVariantAlternatesKTable[];
|
||||
static const KTableValue kFontVariantAlternatesFuncsKTable[];
|
||||
static const KTableValue kFontVariantCapsKTable[];
|
||||
static const KTableValue kFontVariantEastAsianKTable[];
|
||||
static const KTableValue kFontVariantLigaturesKTable[];
|
||||
static const KTableValue kFontVariantNumericKTable[];
|
||||
static const KTableValue kFontVariantPositionKTable[];
|
||||
static const KTableValue kFontWeightKTable[];
|
||||
static const KTableValue kGridAutoFlowKTable[];
|
||||
static const KTableValue kGridTrackBreadthKTable[];
|
||||
static const KTableValue kHyphensKTable[];
|
||||
static const KTableValue kImageOrientationKTable[];
|
||||
static const KTableValue kImageOrientationFlipKTable[];
|
||||
static const KTableValue kIsolationKTable[];
|
||||
static const KTableValue kIMEModeKTable[];
|
||||
static const KTableValue kLineHeightKTable[];
|
||||
static const KTableValue kListStylePositionKTable[];
|
||||
static const KTableValue kListStyleKTable[];
|
||||
static const KTableValue kMaskTypeKTable[];
|
||||
static const KTableValue kMathVariantKTable[];
|
||||
static const KTableValue kMathDisplayKTable[];
|
||||
static const KTableValue kContainKTable[];
|
||||
static const KTableValue kContextOpacityKTable[];
|
||||
static const KTableValue kContextPatternKTable[];
|
||||
static const KTableValue kObjectFitKTable[];
|
||||
static const KTableValue kOrientKTable[];
|
||||
static const KTableValue kOutlineStyleKTable[];
|
||||
static const KTableValue kOutlineColorKTable[];
|
||||
static const KTableValue kOverflowKTable[];
|
||||
static const KTableValue kOverflowSubKTable[];
|
||||
static const KTableValue kOverflowClipBoxKTable[];
|
||||
static const KTableValue kPageBreakKTable[];
|
||||
static const KTableValue kPageBreakInsideKTable[];
|
||||
static const KTableValue kPageMarksKTable[];
|
||||
static const KTableValue kPageSizeKTable[];
|
||||
static const KTableValue kPitchKTable[];
|
||||
static const KTableValue kPointerEventsKTable[];
|
||||
static KTableEntry kFloatKTable[];
|
||||
static const KTableEntry kFloatEdgeKTable[];
|
||||
static const KTableEntry kFontKTable[];
|
||||
static const KTableEntry kFontKerningKTable[];
|
||||
static const KTableEntry kFontSizeKTable[];
|
||||
static const KTableEntry kFontSmoothingKTable[];
|
||||
static const KTableEntry kFontStretchKTable[];
|
||||
static const KTableEntry kFontStyleKTable[];
|
||||
static const KTableEntry kFontSynthesisKTable[];
|
||||
static const KTableEntry kFontVariantKTable[];
|
||||
static const KTableEntry kFontVariantAlternatesKTable[];
|
||||
static const KTableEntry kFontVariantAlternatesFuncsKTable[];
|
||||
static const KTableEntry kFontVariantCapsKTable[];
|
||||
static const KTableEntry kFontVariantEastAsianKTable[];
|
||||
static const KTableEntry kFontVariantLigaturesKTable[];
|
||||
static const KTableEntry kFontVariantNumericKTable[];
|
||||
static const KTableEntry kFontVariantPositionKTable[];
|
||||
static const KTableEntry kFontWeightKTable[];
|
||||
static const KTableEntry kGridAutoFlowKTable[];
|
||||
static const KTableEntry kGridTrackBreadthKTable[];
|
||||
static const KTableEntry kHyphensKTable[];
|
||||
static const KTableEntry kImageOrientationKTable[];
|
||||
static const KTableEntry kImageOrientationFlipKTable[];
|
||||
static const KTableEntry kIsolationKTable[];
|
||||
static const KTableEntry kIMEModeKTable[];
|
||||
static const KTableEntry kLineHeightKTable[];
|
||||
static const KTableEntry kListStylePositionKTable[];
|
||||
static const KTableEntry kListStyleKTable[];
|
||||
static const KTableEntry kMaskTypeKTable[];
|
||||
static const KTableEntry kMathVariantKTable[];
|
||||
static const KTableEntry kMathDisplayKTable[];
|
||||
static const KTableEntry kContainKTable[];
|
||||
static const KTableEntry kContextOpacityKTable[];
|
||||
static const KTableEntry kContextPatternKTable[];
|
||||
static const KTableEntry kObjectFitKTable[];
|
||||
static const KTableEntry kOrientKTable[];
|
||||
static const KTableEntry kOutlineStyleKTable[];
|
||||
static const KTableEntry kOutlineColorKTable[];
|
||||
static const KTableEntry kOverflowKTable[];
|
||||
static const KTableEntry kOverflowSubKTable[];
|
||||
static const KTableEntry kOverflowClipBoxKTable[];
|
||||
static const KTableEntry kPageBreakKTable[];
|
||||
static const KTableEntry kPageBreakInsideKTable[];
|
||||
static const KTableEntry kPageMarksKTable[];
|
||||
static const KTableEntry kPageSizeKTable[];
|
||||
static const KTableEntry kPitchKTable[];
|
||||
static const KTableEntry kPointerEventsKTable[];
|
||||
// Not const because we modify its entries when the pref
|
||||
// "layout.css.sticky.enabled" changes:
|
||||
static KTableValue kPositionKTable[];
|
||||
static const KTableValue kRadialGradientShapeKTable[];
|
||||
static const KTableValue kRadialGradientSizeKTable[];
|
||||
static const KTableValue kRadialGradientLegacySizeKTable[];
|
||||
static const KTableValue kResizeKTable[];
|
||||
static const KTableValue kRubyAlignKTable[];
|
||||
static const KTableValue kRubyPositionKTable[];
|
||||
static const KTableValue kScrollBehaviorKTable[];
|
||||
static const KTableValue kScrollSnapTypeKTable[];
|
||||
static const KTableValue kSpeakKTable[];
|
||||
static const KTableValue kSpeakHeaderKTable[];
|
||||
static const KTableValue kSpeakNumeralKTable[];
|
||||
static const KTableValue kSpeakPunctuationKTable[];
|
||||
static const KTableValue kSpeechRateKTable[];
|
||||
static const KTableValue kStackSizingKTable[];
|
||||
static const KTableValue kTableLayoutKTable[];
|
||||
static KTableEntry kPositionKTable[];
|
||||
static const KTableEntry kRadialGradientShapeKTable[];
|
||||
static const KTableEntry kRadialGradientSizeKTable[];
|
||||
static const KTableEntry kRadialGradientLegacySizeKTable[];
|
||||
static const KTableEntry kResizeKTable[];
|
||||
static const KTableEntry kRubyAlignKTable[];
|
||||
static const KTableEntry kRubyPositionKTable[];
|
||||
static const KTableEntry kScrollBehaviorKTable[];
|
||||
static const KTableEntry kScrollSnapTypeKTable[];
|
||||
static const KTableEntry kSpeakKTable[];
|
||||
static const KTableEntry kSpeakHeaderKTable[];
|
||||
static const KTableEntry kSpeakNumeralKTable[];
|
||||
static const KTableEntry kSpeakPunctuationKTable[];
|
||||
static const KTableEntry kSpeechRateKTable[];
|
||||
static const KTableEntry kStackSizingKTable[];
|
||||
static const KTableEntry kTableLayoutKTable[];
|
||||
// Not const because we modify its entries when the pref
|
||||
// "layout.css.text-align-true-value.enabled" changes:
|
||||
static KTableValue kTextAlignKTable[];
|
||||
static KTableValue kTextAlignLastKTable[];
|
||||
static const KTableValue kTextCombineUprightKTable[];
|
||||
static const KTableValue kTextDecorationLineKTable[];
|
||||
static const KTableValue kTextDecorationStyleKTable[];
|
||||
static const KTableValue kTextOrientationKTable[];
|
||||
static const KTableValue kTextOverflowKTable[];
|
||||
static const KTableValue kTextTransformKTable[];
|
||||
static const KTableValue kTouchActionKTable[];
|
||||
static const KTableValue kTopLayerKTable[];
|
||||
static const KTableValue kTransformBoxKTable[];
|
||||
static const KTableValue kTransitionTimingFunctionKTable[];
|
||||
static const KTableValue kUnicodeBidiKTable[];
|
||||
static const KTableValue kUserFocusKTable[];
|
||||
static const KTableValue kUserInputKTable[];
|
||||
static const KTableValue kUserModifyKTable[];
|
||||
static const KTableValue kUserSelectKTable[];
|
||||
static const KTableValue kVerticalAlignKTable[];
|
||||
static const KTableValue kVisibilityKTable[];
|
||||
static const KTableValue kVolumeKTable[];
|
||||
static const KTableValue kWhitespaceKTable[];
|
||||
static const KTableValue kWidthKTable[]; // also min-width, max-width
|
||||
static const KTableValue kWindowDraggingKTable[];
|
||||
static const KTableValue kWindowShadowKTable[];
|
||||
static const KTableValue kWordBreakKTable[];
|
||||
static const KTableValue kWordWrapKTable[];
|
||||
static const KTableValue kWritingModeKTable[];
|
||||
static KTableEntry kTextAlignKTable[];
|
||||
static KTableEntry kTextAlignLastKTable[];
|
||||
static const KTableEntry kTextCombineUprightKTable[];
|
||||
static const KTableEntry kTextDecorationLineKTable[];
|
||||
static const KTableEntry kTextDecorationStyleKTable[];
|
||||
static const KTableEntry kTextOrientationKTable[];
|
||||
static const KTableEntry kTextOverflowKTable[];
|
||||
static const KTableEntry kTextTransformKTable[];
|
||||
static const KTableEntry kTouchActionKTable[];
|
||||
static const KTableEntry kTopLayerKTable[];
|
||||
static const KTableEntry kTransformBoxKTable[];
|
||||
static const KTableEntry kTransitionTimingFunctionKTable[];
|
||||
static const KTableEntry kUnicodeBidiKTable[];
|
||||
static const KTableEntry kUserFocusKTable[];
|
||||
static const KTableEntry kUserInputKTable[];
|
||||
static const KTableEntry kUserModifyKTable[];
|
||||
static const KTableEntry kUserSelectKTable[];
|
||||
static const KTableEntry kVerticalAlignKTable[];
|
||||
static const KTableEntry kVisibilityKTable[];
|
||||
static const KTableEntry kVolumeKTable[];
|
||||
static const KTableEntry kWhitespaceKTable[];
|
||||
static const KTableEntry kWidthKTable[]; // also min-width, max-width
|
||||
static const KTableEntry kWindowDraggingKTable[];
|
||||
static const KTableEntry kWindowShadowKTable[];
|
||||
static const KTableEntry kWordBreakKTable[];
|
||||
static const KTableEntry kWordWrapKTable[];
|
||||
static const KTableEntry kWritingModeKTable[];
|
||||
};
|
||||
|
||||
inline nsCSSProps::EnabledState operator|(nsCSSProps::EnabledState a,
|
||||
|
|
|
@ -533,12 +533,15 @@ nsComputedDOMStyle::GetAdjustedValuesForBoxSizing()
|
|||
|
||||
nsMargin adjustment;
|
||||
switch(stylePos->mBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
case StyleBoxSizing::Border:
|
||||
adjustment += mInnerFrame->GetUsedBorder();
|
||||
// fall through
|
||||
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
case StyleBoxSizing::Padding:
|
||||
adjustment += mInnerFrame->GetUsedPadding();
|
||||
// fall through
|
||||
case StyleBoxSizing::Content:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return adjustment;
|
||||
|
@ -1791,7 +1794,7 @@ nsComputedDOMStyle::DoGetFontVariantPosition()
|
|||
CSSValue*
|
||||
nsComputedDOMStyle::GetBackgroundList(uint8_t nsStyleBackground::Layer::* aMember,
|
||||
uint32_t nsStyleBackground::* aCount,
|
||||
const KTableValue aTable[])
|
||||
const KTableEntry aTable[])
|
||||
{
|
||||
const nsStyleBackground* bg = StyleBackground();
|
||||
|
||||
|
@ -3310,7 +3313,7 @@ nsComputedDOMStyle::DoGetVerticalAlign()
|
|||
|
||||
CSSValue*
|
||||
nsComputedDOMStyle::CreateTextAlignValue(uint8_t aAlign, bool aAlignTrue,
|
||||
const KTableValue aTable[])
|
||||
const KTableEntry aTable[])
|
||||
{
|
||||
nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(nsCSSProps::ValueToKeywordEnum(aAlign, aTable));
|
||||
|
@ -3779,7 +3782,7 @@ nsComputedDOMStyle::DoGetBoxSizing()
|
|||
{
|
||||
nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
|
||||
val->SetIdent(
|
||||
nsCSSProps::ValueToKeywordEnum(StylePosition()->mBoxSizing,
|
||||
nsCSSProps::ValueToKeywordEnum(uint8_t(StylePosition()->mBoxSizing),
|
||||
nsCSSProps::kBoxSizingKTable));
|
||||
return val;
|
||||
}
|
||||
|
@ -4866,7 +4869,7 @@ nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
|
|||
const nsStyleCoord& aCoord,
|
||||
bool aClampNegativeCalc,
|
||||
PercentageBaseGetter aPercentageBaseGetter,
|
||||
const KTableValue aTable[],
|
||||
const KTableEntry aTable[],
|
||||
nscoord aMinAppUnits,
|
||||
nscoord aMaxAppUnits)
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration
|
|||
, public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
typedef nsCSSProps::KTableValue KTableValue;
|
||||
typedef nsCSSProps::KTableEntry KTableEntry;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsComputedDOMStyle,
|
||||
|
@ -127,7 +127,7 @@ private:
|
|||
// Helper method for DoGetTextAlign[Last].
|
||||
mozilla::dom::CSSValue* CreateTextAlignValue(uint8_t aAlign,
|
||||
bool aAlignTrue,
|
||||
const KTableValue aTable[]);
|
||||
const KTableEntry aTable[]);
|
||||
// This indicates error by leaving mStyleContext null.
|
||||
void UpdateCurrentStyleSources(bool aNeedsLayoutFlush);
|
||||
void ClearCurrentStyleSources();
|
||||
|
@ -190,7 +190,7 @@ private:
|
|||
|
||||
mozilla::dom::CSSValue* GetBackgroundList(uint8_t nsStyleBackground::Layer::* aMember,
|
||||
uint32_t nsStyleBackground::* aCount,
|
||||
const KTableValue aTable[]);
|
||||
const KTableEntry aTable[]);
|
||||
|
||||
void GetCSSGradientString(const nsStyleGradient* aGradient,
|
||||
nsAString& aString);
|
||||
|
@ -568,7 +568,7 @@ private:
|
|||
const nsStyleCoord& aCoord,
|
||||
bool aClampNegativeCalc,
|
||||
PercentageBaseGetter aPercentageBaseGetter = nullptr,
|
||||
const KTableValue aTable[] = nullptr,
|
||||
const KTableEntry aTable[] = nullptr,
|
||||
nscoord aMinAppUnits = nscoord_MIN,
|
||||
nscoord aMaxAppUnits = nscoord_MAX);
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче