зеркало из https://github.com/mozilla/gecko-dev.git
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
This commit is contained in:
Коммит
b5f4776008
|
@ -15,7 +15,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
function AlertsService() { }
|
||||
|
||||
AlertsService.prototype = {
|
||||
classID: Components.ID("{5dce03b2-8faa-4b6e-9242-6ddb0411750c}"),
|
||||
classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]),
|
||||
|
||||
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName) {
|
||||
|
|
|
@ -7,8 +7,8 @@ contract @mozilla.org/b2g-camera-content;1 {eff4231b-abce-4f7f-a40a-d646e8fde3ce
|
|||
category JavaScript-navigator-property mozCamera @mozilla.org/b2g-camera-content;1
|
||||
|
||||
# AlertsService.js
|
||||
component {5dce03b2-8faa-4b6e-9242-6ddb0411750c} AlertsService.js
|
||||
contract @mozilla.org/alerts-service;1 {5dce03b2-8faa-4b6e-9242-6ddb0411750c}
|
||||
component {fe33c107-82a4-41d6-8c64-5353267e04c9} AlertsService.js
|
||||
contract @mozilla.org/system-alerts-service;1 {fe33c107-82a4-41d6-8c64-5353267e04c9}
|
||||
|
||||
# ContentPermissionPrompt.js
|
||||
component {8c719f03-afe0-4aac-91ff-6c215895d467} ContentPermissionPrompt.js
|
||||
|
|
|
@ -18,9 +18,7 @@ Browser context menu tests.
|
|||
|
||||
/** Test for Login Manager: multiple login autocomplete. **/
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
SpecialPowers.wrap(Components).utils.import("resource://gre/modules/InlineSpellChecker.jsm", window);
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
@ -729,7 +727,7 @@ function runTest(testNum) {
|
|||
|
||||
case 24:
|
||||
// Context menu for selected text
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
if (SpecialPowers.Services.appinfo.OS == "Darwin") {
|
||||
// This test is only enabled on Mac due to bug 736399.
|
||||
checkContextMenu(["context-copy", true,
|
||||
"context-selectall", true,
|
||||
|
@ -745,7 +743,7 @@ function runTest(testNum) {
|
|||
|
||||
case 25:
|
||||
// Context menu for selected text which matches valid URL pattern
|
||||
if (Services.appinfo.OS == "Darwin") {
|
||||
if (SpecialPowers.Services.appinfo.OS == "Darwin") {
|
||||
// This test is only enabled on Mac due to bug 736399.
|
||||
checkContextMenu(["context-openlinkincurrent", true,
|
||||
"context-openlinkintab", true,
|
||||
|
@ -790,8 +788,7 @@ var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
|
|||
inputspell, pagemenu, dom_full_screen, plainTextItems, audio_in_video;
|
||||
|
||||
function startTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
chromeWin = subwindow
|
||||
chromeWin = SpecialPowers.wrap(subwindow)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
|
|
|
@ -26,6 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=462856
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const Cc = SpecialPowers.wrap(Components).classes;
|
||||
|
||||
var numFinished = 0;
|
||||
|
||||
|
@ -34,18 +35,17 @@ window.addEventListener("message", function(event) {
|
|||
|
||||
if (++numFinished == 3) {
|
||||
// Clean up after ourself
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var pm = Components.classes["@mozilla.org/permissionmanager;1"].
|
||||
var pm = Cc["@mozilla.org/permissionmanager;1"].
|
||||
getService(Components.interfaces.nsIPermissionManager);
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
var ioService = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
var uri1 = ioService.newURI(frames.testFrame.location, null, null);
|
||||
var uri2 = ioService.newURI(frames.testFrame3.location, null, null);
|
||||
|
||||
var principal1 = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||
var principal1 = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Components.interfaces.nsIScriptSecurityManager)
|
||||
.getNoAppCodebasePrincipal(uri1);
|
||||
var principal2 = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||
var principal2 = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Components.interfaces.nsIScriptSecurityManager)
|
||||
.getNoAppCodebasePrincipal(uri2);
|
||||
|
||||
|
@ -108,8 +108,7 @@ function loaded() {
|
|||
// Click the notification bar's "Allow" button. This should kick
|
||||
// off updates, which will eventually lead to getting messages from
|
||||
// the children.
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
|
||||
var wm = SpecialPowers.wrap(Components).classes["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Components.interfaces.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
var notificationBox = win.gBrowser.getNotificationBox();
|
||||
|
@ -117,7 +116,7 @@ function loaded() {
|
|||
var notification = notificationBox.getNotificationWithValue("offline-app-requested-mochi.test");
|
||||
notification.childNodes[0].click();
|
||||
|
||||
notification = notificationBox.getNotificationWithValue("offline-app-requested-example.com");
|
||||
notification = SpecialPowers.wrap(notificationBox).getNotificationWithValue("offline-app-requested-example.com");
|
||||
notification.childNodes[0].click();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,15 +32,13 @@ SimpleTest.waitForExplicitFinish();
|
|||
|
||||
function finishTest() {
|
||||
// Clean up after ourselves.
|
||||
netscape.security.PrivilegeManager
|
||||
.enablePrivilege("UniversalXPConnect");
|
||||
var pm = Components.classes["@mozilla.org/permissionmanager;1"].
|
||||
var Cc = SpecialPowers.wrap(Components).classes;
|
||||
var pm = Cc["@mozilla.org/permissionmanager;1"].
|
||||
getService(Components.interfaces.nsIPermissionManager);
|
||||
|
||||
var uri = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService)
|
||||
var uri = Cc["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService)
|
||||
.newURI(window.frames[0].location, null, null);
|
||||
var principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
|
||||
var principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Components.interfaces.nsIScriptSecurityManager)
|
||||
.getNoAppCodebasePrincipal(uri);
|
||||
|
||||
|
@ -70,8 +68,6 @@ function handleMessageEvents(event) {
|
|||
// successfully reloaded), or the string "error" appears
|
||||
// in the iframe, as in the case of bug 501422.
|
||||
intervalID = setInterval(function() {
|
||||
netscape.security.PrivilegeManager
|
||||
.enablePrivilege("UniversalXPConnect");
|
||||
// Sometimes document.body may not exist, and trying to access
|
||||
// it will throw an exception, so handle this case.
|
||||
try {
|
||||
|
@ -103,8 +99,7 @@ function loaded() {
|
|||
// Click the notification bar's "Allow" button. This should kick
|
||||
// off updates, which will eventually lead to getting messages from
|
||||
// the iframe.
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
|
||||
var wm = SpecialPowers.wrap(Components).classes["@mozilla.org/appshell/window-mediator;1"].
|
||||
getService(Components.interfaces.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("navigator:browser");
|
||||
var notificationBox = win.gBrowser.getNotificationBox();
|
||||
|
|
|
@ -20,8 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=589543
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
addLoadEvent(function() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var doc = $("testFrame").contentDocument;
|
||||
var doc = SpecialPowers.wrap($("testFrame").contentDocument);
|
||||
var daddy = doc.getElementById("feedSubscribeLine");
|
||||
var popup = doc.getAnonymousElementByAttribute(daddy, "anonid", "handlersMenuPopup");
|
||||
isnot(popup, null, "Feed preview should have a handlers popup");
|
||||
|
|
|
@ -18,11 +18,13 @@ let webappsUI = {
|
|||
init: function webappsUI_init() {
|
||||
Services.obs.addObserver(this, "webapps-ask-install", false);
|
||||
Services.obs.addObserver(this, "webapps-launch", false);
|
||||
Services.obs.addObserver(this, "webapps-uninstall", false);
|
||||
},
|
||||
|
||||
uninit: function webappsUI_uninit() {
|
||||
Services.obs.removeObserver(this, "webapps-ask-install");
|
||||
Services.obs.removeObserver(this, "webapps-launch");
|
||||
Services.obs.removeObserver(this, "webapps-uninstall");
|
||||
},
|
||||
|
||||
observe: function webappsUI_observe(aSubject, aTopic, aData) {
|
||||
|
@ -37,6 +39,9 @@ let webappsUI = {
|
|||
case "webapps-launch":
|
||||
WebappOSUtils.launch(data);
|
||||
break;
|
||||
case "webapps-uninstall":
|
||||
WebappOSUtils.uninstall(data);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "prenv.h"
|
||||
|
||||
#include "mozIApplication.h"
|
||||
#include "nsIDOMHTMLIFrameElement.h"
|
||||
#include "nsIDOMHTMLFrameElement.h"
|
||||
#include "nsIDOMMozBrowserFrame.h"
|
||||
|
@ -31,6 +32,7 @@
|
|||
#include "nsIDocShellTreeNode.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIDocShellLoadInfo.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
#include "nsIBaseWindow.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
@ -1973,9 +1975,8 @@ nsFrameLoader::TryRemoteBrowser()
|
|||
return false;
|
||||
}
|
||||
|
||||
PRUint32 appId = 0;
|
||||
bool isBrowserElement = false;
|
||||
|
||||
nsCOMPtr<mozIApplication> app;
|
||||
if (OwnerIsBrowserFrame()) {
|
||||
isBrowserElement = true;
|
||||
|
||||
|
@ -1989,24 +1990,21 @@ nsFrameLoader::TryRemoteBrowser()
|
|||
return false;
|
||||
}
|
||||
|
||||
appsService->GetAppLocalIdByManifestURL(manifest, &appId);
|
||||
|
||||
// If the frame is actually an app, we should not mark it as a browser.
|
||||
if (appId != nsIScriptSecurityManager::NO_APP_ID) {
|
||||
nsCOMPtr<mozIDOMApplication> domApp;
|
||||
appsService->GetAppByManifestURL(manifest, getter_AddRefs(domApp));
|
||||
// If the frame is actually an app, we should not mark it as a
|
||||
// browser. This is to identify the data store: since <app>s
|
||||
// and <browser>s-within-<app>s have different stores, we want
|
||||
// to ensure the <app> uses its store, not the one for its
|
||||
// <browser>s.
|
||||
app = do_QueryInterface(domApp);
|
||||
if (app) {
|
||||
isBrowserElement = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If our owner has no app manifest URL, then this is equivalent to
|
||||
// ContentParent::GetNewOrUsed().
|
||||
nsAutoString appManifest;
|
||||
GetOwnerAppManifestURL(appManifest);
|
||||
ContentParent* parent = ContentParent::GetForApp(appManifest);
|
||||
|
||||
NS_ASSERTION(parent->IsAlive(), "Process parent should be alive; something is very wrong!");
|
||||
mRemoteBrowser = parent->CreateTab(chromeFlags, isBrowserElement, appId);
|
||||
if (mRemoteBrowser) {
|
||||
if ((mRemoteBrowser = ContentParent::CreateBrowser(app, isBrowserElement))) {
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mOwnerContent);
|
||||
mRemoteBrowser->SetOwnerElement(element);
|
||||
|
||||
|
@ -2020,7 +2018,7 @@ nsFrameLoader::TryRemoteBrowser()
|
|||
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
|
||||
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
|
||||
|
||||
mChildHost = parent;
|
||||
mChildHost = static_cast<ContentParent*>(mRemoteBrowser->Manager());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -32,15 +32,14 @@ function afterLoad() {
|
|||
iframeDoc.getElementById("password").value = "123456";
|
||||
iframeDoc.getElementById("hidden").value = "gecko";
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var file = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
var file = SpecialPowers.wrap(Components).classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties)
|
||||
.get("TmpD", Components.interfaces.nsILocalFile);
|
||||
file.append("345339_test.file");
|
||||
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
|
||||
filePath = file.path;
|
||||
|
||||
iframeDoc.getElementById("file").value = filePath;
|
||||
SpecialPowers.wrap(iframeDoc).getElementById("file").value = filePath;
|
||||
|
||||
/* Reload the page */
|
||||
$("testframe").setAttribute("onload", "afterReload()");
|
||||
|
@ -62,8 +61,7 @@ function afterReload() {
|
|||
"password field value forgotten");
|
||||
is(iframeDoc.getElementById("hidden").value, "gecko",
|
||||
"hidden field value preserved");
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(iframeDoc.getElementById("file").value, filePath,
|
||||
is(SpecialPowers.wrap(iframeDoc).getElementById("file").value, filePath,
|
||||
"file field value preserved");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
|
|
@ -31,9 +31,10 @@ function eventHandler(evt) {
|
|||
|
||||
function test(trusted, type, removeAddedListener, removeSetListener, allowUntrusted) {
|
||||
if (trusted) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var x1 = SpecialPowers.wrap(new XMLHttpRequest());
|
||||
} else {
|
||||
x1 = new XMLHttpRequest();
|
||||
}
|
||||
var x1 = new XMLHttpRequest();
|
||||
|
||||
var handlerCount = 0;
|
||||
if (trusted || allowUntrusted || allowUntrusted == undefined) {
|
||||
|
|
|
@ -22,14 +22,13 @@
|
|||
request.send(null);
|
||||
|
||||
// Try reading headers in privileged context
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(request.getResponseHeader("Set-Cookie"), "test", "Reading Set-Cookie response header in privileged context");
|
||||
is(request.getResponseHeader("Set-Cookie2"), "test2", "Reading Set-Cookie2 response header in privileged context");
|
||||
is(request.getResponseHeader("X-Dummy"), "test", "Reading X-Dummy response header in privileged context");
|
||||
is(SpecialPowers.wrap(request).getResponseHeader("Set-Cookie"), "test", "Reading Set-Cookie response header in privileged context");
|
||||
is(SpecialPowers.wrap(request).getResponseHeader("Set-Cookie2"), "test2", "Reading Set-Cookie2 response header in privileged context");
|
||||
is(SpecialPowers.wrap(request).getResponseHeader("X-Dummy"), "test", "Reading X-Dummy response header in privileged context");
|
||||
|
||||
ok(/\bSet-Cookie:/i.test(request.getAllResponseHeaders()), "Looking for Set-Cookie in all response headers in privileged context");
|
||||
ok(/\bSet-Cookie2:/i.test(request.getAllResponseHeaders()), "Looking for Set-Cookie2 in all response headers in privileged context");
|
||||
ok(/\bX-Dummy:/i.test(request.getAllResponseHeaders()), "Looking for X-Dummy in all response headers in privileged context");
|
||||
ok(/\bSet-Cookie:/i.test(SpecialPowers.wrap(request).getAllResponseHeaders()), "Looking for Set-Cookie in all response headers in privileged context");
|
||||
ok(/\bSet-Cookie2:/i.test(SpecialPowers.wrap(request).getAllResponseHeaders()), "Looking for Set-Cookie2 in all response headers in privileged context");
|
||||
ok(/\bX-Dummy:/i.test(SpecialPowers.wrap(request).getAllResponseHeaders()), "Looking for X-Dummy in all response headers in privileged context");
|
||||
|
||||
// Try reading headers in unprivileged context
|
||||
setTimeout(function() {
|
||||
|
|
|
@ -19,10 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=422537
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 422537 **/
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var isupports_string = Components.classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
var isupports_string = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
isupports_string.data = "foo";
|
||||
|
||||
const url = "http://mochi.test:8888";
|
||||
|
@ -35,12 +34,15 @@ var body = [
|
|||
for each (var i in body) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url, true);
|
||||
xhr.send(i);
|
||||
var chan = SpecialPowers.unwrap(SpecialPowers.wrap(xhr).channel);
|
||||
if (!(chan instanceof Components.interfaces.nsIUploadChannel))
|
||||
if (i == isupports_string)
|
||||
SpecialPowers.wrap(xhr).send(i);
|
||||
else
|
||||
xhr.send(i);
|
||||
var chan = SpecialPowers.wrap(xhr).channel;
|
||||
if (!SpecialPowers.call_Instanceof(chan, Components.interfaces.nsIUploadChannel))
|
||||
throw "Must be an upload channel";
|
||||
var stream = chan.uploadStream;
|
||||
if (!stream || !(stream instanceof Components.interfaces.nsISeekableStream))
|
||||
if (!stream || !SpecialPowers.call_Instanceof(stream, Components.interfaces.nsISeekableStream))
|
||||
throw "Stream must be seekable";
|
||||
// the following is a no-op, but should not throw an exception
|
||||
stream.seek(Components.interfaces.nsISeekableStream.NS_SEEK_CUR, 0);
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!doctype HTML>
|
||||
<html>
|
||||
<body>
|
||||
<canvas id="c" width="10000" height="10000"></canvas>
|
||||
<script>
|
||||
var ctx = document.getElementById("c").getContext("2d");
|
||||
ctx.fillText("Hello world!", 50, 50);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -12,3 +12,4 @@ load 746813-1.html
|
|||
#load 745818-large-source.html
|
||||
load 743499-negative-size.html
|
||||
load 767337-1.html
|
||||
load 780392-1.html
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
<script>
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const Cc = SpecialPowers.wrap(Components).classes;
|
||||
const Cr = SpecialPowers.wrap(Components).results;
|
||||
|
||||
function IsD2DEnabled() {
|
||||
var enabled = false;
|
||||
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
enabled = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled;
|
||||
enabled = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).D2DEnabled;
|
||||
} catch(e) {}
|
||||
|
||||
return enabled;
|
||||
|
@ -26,10 +27,9 @@ function IsMacOSX10_5orOlder() {
|
|||
var is105orOlder = false;
|
||||
|
||||
if (navigator.platform.indexOf("Mac") == 0) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var version = Components.classes["@mozilla.org/system-info;1"]
|
||||
.getService(Components.interfaces.nsIPropertyBag2)
|
||||
.getProperty("version");
|
||||
var version = Cc["@mozilla.org/system-info;1"]
|
||||
.getService(Components.interfaces.nsIPropertyBag2)
|
||||
.getProperty("version");
|
||||
// the next line is correct: Mac OS 10.6 corresponds to Darwin version 10 !
|
||||
// Mac OS 10.5 would be Darwin version 9. the |version| string we've got here
|
||||
// is the Darwin version.
|
||||
|
@ -43,8 +43,7 @@ function IsAzureEnabled() {
|
|||
var enabled = false;
|
||||
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
|
||||
var backend = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
|
||||
enabled = (backend != "none");
|
||||
} catch (e) { }
|
||||
|
||||
|
@ -55,8 +54,7 @@ function IsAzureSkia() {
|
|||
var enabled = false;
|
||||
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
|
||||
var backend = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
|
||||
enabled = (backend == "skia");
|
||||
} catch (e) { }
|
||||
|
||||
|
@ -67,8 +65,7 @@ function IsAzureCairo() {
|
|||
var enabled = false;
|
||||
|
||||
try {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var backend = Components.classes["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
|
||||
var backend = Cc["@mozilla.org/gfx/info;1"].getService(Components.interfaces.nsIGfxInfo).getInfo().AzureCanvasBackend;
|
||||
enabled = (backend == "cairo");
|
||||
} catch (e) { }
|
||||
|
||||
|
@ -126,7 +123,8 @@ ok(ctx.canvas === canvas, "ctx.canvas === canvas");
|
|||
function isPixel(ctx, x,y, r,g,b,a, d) {
|
||||
var pos = x + "," + y;
|
||||
var colour = r + "," + g + "," + b + "," + a;
|
||||
var pixel = ctx.getImageData(x, y, 1, 1);
|
||||
var pixel = SpecialPowers.unwrap(SpecialPowers.wrap(ctx)
|
||||
.getImageData(x, y, 1, 1));
|
||||
var pr = pixel.data[0],
|
||||
pg = pixel.data[1],
|
||||
pb = pixel.data[2],
|
||||
|
@ -19804,9 +19802,8 @@ function test_bug397524() {
|
|||
<script>
|
||||
function test_bug405982() {
|
||||
|
||||
var canvas = document.getElementById('c614');
|
||||
var canvas = SpecialPowers.wrap(document.getElementById('c614'));
|
||||
var ctx = canvas.getContext('2d');
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var _threw = false;
|
||||
try {
|
||||
|
@ -21123,7 +21120,6 @@ img.onload = wrapFunction(function ()
|
|||
ctx667.drawImage(img, 0, 25);
|
||||
// (The alpha values do not really survive float->int conversion, so just
|
||||
// do approximate comparisons)
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
isPixel(ctx667, 12,40, 1,3,254,255, 0);
|
||||
isPixel(ctx667, 37,40, 8,252,248,191, 2);
|
||||
isPixel(ctx667, 62,40, 6,10,250,127, 4);
|
||||
|
@ -21250,7 +21246,6 @@ deferTest();
|
|||
img.onload = wrapFunction(function ()
|
||||
{
|
||||
ctx672.drawImage(img, 0, 0);
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
isPixel(ctx672, 12,20, 255,255,0,255, 0);
|
||||
isPixel(ctx672, 50,20, 0,255,255,255, 0);
|
||||
isPixel(ctx672, 87,20, 0,0,255,255, 0);
|
||||
|
|
|
@ -24,10 +24,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=143220
|
|||
var leafName;
|
||||
var fullPath;
|
||||
|
||||
|
||||
function initVals() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var dirSvc = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var file = dirSvc.get("XpcomLib", Components.interfaces.nsILocalFile);
|
||||
isnot(file, null, "Must have file here");
|
||||
|
||||
|
@ -36,15 +37,13 @@ function initVals() {
|
|||
}
|
||||
|
||||
function initControl1() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
$("i1").value = fullPath;
|
||||
is($("i1").value, fullPath, "Should have set full path 1");
|
||||
SpecialPowers.wrap($("i1")).value = fullPath;
|
||||
is(SpecialPowers.wrap($("i1")).value, fullPath, "Should have set full path 1");
|
||||
}
|
||||
|
||||
function initControl2() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
$("i2").value = fullPath;
|
||||
is($("i2").value, fullPath, "Should have set full path 2");
|
||||
SpecialPowers.wrap($("i2")).value = fullPath;
|
||||
is(SpecialPowers.wrap($("i2")).value, fullPath, "Should have set full path 2");
|
||||
}
|
||||
|
||||
initVals();
|
||||
|
|
|
@ -32,26 +32,25 @@ var input2Files =
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function setFileInputs () {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
f = createFileWithData(input1File.name, input1File.body);
|
||||
singleFileInput.mozSetFileNameArray([f.path], 1);
|
||||
SpecialPowers.wrap(singleFileInput).mozSetFileNameArray([f.path], 1);
|
||||
|
||||
var input2FileNames = [];
|
||||
for each (file in input2Files) {
|
||||
f = createFileWithData(file.name, file.body);
|
||||
input2FileNames.push(f.path);
|
||||
}
|
||||
multiFileInput.mozSetFileNameArray(input2FileNames, input2FileNames.length);
|
||||
SpecialPowers.wrap(multiFileInput).mozSetFileNameArray(input2FileNames, input2FileNames.length);
|
||||
}
|
||||
|
||||
function createFileWithData(fileName, fileData) {
|
||||
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var dirSvc = SpecialPowers.wrap(Components).classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties);
|
||||
var testFile = dirSvc.get("ProfD", Components.interfaces.nsIFile);
|
||||
testFile.append(fileName);
|
||||
var outStream = Components.
|
||||
classes["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
var outStream = SpecialPowers.wrap(Components).
|
||||
classes["@mozilla.org/network/file-output-stream;1"].
|
||||
createInstance(Components.interfaces.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||
0666, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
|
|
|
@ -92,7 +92,9 @@ public:
|
|||
|
||||
// imgIDecoderObserver (override nsStubImageDecoderObserver)
|
||||
NS_IMETHOD OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage);
|
||||
NS_IMETHOD OnStopContainer(imgIRequest* aRequest, imgIContainer* aImage);
|
||||
NS_IMETHOD OnStopDecode(imgIRequest *aRequest, nsresult aStatus, const PRUnichar *aStatusArg);
|
||||
NS_IMETHOD OnDiscard(imgIRequest *aRequest);
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||
|
@ -519,6 +521,20 @@ ImageDocument::OnStartContainer(imgIRequest* aRequest, imgIContainer* aImage)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageDocument::OnStopContainer(imgIRequest* aRequest, imgIContainer* aImage)
|
||||
{
|
||||
if (mImageContent) {
|
||||
// Update the background-color of the image only after the
|
||||
// image has been decoded to prevent flashes of just the
|
||||
// background-color.
|
||||
mImageContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
NS_LITERAL_STRING("decoded"), true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageDocument::OnStopDecode(imgIRequest *aRequest,
|
||||
nsresult aStatus,
|
||||
|
@ -526,12 +542,6 @@ ImageDocument::OnStopDecode(imgIRequest *aRequest,
|
|||
{
|
||||
UpdateTitleAndCharset();
|
||||
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mImageContent);
|
||||
if (imageLoader) {
|
||||
mObservingImageLoader = false;
|
||||
imageLoader->RemoveObserver(this);
|
||||
}
|
||||
|
||||
// mImageContent can be null if the document is already destroyed
|
||||
if (NS_FAILED(aStatus) && mStringBundle && mImageContent) {
|
||||
nsCAutoString src;
|
||||
|
@ -549,6 +559,18 @@ ImageDocument::OnStopDecode(imgIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageDocument::OnDiscard(imgIRequest *aRequest)
|
||||
{
|
||||
// mImageContent can be null if the document is already destroyed
|
||||
if (mImageContent) {
|
||||
// Remove any decoded-related styling when the image is unloaded.
|
||||
mImageContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_class,
|
||||
true);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageDocument::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
|
|
|
@ -55,9 +55,7 @@ function checkURI(uri, name, type) {
|
|||
|
||||
function checkFrame(num) {
|
||||
// Just snarf our data
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var outer = window.frames[num]
|
||||
var outer = SpecialPowers.wrap(window.frames[num]);
|
||||
name = outer.name;
|
||||
|
||||
is(outer.document.baseURI,
|
||||
|
|
|
@ -24,21 +24,19 @@ var frame = document.getElementById("i");
|
|||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(function() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
var viewer =
|
||||
frame.contentWindow
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShell)
|
||||
.contentViewer
|
||||
.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
|
||||
SpecialPowers.wrap(frame.contentWindow
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor))
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShell)
|
||||
.contentViewer
|
||||
.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
|
||||
|
||||
viewer.fullZoom = 1.5;
|
||||
|
||||
setTimeout(function() {
|
||||
synthesizeMouse(frame, 30, 30, {});
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
is(viewer.fullZoom, 1.5, "Zoom in the image frame should not have been reset");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
|
|
@ -159,10 +159,9 @@ function fileUriToSrc(path, mustExist) {
|
|||
if (navigator.appVersion.indexOf("Android") != -1)
|
||||
return path;
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
const Cc = SpecialPowers.wrap(Components).classes;
|
||||
const Cr = SpecialPowers.wrap(Components).results;
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
|
||||
getService(Ci.nsIProperties);
|
||||
var f = dirSvc.get("CurWorkD", Ci.nsILocalFile);
|
||||
|
@ -444,8 +443,7 @@ function MediaTestManager() {
|
|||
// Force a GC after every completed testcase. This ensures that any decoders
|
||||
// with live threads waiting for the GC are killed promptly, to free up the
|
||||
// thread stacks' address space.
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
Components.utils.forceGC();
|
||||
SpecialPowers.forceGC();
|
||||
|
||||
while (this.testNum < this.tests.length && this.tokens.length < PARALLEL_TESTS) {
|
||||
var test = this.tests[this.testNum];
|
||||
|
@ -497,15 +495,14 @@ function mediaTestCleanup() {
|
|||
A[i].parentNode.removeChild(A[i]);
|
||||
A[i] = null;
|
||||
}
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
Components.utils.forceGC();
|
||||
SpecialPowers.forceGC();
|
||||
}
|
||||
|
||||
(function() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
// Ensure that preload preferences are comsistent
|
||||
var prefService = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefService);
|
||||
var prefService = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefService);
|
||||
var branch = prefService.getBranch("media.");
|
||||
var oldDefault = 2;
|
||||
var oldAuto = 3;
|
||||
|
@ -522,7 +519,6 @@ function mediaTestCleanup() {
|
|||
branch.setBoolPref("opus.enabled", true);
|
||||
|
||||
window.addEventListener("unload", function() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
branch.setIntPref("preload.default", oldDefault);
|
||||
branch.setIntPref("preload.auto", oldAuto);
|
||||
if (oldOpus !== undefined)
|
||||
|
|
|
@ -6055,17 +6055,19 @@ nsDocShell::OnStateChange(nsIWebProgress * aProgress, nsIRequest * aRequest,
|
|||
channel->GetURI(getter_AddRefs(uri));
|
||||
nsCAutoString aURI;
|
||||
uri->GetAsciiSpec(aURI);
|
||||
if (this == aProgress){
|
||||
|
||||
nsCOMPtr<nsIWyciwygChannel> wcwgChannel(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsIWebProgress> webProgress =
|
||||
do_QueryInterface(GetAsSupports(this));
|
||||
|
||||
// We don't update navigation timing for wyciwyg channels
|
||||
if (this == aProgress && !wcwgChannel){
|
||||
rv = MaybeInitTiming();
|
||||
if (mTiming) {
|
||||
mTiming->NotifyFetchStart(uri, ConvertLoadTypeToNavigationType(mLoadType));
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWyciwygChannel> wcwgChannel(do_QueryInterface(aRequest));
|
||||
nsCOMPtr<nsIWebProgress> webProgress =
|
||||
do_QueryInterface(GetAsSupports(this));
|
||||
|
||||
// Was the wyciwyg document loaded on this docshell?
|
||||
if (wcwgChannel && !mLSHE && (mItemType == typeContent) && aProgress == webProgress.get()) {
|
||||
bool equalUri = true;
|
||||
|
|
|
@ -95,6 +95,8 @@ MOCHITEST_FILES = \
|
|||
test_bug691547.html \
|
||||
bug691547_frame.html \
|
||||
test_bug694612.html \
|
||||
test_bug703855.html \
|
||||
file_bug703855.html \
|
||||
test_bug713825.html \
|
||||
test_bug728939.html \
|
||||
file_bug728939.html \
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- Just need an empty file here, as long as it's served over HTTP -->
|
|
@ -98,17 +98,18 @@ function isInaccessible(wnd, message) {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function xpcEnumerateContentWindows(callback) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Ci.nsIWindowWatcher);
|
||||
var ww = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
||||
.getService(Ci.nsIWindowWatcher);
|
||||
var enumerator = ww.getWindowEnumerator();
|
||||
|
||||
var contentWindows = [];
|
||||
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var win = enumerator.getNext();
|
||||
if (typeof ChromeWindow != "undefined" && win instanceof ChromeWindow) {
|
||||
if (typeof ChromeWindow != "undefined" && SpecialPowers.call_Instanceof(win, ChromeWindow)) {
|
||||
var docshellTreeNode = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeNode);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
function testDone() {
|
||||
document.body.removeChild(document.body.firstChild);
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var isOK = false;
|
||||
try {
|
||||
isOK = history.previous != location;
|
||||
|
|
|
@ -60,7 +60,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
|
|||
}
|
||||
|
||||
function beginTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
gTest.window.document.body.focus();
|
||||
|
||||
// WARNING: If the following test fails, give the setTimeout() in the onload()
|
||||
|
@ -74,7 +73,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
|
|||
}
|
||||
|
||||
function goBack() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
gTest.window.history.back();
|
||||
setTimeout(function() {
|
||||
SimpleTest.waitForFocus(checkStillEditable, gTest.window);
|
||||
|
@ -82,7 +80,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=386782
|
|||
}
|
||||
|
||||
function checkStillEditable() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
// Check that the contents are correct.
|
||||
is(gTest.window.document.body.innerHTML, gTest.expectedBodyAfterEdit, "Edited contents still correct?");
|
||||
|
|
|
@ -186,9 +186,9 @@ var gNextTest = 0;
|
|||
|
||||
function runNextTest()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
var prefs = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
|
||||
if (gNextTest < gTests.length) {
|
||||
gCurrentTest = gTests[gNextTest++];
|
||||
|
@ -214,9 +214,9 @@ function runNextTest()
|
|||
|
||||
function finishTest()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
var prefs = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
prefs.setBoolPref("network.jar.open-unsafe-types", false);
|
||||
|
||||
if (gNumPokes == 0) {
|
||||
|
@ -228,9 +228,9 @@ function finishTest()
|
|||
|
||||
function startTests()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||
getService(Components.interfaces.nsIPrefBranch);
|
||||
var prefs = SpecialPowers.wrap(Components)
|
||||
.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
gPrefValue = prefs.getBoolPref("network.jar.open-unsafe-types");
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,6 @@ function onChildLoad(e) {
|
|||
}
|
||||
|
||||
function runTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var popup = window.open("file_bug509055.html", "popup 0",
|
||||
"height=200,width=200,location=yes," +
|
||||
"menubar=yes,status=yes,toolbar=yes,dependent=yes");
|
||||
|
@ -72,9 +70,10 @@ function runTest() {
|
|||
dump('Got second hashchange. Spinning event loop.\n');
|
||||
yield;
|
||||
|
||||
var sh = popup.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.sessionHistory;
|
||||
var sh = SpecialPowers.wrap(popup)
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.sessionHistory;
|
||||
|
||||
// Get the title of the inner popup's current SHEntry
|
||||
var sheTitle = sh.getEntryAtIndex(sh.index, false).title;
|
||||
|
|
|
@ -43,7 +43,6 @@ function pollForPage(f, w)
|
|||
|
||||
function windowLoaded()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
switch (phase)
|
||||
{
|
||||
case 0:
|
||||
|
@ -57,18 +56,16 @@ function windowLoaded()
|
|||
pollForPage(function(succeeded) {
|
||||
ok(succeeded, "Waiting for error page succeeded");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
/* 3. now, while we are on the error page, try to reload it, actually
|
||||
click the "Try Again" button */
|
||||
w.location.reload();
|
||||
SpecialPowers.wrap(w).location.reload();
|
||||
|
||||
pollForPage(function(succeeded) {
|
||||
ok(succeeded, "Waiting for error page succeeded");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
/* 4-finish, check we are still on the error page */
|
||||
is(w.location.href, faultyURL, "Is on an error page");
|
||||
isnot(w.location.href, workingURL, "Is not on the previous page");
|
||||
is(SpecialPowers.wrap(w).location.href, faultyURL, "Is on an error page");
|
||||
isnot(SpecialPowers.wrap(w).location.href, workingURL, "Is not on the previous page");
|
||||
is(gotWrongPageOnTryAgainClick, false,
|
||||
"Must not get www.example.com page on reload of an error page");
|
||||
w.close();
|
||||
|
|
|
@ -42,8 +42,6 @@ function pollForPage(expectErrorPage, f, w)
|
|||
|
||||
function windowLoaded()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
/* 2. We have successfully loaded a page, now go to a faulty URL */
|
||||
// XXX The test fails when we change the location synchronously
|
||||
window.setTimeout(function() {
|
||||
|
@ -52,11 +50,9 @@ function windowLoaded()
|
|||
|
||||
pollForPage(true, function(succeeded) {
|
||||
ok(succeeded, "Waiting for error page succeeded");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
/* 3. now, while we are on the error page, navigate back */
|
||||
try {
|
||||
w.back();
|
||||
SpecialPowers.wrap(w).back();
|
||||
}
|
||||
catch(ex) {
|
||||
ok(false, "w.back() threw " + ex);
|
||||
|
@ -64,11 +60,9 @@ function windowLoaded()
|
|||
|
||||
pollForPage(false, function(succeeded) {
|
||||
ok(succeeded, "Waiting for original page succeeded");
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
/* 4-finish, check we are back at the original page */
|
||||
isnot(w.location.href, faultyURL, "Is on an error page");
|
||||
is(w.location.href, workingURL, "Is not on the previous page");
|
||||
isnot(SpecialPowers.wrap(w).location.href, faultyURL, "Is on an error page");
|
||||
is(SpecialPowers.wrap(w).location.href, workingURL, "Is not on the previous page");
|
||||
w.close();
|
||||
SimpleTest.finish();
|
||||
}, w);
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=703855
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 703855</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=703855">Mozilla Bug 703855</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<iframe id="f" src="file_bug703855.html"></iframe>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 703855 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var timingAttributes = [
|
||||
'connectEnd',
|
||||
'connectStart',
|
||||
'domComplete',
|
||||
'domContentLoadedEventEnd',
|
||||
'domContentLoadedEventStart',
|
||||
'domInteractive',
|
||||
'domLoading',
|
||||
'domainLookupEnd',
|
||||
'domainLookupStart',
|
||||
'fetchStart',
|
||||
'loadEventEnd',
|
||||
'loadEventStart',
|
||||
'navigationStart',
|
||||
'redirectEnd',
|
||||
'redirectStart',
|
||||
'requestStart',
|
||||
'responseEnd',
|
||||
'responseStart',
|
||||
'unloadEventEnd',
|
||||
'unloadEventStart'
|
||||
];
|
||||
var originalTiming = {};
|
||||
|
||||
function runTest() {
|
||||
var timing = $("f").contentWindow.performance.timing;
|
||||
for (i in timingAttributes) {
|
||||
originalTiming[timingAttributes[i]] = timing[timingAttributes[i]];
|
||||
}
|
||||
|
||||
var doc = $("f").contentDocument;
|
||||
doc.open();
|
||||
doc.write("<!DOCTYPE html>");
|
||||
doc.close();
|
||||
|
||||
SimpleTest.executeSoon(function() {
|
||||
var newTiming = $("f").contentWindow.performance.timing;
|
||||
for (var i in timingAttributes) {
|
||||
is(timing[timingAttributes[i]], originalTiming[timingAttributes[i]],
|
||||
"document.open should not affect value of " + timingAttributes[i]);
|
||||
}
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
addLoadEvent(function() {
|
||||
SimpleTest.executeSoon(runTest);
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -221,6 +221,7 @@ let DOMApplicationRegistry = {
|
|||
this.getSelf(msg);
|
||||
break;
|
||||
case "Webapps:Uninstall":
|
||||
Services.obs.notifyObservers(this, "webapps-uninstall", JSON.stringify(msg));
|
||||
this.uninstall(msg);
|
||||
break;
|
||||
case "Webapps:Launch":
|
||||
|
@ -698,7 +699,25 @@ let DOMApplicationRegistry = {
|
|||
for (let id in this.webapps) {
|
||||
let app = this.webapps[id];
|
||||
if (app.manifestURL == aManifestURL) {
|
||||
return this._cloneAppObject(app);
|
||||
let res = this._cloneAppObject(app);
|
||||
res.hasPermission = function(permission) {
|
||||
let localId = DOMApplicationRegistry.getAppLocalIdByManifestURL(
|
||||
this.manifestURL);
|
||||
let uri = Services.io.newURI(this.manifestURL, null, null);
|
||||
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||
.getService(Ci.nsIScriptSecurityManager);
|
||||
// XXX for the purposes of permissions checking, this helper
|
||||
// should always be called on !isBrowser frames, so we
|
||||
// assume false here.
|
||||
let principal = secMan.getAppCodebasePrincipal(uri, localId,
|
||||
/*mozbrowser*/false);
|
||||
let perm = Services.perms.testExactPermissionFromPrincipal(principal,
|
||||
permission);
|
||||
return (perm === Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
};
|
||||
res.QueryInterface = XPCOMUtils.generateQI([Ci.mozIDOMApplication,
|
||||
Ci.mozIApplication]);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -957,6 +976,10 @@ DOMApplicationManifest.prototype = {
|
|||
return this._localeProp("appcache_path");
|
||||
},
|
||||
|
||||
get orientation() {
|
||||
return this._localeProp("orientation");
|
||||
},
|
||||
|
||||
iconURLForSize: function(aSize) {
|
||||
let icons = this._localeProp("icons");
|
||||
if (!icons)
|
||||
|
|
|
@ -41,6 +41,14 @@ nsDOMNavigationTiming::Clear()
|
|||
mDOMContentLoadedEventEnd = 0;
|
||||
mDOMComplete = 0;
|
||||
mRedirectCheck = NOT_CHECKED;
|
||||
|
||||
mLoadEventStartSet = false;
|
||||
mLoadEventEndSet = false;
|
||||
mDOMLoadingSet = false;
|
||||
mDOMInteractiveSet = false;
|
||||
mDOMContentLoadedEventStartSet = false;
|
||||
mDOMContentLoadedEventEndSet = false;
|
||||
mDOMCompleteSet = false;
|
||||
}
|
||||
|
||||
DOMTimeMilliSec
|
||||
|
@ -128,13 +136,19 @@ nsDOMNavigationTiming::NotifyUnloadEventEnd()
|
|||
void
|
||||
nsDOMNavigationTiming::NotifyLoadEventStart()
|
||||
{
|
||||
mLoadEventStart = DurationFromStart();
|
||||
if (!mLoadEventStartSet) {
|
||||
mLoadEventStart = DurationFromStart();
|
||||
mLoadEventStartSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMNavigationTiming::NotifyLoadEventEnd()
|
||||
{
|
||||
mLoadEventEnd = DurationFromStart();
|
||||
if (!mLoadEventEndSet) {
|
||||
mLoadEventEnd = DurationFromStart();
|
||||
mLoadEventEndSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -166,43 +180,61 @@ nsDOMNavigationTiming::ReportRedirects()
|
|||
void
|
||||
nsDOMNavigationTiming::SetDOMLoadingTimeStamp(nsIURI* aURI, mozilla::TimeStamp aValue)
|
||||
{
|
||||
mLoadedURI = aURI;
|
||||
mDOMLoading = TimeStampToDOM(aValue);
|
||||
if (!mDOMLoadingSet) {
|
||||
mLoadedURI = aURI;
|
||||
mDOMLoading = TimeStampToDOM(aValue);
|
||||
mDOMLoadingSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMNavigationTiming::NotifyDOMLoading(nsIURI* aURI)
|
||||
{
|
||||
mLoadedURI = aURI;
|
||||
mDOMLoading = DurationFromStart();
|
||||
if (!mDOMLoadingSet) {
|
||||
mLoadedURI = aURI;
|
||||
mDOMLoading = DurationFromStart();
|
||||
mDOMLoadingSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMNavigationTiming::NotifyDOMInteractive(nsIURI* aURI)
|
||||
{
|
||||
mLoadedURI = aURI;
|
||||
mDOMInteractive = DurationFromStart();
|
||||
if (!mDOMInteractiveSet) {
|
||||
mLoadedURI = aURI;
|
||||
mDOMInteractive = DurationFromStart();
|
||||
mDOMInteractiveSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMNavigationTiming::NotifyDOMComplete(nsIURI* aURI)
|
||||
{
|
||||
mLoadedURI = aURI;
|
||||
mDOMComplete = DurationFromStart();
|
||||
if (!mDOMCompleteSet) {
|
||||
mLoadedURI = aURI;
|
||||
mDOMComplete = DurationFromStart();
|
||||
mDOMCompleteSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMNavigationTiming::NotifyDOMContentLoadedStart(nsIURI* aURI)
|
||||
{
|
||||
mLoadedURI = aURI;
|
||||
mDOMContentLoadedEventStart = DurationFromStart();
|
||||
if (!mDOMContentLoadedEventStartSet) {
|
||||
mLoadedURI = aURI;
|
||||
mDOMContentLoadedEventStart = DurationFromStart();
|
||||
mDOMContentLoadedEventStartSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMNavigationTiming::NotifyDOMContentLoadedEnd(nsIURI* aURI)
|
||||
{
|
||||
mLoadedURI = aURI;
|
||||
mDOMContentLoadedEventEnd = DurationFromStart();
|
||||
if (!mDOMContentLoadedEventEndSet) {
|
||||
mLoadedURI = aURI;
|
||||
mDOMContentLoadedEventEnd = DurationFromStart();
|
||||
mDOMContentLoadedEventEndSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
PRUint16
|
||||
|
|
|
@ -136,6 +136,17 @@ private:
|
|||
DOMTimeMilliSec mDOMContentLoadedEventStart;
|
||||
DOMTimeMilliSec mDOMContentLoadedEventEnd;
|
||||
DOMTimeMilliSec mDOMComplete;
|
||||
|
||||
// Booleans to keep track of what things we've already been notified
|
||||
// about. We don't update those once we've been notified about them
|
||||
// once.
|
||||
bool mLoadEventStartSet : 1;
|
||||
bool mLoadEventEndSet : 1;
|
||||
bool mDOMLoadingSet : 1;
|
||||
bool mDOMInteractiveSet : 1;
|
||||
bool mDOMContentLoadedEventStartSet : 1;
|
||||
bool mDOMContentLoadedEventEndSet : 1;
|
||||
bool mDOMCompleteSet : 1;
|
||||
};
|
||||
|
||||
#endif /* nsDOMNavigationTiming_h___ */
|
||||
|
|
|
@ -1956,6 +1956,17 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
|
|||
if (newInnerWindow->mNavigator) {
|
||||
newInnerWindow->mNavigator->SetWindow(newInnerWindow);
|
||||
}
|
||||
|
||||
// Make a copy of the old window's performance object on document.open.
|
||||
// Note that we have to force eager creation of it here, because we need
|
||||
// to grab the current document channel and whatnot before that changes.
|
||||
currentInner->CreatePerformanceObjectIfNeeded();
|
||||
if (currentInner->mPerformance) {
|
||||
newInnerWindow->mPerformance =
|
||||
new nsPerformance(newInnerWindow,
|
||||
currentInner->mPerformance->GetDOMTiming(),
|
||||
currentInner->mPerformance->GetChannel());
|
||||
}
|
||||
}
|
||||
|
||||
// Don't free objects on our current inner window if it's going to be
|
||||
|
@ -2931,27 +2942,31 @@ nsGlobalWindow::GetPerformance(nsISupports** aPerformance)
|
|||
*aPerformance = nullptr;
|
||||
|
||||
if (nsGlobalWindow::HasPerformanceSupport()) {
|
||||
if (!mPerformance) {
|
||||
if (!mDoc) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsRefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
|
||||
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
|
||||
bool timingEnabled = false;
|
||||
if (!timedChannel ||
|
||||
!NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
|
||||
!timingEnabled) {
|
||||
timedChannel = nullptr;
|
||||
}
|
||||
if (timing) {
|
||||
mPerformance = new nsPerformance(this, timing, timedChannel);
|
||||
}
|
||||
}
|
||||
CreatePerformanceObjectIfNeeded();
|
||||
NS_IF_ADDREF(*aPerformance = mPerformance);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindow::CreatePerformanceObjectIfNeeded()
|
||||
{
|
||||
if (mPerformance || !mDoc) {
|
||||
return;
|
||||
}
|
||||
nsRefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
|
||||
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
|
||||
bool timingEnabled = false;
|
||||
if (!timedChannel ||
|
||||
!NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
|
||||
!timingEnabled) {
|
||||
timedChannel = nullptr;
|
||||
}
|
||||
if (timing) {
|
||||
mPerformance = new nsPerformance(this, timing, timedChannel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GetScriptableParent is called when script reads window.parent.
|
||||
*
|
||||
|
|
|
@ -905,6 +905,9 @@ protected:
|
|||
// Implements Get{Real,Scriptable}Top.
|
||||
nsresult GetTopImpl(nsIDOMWindow **aWindow, bool aScriptable);
|
||||
|
||||
// Helper for creating performance objects.
|
||||
void CreatePerformanceObjectIfNeeded();
|
||||
|
||||
// When adding new member variables, be careful not to create cycles
|
||||
// through JavaScript. If there is any chance that a member variable
|
||||
// could own objects that are implemented in JavaScript, then those
|
||||
|
@ -990,6 +993,7 @@ protected:
|
|||
nsCOMPtr<nsIPrincipal> mArgumentsOrigin;
|
||||
nsRefPtr<Navigator> mNavigator;
|
||||
nsRefPtr<nsScreen> mScreen;
|
||||
// mPerformance is only used on inner windows.
|
||||
nsRefPtr<nsPerformance> mPerformance;
|
||||
nsRefPtr<nsDOMWindowList> mFrames;
|
||||
nsRefPtr<nsBarProp> mMenubar;
|
||||
|
|
|
@ -140,6 +140,11 @@ public:
|
|||
return mDOMTiming;
|
||||
}
|
||||
|
||||
nsITimedChannel* GetChannel() const
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
nsIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return mWindow.get();
|
||||
|
|
|
@ -64,7 +64,7 @@ struct TypedArray : public TypedArray_base<T,UnboxArray> {
|
|||
|
||||
static inline JSObject*
|
||||
Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
|
||||
T* data = NULL) {
|
||||
const T* data = NULL) {
|
||||
JSObject* creatorWrapper;
|
||||
JSAutoEnterCompartment ac;
|
||||
if (creator && (creatorWrapper = creator->GetWrapperPreserveColor())) {
|
||||
|
|
|
@ -9,6 +9,7 @@ const ContentPanning = {
|
|||
});
|
||||
|
||||
addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
|
||||
addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
|
||||
},
|
||||
|
||||
handleEvent: function cp_handleEvent(evt) {
|
||||
|
@ -43,6 +44,16 @@ const ContentPanning = {
|
|||
let oldTarget = this.target;
|
||||
[this.target, this.scrollCallback] = this.getPannable(evt.target);
|
||||
|
||||
// If we found a target, that means we have found a scrollable subframe. In
|
||||
// this case, and if we are using async panning and zooming on the parent
|
||||
// frame, inform the pan/zoom controller that it should not attempt to
|
||||
// handle any touch events it gets until the next batch (meaning the next
|
||||
// time we get a touch end).
|
||||
if (this.target != null && ContentPanning._asyncPanZoomForViewportFrame) {
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(docShell, 'cancel-default-pan-zoom', null);
|
||||
}
|
||||
|
||||
// If there is a pan animation running (from a previous pan gesture) and
|
||||
// the user touch back the screen, stop this animation immediatly and
|
||||
// prevent the possible click action if the touch happens on the same
|
||||
|
@ -190,21 +201,34 @@ const ContentPanning = {
|
|||
},
|
||||
|
||||
_recvViewportChange: function(data) {
|
||||
let viewport = data.json;
|
||||
let displayPort = viewport.displayPort;
|
||||
let metrics = data.json;
|
||||
let displayPort = metrics.displayPort;
|
||||
|
||||
let screenWidth = viewport.screenSize.width;
|
||||
let screenHeight = viewport.screenSize.height;
|
||||
let screenWidth = metrics.screenSize.width;
|
||||
let screenHeight = metrics.screenSize.height;
|
||||
|
||||
let x = viewport.x;
|
||||
let y = viewport.y;
|
||||
let x = metrics.x;
|
||||
let y = metrics.y;
|
||||
|
||||
this._zoom = metrics.zoom;
|
||||
this._viewport = new Rect(x, y,
|
||||
screenWidth / metrics.zoom,
|
||||
screenHeight / metrics.zoom);
|
||||
this._cssPageRect = new Rect(metrics.cssPageRect.x,
|
||||
metrics.cssPageRect.y,
|
||||
metrics.cssPageRect.width,
|
||||
metrics.cssPageRect.height);
|
||||
|
||||
let cwu = content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
cwu.setCSSViewport(screenWidth, screenHeight);
|
||||
if (this._screenWidth != screenWidth || this._screenHeight != screenHeight) {
|
||||
cwu.setCSSViewport(screenWidth, screenHeight);
|
||||
this._screenWidth = screenWidth;
|
||||
this._screenHeight = screenHeight;
|
||||
}
|
||||
|
||||
// Set scroll position
|
||||
cwu.setScrollPositionClampingScrollPortSize(
|
||||
screenWidth / viewport.zoom, screenHeight / viewport.zoom);
|
||||
screenWidth / metrics.zoom, screenHeight / metrics.zoom);
|
||||
content.scrollTo(x, y);
|
||||
cwu.setResolution(displayPort.resolution, displayPort.resolution);
|
||||
|
||||
|
@ -216,6 +240,109 @@ const ContentPanning = {
|
|||
displayPort.height,
|
||||
element);
|
||||
}
|
||||
},
|
||||
|
||||
_recvDoubleTap: function(data) {
|
||||
let data = data.json;
|
||||
|
||||
// We haven't received a metrics update yet; don't do anything.
|
||||
if (this._viewport == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let win = content;
|
||||
|
||||
let zoom = this._zoom;
|
||||
let element = ElementTouchHelper.anyElementFromPoint(win, data.x, data.y);
|
||||
if (!element) {
|
||||
this._zoomOut();
|
||||
return;
|
||||
}
|
||||
|
||||
while (element && !this._shouldZoomToElement(element))
|
||||
element = element.parentNode;
|
||||
|
||||
if (!element) {
|
||||
this._zoomOut();
|
||||
} else {
|
||||
const margin = 15;
|
||||
let rect = ElementTouchHelper.getBoundingContentRect(element);
|
||||
|
||||
let cssPageRect = this._cssPageRect;
|
||||
let viewport = this._viewport;
|
||||
let bRect = new Rect(Math.max(cssPageRect.left, rect.x - margin),
|
||||
rect.y,
|
||||
rect.w + 2 * margin,
|
||||
rect.h);
|
||||
// constrict the rect to the screen's right edge
|
||||
bRect.width = Math.min(bRect.width, cssPageRect.right - bRect.x);
|
||||
|
||||
// if the rect is already taking up most of the visible area and is stretching the
|
||||
// width of the page, then we want to zoom out instead.
|
||||
if (this._isRectZoomedIn(bRect, viewport)) {
|
||||
this._zoomOut();
|
||||
return;
|
||||
}
|
||||
|
||||
rect.x = Math.round(bRect.x);
|
||||
rect.y = Math.round(bRect.y);
|
||||
rect.w = Math.round(bRect.width);
|
||||
rect.h = Math.round(Math.min(bRect.width * viewport.height / viewport.height, bRect.height));
|
||||
|
||||
// if the block we're zooming to is really tall, and the user double-tapped
|
||||
// more than a screenful of height from the top of it, then adjust the y-coordinate
|
||||
// so that we center the actual point the user double-tapped upon. this prevents
|
||||
// flying to the top of a page when double-tapping to zoom in (bug 761721).
|
||||
// the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal
|
||||
// margins but not vertical ones.
|
||||
let cssTapY = viewport.y + data.y;
|
||||
if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) {
|
||||
rect.y = cssTapY - (rect.h / 2);
|
||||
}
|
||||
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
|
||||
}
|
||||
},
|
||||
|
||||
_shouldZoomToElement: function(aElement) {
|
||||
let win = aElement.ownerDocument.defaultView;
|
||||
if (win.getComputedStyle(aElement, null).display == "inline")
|
||||
return false;
|
||||
if (aElement instanceof Ci.nsIDOMHTMLLIElement)
|
||||
return false;
|
||||
if (aElement instanceof Ci.nsIDOMHTMLQuoteElement)
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
|
||||
_zoomOut: function() {
|
||||
let rect = new Rect(0, 0, 0, 0);
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
|
||||
},
|
||||
|
||||
_isRectZoomedIn: function(aRect, aViewport) {
|
||||
// This function checks to see if the area of the rect visible in the
|
||||
// viewport (i.e. the "overlapArea" variable below) is approximately
|
||||
// the max area of the rect we can show. It also checks that the rect
|
||||
// is actually on-screen by testing the left and right edges of the rect.
|
||||
// In effect, this tells us whether or not zooming in to this rect
|
||||
// will significantly change what the user is seeing.
|
||||
const minDifference = -20;
|
||||
const maxDifference = 20;
|
||||
|
||||
let vRect = new Rect(aViewport.x, aViewport.y, aViewport.width, aViewport.height);
|
||||
let overlap = vRect.intersect(aRect);
|
||||
let overlapArea = overlap.width * overlap.height;
|
||||
let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height);
|
||||
let showing = overlapArea / (aRect.width * availHeight);
|
||||
let dw = (aRect.width - vRect.width);
|
||||
let dx = (aRect.x - vRect.x);
|
||||
|
||||
return (showing > 0.9 &&
|
||||
dx > minDifference && dx < maxDifference &&
|
||||
dw > minDifference && dw < maxDifference);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -389,3 +516,52 @@ const KineticPanning = {
|
|||
content.mozRequestAnimationFrame(callback);
|
||||
}
|
||||
};
|
||||
|
||||
const ElementTouchHelper = {
|
||||
anyElementFromPoint: function(aWindow, aX, aY) {
|
||||
let cwu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let elem = cwu.elementFromPoint(aX, aY, true, true);
|
||||
|
||||
let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
|
||||
let HTMLFrameElement = Ci.nsIDOMHTMLFrameElement;
|
||||
while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) {
|
||||
let rect = elem.getBoundingClientRect();
|
||||
aX -= rect.left;
|
||||
aY -= rect.top;
|
||||
cwu = elem.contentDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
elem = cwu.elementFromPoint(aX, aY, true, true);
|
||||
}
|
||||
|
||||
return elem;
|
||||
},
|
||||
|
||||
getBoundingContentRect: function(aElement) {
|
||||
if (!aElement)
|
||||
return {x: 0, y: 0, w: 0, h: 0};
|
||||
|
||||
let document = aElement.ownerDocument;
|
||||
while (document.defaultView.frameElement)
|
||||
document = document.defaultView.frameElement.ownerDocument;
|
||||
|
||||
let cwu = document.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
let scrollX = {}, scrollY = {};
|
||||
cwu.getScrollXY(false, scrollX, scrollY);
|
||||
|
||||
let r = aElement.getBoundingClientRect();
|
||||
|
||||
// step out of iframes and frames, offsetting scroll values
|
||||
for (let frame = aElement.ownerDocument.defaultView; frame.frameElement && frame != content; frame = frame.parent) {
|
||||
// adjust client coordinates' origin to be top left of iframe viewport
|
||||
let rect = frame.frameElement.getBoundingClientRect();
|
||||
let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth;
|
||||
let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth;
|
||||
scrollX.value += rect.left + parseInt(left);
|
||||
scrollY.value += rect.top + parseInt(top);
|
||||
}
|
||||
|
||||
return {x: r.left + scrollX.value,
|
||||
y: r.top + scrollY.value,
|
||||
w: r.width,
|
||||
h: r.height };
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ XPIDL_MODULE = dom_apps
|
|||
GRE_MODULE = 1
|
||||
|
||||
XPIDLSRCS = \
|
||||
mozIApplication.idl \
|
||||
nsIDOMApplicationRegistry.idl \
|
||||
nsIAppsService.idl \
|
||||
nsIDOMMozApplicationEvent.idl \
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 "nsIDOMApplicationRegistry.idl"
|
||||
|
||||
/**
|
||||
* We expose Gecko-internal helpers related to "web apps" through this
|
||||
* sub-interface.
|
||||
*/
|
||||
[scriptable, uuid(8de25e36-b4cb-4e89-9310-a199dce4e5f4)]
|
||||
interface mozIApplication: mozIDOMApplication
|
||||
{
|
||||
/* Return true if this app has |permission|. */
|
||||
boolean hasPermission(in string permission);
|
||||
};
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 "AppProcessPermissions.h"
|
||||
#include "ContentParent.h"
|
||||
#include "mozIApplication.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
#include "TabParent.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::services;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool
|
||||
AppProcessHasPermission(PBrowserParent* aActor, const char* aPermission)
|
||||
{
|
||||
if (!aActor) {
|
||||
NS_WARNING("Testing permissions for null actor");
|
||||
return false;
|
||||
}
|
||||
|
||||
TabParent* tab = static_cast<TabParent*>(aActor);
|
||||
nsCOMPtr<mozIApplication> app = tab->GetApp();
|
||||
// isBrowser frames inherit their app descriptor to identify their
|
||||
// data storage, but they don't inherit the permissions associated
|
||||
// with that descriptor.
|
||||
if (!app || tab->IsBrowserElement()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasPermission = false;
|
||||
return (NS_SUCCEEDED(app->HasPermission(aPermission, &hasPermission)) &&
|
||||
hasPermission);
|
||||
}
|
||||
|
||||
bool
|
||||
AppProcessHasPermission(PContentParent* aActor, const char* aPermission)
|
||||
{
|
||||
const InfallibleTArray<PBrowserParent*>& browsers =
|
||||
aActor->ManagedPBrowserParent();
|
||||
for (uint32_t i = 0; i < browsers.Length(); ++i) {
|
||||
if (AppProcessHasPermission(browsers[i], aPermission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,43 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_Capabilities_h
|
||||
#define mozilla_Capabilities_h
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class PBrowserParent;
|
||||
class PContentParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true iff the specified browser has the specified capability.
|
||||
*/
|
||||
bool
|
||||
AppProcessHasPermissions(mozilla::dom::PBrowserParent* aActor,
|
||||
const char* aPermission);
|
||||
|
||||
/**
|
||||
* Return true iff any of the PBrowsers loaded in this content process
|
||||
* has the specified capability.
|
||||
*/
|
||||
bool
|
||||
AppProcessHasPermission(mozilla::dom::PContentParent* aActor,
|
||||
const char* aPermission);
|
||||
|
||||
// NB: when adding capability checks for other IPDL actors, please add
|
||||
// them to this file and have them delegate to the two functions above
|
||||
// as appropriate. For example,
|
||||
//
|
||||
// bool AppProcessHasCapability(PNeckoParent* aActor) {
|
||||
// return AppProcessHasCapability(aActor->Manager());
|
||||
// }
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_Capabilities_h
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsIObserverService.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
@ -402,10 +403,11 @@ ContentChild::AllocPCompositor(mozilla::ipc::Transport* aTransport,
|
|||
|
||||
PBrowserChild*
|
||||
ContentChild::AllocPBrowser(const PRUint32& aChromeFlags,
|
||||
const bool& aIsBrowserElement,
|
||||
const PRUint32& aAppId)
|
||||
const bool& aIsBrowserElement, const AppId& aApp)
|
||||
{
|
||||
nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement, aAppId);
|
||||
PRUint32 appId = aApp.get_uint32_t();
|
||||
nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement,
|
||||
appId);
|
||||
return NS_SUCCEEDED(iframe->Init()) ? iframe.forget().get() : NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags,
|
||||
const bool& aIsBrowserElement,
|
||||
const PRUint32& aAppId);
|
||||
const AppId& aAppId);
|
||||
virtual bool DeallocPBrowser(PBrowserChild*);
|
||||
|
||||
virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "IDBFactory.h"
|
||||
#include "IndexedDBParent.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "mozIApplication.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
@ -49,8 +50,10 @@
|
|||
#include "nsFrameMessageManager.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIAlertsService.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsIClipboard.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
#include "nsIDOMGeoGeolocation.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIFilePicker.h"
|
||||
|
@ -59,6 +62,7 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "nsIRemoteBlob.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsMemoryReporterManager.h"
|
||||
|
@ -149,7 +153,7 @@ nsTArray<ContentParent*>* ContentParent::gPrivateContent;
|
|||
// The first content child has ID 1, so the chrome process can have ID 0.
|
||||
static PRUint64 gContentChildID = 1;
|
||||
|
||||
ContentParent*
|
||||
/*static*/ ContentParent*
|
||||
ContentParent::GetNewOrUsed()
|
||||
{
|
||||
if (!gNonAppContentParents)
|
||||
|
@ -173,11 +177,20 @@ ContentParent::GetNewOrUsed()
|
|||
return p;
|
||||
}
|
||||
|
||||
ContentParent*
|
||||
ContentParent::GetForApp(const nsAString& aAppManifestURL)
|
||||
/*static*/ TabParent*
|
||||
ContentParent::CreateBrowser(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
{
|
||||
if (aAppManifestURL.IsEmpty()) {
|
||||
return GetNewOrUsed();
|
||||
if (!aApp) {
|
||||
if (ContentParent* cp = GetNewOrUsed()) {
|
||||
nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
|
||||
return static_cast<TabParent*>(
|
||||
cp->SendPBrowserConstructor(
|
||||
// DeallocPBrowserParent() releases the ref we take here
|
||||
tp.forget().get(),
|
||||
/*chromeFlags*/0,
|
||||
aIsBrowserElement, nsIScriptSecurityManager::NO_APP_ID));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!gAppContentParents) {
|
||||
|
@ -187,14 +200,39 @@ ContentParent::GetForApp(const nsAString& aAppManifestURL)
|
|||
}
|
||||
|
||||
// Each app gets its own ContentParent instance.
|
||||
ContentParent* p = gAppContentParents->Get(aAppManifestURL);
|
||||
if (!p) {
|
||||
p = new ContentParent(aAppManifestURL);
|
||||
p->Init();
|
||||
gAppContentParents->Put(aAppManifestURL, p);
|
||||
nsAutoString manifestURL;
|
||||
if (NS_FAILED(aApp->GetManifestURL(manifestURL))) {
|
||||
NS_ERROR("Failed to get manifest URL");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return p;
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (!appsService) {
|
||||
NS_ERROR("Failed to get apps service");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Send the local app ID to the new TabChild so it knows what app
|
||||
// it is.
|
||||
PRUint32 appId;
|
||||
if (NS_FAILED(appsService->GetAppLocalIdByManifestURL(manifestURL, &appId))) {
|
||||
NS_ERROR("Failed to get local app ID");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ContentParent* p = gAppContentParents->Get(manifestURL);
|
||||
if (!p) {
|
||||
p = new ContentParent(manifestURL);
|
||||
p->Init();
|
||||
gAppContentParents->Put(manifestURL, p);
|
||||
}
|
||||
|
||||
nsRefPtr<TabParent> tp(new TabParent(aApp, aIsBrowserElement));
|
||||
return static_cast<TabParent*>(
|
||||
// DeallocPBrowserParent() releases the ref we take here
|
||||
p->SendPBrowserConstructor(tp.forget().get(),
|
||||
/*chromeFlags*/0,
|
||||
aIsBrowserElement, appId));
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
|
@ -455,12 +493,6 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
|||
NS_DispatchToCurrentThread(new DelayedDeleteContentParentTask(this));
|
||||
}
|
||||
|
||||
TabParent*
|
||||
ContentParent::CreateTab(PRUint32 aChromeFlags, bool aIsBrowserElement, PRUint32 aAppId)
|
||||
{
|
||||
return static_cast<TabParent*>(SendPBrowserConstructor(aChromeFlags, aIsBrowserElement, aAppId));
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::NotifyTabDestroyed(PBrowserParent* aTab)
|
||||
{
|
||||
|
@ -862,22 +894,40 @@ ContentParent::AllocPCompositor(mozilla::ipc::Transport* aTransport,
|
|||
|
||||
PBrowserParent*
|
||||
ContentParent::AllocPBrowser(const PRUint32& aChromeFlags,
|
||||
const bool& aIsBrowserElement,
|
||||
const PRUint32& aAppId)
|
||||
const bool& aIsBrowserElement, const AppId& aApp)
|
||||
{
|
||||
TabParent* parent = new TabParent();
|
||||
if (parent){
|
||||
// We only use this Alloc() method when the content processes asks
|
||||
// us to open a window. In that case, we're expecting to see the
|
||||
// opening PBrowser as its app descriptor, and we can trust the data
|
||||
// associated with that PBrowser since it's fully owned by this
|
||||
// process.
|
||||
if (AppId::TPBrowserParent != aApp.type()) {
|
||||
NS_ERROR("Content process attempting to forge app ID");
|
||||
return nullptr;
|
||||
}
|
||||
TabParent* opener = static_cast<TabParent*>(aApp.get_PBrowserParent());
|
||||
|
||||
// Popup windows of isBrowser frames are isBrowser if the parent
|
||||
// isBrowser. Allocating a !isBrowser frame with same app ID
|
||||
// would allow the content to access data it's not supposed to.
|
||||
if (opener && opener->IsBrowserElement() && !aIsBrowserElement) {
|
||||
NS_ERROR("Content process attempting to escalate data access privileges");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TabParent* parent = new TabParent(opener ? opener->GetApp() : nullptr,
|
||||
aIsBrowserElement);
|
||||
// We release this ref in DeallocPBrowser()
|
||||
NS_ADDREF(parent);
|
||||
}
|
||||
return parent;
|
||||
return parent;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::DeallocPBrowser(PBrowserParent* frame)
|
||||
{
|
||||
TabParent* parent = static_cast<TabParent*>(frame);
|
||||
NS_RELEASE(parent);
|
||||
return true;
|
||||
TabParent* parent = static_cast<TabParent*>(frame);
|
||||
NS_RELEASE(parent);
|
||||
return true;
|
||||
}
|
||||
|
||||
PDeviceStorageRequestParent*
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
class mozIApplication;
|
||||
class nsFrameMessageManager;
|
||||
class nsIDOMBlob;
|
||||
|
||||
|
@ -60,13 +61,16 @@ public:
|
|||
static ContentParent* GetNewOrUsed();
|
||||
|
||||
/**
|
||||
* Get or create a content process for the given app. A given app
|
||||
* (identified by its manifest URL) gets one process all to itself.
|
||||
* Get or create a content process for the given app descriptor,
|
||||
* which may be null. This function will assign processes to app
|
||||
* or non-app browsers by internal heuristics.
|
||||
*
|
||||
* If the given manifest is the empty string, then this method is equivalent
|
||||
* to GetNewOrUsed().
|
||||
* Currently apps are given their own process, and browser tabs
|
||||
* share processes.
|
||||
*/
|
||||
static ContentParent* GetForApp(const nsAString& aManifestURL);
|
||||
static TabParent* CreateBrowser(mozIApplication* aApp,
|
||||
bool aIsBrowserFrame);
|
||||
|
||||
static void GetAll(nsTArray<ContentParent*>& aArray);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -74,14 +78,6 @@ public:
|
|||
NS_DECL_NSITHREADOBSERVER
|
||||
NS_DECL_NSIDOMGEOPOSITIONCALLBACK
|
||||
|
||||
/**
|
||||
* Create a new tab.
|
||||
*
|
||||
* |aIsBrowserElement| indicates whether this tab is part of an
|
||||
* <iframe mozbrowser>.
|
||||
* |aAppId| indicates which app the tab belongs to.
|
||||
*/
|
||||
TabParent* CreateTab(PRUint32 aChromeFlags, bool aIsBrowserElement, PRUint32 aAppId);
|
||||
/** Notify that a tab was destroyed during normal operation. */
|
||||
void NotifyTabDestroyed(PBrowserParent* aTab);
|
||||
|
||||
|
@ -143,7 +139,9 @@ private:
|
|||
PCompositorParent* AllocPCompositor(mozilla::ipc::Transport* aTransport,
|
||||
base::ProcessId aOtherProcess) MOZ_OVERRIDE;
|
||||
|
||||
virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags, const bool& aIsBrowserElement, const PRUint32& aAppId);
|
||||
virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags,
|
||||
const bool& aIsBrowserElement,
|
||||
const AppId& aApp);
|
||||
virtual bool DeallocPBrowser(PBrowserParent* frame);
|
||||
|
||||
virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);
|
||||
|
|
|
@ -23,10 +23,15 @@ endif
|
|||
EXPORTS = PCOMContentPermissionRequestChild.h
|
||||
|
||||
EXPORTS_NAMESPACES = \
|
||||
mozilla \
|
||||
mozilla/dom \
|
||||
mozilla/dom/ipc \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla = \
|
||||
AppProcessPermissions.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_mozilla/dom = \
|
||||
ContentChild.h \
|
||||
ContentParent.h \
|
||||
|
@ -47,6 +52,7 @@ EXPORTS_mozilla/dom/ipc = \
|
|||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
AppProcessPermissions.cpp \
|
||||
Blob.cpp \
|
||||
ContentProcess.cpp \
|
||||
ContentParent.cpp \
|
||||
|
|
|
@ -15,6 +15,7 @@ include protocol POfflineCacheUpdate;
|
|||
include protocol PIndexedDB;
|
||||
|
||||
include "gfxMatrix.h";
|
||||
include "FrameMetrics.h";
|
||||
include "IPC/nsGUIEventIPC.h";
|
||||
include "mozilla/dom/TabMessageUtils.h";
|
||||
include "mozilla/dom/PermissionMessageUtils.h";
|
||||
|
@ -26,8 +27,10 @@ include DOMTypes;
|
|||
using IPC::URI;
|
||||
using IPC::Principal;
|
||||
using gfxMatrix;
|
||||
using gfxRect;
|
||||
using gfxSize;
|
||||
using mozilla::layers::LayersBackend;
|
||||
using mozilla::layers::FrameMetrics;
|
||||
using mozilla::layout::ScrollingBehavior;
|
||||
using mozilla::WindowsHandle;
|
||||
using nscolor;
|
||||
|
@ -247,6 +250,14 @@ parent:
|
|||
nsString aName, nsString aFeatures)
|
||||
returns (bool windowOpened);
|
||||
|
||||
NotifyDOMTouchListenerAdded();
|
||||
|
||||
/**
|
||||
* Instructs the TabParent to forward a request to zoom to a rect given in
|
||||
* CSS pixels. This rect is relative to the document.
|
||||
*/
|
||||
ZoomToRect(gfxRect aRect);
|
||||
|
||||
__delete__();
|
||||
|
||||
child:
|
||||
|
@ -265,10 +276,14 @@ child:
|
|||
|
||||
UpdateDimensions(nsRect rect, nsIntSize size);
|
||||
|
||||
UpdateFrame(nsIntRect displayPort,
|
||||
nsIntPoint scrollOffset,
|
||||
gfxSize resolution,
|
||||
nsIntRect screenSize);
|
||||
UpdateFrame(FrameMetrics frame);
|
||||
|
||||
/**
|
||||
* Requests handling of a double tap. |point| is in CSS pixels, relative to
|
||||
* the scroll offset. This message is expected to round-trip back to
|
||||
* ZoomToRect() with a rect indicating where we should zoom to.
|
||||
*/
|
||||
HandleDoubleTap(nsIntPoint point);
|
||||
|
||||
/**
|
||||
* Sending an activate message moves focus to the child.
|
||||
|
|
|
@ -122,6 +122,11 @@ union BlobConstructorParams
|
|||
MysteryBlobConstructorParams;
|
||||
};
|
||||
|
||||
union AppId {
|
||||
uint32_t;
|
||||
nullable PBrowser;
|
||||
};
|
||||
|
||||
rpc protocol PContent
|
||||
{
|
||||
parent opens PCompositor;
|
||||
|
@ -145,9 +150,16 @@ both:
|
|||
// created from either the child or parent process!
|
||||
//
|
||||
// The child creates the PBrowser as part of
|
||||
// TabChild::BrowserFrameProvideWindow, and the parent creates the PBrowser
|
||||
// as part of ContentParent::CreateTab.
|
||||
async PBrowser(PRUint32 chromeFlags, bool isBrowserElement, PRUint32 appId);
|
||||
// TabChild::BrowserFrameProvideWindow, and the parent creates the
|
||||
// PBrowser as part of ContentParent::CreateTab.
|
||||
//
|
||||
// When the parent constructs a PBrowser, the app ID handed to the
|
||||
// child side is trusted. In that case, |appId| is uint32_t.
|
||||
// However, when the child side constructs a PBrowser, for
|
||||
// window.open(), the parent must validate the app ID used on the
|
||||
// parent side. To do so, the child process must pass a valid
|
||||
// PBrowser as its |AppId|.
|
||||
async PBrowser(PRUint32 chromeFlags, bool isBrowserElement, AppId appId);
|
||||
|
||||
async PBlob(BlobConstructorParams params);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "mozilla/layers/CompositorChild.h"
|
||||
#include "mozilla/layers/PLayersChild.h"
|
||||
#include "mozilla/layout/RenderFrameChild.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
@ -106,6 +107,40 @@ TabChild::TabChild(PRUint32 aChromeFlags, bool aIsBrowserElement,
|
|||
printf("creating %d!\n", NS_IsMainThread());
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabChild::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
if (!strcmp(aTopic, "dom-touch-listener-added")) {
|
||||
nsCOMPtr<nsIDOMWindow> subject(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsIDOMWindow> win(do_GetInterface(mWebNav));
|
||||
nsCOMPtr<nsIDOMWindow> topSubject;
|
||||
subject->GetTop(getter_AddRefs(topSubject));
|
||||
if (win == topSubject) {
|
||||
SendNotifyDOMTouchListenerAdded();
|
||||
}
|
||||
} else if (!strcmp(aTopic, "cancel-default-pan-zoom")) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
|
||||
if (tabChild == this) {
|
||||
mRemoteFrame->CancelDefaultPanZoom();
|
||||
}
|
||||
} else if (!strcmp(aTopic, "browser-zoom-to-rect")) {
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
|
||||
if (tabChild == this) {
|
||||
gfxRect rect;
|
||||
sscanf(NS_ConvertUTF16toUTF8(aData).get(),
|
||||
"{\"x\":%lf,\"y\":%lf,\"w\":%lf,\"h\":%lf}",
|
||||
&rect.x, &rect.y, &rect.width, &rect.height);
|
||||
SendZoomToRect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabChild::Init()
|
||||
{
|
||||
|
@ -121,6 +156,22 @@ TabChild::Init()
|
|||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(mWebNav));
|
||||
docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
|
||||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
|
||||
|
||||
if (observerService) {
|
||||
observerService->AddObserver(this,
|
||||
"dom-touch-listener-added",
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
"cancel-default-pan-zoom",
|
||||
false);
|
||||
observerService->AddObserver(this,
|
||||
"browser-zoom-to-rect",
|
||||
false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -384,10 +435,16 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
|||
{
|
||||
*aReturn = nullptr;
|
||||
|
||||
nsRefPtr<TabChild> newChild =
|
||||
static_cast<TabChild*>(Manager()->SendPBrowserConstructor(
|
||||
/* aChromeFlags = */ 0, mIsBrowserElement, mAppId));
|
||||
|
||||
PRUint32 chromeFlags = 0;
|
||||
nsRefPtr<TabChild> newChild = new TabChild(chromeFlags,
|
||||
mIsBrowserElement, mAppId);
|
||||
if (!NS_SUCCEEDED(newChild->Init())) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
unused << Manager()->SendPBrowserConstructor(
|
||||
// We release this ref in DeallocPBrowserChild
|
||||
nsRefPtr<TabChild>(newChild).forget().get(),
|
||||
chromeFlags, mIsBrowserElement, this);
|
||||
nsCAutoString spec;
|
||||
if (aURI) {
|
||||
aURI->GetSpec(spec);
|
||||
|
@ -644,41 +701,17 @@ TabChild::RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort,
|
||||
const nsIntPoint& aScrollOffset,
|
||||
const gfxSize& aResolution,
|
||||
const nsIntRect& aScreenSize)
|
||||
void
|
||||
TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
|
||||
const nsACString& aJSONData)
|
||||
{
|
||||
if (!mCx || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
nsCString data;
|
||||
data += nsPrintfCString("{ \"x\" : %d", aScrollOffset.x);
|
||||
data += nsPrintfCString(", \"y\" : %d", aScrollOffset.y);
|
||||
// We don't treat the x and y scales any differently for this
|
||||
// semi-platform-specific code.
|
||||
data += nsPrintfCString(", \"zoom\" : %f", aResolution.width);
|
||||
data += nsPrintfCString(", \"displayPort\" : ");
|
||||
data += nsPrintfCString("{ \"left\" : %d", aDisplayPort.X());
|
||||
data += nsPrintfCString(", \"top\" : %d", aDisplayPort.Y());
|
||||
data += nsPrintfCString(", \"width\" : %d", aDisplayPort.Width());
|
||||
data += nsPrintfCString(", \"height\" : %d", aDisplayPort.Height());
|
||||
data += nsPrintfCString(", \"resolution\" : %f", aResolution.width);
|
||||
data += nsPrintfCString(" }");
|
||||
data += nsPrintfCString(", \"screenSize\" : ");
|
||||
data += nsPrintfCString("{ \"width\" : %d", aScreenSize.width);
|
||||
data += nsPrintfCString(", \"height\" : %d", aScreenSize.height);
|
||||
data += nsPrintfCString(" }");
|
||||
data += nsPrintfCString(" }");
|
||||
|
||||
JSAutoRequest ar(mCx);
|
||||
jsval json = JSVAL_NULL;
|
||||
StructuredCloneData cloneData;
|
||||
JSAutoStructuredCloneBuffer buffer;
|
||||
if (JS_ParseJSON(mCx,
|
||||
static_cast<const jschar*>(NS_ConvertUTF8toUTF16(data).get()),
|
||||
data.Length(),
|
||||
static_cast<const jschar*>(NS_ConvertUTF8toUTF16(aJSONData).get()),
|
||||
aJSONData.Length(),
|
||||
&json)) {
|
||||
WriteStructuredClone(mCx, json, buffer, cloneData.mClosure);
|
||||
cloneData.mData = buffer.data();
|
||||
|
@ -691,8 +724,60 @@ TabChild::RecvUpdateFrame(const nsIntRect& aDisplayPort,
|
|||
nsRefPtr<nsFrameMessageManager> mm =
|
||||
static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
|
||||
mm->ReceiveMessage(static_cast<nsIDOMEventTarget*>(mTabChildGlobal),
|
||||
NS_LITERAL_STRING("Viewport:Change"), false,
|
||||
&cloneData, nullptr, nullptr);
|
||||
aMessageName, false, &cloneData, nullptr, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
if (!mCx || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCString data;
|
||||
data += nsPrintfCString("{ \"x\" : %d", aFrameMetrics.mViewportScrollOffset.x);
|
||||
data += nsPrintfCString(", \"y\" : %d", aFrameMetrics.mViewportScrollOffset.y);
|
||||
// We don't treat the x and y scales any differently for this
|
||||
// semi-platform-specific code.
|
||||
data += nsPrintfCString(", \"zoom\" : %f", aFrameMetrics.mResolution.width);
|
||||
data += nsPrintfCString(", \"displayPort\" : ");
|
||||
data += nsPrintfCString("{ \"left\" : %d", aFrameMetrics.mDisplayPort.X());
|
||||
data += nsPrintfCString(", \"top\" : %d", aFrameMetrics.mDisplayPort.Y());
|
||||
data += nsPrintfCString(", \"width\" : %d", aFrameMetrics.mDisplayPort.Width());
|
||||
data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mDisplayPort.Height());
|
||||
data += nsPrintfCString(", \"resolution\" : %f", aFrameMetrics.mResolution.width);
|
||||
data += nsPrintfCString(" }");
|
||||
data += nsPrintfCString(", \"screenSize\" : ");
|
||||
data += nsPrintfCString("{ \"width\" : %d", aFrameMetrics.mViewport.width);
|
||||
data += nsPrintfCString(", \"height\" : %d", aFrameMetrics.mViewport.height);
|
||||
data += nsPrintfCString(" }");
|
||||
data += nsPrintfCString(", \"cssPageRect\" : ");
|
||||
data += nsPrintfCString("{ \"x\" : %f", aFrameMetrics.mCSSContentRect.x);
|
||||
data += nsPrintfCString(", \"y\" : %f", aFrameMetrics.mCSSContentRect.y);
|
||||
data += nsPrintfCString(", \"width\" : %f", aFrameMetrics.mCSSContentRect.width);
|
||||
data += nsPrintfCString(", \"height\" : %f", aFrameMetrics.mCSSContentRect.height);
|
||||
data += nsPrintfCString(" }");
|
||||
data += nsPrintfCString(" }");
|
||||
|
||||
DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvHandleDoubleTap(const nsIntPoint& aPoint)
|
||||
{
|
||||
if (!mCx || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCString data;
|
||||
data += nsPrintfCString("{ \"x\" : %d", aPoint.x);
|
||||
data += nsPrintfCString(", \"y\" : %d", aPoint.y);
|
||||
data += nsPrintfCString(" }");
|
||||
|
||||
DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsWeakReference.h"
|
||||
#include "nsITabChild.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "FrameMetrics.h"
|
||||
|
||||
struct gfxMatrix;
|
||||
|
||||
|
@ -140,7 +141,8 @@ class TabChild : public PBrowserChild,
|
|||
public nsIWindowProvider,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIDialogCreator,
|
||||
public nsITabChild
|
||||
public nsITabChild,
|
||||
public nsIObserver
|
||||
{
|
||||
typedef mozilla::layout::RenderFrameChild RenderFrameChild;
|
||||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
@ -157,6 +159,8 @@ public:
|
|||
virtual ~TabChild();
|
||||
nsresult Init();
|
||||
|
||||
PRUint32 GetAppId() { return mAppId; }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBBROWSERCHROME
|
||||
NS_DECL_NSIWEBBROWSERCHROME2
|
||||
|
@ -166,14 +170,13 @@ public:
|
|||
NS_DECL_NSIWINDOWPROVIDER
|
||||
NS_DECL_NSIDIALOGCREATOR
|
||||
NS_DECL_NSITABCHILD
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
virtual bool RecvLoadURL(const nsCString& uri);
|
||||
virtual bool RecvShow(const nsIntSize& size);
|
||||
virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size);
|
||||
virtual bool RecvUpdateFrame(const nsIntRect& aDisplayPort,
|
||||
const nsIntPoint& aScrollOffset,
|
||||
const gfxSize& aResolution,
|
||||
const nsIntRect& aScreenSize);
|
||||
virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
|
||||
virtual bool RecvHandleDoubleTap(const nsIntPoint& aPoint);
|
||||
virtual bool RecvActivate();
|
||||
virtual bool RecvDeactivate();
|
||||
virtual bool RecvMouseEvent(const nsString& aType,
|
||||
|
@ -287,6 +290,14 @@ private:
|
|||
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
|
||||
void DoFakeShow();
|
||||
|
||||
// Wraps up a JSON object as a structured clone and sends it to the browser
|
||||
// chrome script.
|
||||
//
|
||||
// XXX/bug 780335: Do the work the browser chrome script does in C++ instead
|
||||
// so we don't need things like this.
|
||||
void DispatchMessageManagerMessage(const nsAString& aMessageName,
|
||||
const nsACString& aJSONData);
|
||||
|
||||
nsresult
|
||||
BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
nsIURI* aURI,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Blob.h"
|
||||
#include "IDBFactory.h"
|
||||
#include "IndexedDBParent.h"
|
||||
#include "mozIApplication.h"
|
||||
#include "mozilla/BrowserElementParent.h"
|
||||
#include "mozilla/docshell/OfflineCacheUpdateParent.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include "nsFocusManager.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMApplicationRegistry.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
|
@ -36,6 +38,7 @@
|
|||
#include "nsIPromptFactory.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
|
@ -52,6 +55,7 @@ using namespace mozilla::dom;
|
|||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::layout;
|
||||
using namespace mozilla::services;
|
||||
using namespace mozilla::widget;
|
||||
using namespace mozilla::dom::indexedDB;
|
||||
|
||||
|
@ -66,8 +70,9 @@ TabParent *TabParent::mIMETabParent = nullptr;
|
|||
|
||||
NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
|
||||
|
||||
TabParent::TabParent()
|
||||
TabParent::TabParent(mozIApplication* aApp, bool aIsBrowserElement)
|
||||
: mFrameElement(NULL)
|
||||
, mApp(aApp)
|
||||
, mIMESelectionAnchor(0)
|
||||
, mIMESelectionFocus(0)
|
||||
, mIMEComposing(false)
|
||||
|
@ -76,6 +81,7 @@ TabParent::TabParent()
|
|||
, mIMESeqno(0)
|
||||
, mDPI(0)
|
||||
, mActive(false)
|
||||
, mIsBrowserElement(aIsBrowserElement)
|
||||
, mShown(false)
|
||||
{
|
||||
}
|
||||
|
@ -225,10 +231,12 @@ TabParent::UpdateDimensions(const nsRect& rect, const nsIntSize& size)
|
|||
void
|
||||
TabParent::UpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
unused << SendUpdateFrame(aFrameMetrics.mDisplayPort,
|
||||
aFrameMetrics.mViewportScrollOffset,
|
||||
aFrameMetrics.mResolution,
|
||||
aFrameMetrics.mViewport);
|
||||
unused << SendUpdateFrame(aFrameMetrics);
|
||||
}
|
||||
|
||||
void TabParent::HandleDoubleTap(const nsIntPoint& aPoint)
|
||||
{
|
||||
unused << SendHandleDoubleTap(aPoint);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1090,5 +1098,23 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvNotifyDOMTouchListenerAdded()
|
||||
{
|
||||
if (RenderFrameParent* rfp = GetRenderFrame()) {
|
||||
rfp->NotifyDOMTouchListenerAdded();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvZoomToRect(const gfxRect& aRect)
|
||||
{
|
||||
if (RenderFrameParent* rfp = GetRenderFrame()) {
|
||||
rfp->ZoomToRect(aRect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace tabs
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
struct gfxMatrix;
|
||||
struct JSContext;
|
||||
struct JSObject;
|
||||
class mozIApplication;
|
||||
class nsFrameLoader;
|
||||
class nsIDOMElement;
|
||||
class nsIURI;
|
||||
|
@ -53,7 +54,7 @@ class TabParent : public PBrowserParent
|
|||
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
|
||||
|
||||
public:
|
||||
TabParent();
|
||||
TabParent(mozIApplication* aApp, bool aIsBrowserElement);
|
||||
virtual ~TabParent();
|
||||
nsIDOMElement* GetOwnerElement() { return mFrameElement; }
|
||||
void SetOwnerElement(nsIDOMElement* aElement);
|
||||
|
@ -62,6 +63,9 @@ public:
|
|||
mBrowserDOMWindow = aBrowserDOMWindow;
|
||||
}
|
||||
|
||||
mozIApplication* GetApp() { return mApp; }
|
||||
bool IsBrowserElement() { return mIsBrowserElement; }
|
||||
|
||||
void Destroy();
|
||||
|
||||
virtual bool RecvMoveFocus(const bool& aForward);
|
||||
|
@ -101,6 +105,8 @@ public:
|
|||
virtual bool RecvSetBackgroundColor(const nscolor& aValue);
|
||||
virtual bool RecvGetDPI(float* aValue);
|
||||
virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue);
|
||||
virtual bool RecvNotifyDOMTouchListenerAdded();
|
||||
virtual bool RecvZoomToRect(const gfxRect& aRect);
|
||||
virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType,
|
||||
const nsCString& aName,
|
||||
const nsCString& aFeatures,
|
||||
|
@ -120,6 +126,7 @@ public:
|
|||
void Show(const nsIntSize& size);
|
||||
void UpdateDimensions(const nsRect& rect, const nsIntSize& size);
|
||||
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
|
||||
void HandleDoubleTap(const nsIntPoint& aPoint);
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
|
||||
|
@ -224,6 +231,7 @@ protected:
|
|||
uint64_t* aLayersId) MOZ_OVERRIDE;
|
||||
virtual bool DeallocPRenderFrame(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
|
||||
|
||||
nsCOMPtr<mozIApplication> mApp;
|
||||
// IME
|
||||
static TabParent *mIMETabParent;
|
||||
nsString mIMECacheText;
|
||||
|
@ -239,6 +247,7 @@ protected:
|
|||
|
||||
float mDPI;
|
||||
bool mActive;
|
||||
bool mIsBrowserElement;
|
||||
bool mShown;
|
||||
|
||||
private:
|
||||
|
|
|
@ -24,21 +24,21 @@ NS_IMPL_ISUPPORTS1(AlertServiceObserver, nsIObserver)
|
|||
/* nsDesktopNotification */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
void
|
||||
nsresult
|
||||
nsDOMDesktopNotification::PostDesktopNotification()
|
||||
{
|
||||
nsCOMPtr<nsIAlertsService> alerts = do_GetService("@mozilla.org/alerts-service;1");
|
||||
if (!alerts)
|
||||
return;
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if (!mObserver)
|
||||
mObserver = new AlertServiceObserver(this);
|
||||
|
||||
alerts->ShowAlertNotification(mIconURL, mTitle, mDescription,
|
||||
true,
|
||||
EmptyString(),
|
||||
mObserver,
|
||||
EmptyString());
|
||||
return alerts->ShowAlertNotification(mIconURL, mTitle, mDescription,
|
||||
true,
|
||||
EmptyString(),
|
||||
mObserver,
|
||||
EmptyString());
|
||||
}
|
||||
|
||||
DOMCI_DATA(DesktopNotification, nsDOMDesktopNotification)
|
||||
|
@ -145,14 +145,16 @@ nsDOMDesktopNotification::DispatchNotificationEvent(const nsString& aName)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
nsDOMDesktopNotification::SetAllow(bool aAllow)
|
||||
{
|
||||
mAllow = aAllow;
|
||||
|
||||
// if we have called Show() already, lets go ahead and post a notification
|
||||
if (mShowHasBeenCalled && aAllow)
|
||||
PostDesktopNotification();
|
||||
return PostDesktopNotification();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -176,8 +178,7 @@ nsDOMDesktopNotification::Show()
|
|||
if (!mAllow)
|
||||
return NS_OK;
|
||||
|
||||
PostDesktopNotification();
|
||||
return NS_OK;
|
||||
return PostDesktopNotification();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -277,17 +278,17 @@ nsDesktopNotificationRequest::GetElement(nsIDOMElement * *aElement)
|
|||
NS_IMETHODIMP
|
||||
nsDesktopNotificationRequest::Cancel()
|
||||
{
|
||||
mDesktopNotification->SetAllow(false);
|
||||
nsresult rv = mDesktopNotification->SetAllow(false);
|
||||
mDesktopNotification = nullptr;
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDesktopNotificationRequest::Allow()
|
||||
{
|
||||
mDesktopNotification->SetAllow(true);
|
||||
nsresult rv = mDesktopNotification->SetAllow(true);
|
||||
mDesktopNotification = nullptr;
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -87,9 +87,9 @@ public:
|
|||
* PostDesktopNotification
|
||||
* Uses alert service to display a notification
|
||||
*/
|
||||
void PostDesktopNotification();
|
||||
nsresult PostDesktopNotification();
|
||||
|
||||
void SetAllow(bool aAllow);
|
||||
nsresult SetAllow(bool aAllow);
|
||||
|
||||
/*
|
||||
* Creates and dispatches a dom event of type aName
|
||||
|
|
|
@ -21,16 +21,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=317448
|
|||
var x = new XMLHttpRequest();
|
||||
x.open("GET", document.location.href);
|
||||
x.send("");
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
is(x instanceof Components.interfaces.nsIInterfaceRequestor,
|
||||
true, "Must be interface requestor");
|
||||
|
||||
var count = {};
|
||||
var interfaces = x.
|
||||
var interfaces = SpecialPowers.wrap(x).
|
||||
QueryInterface(Components.interfaces.nsIClassInfo).
|
||||
getInterfaces(count).
|
||||
map(function(id) {
|
||||
return Components.interfacesByID[id].toString();
|
||||
id = SpecialPowers.wrap(id);
|
||||
return SpecialPowers.wrap(Components).interfacesByID[id].toString();
|
||||
});
|
||||
isnot(interfaces.indexOf("nsIInterfaceRequestor"), "-1",
|
||||
"Must have interface requestor classinfo");
|
||||
|
|
|
@ -116,9 +116,8 @@ function test5()
|
|||
SimpleTest.executeSoon(function() {
|
||||
// We have to focus back the originating window but we can't do that with
|
||||
// .focus() or .blur() anymore.
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var fm = Components.classes["@mozilla.org/focus-manager;1"].
|
||||
getService(Components.interfaces.nsIFocusManager);
|
||||
var fm = SpecialPowers.wrap(Components).classes["@mozilla.org/focus-manager;1"]
|
||||
.getService(Components.interfaces.nsIFocusManager);
|
||||
fm.focusedWindow = window;
|
||||
});
|
||||
}, w, true);
|
||||
|
@ -126,10 +125,9 @@ function test5()
|
|||
|
||||
function finished()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch)
|
||||
.setBoolPref("dom.disable_window_flip", gOldPrefValue);
|
||||
SpecialPowers.wrap(Components).classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch)
|
||||
.setBoolPref("dom.disable_window_flip", gOldPrefValue);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -137,9 +135,8 @@ SimpleTest.waitForExplicitFinish();
|
|||
|
||||
|
||||
// dom.disable_window_flip has to be set to true for this test.
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
var prefs = SpecialPowers.wrap(Components).classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
gOldPrefValue = prefs.getBoolPref("dom.disable_window_flip");
|
||||
prefs.setBoolPref("dom.disable_window_flip", true);
|
||||
|
||||
|
|
|
@ -153,8 +153,7 @@ function popstateExpected(msg) {
|
|||
}
|
||||
|
||||
function getColor(elem) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var utils = document.defaultView.
|
||||
var utils = SpecialPowers.wrap(document).defaultView.
|
||||
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
return utils.getVisitedDependentComputedStyle(elem, "", "color");
|
||||
|
@ -162,12 +161,10 @@ function getColor(elem) {
|
|||
|
||||
function getSHistory(theWindow)
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
var sh = theWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.sessionHistory;
|
||||
var sh = SpecialPowers.wrap(theWindow.QueryInterface(Ci.nsIInterfaceRequestor))
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.sessionHistory;
|
||||
if (!sh || sh == null)
|
||||
throw("Couldn't get shistory for window!");
|
||||
|
||||
|
@ -176,8 +173,6 @@ function getSHistory(theWindow)
|
|||
|
||||
function getSHTitle(sh, offset)
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
if (!offset)
|
||||
offset = 0;
|
||||
|
||||
|
|
|
@ -22,11 +22,10 @@ var iframe = document.getElementById("load-frame");
|
|||
function enableJS() allowJS(true, iframe);
|
||||
function disableJS() allowJS(false, iframe);
|
||||
function allowJS(allow, frame) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
frame.contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShell)
|
||||
.allowJavascript = allow;
|
||||
SpecialPowers.wrap(frame.contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor))
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShell)
|
||||
.allowJavascript = allow;
|
||||
}
|
||||
function expectJSAllowed(allowed, testCondition, callback) {
|
||||
window.ICanRunMyJS = false;
|
||||
|
|
|
@ -36,10 +36,10 @@ function editDoc() {
|
|||
function getSpellCheckSelection() {
|
||||
var Ci = Components.interfaces;
|
||||
var win = editDoc().defaultView;
|
||||
var editingSession = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession);
|
||||
var editingSession = SpecialPowers.wrap(win.QueryInterface(Ci.nsIInterfaceRequestor))
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession);
|
||||
var editor = editingSession.getEditorForWindow(win);
|
||||
var selcon = editor.selectionController;
|
||||
return selcon.getSelection(selcon.SELECTION_SPELLCHECK);
|
||||
|
@ -51,7 +51,6 @@ function runTest() {
|
|||
}
|
||||
|
||||
function addWords(aLimit) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
if (aLimit == 0) {
|
||||
is(isSpellingCheckOk(), true, "All misspellings accounted for.");
|
||||
SimpleTest.finish();
|
||||
|
|
|
@ -20,8 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=468353
|
|||
var styleSheets = null;
|
||||
|
||||
function checkStylesheets() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
// Evidently RemoveStyleSheet is the only method in nsIEditorStyleSheets
|
||||
// that would throw. RemoveOverrideStyleSheet returns NS_OK even if the
|
||||
// sheet is not there
|
||||
|
@ -43,8 +41,6 @@ function checkStylesheets() {
|
|||
}
|
||||
|
||||
function runTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
|
||||
|
@ -58,7 +54,7 @@ function runTest() {
|
|||
editdoc.designMode='on';
|
||||
|
||||
// Hold the reference to the editor
|
||||
editor = editframe.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
editor = SpecialPowers.wrap(editframe.QueryInterface(Ci.nsIInterfaceRequestor))
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession)
|
||||
|
@ -77,7 +73,7 @@ function runTest() {
|
|||
editdoc.body.contentEditable = true;
|
||||
|
||||
// Hold the reference to the editor
|
||||
editor = editframe.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
editor = SpecialPowers.wrap(editframe.QueryInterface(Ci.nsIInterfaceRequestor))
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession)
|
||||
|
@ -94,7 +90,7 @@ function runTest() {
|
|||
editdoc.designMode = "off";
|
||||
|
||||
// Hold the reference to the editor
|
||||
editor = editframe.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
editor = SpecialPowers.wrap(editframe.QueryInterface(Ci.nsIInterfaceRequestor))
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEditingSession)
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
<script class="testbody" type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
function verifyContent(s) {
|
||||
var e = document.getElementById('i1');
|
||||
var doc = e.contentDocument;
|
||||
|
@ -27,7 +25,7 @@ function runTest() {
|
|||
selection.removeAllRanges();
|
||||
selection.selectAllChildren(e);
|
||||
selection.collapseToEnd();
|
||||
doc.execCommand("paste", false, null);
|
||||
SpecialPowers.wrap(doc).execCommand("paste", false, null);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -51,7 +49,7 @@ function runTest() {
|
|||
range.selectNode(doc.getElementById(target_id));
|
||||
selection.addRange(range);
|
||||
}
|
||||
doc.execCommand("copy", false, null);
|
||||
SpecialPowers.wrap(doc).execCommand("copy", false, null);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
<script class="testbody" type="application/javascript">
|
||||
|
||||
function runTest() {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
function verifyContent(s) {
|
||||
var e = document.getElementById('i1');
|
||||
var doc = e.contentDocument;
|
||||
|
@ -30,7 +28,7 @@ function runTest() {
|
|||
selection.removeAllRanges();
|
||||
selection.selectAllChildren(e);
|
||||
selection.collapseToEnd();
|
||||
doc.execCommand("paste", false, null);
|
||||
SpecialPowers.wrap(doc).execCommand("paste", false, null);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -54,7 +52,7 @@ function runTest() {
|
|||
range.selectNode(doc.getElementById(target_id));
|
||||
selection.addRange(range);
|
||||
}
|
||||
doc.execCommand("copy", false, null);
|
||||
SpecialPowers.wrap(doc).execCommand("copy", false, null);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -550,7 +550,8 @@ function doNextTest() {
|
|||
|
||||
function getLoadContext() {
|
||||
const Ci = Components.interfaces;
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
return SpecialPowers.wrap(window)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext);
|
||||
}
|
||||
|
@ -563,13 +564,11 @@ function runTest(test) {
|
|||
} else
|
||||
elem.focus();
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var trans = Components.classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
var trans = SpecialPowers.wrap(Components).classes["@mozilla.org/widget/transferable;1"]
|
||||
.createInstance(Components.interfaces.nsITransferable);
|
||||
trans.init(getLoadContext());
|
||||
var data = Components.classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
var data = SpecialPowers.wrap(Components).classes["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Components.interfaces.nsISupportsString);
|
||||
data.data = test.payload;
|
||||
trans.addDataFlavor("text/html");
|
||||
trans.setTransferData("text/html", data, data.data.length * 2);
|
||||
|
@ -582,14 +581,14 @@ function runTest(test) {
|
|||
getSelection().collapse(elem, 0);
|
||||
win = window;
|
||||
}
|
||||
editor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIEditorDocShell)
|
||||
.editor;
|
||||
editor = SpecialPowers.wrap(win).QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIEditorDocShell)
|
||||
.editor;
|
||||
editor.pasteTransferable(trans);
|
||||
} else {
|
||||
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService(Components.interfaces.nsIClipboard);
|
||||
var clipboard = SpecialPowers.wrap(Components).classes["@mozilla.org/widget/clipboard;1"]
|
||||
.getService(Components.interfaces.nsIClipboard);
|
||||
|
||||
clipboard.setData(trans, null, Components.interfaces.nsIClipboard.kGlobalClipboard);
|
||||
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
var Cc = Components.classes;
|
||||
var utils = SpecialPowers.wrap(window)
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
var Cc = SpecialPowers.wrap(Components).classes;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
function getLoadContext() {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
return SpecialPowers.wrap(window)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsILoadContext);
|
||||
}
|
||||
|
@ -29,7 +30,6 @@ function runTest() {
|
|||
}
|
||||
|
||||
function pasteInto(trans, html, target_id) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var e = document.getElementById('i1');
|
||||
var doc = e.contentDocument;
|
||||
doc.designMode = "on";
|
||||
|
@ -53,7 +53,6 @@ function runTest() {
|
|||
}
|
||||
|
||||
function getTransferableFromClipboard(asHTML) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var trans = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
|
||||
trans.init(getLoadContext());
|
||||
if (asHTML) {
|
||||
|
@ -67,8 +66,6 @@ function runTest() {
|
|||
}
|
||||
|
||||
function makeTransferable(s,asHTML,target_id) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
var e = document.getElementById('i2');
|
||||
var doc = e.contentDocument;
|
||||
if (asHTML) {
|
||||
|
@ -112,7 +109,6 @@ function runTest() {
|
|||
}
|
||||
|
||||
function copyToClipBoard(s,asHTML,target_id) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var e = document.getElementById('i2');
|
||||
var doc = e.contentDocument;
|
||||
if (asHTML) {
|
||||
|
@ -132,7 +128,7 @@ function runTest() {
|
|||
range.selectNode(doc.getElementById(target_id));
|
||||
selection.addRange(range);
|
||||
}
|
||||
doc.execCommand("copy", false, null);
|
||||
SpecialPowers.wrap(doc).execCommand("copy", false, null);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(runTest);
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
function runDesignModeTest(aDoc, aFocus, aNewSource)
|
||||
{
|
||||
aDoc.designMode = "on";
|
||||
|
@ -83,11 +81,9 @@ var gSetFocusToIFrame = false;
|
|||
|
||||
function onLoadIFrame()
|
||||
{
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
|
||||
var frameDoc = gIFrame.contentWindow.document;
|
||||
|
||||
var selCon = gIFrame.contentWindow.
|
||||
var selCon = SpecialPowers.wrap(gIFrame).contentWindow.
|
||||
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIWebNavigation).
|
||||
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
|
|
|
@ -355,10 +355,7 @@ DrawTargetCairo::DrawSurface(SourceSurface *aSurface,
|
|||
cairo_push_group(mContext);
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
|
||||
//TODO[nrc] remove comments if test ok
|
||||
//cairo_clip(mContext);
|
||||
cairo_set_source(mContext, pat);
|
||||
//cairo_paint(mContext);
|
||||
cairo_fill(mContext);
|
||||
cairo_pop_group_to_source(mContext);
|
||||
} else {
|
||||
|
@ -449,10 +446,7 @@ DrawTargetCairo::DrawSurfaceWithShadow(SourceSurface *aSurface,
|
|||
cairo_push_group(mContext);
|
||||
cairo_new_path(mContext);
|
||||
cairo_rectangle(mContext, 0, 0, width, height);
|
||||
//TODO[nrc] remove comments if test ok
|
||||
//cairo_clip(mContext);
|
||||
cairo_set_source(mContext, pat);
|
||||
//cairo_paint(mContext);
|
||||
cairo_fill(mContext);
|
||||
cairo_pop_group_to_source(mContext);
|
||||
} else {
|
||||
|
|
|
@ -1803,7 +1803,7 @@ DrawTargetD2D::FillGlyphsManual(ScaledFontDWrite *aFont,
|
|||
DWRITE_RENDERING_MODE renderMode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||
if (params) {
|
||||
hr = aFont->mFontFace->GetRecommendedRenderingMode(
|
||||
(FLOAT)aFont->mSize,
|
||||
(FLOAT)aFont->GetSize(),
|
||||
1.0f,
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
params,
|
||||
|
@ -1822,7 +1822,7 @@ DrawTargetD2D::FillGlyphsManual(ScaledFontDWrite *aFont,
|
|||
case DWRITE_RENDERING_MODE_DEFAULT:
|
||||
// As per DWRITE_RENDERING_MODE documentation, pick Natural for font
|
||||
// sizes under 16 ppem
|
||||
if (aFont->mSize < 16.0f) {
|
||||
if (aFont->GetSize() < 16.0f) {
|
||||
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
|
||||
} else {
|
||||
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "2D.h"
|
||||
#include "cairo.h"
|
||||
#include "Logging.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -87,7 +88,10 @@ GfxFormatToCairoFormat(SurfaceFormat format)
|
|||
return CAIRO_FORMAT_RGB24;
|
||||
case FORMAT_A8:
|
||||
return CAIRO_FORMAT_A8;
|
||||
case FORMAT_R5G6B5:
|
||||
return CAIRO_FORMAT_RGB16_565;
|
||||
default:
|
||||
gfxWarning() << "Unknown image format";
|
||||
return CAIRO_FORMAT_ARGB32;
|
||||
}
|
||||
}
|
||||
|
@ -100,10 +104,12 @@ GfxFormatToCairoContent(SurfaceFormat format)
|
|||
case FORMAT_B8G8R8A8:
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
case FORMAT_B8G8R8X8:
|
||||
case FORMAT_R5G6B5: //fall through
|
||||
return CAIRO_CONTENT_COLOR;
|
||||
case FORMAT_A8:
|
||||
return CAIRO_CONTENT_ALPHA;
|
||||
default:
|
||||
gfxWarning() << "Unknown image format";
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +156,7 @@ CairoContentToGfxFormat(cairo_content_t content)
|
|||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
return FORMAT_B8G8R8A8;
|
||||
case CAIRO_CONTENT_COLOR:
|
||||
// BEWARE! format may be 565
|
||||
return FORMAT_B8G8R8X8;
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
return FORMAT_A8;
|
||||
|
|
|
@ -242,7 +242,7 @@ DWriteGlyphRunFromGlyphs(const GlyphBuffer &aGlyphs, ScaledFontDWrite *aFont, Au
|
|||
|
||||
run->bidiLevel = 0;
|
||||
run->fontFace = aFont->mFontFace;
|
||||
run->fontEmSize = aFont->mSize;
|
||||
run->fontEmSize = aFont->GetSize();
|
||||
run->glyphCount = aGlyphs.mNumGlyphs;
|
||||
run->isSideways = FALSE;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ public:
|
|||
|
||||
virtual void CopyGlyphsToBuilder(const GlyphBuffer &aBuffer, PathBuilder *aBuilder);
|
||||
|
||||
float GetSize() { return mSize; }
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface() { return mTypeface; }
|
||||
#endif
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
#ifndef MOZILLA_GFX_SCALEDFONTDWRITE_H_
|
||||
#define MOZILLA_GFX_SCALEDFONTDWRITE_H_
|
||||
|
||||
#include "2D.h"
|
||||
#include <dwrite.h>
|
||||
#include "ScaledFontBase.h"
|
||||
|
||||
struct ID2D1GeometrySink;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class ScaledFontDWrite : public ScaledFont
|
||||
class ScaledFontDWrite : public ScaledFontBase
|
||||
{
|
||||
public:
|
||||
ScaledFontDWrite(IDWriteFontFace *aFont, Float aSize)
|
||||
: mFontFace(aFont)
|
||||
, mSize(aSize)
|
||||
, ScaledFontBase(aSize)
|
||||
{}
|
||||
|
||||
virtual FontType GetType() const { return FONT_DWRITE; }
|
||||
|
@ -29,8 +29,15 @@ public:
|
|||
|
||||
void CopyGlyphsToSink(const GlyphBuffer &aBuffer, ID2D1GeometrySink *aSink);
|
||||
|
||||
#ifdef USE_SKIA
|
||||
virtual SkTypeface* GetSkTypeface()
|
||||
{
|
||||
MOZ_ASSERT(false, "Skia and DirectWrite do not mix");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
RefPtr<IDWriteFontFace> mFontFace;
|
||||
Float mSize;
|
||||
};
|
||||
|
||||
class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions
|
||||
|
|
|
@ -6,19 +6,26 @@
|
|||
|
||||
#include "CompositorParent.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Constants.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "mozilla/XPCOM.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "AsyncPanZoomController.h"
|
||||
#include "GestureEventListener.h"
|
||||
#include "nsIThreadManager.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "Layers.h"
|
||||
#include "AnimationCommon.h"
|
||||
|
||||
using namespace mozilla::css;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
const float AsyncPanZoomController::TOUCH_START_TOLERANCE = 1.0f/16.0f;
|
||||
|
||||
static const float EPSILON = 0.0001;
|
||||
|
||||
/**
|
||||
|
@ -44,6 +51,26 @@ static const float MIN_SKATE_SPEED = 0.5f;
|
|||
*/
|
||||
static const float AXIS_LOCK_ANGLE = M_PI / 6.0;
|
||||
|
||||
/**
|
||||
* Duration of a zoom to animation.
|
||||
*/
|
||||
static const TimeDuration ZOOM_TO_DURATION = TimeDuration::FromSeconds(0.25);
|
||||
|
||||
/**
|
||||
* Computed time function used for sampling frames of a zoom to animation.
|
||||
*/
|
||||
StaticAutoPtr<ComputedTimingFunction> gComputedTimingFunction;
|
||||
|
||||
/**
|
||||
* Maximum zoom amount, always used, even if a page asks for higher.
|
||||
*/
|
||||
static const double MAX_ZOOM = 8.0;
|
||||
|
||||
/**
|
||||
* Minimum zoom amount, always used, even if a page asks for lower.
|
||||
*/
|
||||
static const double MIN_ZOOM = 0.125;
|
||||
|
||||
AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoContentController,
|
||||
GestureBehavior aGestures)
|
||||
: mGeckoContentController(aGeckoContentController),
|
||||
|
@ -53,13 +80,22 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
|
|||
mLastSampleTime(TimeStamp::Now()),
|
||||
mState(NOTHING),
|
||||
mDPI(72),
|
||||
mContentPainterStatus(CONTENT_IDLE)
|
||||
mContentPainterStatus(CONTENT_IDLE),
|
||||
mMayHaveTouchListeners(false),
|
||||
mDisableNextTouchBatch(false)
|
||||
{
|
||||
if (aGestures == USE_GESTURE_DETECTOR) {
|
||||
mGestureEventListener = new GestureEventListener(this);
|
||||
}
|
||||
|
||||
SetDPI(mDPI);
|
||||
|
||||
if (!gComputedTimingFunction) {
|
||||
gComputedTimingFunction = new ComputedTimingFunction();
|
||||
gComputedTimingFunction->Init(
|
||||
nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
|
||||
ClearOnShutdown(&gComputedTimingFunction);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncPanZoomController::~AsyncPanZoomController() {
|
||||
|
@ -146,7 +182,7 @@ AsyncPanZoomController::HandleInputEvent(const nsInputEvent& aEvent,
|
|||
nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) {
|
||||
nsEventStatus rv = nsEventStatus_eIgnore;
|
||||
|
||||
if (mGestureEventListener) {
|
||||
if (mGestureEventListener && !mDisableNextTouchBatch) {
|
||||
nsEventStatus rv = mGestureEventListener->HandleInputEvent(aEvent);
|
||||
if (rv == nsEventStatus_eConsumeNoDefault)
|
||||
return rv;
|
||||
|
@ -200,13 +236,19 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
|||
PRInt32 xPos = point.x, yPos = point.y;
|
||||
|
||||
switch (mState) {
|
||||
case ANIMATING_ZOOM:
|
||||
// We just interrupted a double-tap animation, so force a redraw in case
|
||||
// this touchstart is just a tap that doesn't end up triggering a redraw.
|
||||
RequestContentRepaint();
|
||||
ScheduleComposite();
|
||||
// Fall through.
|
||||
case FLING:
|
||||
CancelAnimation();
|
||||
// Fall through.
|
||||
case NOTHING:
|
||||
mX.StartTouch(xPos);
|
||||
mY.StartTouch(yPos);
|
||||
mState = TOUCHING;
|
||||
SetState(TOUCHING);
|
||||
break;
|
||||
case TOUCHING:
|
||||
case PANNING:
|
||||
|
@ -222,20 +264,28 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) {
|
||||
if (mDisableNextTouchBatch) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
switch (mState) {
|
||||
case FLING:
|
||||
case NOTHING:
|
||||
case ANIMATING_ZOOM:
|
||||
// May happen if the user double-taps and drags without lifting after the
|
||||
// second tap. Ignore the move if this happens.
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case TOUCHING: {
|
||||
float panThreshold = 1.0f/2.0f * mDPI;
|
||||
float panThreshold = TOUCH_START_TOLERANCE * mDPI;
|
||||
UpdateWithTouchAtDevicePoint(aEvent);
|
||||
|
||||
if (PanDistance() < panThreshold) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
StartPanning(aEvent);
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
|
@ -253,18 +303,24 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent)
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) {
|
||||
if (mDisableNextTouchBatch) {
|
||||
mDisableNextTouchBatch = false;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
switch (mState) {
|
||||
case FLING:
|
||||
// Should never happen.
|
||||
NS_WARNING("Received impossible touch end in OnTouchEnd.");
|
||||
// Fall through.
|
||||
case ANIMATING_ZOOM:
|
||||
case NOTHING:
|
||||
// May happen if the user double-taps and drags without lifting after the
|
||||
// second tap. Ignore if this happens.
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case TOUCHING:
|
||||
mState = NOTHING;
|
||||
SetState(NOTHING);
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
case PANNING:
|
||||
|
@ -273,10 +329,10 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
|||
ScheduleComposite();
|
||||
RequestContentRepaint();
|
||||
}
|
||||
mState = FLING;
|
||||
SetState(FLING);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
case PINCHING:
|
||||
mState = NOTHING;
|
||||
SetState(NOTHING);
|
||||
// Scale gesture listener should have handled this.
|
||||
NS_WARNING("Gesture listener should have handled pinching in OnTouchEnd.");
|
||||
return nsEventStatus_eIgnore;
|
||||
|
@ -286,12 +342,12 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEvent) {
|
||||
mState = NOTHING;
|
||||
SetState(NOTHING);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) {
|
||||
mState = PINCHING;
|
||||
SetState(PINCHING);
|
||||
mLastZoomFocus = aEvent.mFocusPoint;
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
|
@ -329,14 +385,14 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
|
|||
PRInt32 neededDisplacementX = 0, neededDisplacementY = 0;
|
||||
|
||||
// Only do the scaling if we won't go over 8x zoom in or out.
|
||||
bool doScale = (scale < 8.0f && spanRatio > 1.0f) || (scale > 0.125f && spanRatio < 1.0f);
|
||||
bool doScale = (scale < MAX_ZOOM && spanRatio > 1.0f) || (scale > MIN_ZOOM && spanRatio < 1.0f);
|
||||
|
||||
// If this zoom will take it over 8x zoom in either direction, but it's not
|
||||
// already there, then normalize it.
|
||||
if (scale * spanRatio > 8.0f) {
|
||||
spanRatio = scale / 8.0f;
|
||||
} else if (scale * spanRatio < 0.125f) {
|
||||
spanRatio = scale / 0.125f;
|
||||
if (scale * spanRatio > MAX_ZOOM) {
|
||||
spanRatio = scale / MAX_ZOOM;
|
||||
} else if (scale * spanRatio < MIN_ZOOM) {
|
||||
spanRatio = scale / MIN_ZOOM;
|
||||
}
|
||||
|
||||
if (doScale) {
|
||||
|
@ -393,7 +449,7 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) {
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent) {
|
||||
mState = PANNING;
|
||||
SetState(PANNING);
|
||||
mX.StartTouch(aEvent.mFocusPoint.x);
|
||||
mY.StartTouch(aEvent.mFocusPoint.y);
|
||||
{
|
||||
|
@ -421,7 +477,15 @@ nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
|
||||
// XXX: Implement this.
|
||||
if (mGeckoContentController) {
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
|
||||
gfx::Point point = WidgetSpaceToCompensatedViewportSpace(
|
||||
gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y),
|
||||
mFrameMetrics.mResolution.width);
|
||||
mGeckoContentController->HandleDoubleTap(nsIntPoint(NS_lround(point.x), NS_lround(point.y)));
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
|
@ -431,14 +495,12 @@ nsEventStatus AsyncPanZoomController::OnCancelTap(const TapGestureInput& aEvent)
|
|||
}
|
||||
|
||||
float AsyncPanZoomController::PanDistance() {
|
||||
return NS_hypot(mX.PanDistance(), mY.PanDistance()) * mFrameMetrics.mResolution.width;
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
return NS_hypot(mX.PanDistance(), mY.PanDistance());
|
||||
}
|
||||
|
||||
const nsPoint AsyncPanZoomController::GetVelocityVector() {
|
||||
return nsPoint(
|
||||
mX.GetVelocity(),
|
||||
mY.GetVelocity()
|
||||
);
|
||||
const gfx::Point AsyncPanZoomController::GetVelocityVector() {
|
||||
return gfx::Point(mX.GetVelocity(), mY.GetVelocity());
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
|
||||
|
@ -452,7 +514,7 @@ void AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
|
|||
|
||||
mX.StartTouch(touch.mScreenPoint.x);
|
||||
mY.StartTouch(touch.mScreenPoint.y);
|
||||
mState = PANNING;
|
||||
SetState(PANNING);
|
||||
|
||||
if (angle < AXIS_LOCK_ANGLE || angle > (M_PI - AXIS_LOCK_ANGLE)) {
|
||||
mY.LockPanning();
|
||||
|
@ -559,7 +621,7 @@ void AsyncPanZoomController::SetPageRect(const gfx::Rect& aCSSPageRect) {
|
|||
float scale = mFrameMetrics.mResolution.width;
|
||||
|
||||
// The page rect is the css page rect scaled by the current zoom.
|
||||
pageSize.ScaleRoundOut(scale);
|
||||
pageSize.ScaleRoundOut(1 / scale);
|
||||
|
||||
// Round the page rect so we don't get any truncation, then get the nsIntRect
|
||||
// from this.
|
||||
|
@ -573,7 +635,8 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc
|
|||
FrameMetrics metrics(mFrameMetrics);
|
||||
|
||||
// Don't set the scale to the inputted value, but rather multiply it in.
|
||||
float scaleFactor = aScale / metrics.mResolution.width;
|
||||
float scaleFactor = aScale / metrics.mResolution.width,
|
||||
oldScale = metrics.mResolution.width;
|
||||
|
||||
metrics.mResolution.width = metrics.mResolution.height = aScale;
|
||||
|
||||
|
@ -583,21 +646,38 @@ void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFoc
|
|||
|
||||
nsIntPoint scrollOffset = metrics.mViewportScrollOffset;
|
||||
|
||||
scrollOffset.x += aFocus.x * (scaleFactor - 1.0f);
|
||||
scrollOffset.y += aFocus.y * (scaleFactor - 1.0f);
|
||||
scrollOffset.x += NS_lround(float(aFocus.x) * (scaleFactor - 1.0f) / oldScale);
|
||||
scrollOffset.y += NS_lround(float(aFocus.y) * (scaleFactor - 1.0f) / oldScale);
|
||||
|
||||
metrics.mViewportScrollOffset = scrollOffset;
|
||||
|
||||
mFrameMetrics = metrics;
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::EnlargeDisplayPortAlongAxis(float aViewport,
|
||||
float aVelocity,
|
||||
float* aDisplayPortOffset,
|
||||
float* aDisplayPortLength)
|
||||
{
|
||||
const float MIN_SKATE_SIZE_MULTIPLIER = 2.0f;
|
||||
const float MAX_SKATE_SIZE_MULTIPLIER = 4.0f;
|
||||
|
||||
if (fabsf(aVelocity) > MIN_SKATE_SPEED) {
|
||||
*aDisplayPortLength = aViewport * clamped(fabsf(aVelocity),
|
||||
MIN_SKATE_SIZE_MULTIPLIER, MAX_SKATE_SIZE_MULTIPLIER);
|
||||
*aDisplayPortOffset = aVelocity > 0 ? 0 : aViewport - *aDisplayPortLength;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() {
|
||||
float scale = mFrameMetrics.mResolution.width;
|
||||
nsIntRect viewport = mFrameMetrics.mViewport;
|
||||
viewport.ScaleRoundIn(1 / scale);
|
||||
|
||||
nsIntPoint scrollOffset = mFrameMetrics.mViewportScrollOffset;
|
||||
nsPoint velocity = GetVelocityVector();
|
||||
gfx::Point velocity = GetVelocityVector();
|
||||
|
||||
// The displayport is relative to the current scroll offset. Here's a little
|
||||
// diagram to make it easier to see:
|
||||
|
@ -624,28 +704,25 @@ const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() {
|
|||
// and far top, it is clear that this distance is 1/4 of the displayport's
|
||||
// height/width dimension.
|
||||
const float STATIONARY_SIZE_MULTIPLIER = 2.0f;
|
||||
const float SKATE_SIZE_MULTIPLIER = 3.0f;
|
||||
gfx::Rect displayPort(0, 0,
|
||||
viewport.width * STATIONARY_SIZE_MULTIPLIER,
|
||||
viewport.height * STATIONARY_SIZE_MULTIPLIER);
|
||||
|
||||
// Iff there's motion along only one axis of movement, and it's above a
|
||||
// threshold, then we want to paint a larger area in the direction of that
|
||||
// motion so that it's less likely to checkerboard. Also note that the other
|
||||
// axis doesn't need its displayport enlarged beyond the viewport dimension,
|
||||
// since it is impossible for it to checkerboard along that axis until motion
|
||||
// begins on it.
|
||||
if (fabsf(velocity.x) > MIN_SKATE_SPEED && fabsf(velocity.y) < MIN_SKATE_SPEED) {
|
||||
displayPort.height = viewport.height;
|
||||
displayPort.width = viewport.width * SKATE_SIZE_MULTIPLIER;
|
||||
displayPort.x = velocity.x > 0 ? 0 : viewport.width - displayPort.width;
|
||||
} else if (fabsf(velocity.x) < MIN_SKATE_SPEED && fabsf(velocity.y) > MIN_SKATE_SPEED) {
|
||||
displayPort.width = viewport.width;
|
||||
displayPort.height = viewport.height * SKATE_SIZE_MULTIPLIER;
|
||||
displayPort.y = velocity.y > 0 ? 0 : viewport.height - displayPort.height;
|
||||
} else {
|
||||
// If there's motion along an axis of movement, and it's above a threshold,
|
||||
// then we want to paint a larger area in the direction of that motion so that
|
||||
// it's less likely to checkerboard.
|
||||
bool enlargedX = EnlargeDisplayPortAlongAxis(
|
||||
viewport.width, velocity.x, &displayPort.x, &displayPort.width);
|
||||
bool enlargedY = EnlargeDisplayPortAlongAxis(
|
||||
viewport.height, velocity.y, &displayPort.y, &displayPort.height);
|
||||
|
||||
if (!enlargedX && !enlargedY) {
|
||||
displayPort.x = -displayPort.width / 4;
|
||||
displayPort.y = -displayPort.height / 4;
|
||||
} else if (!enlargedX) {
|
||||
displayPort.width = viewport.width;
|
||||
} else if (!enlargedY) {
|
||||
displayPort.height = viewport.height;
|
||||
}
|
||||
|
||||
gfx::Rect shiftedDisplayPort = displayPort;
|
||||
|
@ -663,6 +740,10 @@ void AsyncPanZoomController::SetDPI(int aDPI) {
|
|||
mDPI = aDPI;
|
||||
}
|
||||
|
||||
int AsyncPanZoomController::GetDPI() {
|
||||
return mDPI;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScheduleComposite() {
|
||||
if (mCompositorParent) {
|
||||
mCompositorParent->ScheduleRenderOnCompositorThread();
|
||||
|
@ -716,9 +797,43 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
|||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
||||
// If a fling is currently happening, apply it now. We can pull the updated
|
||||
// metrics afterwards.
|
||||
requestAnimationFrame = requestAnimationFrame || DoFling(aSampleTime - mLastSampleTime);
|
||||
switch (mState)
|
||||
{
|
||||
case FLING:
|
||||
// If a fling is currently happening, apply it now. We can pull the updated
|
||||
// metrics afterwards.
|
||||
requestAnimationFrame |= DoFling(aSampleTime - mLastSampleTime);
|
||||
break;
|
||||
case ANIMATING_ZOOM: {
|
||||
double animPosition = (aSampleTime - mAnimationStartTime) / ZOOM_TO_DURATION;
|
||||
if (animPosition > 1.0) {
|
||||
animPosition = 1.0;
|
||||
}
|
||||
double sampledPosition = gComputedTimingFunction->GetValue(animPosition);
|
||||
|
||||
mFrameMetrics.mResolution.width = mFrameMetrics.mResolution.height =
|
||||
mEndZoomToMetrics.mResolution.width * sampledPosition +
|
||||
mStartZoomToMetrics.mResolution.width * (1 - sampledPosition);
|
||||
|
||||
mFrameMetrics.mViewportScrollOffset = nsIntPoint(
|
||||
mEndZoomToMetrics.mViewportScrollOffset.x * sampledPosition +
|
||||
mStartZoomToMetrics.mViewportScrollOffset.x * (1 - sampledPosition),
|
||||
mEndZoomToMetrics.mViewportScrollOffset.y * sampledPosition +
|
||||
mStartZoomToMetrics.mViewportScrollOffset.y * (1 - sampledPosition)
|
||||
);
|
||||
|
||||
requestAnimationFrame = true;
|
||||
|
||||
if (aSampleTime - mAnimationStartTime >= ZOOM_TO_DURATION) {
|
||||
mState = NOTHING;
|
||||
RequestContentRepaint();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Current local transform; this is not what's painted but rather what PZC has
|
||||
// transformed due to touches like panning or pinching. Eventually, the root
|
||||
|
@ -784,7 +899,11 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
|
|||
// we get a larger displayport. This is very bad because we're wasting a
|
||||
// paint and not initializating the displayport correctly.
|
||||
RequestContentRepaint();
|
||||
} else if (!mFrameMetrics.mContentRect.IsEqualEdges(aViewportFrame.mContentRect)) {
|
||||
|
||||
// Assuming a first paint means a new page has been loaded, clear the flag
|
||||
// indicating that we may have touch listeners.
|
||||
mMayHaveTouchListeners = false;
|
||||
} else if (!mFrameMetrics.mCSSContentRect.IsEqualEdges(aViewportFrame.mCSSContentRect)) {
|
||||
mFrameMetrics.mCSSContentRect = aViewportFrame.mCSSContentRect;
|
||||
SetPageRect(mFrameMetrics.mCSSContentRect);
|
||||
}
|
||||
|
@ -802,5 +921,95 @@ void AsyncPanZoomController::UpdateViewportSize(int aWidth, int aHeight) {
|
|||
mFrameMetrics = metrics;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::NotifyDOMTouchListenerAdded() {
|
||||
mMayHaveTouchListeners = true;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::CancelDefaultPanZoom() {
|
||||
mDisableNextTouchBatch = true;
|
||||
if (mGestureEventListener) {
|
||||
mGestureEventListener->CancelGesture();
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
|
||||
gfx::Rect zoomToRect(gfx::Rect(aRect.x, aRect.y, aRect.width, aRect.height));
|
||||
gfx::Rect cssPageRect = mFrameMetrics.mCSSContentRect;
|
||||
|
||||
SetState(ANIMATING_ZOOM);
|
||||
|
||||
{
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
||||
nsIntRect viewport = mFrameMetrics.mViewport;
|
||||
|
||||
// If the rect is empty, treat it as a request to zoom out to the full page
|
||||
// size.
|
||||
if (zoomToRect.IsEmpty()) {
|
||||
nsIntRect cssViewport = viewport;
|
||||
cssViewport.ScaleRoundIn(1 / mFrameMetrics.mResolution.width);
|
||||
cssViewport.MoveBy(mFrameMetrics.mViewportScrollOffset);
|
||||
|
||||
float y = mFrameMetrics.mViewportScrollOffset.y;
|
||||
float newHeight = cssViewport.height * cssPageRect.width / cssViewport.width;
|
||||
float dh = cssViewport.height - newHeight;
|
||||
|
||||
zoomToRect = gfx::Rect(0.0f,
|
||||
y + dh/2,
|
||||
cssPageRect.width,
|
||||
y + dh/2 + newHeight);
|
||||
} else {
|
||||
float targetRatio = float(viewport.width) / float(viewport.height);
|
||||
float rectRatio = zoomToRect.width / zoomToRect.height;
|
||||
|
||||
if (fabsf(targetRatio - rectRatio) < EPSILON) {
|
||||
// All good, do nothing.
|
||||
} else if (targetRatio < rectRatio) {
|
||||
// Need to increase zoomToRect height.
|
||||
float newHeight = zoomToRect.height / targetRatio;
|
||||
zoomToRect.y -= (newHeight - zoomToRect.height) / 2;
|
||||
zoomToRect.height = newHeight;
|
||||
} else { // (targetRatio > rectRatio) {
|
||||
// Need to increase zoomToRect width.
|
||||
float newWidth = targetRatio * zoomToRect.width;
|
||||
zoomToRect.x -= (newWidth - zoomToRect.width) / 2;
|
||||
zoomToRect.width = newWidth;
|
||||
}
|
||||
|
||||
zoomToRect = zoomToRect.Intersect(cssPageRect);
|
||||
}
|
||||
|
||||
mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height =
|
||||
NS_MIN(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height);
|
||||
|
||||
mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height =
|
||||
clamped(mEndZoomToMetrics.mResolution.width, MIN_ZOOM, MAX_ZOOM);
|
||||
|
||||
// Recalculate the zoom to rect using the new dimensions.
|
||||
zoomToRect.width = viewport.width / mEndZoomToMetrics.mResolution.width;
|
||||
zoomToRect.height = viewport.height / mEndZoomToMetrics.mResolution.height;
|
||||
|
||||
// Clamp the zoom to rect to the CSS rect to make sure it fits.
|
||||
zoomToRect = zoomToRect.Intersect(cssPageRect);
|
||||
|
||||
// Do one final recalculation to get the resolution.
|
||||
mEndZoomToMetrics.mResolution.width = mEndZoomToMetrics.mResolution.height =
|
||||
NS_MAX(viewport.width / zoomToRect.width, viewport.height / zoomToRect.height);
|
||||
|
||||
mStartZoomToMetrics = mFrameMetrics;
|
||||
mEndZoomToMetrics.mViewportScrollOffset =
|
||||
nsIntPoint(NS_lround(zoomToRect.x), NS_lround(zoomToRect.y));
|
||||
|
||||
mAnimationStartTime = TimeStamp::Now();
|
||||
|
||||
ScheduleComposite();
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SetState(PanZoomState aState) {
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
mState = aState;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,14 @@ public:
|
|||
USE_GESTURE_DETECTOR
|
||||
};
|
||||
|
||||
/**
|
||||
* Constant describing the tolerance in distance we use, multiplied by the
|
||||
* device DPI, before we start panning the screen. This is to prevent us from
|
||||
* accidentally processing taps as touch moves, and from very short/accidental
|
||||
* touches moving the screen.
|
||||
*/
|
||||
static const float TOUCH_START_TOLERANCE;
|
||||
|
||||
AsyncPanZoomController(GeckoContentController* aController,
|
||||
GestureBehavior aGestures = DEFAULT_GESTURES);
|
||||
~AsyncPanZoomController();
|
||||
|
@ -99,6 +107,33 @@ public:
|
|||
*/
|
||||
void UpdateViewportSize(int aWidth, int aHeight);
|
||||
|
||||
/**
|
||||
* A DOM touch listener has been added. When called, we enable the machinery
|
||||
* that allows touch listeners to preventDefault any touch inputs. This should
|
||||
* not be called unless there are actually touch listeners as it introduces
|
||||
* potentially unbounded lag because it causes a round-trip through content.
|
||||
* Usually, if content is responding in a timely fashion, this only introduces
|
||||
* a nearly constant few hundred ms of lag.
|
||||
*/
|
||||
void NotifyDOMTouchListenerAdded();
|
||||
|
||||
/**
|
||||
* We have found a scrollable subframe, so disable our machinery until we hit
|
||||
* a touch end or a new touch start. This prevents us from accidentally
|
||||
* panning both the subframe and the parent frame.
|
||||
*
|
||||
* XXX/bug 775452: We should eventually be supporting async scrollable
|
||||
* subframes.
|
||||
*/
|
||||
void CancelDefaultPanZoom();
|
||||
|
||||
/**
|
||||
* Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
|
||||
* in. The actual animation is done on the compositor thread after being set
|
||||
* up. |aRect| must be given in CSS pixels, relative to the document.
|
||||
*/
|
||||
void ZoomToRect(const gfxRect& aRect);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// These methods must only be called on the compositor thread.
|
||||
//
|
||||
|
@ -152,6 +187,12 @@ public:
|
|||
*/
|
||||
void SetDPI(int aDPI);
|
||||
|
||||
/**
|
||||
* Gets the DPI of the device for use outside the panning and zooming logic.
|
||||
* It defaults to 72 if not set using SetDPI() at any point.
|
||||
*/
|
||||
int GetDPI();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Helper method for touches beginning. Sets everything up for panning and any
|
||||
|
@ -255,6 +296,8 @@ protected:
|
|||
* Cancels any currently running animation. Note that all this does is set the
|
||||
* state of the AsyncPanZoomController back to NOTHING, but it is the
|
||||
* animation's responsibility to check this before advancing.
|
||||
*
|
||||
* *** The monitor must be held while calling this.
|
||||
*/
|
||||
void CancelAnimation();
|
||||
|
||||
|
@ -269,7 +312,7 @@ protected:
|
|||
/**
|
||||
* Gets a vector of the velocities of each axis.
|
||||
*/
|
||||
const nsPoint GetVelocityVector();
|
||||
const gfx::Point GetVelocityVector();
|
||||
|
||||
/**
|
||||
* Gets a reference to the first SingleTouchData from a MultiTouchInput. This
|
||||
|
@ -304,6 +347,17 @@ protected:
|
|||
*/
|
||||
const nsIntRect CalculatePendingDisplayPort();
|
||||
|
||||
/**
|
||||
* Attempts to enlarge the displayport along a single axis. Returns whether or
|
||||
* not the displayport was enlarged. This will fail in circumstances where the
|
||||
* velocity along that axis is not high enough to need any changes. The
|
||||
* displayport metrics are expected to be passed into |aDisplayPortOffset| and
|
||||
* |aDisplayPortLength|. If enlarged, these will be updated with the new
|
||||
* metrics.
|
||||
*/
|
||||
bool EnlargeDisplayPortAlongAxis(float aViewport, float aVelocity,
|
||||
float* aDisplayPortOffset, float* aDisplayPortLength);
|
||||
|
||||
/**
|
||||
* Utility function to send updated FrameMetrics to Gecko so that it can paint
|
||||
* the displayport area. Calls into GeckoContentController to do the actual
|
||||
|
@ -335,6 +389,7 @@ private:
|
|||
TOUCHING, /* one touch-start event received */
|
||||
PANNING, /* panning without axis lock */
|
||||
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
|
||||
ANIMATING_ZOOM /* animated zoom to a new rect */
|
||||
};
|
||||
|
||||
enum ContentPainterStatus {
|
||||
|
@ -356,6 +411,13 @@ private:
|
|||
CONTENT_PAINTING_AND_PAINT_PENDING
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to set the current state. Holds the monitor before actually setting
|
||||
* it. If the monitor is already held by the current thread, it is safe to
|
||||
* instead use: |mState = NEWSTATE;|
|
||||
*/
|
||||
void SetState(PanZoomState aState);
|
||||
|
||||
nsRefPtr<CompositorParent> mCompositorParent;
|
||||
nsRefPtr<GeckoContentController> mGeckoContentController;
|
||||
nsRefPtr<GestureEventListener> mGestureEventListener;
|
||||
|
@ -371,9 +433,23 @@ private:
|
|||
// If we don't do this check, we don't get a ShadowLayersUpdated back.
|
||||
FrameMetrics mLastPaintRequestMetrics;
|
||||
|
||||
// Old metrics from before we started a zoom animation. This is only valid
|
||||
// when we are in the "ANIMATED_ZOOM" state. This is used so that we can
|
||||
// interpolate between the start and end frames. We only use the
|
||||
// |mViewportScrollOffset| and |mResolution| fields on this.
|
||||
FrameMetrics mStartZoomToMetrics;
|
||||
// Target metrics for a zoom to animation. This is only valid when we are in
|
||||
// the "ANIMATED_ZOOM" state. We only use the |mViewportScrollOffset| and
|
||||
// |mResolution| fields on this.
|
||||
FrameMetrics mEndZoomToMetrics;
|
||||
|
||||
AxisX mX;
|
||||
AxisY mY;
|
||||
|
||||
// Protects |mFrameMetrics|, |mLastContentPaintMetrics| and |mState|. Before
|
||||
// manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the monitor
|
||||
// should be held. When setting |mState|, either the SetState() function can
|
||||
// be used, or the monitor can be held and then |mState| updated.
|
||||
Monitor mMonitor;
|
||||
|
||||
// The last time the compositor has sampled the content transform for this
|
||||
|
@ -382,10 +458,18 @@ private:
|
|||
// The last time a touch event came through on the UI thread.
|
||||
PRInt32 mLastEventTime;
|
||||
|
||||
// Start time of an animation. This is used for a zoom to animation to mark
|
||||
// the beginning.
|
||||
TimeStamp mAnimationStartTime;
|
||||
|
||||
// Stores the previous focus point if there is a pinch gesture happening. Used
|
||||
// to allow panning by moving multiple fingers (thus moving the focus point).
|
||||
nsIntPoint mLastZoomFocus;
|
||||
|
||||
// Stores the state of panning and zooming this frame. This is protected by
|
||||
// |mMonitor|; that is, it should be held whenever this is updated.
|
||||
PanZoomState mState;
|
||||
|
||||
int mDPI;
|
||||
|
||||
// Stores the current paint status of the frame that we're managing. Repaints
|
||||
|
@ -394,6 +478,14 @@ private:
|
|||
// requests a repaint.
|
||||
ContentPainterStatus mContentPainterStatus;
|
||||
|
||||
// Whether or not we might have touch listeners. This is a conservative
|
||||
// approximation and may not be accurate.
|
||||
bool mMayHaveTouchListeners;
|
||||
|
||||
// Flag used to determine whether or not we should disable handling of the
|
||||
// next batch of touch events. This is used for sync scrolling of subframes.
|
||||
bool mDisableNextTouchBatch;
|
||||
|
||||
friend class Axis;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,14 @@ public:
|
|||
*/
|
||||
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0;
|
||||
|
||||
/**
|
||||
* Requests handling of a double tap. |aPoint| is in CSS pixels, relative to
|
||||
* the current scroll offset. This should eventually round-trip back to
|
||||
* AsyncPanZoomController::ZoomToRect with the dimensions that we want to zoom
|
||||
* to.
|
||||
*/
|
||||
virtual void HandleDoubleTap(const nsIntPoint& aPoint) = 0;
|
||||
|
||||
GeckoContentController() {}
|
||||
virtual ~GeckoContentController() {}
|
||||
};
|
||||
|
|
|
@ -63,6 +63,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||
size_t length = mTouches.Length();
|
||||
if (length == 1) {
|
||||
mTapStartTime = event.mTime;
|
||||
mTouchStartPosition = event.mTouches[0].mScreenPoint;
|
||||
if (mState == GESTURE_NONE) {
|
||||
mState = GESTURE_WAITING_SINGLE_TAP;
|
||||
}
|
||||
|
@ -74,9 +75,14 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||
break;
|
||||
}
|
||||
case MultiTouchInput::MULTITOUCH_MOVE: {
|
||||
// If we move at all, just bail out of the tap. We need to change this so
|
||||
// that there's some tolerance in the future.
|
||||
HandleTapCancel(event);
|
||||
// If we move too much, bail out of the tap.
|
||||
nsIntPoint touch = (nsIntPoint&)event.mTouches[0].mScreenPoint;
|
||||
if (mTouches.Length() == 1 &&
|
||||
NS_hypot(mTouchStartPosition.x - touch.x, mTouchStartPosition.y - touch.y) >
|
||||
mAsyncPanZoomController->GetDPI() * AsyncPanZoomController::TOUCH_START_TOLERANCE)
|
||||
{
|
||||
HandleTapCancel(event);
|
||||
}
|
||||
|
||||
bool foundAlreadyExistingTouch = false;
|
||||
for (size_t i = 0; i < mTouches.Length(); i++) {
|
||||
|
@ -260,5 +266,10 @@ AsyncPanZoomController* GestureEventListener::GetAsyncPanZoomController() {
|
|||
return mAsyncPanZoomController;
|
||||
}
|
||||
|
||||
void GestureEventListener::CancelGesture() {
|
||||
mTouches.Clear();
|
||||
mState = GESTURE_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=4 ts=8 et 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
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=4 ts=8 et tw=80 : */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_layers_GestureEventListener_h
|
||||
|
@ -47,6 +44,13 @@ public:
|
|||
*/
|
||||
nsEventStatus HandleInputEvent(const InputData& aEvent);
|
||||
|
||||
/**
|
||||
* Cancels any currently active gesture. May not properly handle situations
|
||||
* that require extra work at the gesture's end, like a pinch which only
|
||||
* requests a repaint once it has ended.
|
||||
*/
|
||||
void CancelGesture();
|
||||
|
||||
/**
|
||||
* Returns the AsyncPanZoomController stored on this class and used for
|
||||
* callbacks.
|
||||
|
@ -163,6 +167,13 @@ protected:
|
|||
* we can cancel it if a double tap actually comes in.
|
||||
*/
|
||||
CancelableTask *mDoubleTapTimeoutTask;
|
||||
|
||||
/**
|
||||
* Position of the last touch starting. This is only valid during an attempt
|
||||
* to determine if a touch is a tap. This means that it is used in both the
|
||||
* "GESTURE_WAITING_SINGLE_TAP" and "GESTURE_WAITING_DOUBLE_TAP" states.
|
||||
*/
|
||||
nsIntPoint mTouchStartPosition;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#define IPC_ShadowLayerUtils_h
|
||||
|
||||
#include "IPC/IPCMessageUtils.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/WidgetUtils.h"
|
||||
|
||||
|
@ -39,34 +38,6 @@ struct MagicGrallocBufferHandle {
|
|||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mCSSContentRect);
|
||||
WriteParam(aMsg, aParam.mViewport);
|
||||
WriteParam(aMsg, aParam.mContentRect);
|
||||
WriteParam(aMsg, aParam.mViewportScrollOffset);
|
||||
WriteParam(aMsg, aParam.mDisplayPort);
|
||||
WriteParam(aMsg, aParam.mScrollId);
|
||||
WriteParam(aMsg, aParam.mResolution);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return (ReadParam(aMsg, aIter, &aResult->mCSSContentRect) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mViewport) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mViewportScrollOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mResolution));
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(MOZ_HAVE_SURFACEDESCRIPTORX11)
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::SurfaceDescriptorX11> {
|
||||
|
|
|
@ -20,16 +20,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=627498
|
|||
// Make sure that acceleration is enabled/disabled the way we expect it to be
|
||||
// based on platform.
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var importObj = {};
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Cc = SpecialPowers.wrap(Components).classes;
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
var sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
|
||||
|
||||
var windows = Services.ww.getWindowEnumerator();
|
||||
var windows = SpecialPowers.Services.ww.getWindowEnumerator();
|
||||
var windowutils;
|
||||
var acceleratedWindows = 0;
|
||||
while (windows.hasMoreElements()) {
|
||||
|
|
|
@ -779,10 +779,15 @@ gfxWindowsPlatform::GetScaledFontForFont(DrawTarget* aTarget, gfxFont *aFont)
|
|||
NativeFont nativeFont;
|
||||
nativeFont.mType = NATIVE_FONT_DWRITE_FONT_FACE;
|
||||
nativeFont.mFont = font->GetFontFace();
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
mozilla::gfx::Factory::CreateScaledFontForNativeFont(nativeFont, font->GetAdjustedSize());
|
||||
|
||||
return scaledFont;
|
||||
if (aTarget->GetType() == BACKEND_CAIRO) {
|
||||
return Factory::CreateScaledFontWithCairo(nativeFont,
|
||||
font->GetAdjustedSize(),
|
||||
font->GetCairoScaledFont());
|
||||
}
|
||||
|
||||
return Factory::CreateScaledFontForNativeFont(nativeFont,
|
||||
font->GetAdjustedSize());
|
||||
}
|
||||
|
||||
NS_ASSERTION(aFont->GetType() == gfxFont::FONT_TYPE_GDI,
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
#include "gfxMatrix.h"
|
||||
#include "gfxPattern.h"
|
||||
#include "gfxPoint.h"
|
||||
#include "gfxRect.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsRegion.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "jsapi.h"
|
||||
#include "LayersTypes.h"
|
||||
#include "FrameMetrics.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable : 4800 )
|
||||
|
@ -517,6 +519,28 @@ struct ParamTraits<gfxSize>
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<gfxRect>
|
||||
{
|
||||
typedef gfxRect paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.x);
|
||||
WriteParam(aMsg, aParam.y);
|
||||
WriteParam(aMsg, aParam.width);
|
||||
WriteParam(aMsg, aParam.height);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->x) &&
|
||||
ReadParam(aMsg, aIter, &aResult->y) &&
|
||||
ReadParam(aMsg, aIter, &aResult->width) &&
|
||||
ReadParam(aMsg, aIter, &aResult->height);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<gfx3DMatrix>
|
||||
{
|
||||
|
@ -902,6 +926,34 @@ struct ParamTraits<mozilla::SerializedStructuredCloneBuffer>
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mCSSContentRect);
|
||||
WriteParam(aMsg, aParam.mViewport);
|
||||
WriteParam(aMsg, aParam.mContentRect);
|
||||
WriteParam(aMsg, aParam.mViewportScrollOffset);
|
||||
WriteParam(aMsg, aParam.mDisplayPort);
|
||||
WriteParam(aMsg, aParam.mScrollId);
|
||||
WriteParam(aMsg, aParam.mResolution);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return (ReadParam(aMsg, aIter, &aResult->mCSSContentRect) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mViewport) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mViewportScrollOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mResolution));
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace IPC */
|
||||
|
||||
#endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */
|
||||
|
|
|
@ -17,7 +17,9 @@ include $(DEPTH)/config/autoconf.mk
|
|||
MODULE = jsdebug
|
||||
LIBRARY_NAME = jsd
|
||||
DIRS = idl
|
||||
CPPSRCS = jsd_xpc.cpp
|
||||
CPPSRCS = \
|
||||
jsd_xpc.cpp \
|
||||
jshash.cpp
|
||||
IS_COMPONENT = 1
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ static JSHashAllocOps defaultHashAllocOps = {
|
|||
DefaultAllocEntry, DefaultFreeEntry
|
||||
};
|
||||
|
||||
JS_PUBLIC_API(JSHashTable *)
|
||||
JSHashTable *
|
||||
JS_NewHashTable(uint32_t n, JSHashFunction keyHash,
|
||||
JSHashComparator keyCompare, JSHashComparator valueCompare,
|
||||
JSHashAllocOps *allocOps, void *allocPriv)
|
||||
|
@ -101,7 +101,7 @@ JS_NewHashTable(uint32_t n, JSHashFunction keyHash,
|
|||
return ht;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
void
|
||||
JS_HashTableDestroy(JSHashTable *ht)
|
||||
{
|
||||
uint32_t i, n;
|
||||
|
@ -133,7 +133,7 @@ JS_HashTableDestroy(JSHashTable *ht)
|
|||
#define BUCKET_HEAD(ht, keyHash) \
|
||||
(&(ht)->buckets[((keyHash) * JS_GOLDEN_RATIO) >> (ht)->shift])
|
||||
|
||||
JS_PUBLIC_API(JSHashEntry **)
|
||||
JSHashEntry **
|
||||
JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key)
|
||||
{
|
||||
JSHashEntry *he, **hep, **hep0;
|
||||
|
@ -212,7 +212,7 @@ Resize(JSHashTable *ht, uint32_t newshift)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSHashEntry *)
|
||||
JSHashEntry *
|
||||
JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **&hep,
|
||||
JSHashNumber keyHash, const void *key, void *value)
|
||||
{
|
||||
|
@ -243,7 +243,7 @@ JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **&hep,
|
|||
return he;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSHashEntry *)
|
||||
JSHashEntry *
|
||||
JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
|
@ -265,7 +265,7 @@ JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
|
|||
return JS_HashTableRawAdd(ht, hep, keyHash, key, value);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
void
|
||||
JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he)
|
||||
{
|
||||
uint32_t n;
|
||||
|
@ -283,7 +283,7 @@ JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he)
|
|||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JSBool
|
||||
JS_HashTableRemove(JSHashTable *ht, const void *key)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
|
@ -299,7 +299,7 @@ JS_HashTableRemove(JSHashTable *ht, const void *key)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
void *
|
||||
JS_HashTableLookup(JSHashTable *ht, const void *key)
|
||||
{
|
||||
JSHashNumber keyHash;
|
||||
|
@ -318,7 +318,7 @@ JS_HashTableLookup(JSHashTable *ht, const void *key)
|
|||
** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP).
|
||||
** Return a count of the number of elements scanned.
|
||||
*/
|
||||
JS_PUBLIC_API(int)
|
||||
int
|
||||
JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg)
|
||||
{
|
||||
JSHashEntry *he, **hep, **bucket;
|
||||
|
@ -367,7 +367,7 @@ out:
|
|||
#ifdef JS_HASHMETER
|
||||
#include <stdio.h>
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
void
|
||||
JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
double sqsum, mean, sigma;
|
||||
|
@ -413,7 +413,7 @@ JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
|||
}
|
||||
#endif /* JS_HASHMETER */
|
||||
|
||||
JS_PUBLIC_API(int)
|
||||
int
|
||||
JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
||||
{
|
||||
int count;
|
||||
|
@ -425,7 +425,7 @@ JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
|
|||
return count;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSHashNumber)
|
||||
JSHashNumber
|
||||
JS_HashString(const void *key)
|
||||
{
|
||||
JSHashNumber h;
|
||||
|
@ -437,7 +437,7 @@ JS_HashString(const void *key)
|
|||
return h;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(int)
|
||||
int
|
||||
JS_CompareValues(const void *v1, const void *v2)
|
||||
{
|
||||
return v1 == v2;
|
|
@ -70,49 +70,49 @@ struct JSHashTable {
|
|||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSHashTable *)
|
||||
extern JSHashTable *
|
||||
JS_NewHashTable(uint32_t n, JSHashFunction keyHash,
|
||||
JSHashComparator keyCompare, JSHashComparator valueCompare,
|
||||
JSHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
extern void
|
||||
JS_HashTableDestroy(JSHashTable *ht);
|
||||
|
||||
/* Low level access methods */
|
||||
extern JS_PUBLIC_API(JSHashEntry **)
|
||||
extern JSHashEntry **
|
||||
JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern JS_PUBLIC_API(JSHashEntry *)
|
||||
extern JSHashEntry *
|
||||
JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **&hep, JSHashNumber keyHash,
|
||||
const void *key, void *value);
|
||||
#endif
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
extern void
|
||||
JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he);
|
||||
|
||||
/* Higher level access methods */
|
||||
extern JS_PUBLIC_API(JSHashEntry *)
|
||||
extern JSHashEntry *
|
||||
JS_HashTableAdd(JSHashTable *ht, const void *key, void *value);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
extern JSBool
|
||||
JS_HashTableRemove(JSHashTable *ht, const void *key);
|
||||
|
||||
extern JS_PUBLIC_API(int)
|
||||
extern int
|
||||
JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
extern void *
|
||||
JS_HashTableLookup(JSHashTable *ht, const void *key);
|
||||
|
||||
extern JS_PUBLIC_API(int)
|
||||
extern int
|
||||
JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
extern JS_PUBLIC_API(JSHashNumber)
|
||||
extern JSHashNumber
|
||||
JS_HashString(const void *key);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
extern JS_PUBLIC_API(int)
|
||||
extern int
|
||||
JS_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
JS_END_EXTERN_C
|
|
@ -82,7 +82,6 @@ CPPSRCS = \
|
|||
jsfun.cpp \
|
||||
jsgc.cpp \
|
||||
jscrashreport.cpp \
|
||||
jshash.cpp \
|
||||
jsinfer.cpp \
|
||||
jsinterp.cpp \
|
||||
jsiter.cpp \
|
||||
|
@ -162,7 +161,6 @@ INSTALLED_HEADERS = \
|
|||
jsdhash.h \
|
||||
jsfriendapi.h \
|
||||
jsgc.h \
|
||||
jshash.h \
|
||||
jslock.h \
|
||||
json.h \
|
||||
jsproxy.h \
|
||||
|
|
|
@ -278,8 +278,8 @@ frontend::Emit3(JSContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1,
|
|||
jsbytecode op2)
|
||||
{
|
||||
/* These should filter through EmitVarOp. */
|
||||
JS_ASSERT(JOF_OPTYPE(op) != JOF_QARG);
|
||||
JS_ASSERT(JOF_OPTYPE(op) != JOF_LOCAL);
|
||||
JS_ASSERT(!IsArgOp(op));
|
||||
JS_ASSERT(!IsLocalOp(op));
|
||||
|
||||
ptrdiff_t offset = EmitCheck(cx, bce, 3);
|
||||
|
||||
|
@ -815,12 +815,6 @@ EmitAtomIncDec(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitFunctionOp(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
|
||||
{
|
||||
return EmitIndex32(cx, op, index, bce);
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
|
@ -917,11 +911,11 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
|
|||
}
|
||||
|
||||
ScopeCoordinate sc;
|
||||
if (JOF_OPTYPE(pn->getOp()) == JOF_QARG) {
|
||||
if (IsArgOp(pn->getOp())) {
|
||||
sc.hops = skippedScopes + ClonedBlockDepth(bceOfDef);
|
||||
sc.slot = bceOfDef->sc->bindings.formalIndexToSlot(pn->pn_cookie.slot());
|
||||
} else {
|
||||
JS_ASSERT(JOF_OPTYPE(pn->getOp()) == JOF_LOCAL || pn->isKind(PNK_FUNCTION));
|
||||
JS_ASSERT(IsLocalOp(pn->getOp()) || pn->isKind(PNK_FUNCTION));
|
||||
unsigned local = pn->pn_cookie.slot();
|
||||
if (local < bceOfDef->sc->bindings.numVars()) {
|
||||
sc.hops = skippedScopes + ClonedBlockDepth(bceOfDef);
|
||||
|
@ -946,7 +940,7 @@ static bool
|
|||
EmitVarOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_FUNCTION) || pn->isKind(PNK_NAME));
|
||||
JS_ASSERT_IF(pn->isKind(PNK_NAME), JOF_OPTYPE(op) == JOF_QARG || JOF_OPTYPE(op) == JOF_LOCAL);
|
||||
JS_ASSERT_IF(pn->isKind(PNK_NAME), IsArgOp(op) || IsLocalOp(op));
|
||||
JS_ASSERT(!pn->pn_cookie.isFree());
|
||||
|
||||
if (!bce->isAliasedName(pn)) {
|
||||
|
@ -970,7 +964,7 @@ static bool
|
|||
EmitVarIncDec(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_NAME));
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_QARG || JOF_OPTYPE(op) == JOF_LOCAL);
|
||||
JS_ASSERT(IsArgOp(op) || IsLocalOp(op));
|
||||
JS_ASSERT(js_CodeSpec[op].format & (JOF_INC | JOF_DEC));
|
||||
JS_ASSERT(!pn->pn_cookie.isFree());
|
||||
|
||||
|
@ -1034,8 +1028,7 @@ BytecodeEmitter::noteClosedVar(ParseNode *pn)
|
|||
#ifdef DEBUG
|
||||
JS_ASSERT(shouldNoteClosedName(pn));
|
||||
Definition *dn = (Definition *)pn;
|
||||
JS_ASSERT(dn->kind() == Definition::VAR || dn->kind() == Definition::CONST ||
|
||||
dn->kind() == Definition::FUNCTION);
|
||||
JS_ASSERT(dn->kind() == Definition::VAR || dn->kind() == Definition::CONST);
|
||||
JS_ASSERT(pn->pn_cookie.slot() < sc->bindings.numVars());
|
||||
for (size_t i = 0; i < closedVars.length(); ++i)
|
||||
JS_ASSERT(closedVars[i] != pn->pn_cookie.slot());
|
||||
|
@ -1211,12 +1204,14 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
{
|
||||
JS_ASSERT(pn->isKind(PNK_NAME) || pn->isKind(PNK_INTRINSICNAME));
|
||||
|
||||
/* Don't attempt if 'pn' is already bound or deoptimized or a nop. */
|
||||
JSOp op = pn->getOp();
|
||||
if (pn->isBound() || pn->isDeoptimized() || op == JSOP_NOP)
|
||||
JS_ASSERT_IF(pn->isKind(PNK_FUNCTION), pn->isBound());
|
||||
|
||||
/* Don't attempt if 'pn' is already bound or deoptimized or a function. */
|
||||
if (pn->isBound() || pn->isDeoptimized())
|
||||
return true;
|
||||
|
||||
/* JSOP_CALLEE is pre-bound by definition. */
|
||||
JSOp op = pn->getOp();
|
||||
JS_ASSERT(op != JSOP_CALLEE);
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
|
||||
|
||||
|
@ -1236,8 +1231,6 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
return true;
|
||||
}
|
||||
|
||||
JS_ASSERT_IF(dn->kind() == Definition::CONST, pn->pn_dflags & PND_CONST);
|
||||
|
||||
/*
|
||||
* Turn attempts to mutate const-declared bindings into get ops (for
|
||||
* pre-increment and pre-decrement ops, our caller will have to emit
|
||||
|
@ -1331,9 +1324,6 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* rewrite pn_op and update pn accordingly.
|
||||
*/
|
||||
switch (dn->kind()) {
|
||||
case Definition::UNKNOWN:
|
||||
return true;
|
||||
|
||||
case Definition::ARG:
|
||||
switch (op) {
|
||||
case JSOP_NAME: op = JSOP_GETARG; break;
|
||||
|
@ -1348,55 +1338,6 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
break;
|
||||
|
||||
case Definition::VAR:
|
||||
if (dn->isOp(JSOP_CALLEE)) {
|
||||
JS_ASSERT(op != JSOP_CALLEE);
|
||||
|
||||
/*
|
||||
* Currently, the ALIASEDVAR ops do not support accessing the
|
||||
* callee of a DeclEnvObject, so use NAME.
|
||||
*/
|
||||
if (dn->pn_cookie.level() != bce->script->staticLevel)
|
||||
return true;
|
||||
|
||||
JS_ASSERT(bce->sc->fun()->flags & JSFUN_LAMBDA);
|
||||
JS_ASSERT(pn->pn_atom == bce->sc->fun()->atom);
|
||||
|
||||
/*
|
||||
* Leave pn->isOp(JSOP_NAME) if bce->fun is heavyweight to
|
||||
* address two cases: a new binding introduced by eval, and
|
||||
* assignment to the name in strict mode.
|
||||
*
|
||||
* var fun = (function f(s) { eval(s); return f; });
|
||||
* assertEq(fun("var f = 42"), 42);
|
||||
*
|
||||
* ECMAScript specifies that a function expression's name is bound
|
||||
* in a lexical environment distinct from that used to bind its
|
||||
* named parameters, the arguments object, and its variables. The
|
||||
* new binding for "var f = 42" shadows the binding for the
|
||||
* function itself, so the name of the function will not refer to
|
||||
* the function.
|
||||
*
|
||||
* (function f() { "use strict"; f = 12; })();
|
||||
*
|
||||
* Outside strict mode, assignment to a function expression's name
|
||||
* has no effect. But in strict mode, this attempt to mutate an
|
||||
* immutable binding must throw a TypeError. We implement this by
|
||||
* not optimizing such assignments and by marking such functions as
|
||||
* heavyweight, ensuring that the function name is represented in
|
||||
* the scope chain so that assignment will throw a TypeError.
|
||||
*/
|
||||
if (!bce->sc->funIsHeavyweight()) {
|
||||
op = JSOP_CALLEE;
|
||||
pn->pn_dflags |= PND_CONST;
|
||||
}
|
||||
|
||||
pn->setOp(op);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return true;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
|
||||
case Definition::FUNCTION:
|
||||
case Definition::CONST:
|
||||
case Definition::LET:
|
||||
switch (op) {
|
||||
|
@ -1411,8 +1352,55 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
JS_NOT_REACHED("unexpected dn->kind()");
|
||||
case Definition::NAMED_LAMBDA:
|
||||
JS_ASSERT(dn->isOp(JSOP_CALLEE));
|
||||
JS_ASSERT(op != JSOP_CALLEE);
|
||||
|
||||
/*
|
||||
* Currently, the ALIASEDVAR ops do not support accessing the
|
||||
* callee of a DeclEnvObject, so use NAME.
|
||||
*/
|
||||
if (dn->pn_cookie.level() != bce->script->staticLevel)
|
||||
return true;
|
||||
|
||||
JS_ASSERT(bce->sc->fun()->flags & JSFUN_LAMBDA);
|
||||
JS_ASSERT(pn->pn_atom == bce->sc->fun()->atom);
|
||||
|
||||
/*
|
||||
* Leave pn->isOp(JSOP_NAME) if bce->fun is heavyweight to
|
||||
* address two cases: a new binding introduced by eval, and
|
||||
* assignment to the name in strict mode.
|
||||
*
|
||||
* var fun = (function f(s) { eval(s); return f; });
|
||||
* assertEq(fun("var f = 42"), 42);
|
||||
*
|
||||
* ECMAScript specifies that a function expression's name is bound
|
||||
* in a lexical environment distinct from that used to bind its
|
||||
* named parameters, the arguments object, and its variables. The
|
||||
* new binding for "var f = 42" shadows the binding for the
|
||||
* function itself, so the name of the function will not refer to
|
||||
* the function.
|
||||
*
|
||||
* (function f() { "use strict"; f = 12; })();
|
||||
*
|
||||
* Outside strict mode, assignment to a function expression's name
|
||||
* has no effect. But in strict mode, this attempt to mutate an
|
||||
* immutable binding must throw a TypeError. We implement this by
|
||||
* not optimizing such assignments and by marking such functions as
|
||||
* heavyweight, ensuring that the function name is represented in
|
||||
* the scope chain so that assignment will throw a TypeError.
|
||||
*/
|
||||
if (!bce->sc->funIsHeavyweight()) {
|
||||
op = JSOP_CALLEE;
|
||||
pn->pn_dflags |= PND_CONST;
|
||||
}
|
||||
|
||||
pn->setOp(op);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return true;
|
||||
|
||||
case Definition::PLACEHOLDER:
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2697,7 +2685,7 @@ MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *
|
|||
}
|
||||
|
||||
if (bce->sc->inFunction() &&
|
||||
JOF_OPTYPE(pn->getOp()) == JOF_LOCAL &&
|
||||
IsLocalOp(pn->getOp()) &&
|
||||
!pn->isLet() &&
|
||||
bce->shouldNoteClosedName(pn))
|
||||
{
|
||||
|
@ -4850,7 +4838,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* for the already-emitted function definition prolog opcode. See
|
||||
* comments in EmitStatementList.
|
||||
*/
|
||||
JS_ASSERT(pn->isOp(JSOP_NOP));
|
||||
JS_ASSERT(pn->functionIsHoisted());
|
||||
JS_ASSERT(bce->sc->inFunction());
|
||||
return EmitFunctionDefNop(cx, bce, pn->pn_index);
|
||||
}
|
||||
|
@ -4893,12 +4881,12 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
/* Make the function object a literal in the outer script's pool. */
|
||||
unsigned index = bce->objectList.add(pn->pn_funbox);
|
||||
|
||||
/* Emit a bytecode pointing to the closure object in its immediate. */
|
||||
if (pn->getOp() != JSOP_NOP) {
|
||||
/* Non-hoisted functions simply emit their respective op. */
|
||||
if (!pn->functionIsHoisted()) {
|
||||
if (pn->pn_funbox->inGenexpLambda && NewSrcNote(cx, bce, SRC_GENEXP) < 0)
|
||||
return false;
|
||||
|
||||
return EmitFunctionOp(cx, pn->getOp(), index, bce);
|
||||
return EmitIndex32(cx, pn->getOp(), index, bce);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4911,16 +4899,15 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
* definitions can be scheduled before generating the rest of code.
|
||||
*/
|
||||
if (!bce->sc->inFunction()) {
|
||||
JS_ASSERT(!bce->topStmt);
|
||||
JS_ASSERT(pn->pn_cookie.isFree());
|
||||
if (pn->pn_cookie.isFree()) {
|
||||
bce->switchToProlog();
|
||||
if (!EmitFunctionOp(cx, JSOP_DEFFUN, index, bce))
|
||||
return false;
|
||||
if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno))
|
||||
return false;
|
||||
bce->switchToMain();
|
||||
}
|
||||
JS_ASSERT(pn->getOp() == JSOP_NOP);
|
||||
JS_ASSERT(!bce->topStmt);
|
||||
bce->switchToProlog();
|
||||
if (!EmitIndex32(cx, JSOP_DEFFUN, index, bce))
|
||||
return false;
|
||||
if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno))
|
||||
return false;
|
||||
bce->switchToMain();
|
||||
|
||||
/* Emit NOP for the decompiler. */
|
||||
if (!EmitFunctionDefNop(cx, bce, index))
|
||||
|
@ -4928,18 +4915,29 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
} else {
|
||||
#ifdef DEBUG
|
||||
BindingIter bi(cx, bce->sc->bindings.lookup(cx, fun->atom->asPropertyName()));
|
||||
JS_ASSERT(bi->kind == VARIABLE || bi->kind == CONSTANT);
|
||||
JS_ASSERT(bi->kind == VARIABLE || bi->kind == CONSTANT || bi->kind == ARGUMENT);
|
||||
JS_ASSERT(bi.frameIndex() < JS_BIT(20));
|
||||
#endif
|
||||
pn->pn_index = index;
|
||||
if (bce->shouldNoteClosedName(pn) && !bce->noteClosedVar(pn))
|
||||
return false;
|
||||
if (bce->shouldNoteClosedName(pn)) {
|
||||
Definition::Kind kind = ((Definition *)pn)->kind();
|
||||
if (kind == Definition::ARG) {
|
||||
if (!bce->noteClosedArg(pn))
|
||||
return false;
|
||||
} else {
|
||||
JS_ASSERT(kind == Definition::VAR);
|
||||
if (!bce->noteClosedVar(pn))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
|
||||
return false;
|
||||
if (!EmitIndexOp(cx, JSOP_LAMBDA, index, bce))
|
||||
return false;
|
||||
if (!EmitVarOp(cx, pn, JSOP_SETLOCAL, bce))
|
||||
JS_ASSERT(pn->getOp() == JSOP_GETLOCAL || pn->getOp() == JSOP_GETARG);
|
||||
JSOp setOp = pn->getOp() == JSOP_GETLOCAL ? JSOP_SETLOCAL : JSOP_SETARG;
|
||||
if (!EmitVarOp(cx, pn, setOp, bce))
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0)
|
||||
return false;
|
||||
|
@ -6069,17 +6067,9 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
// Currently this is used only for functions, as compile-as-we go
|
||||
// mode for scripts does not allow separate emitter passes.
|
||||
for (ParseNode *pn2 = pnchild; pn2; pn2 = pn2->pn_next) {
|
||||
if (pn2->isKind(PNK_FUNCTION)) {
|
||||
if (pn2->isOp(JSOP_NOP)) {
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
} else {
|
||||
// JSOP_DEFFUN in a top-level block with function
|
||||
// definitions appears, for example, when "if (true)"
|
||||
// is optimized away from "if (true) function x() {}".
|
||||
// See bug 428424.
|
||||
JS_ASSERT(pn2->isOp(JSOP_DEFFUN));
|
||||
}
|
||||
if (pn2->isKind(PNK_FUNCTION) && pn2->functionIsHoisted()) {
|
||||
if (!EmitTree(cx, bce, pn2))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6130,7 +6120,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
continue;
|
||||
if (!BindNameToSlot(cx, bce, pn2))
|
||||
return false;
|
||||
if (JOF_OPTYPE(pn2->getOp()) == JOF_QARG && bce->shouldNoteClosedName(pn2)) {
|
||||
if (IsArgOp(pn2->getOp()) && bce->shouldNoteClosedName(pn2)) {
|
||||
if (!bce->noteClosedArg(pn2))
|
||||
return false;
|
||||
}
|
||||
|
@ -6517,13 +6507,6 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
break;
|
||||
|
||||
case PNK_NAME:
|
||||
/*
|
||||
* Cope with a left-over function definition that was replaced by a use
|
||||
* of a later function definition of the same name. See FunctionDef and
|
||||
* MakeDefIntoUse in Parser.cpp.
|
||||
*/
|
||||
if (pn->isOp(JSOP_NOP))
|
||||
break;
|
||||
if (!EmitNameOp(cx, bce, pn, false))
|
||||
return false;
|
||||
break;
|
||||
|
@ -6646,6 +6629,10 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
break;
|
||||
#endif /* JS_HAS_XML_SUPPORT */
|
||||
|
||||
case PNK_NOP:
|
||||
JS_ASSERT(pn->getArity() == PN_NULLARY);
|
||||
break;
|
||||
|
||||
default:
|
||||
JS_ASSERT(0);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ class UpvarCookie
|
|||
* The long comment after this enum block describes the kinds in detail.
|
||||
*/
|
||||
enum ParseNodeKind {
|
||||
PNK_NOP,
|
||||
PNK_SEMI,
|
||||
PNK_COMMA,
|
||||
PNK_CONDITIONAL,
|
||||
|
@ -476,6 +477,7 @@ enum ParseNodeKind {
|
|||
* if-guarded PNK_ARRAYPUSH
|
||||
* PNK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP
|
||||
* pn_kid: array comprehension expression
|
||||
* PNK_NOP nullary
|
||||
*/
|
||||
enum ParseNodeArity {
|
||||
PN_NULLARY, /* 0 kids, only pn_atom/pn_dval/etc. */
|
||||
|
@ -776,6 +778,16 @@ struct ParseNode {
|
|||
return pn_cookie.slot();
|
||||
}
|
||||
|
||||
bool functionIsHoisted() const {
|
||||
JS_ASSERT(pn_arity == PN_FUNC);
|
||||
JS_ASSERT(isOp(JSOP_LAMBDA) || // lambda, genexpr
|
||||
isOp(JSOP_DEFFUN) || // non-body-level function statement
|
||||
isOp(JSOP_NOP) || // body-level function stmt in global code
|
||||
isOp(JSOP_GETLOCAL) || // body-level function stmt in function code
|
||||
isOp(JSOP_GETARG)); // body-level function redeclaring formal
|
||||
return !(isOp(JSOP_LAMBDA) || isOp(JSOP_DEFFUN));
|
||||
}
|
||||
|
||||
inline bool test(unsigned flag) const;
|
||||
|
||||
bool isLet() const { return test(PND_LET); }
|
||||
|
@ -1357,18 +1369,23 @@ struct Definition : public ParseNode
|
|||
return pn_cookie.isFree();
|
||||
}
|
||||
|
||||
enum Kind { VAR, CONST, LET, FUNCTION, ARG, UNKNOWN };
|
||||
enum Kind { VAR, CONST, LET, ARG, NAMED_LAMBDA, PLACEHOLDER };
|
||||
|
||||
bool canHaveInitializer() { return int(kind()) <= int(LET) || kind() == ARG; }
|
||||
bool canHaveInitializer() { return int(kind()) <= int(ARG); }
|
||||
|
||||
static const char *kindString(Kind kind);
|
||||
|
||||
Kind kind() {
|
||||
if (getKind() == PNK_FUNCTION)
|
||||
return FUNCTION;
|
||||
if (getKind() == PNK_FUNCTION) {
|
||||
if (isOp(JSOP_GETARG))
|
||||
return ARG;
|
||||
return VAR;
|
||||
}
|
||||
JS_ASSERT(getKind() == PNK_NAME);
|
||||
if (isOp(JSOP_NOP))
|
||||
return UNKNOWN;
|
||||
if (isOp(JSOP_CALLEE))
|
||||
return NAMED_LAMBDA;
|
||||
if (isPlaceholder())
|
||||
return PLACEHOLDER;
|
||||
if (isOp(JSOP_GETARG))
|
||||
return ARG;
|
||||
if (isConst())
|
||||
|
@ -1408,27 +1425,13 @@ ParseNode::test(unsigned flag) const
|
|||
return !!(pn_dflags & flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* We store definition pointers in PN_NAMESET AtomDefnMapPtrs in the AST,
|
||||
* but due to redefinition these nodes may become uses of other
|
||||
* definitions. This is unusual, so we simply chase the pn_lexdef link to
|
||||
* find the final definition node. See functions called from
|
||||
* js::frontend::AnalyzeFunctions.
|
||||
*
|
||||
* FIXME: MakeAssignment mutates for want of a parent link...
|
||||
*/
|
||||
inline Definition *
|
||||
ParseNode::resolve()
|
||||
{
|
||||
ParseNode *pn = this;
|
||||
while (!pn->isDefn()) {
|
||||
if (pn->isAssignment()) {
|
||||
pn = pn->pn_left;
|
||||
continue;
|
||||
}
|
||||
pn = pn->lexdef();
|
||||
}
|
||||
return (Definition *) pn;
|
||||
if (isDefn())
|
||||
return (Definition *)this;
|
||||
JS_ASSERT(lexdef()->isDefn());
|
||||
return (Definition *)lexdef();
|
||||
}
|
||||
|
||||
inline void
|
||||
|
|
|
@ -497,66 +497,6 @@ ReportBadParameter(JSContext *cx, Parser *parser, JSAtom *name, unsigned errorNu
|
|||
parser->reportStrictModeError(dn, errorNumber, bytes.ptr());
|
||||
}
|
||||
|
||||
/*
|
||||
* In strict mode code, all parameter names must be distinct, must not be
|
||||
* strict mode reserved keywords, and must not be 'eval' or 'arguments'. We
|
||||
* must perform these checks here, and not eagerly during parsing, because a
|
||||
* function's body may turn on strict mode for the function head.
|
||||
*/
|
||||
static bool
|
||||
CheckStrictParameters(JSContext *cx, Parser *parser)
|
||||
{
|
||||
SharedContext *sc = parser->tc->sc;
|
||||
JS_ASSERT(sc->inFunction());
|
||||
|
||||
if (!sc->needStrictChecks() || sc->bindings.numArgs() == 0)
|
||||
return true;
|
||||
|
||||
JSAtom *argumentsAtom = cx->runtime->atomState.argumentsAtom;
|
||||
JSAtom *evalAtom = cx->runtime->atomState.evalAtom;
|
||||
|
||||
/* name => whether we've warned about the name already */
|
||||
HashMap<JSAtom *, bool> parameters(cx);
|
||||
if (!parameters.init(sc->bindings.numArgs()))
|
||||
return false;
|
||||
|
||||
// Start with lastVariable(), not the last argument, for destructuring.
|
||||
for (BindingIter bi(cx, sc->bindings); bi; bi++) {
|
||||
PropertyName *name = bi->maybeName;
|
||||
if (!name)
|
||||
continue;
|
||||
|
||||
if (name == argumentsAtom || name == evalAtom) {
|
||||
if (!ReportBadParameter(cx, parser, name, JSMSG_BAD_BINDING))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FindKeyword(name->charsZ(), name->length())) {
|
||||
/*
|
||||
* JSOPTION_STRICT is supposed to warn about future keywords, too,
|
||||
* but we took care of that in the scanner.
|
||||
*/
|
||||
if (!ReportBadParameter(cx, parser, name, JSMSG_RESERVED_ID))
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a duplicate parameter: warn or report an error exactly
|
||||
* once for each duplicated parameter.
|
||||
*/
|
||||
if (HashMap<JSAtom *, bool>::AddPtr p = parameters.lookupForAdd(name)) {
|
||||
if (!p->value && !ReportBadParameter(cx, parser, name, JSMSG_DUPLICATE_FORMAL))
|
||||
return false;
|
||||
p->value = true;
|
||||
} else {
|
||||
if (!parameters.add(p, name, false))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
BindLocalVariable(JSContext *cx, TreeContext *tc, ParseNode *pn, BindingKind kind)
|
||||
{
|
||||
|
@ -626,13 +566,6 @@ Parser::functionBody(FunctionBodyType type)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check CheckStrictParameters before arguments logic below adds
|
||||
* 'arguments' to bindings.
|
||||
*/
|
||||
if (!CheckStrictParameters(context, this))
|
||||
return NULL;
|
||||
|
||||
Rooted<PropertyName*> arguments(context, context->runtime->atomState.argumentsAtom);
|
||||
|
||||
/*
|
||||
|
@ -850,38 +783,31 @@ MakeAssignment(ParseNode *pn, ParseNode *rhs, Parser *parser)
|
|||
return lhs;
|
||||
}
|
||||
|
||||
static ParseNode *
|
||||
/* See comment for use in Parser::functionDef. */
|
||||
static bool
|
||||
MakeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *atom, Parser *parser)
|
||||
{
|
||||
/*
|
||||
* If dn is arg, or in [var, const, let] and has an initializer, then we
|
||||
* must rewrite it to be an assignment node, whose freshly allocated
|
||||
* left-hand side becomes a use of pn.
|
||||
*/
|
||||
if (dn->canHaveInitializer()) {
|
||||
ParseNode *rhs = dn->expr();
|
||||
if (rhs) {
|
||||
ParseNode *lhs = MakeAssignment(dn, rhs, parser);
|
||||
if (!lhs)
|
||||
return NULL;
|
||||
//pn->dn_uses = lhs;
|
||||
dn = (Definition *) lhs;
|
||||
}
|
||||
TreeContext *tc = parser->tc;
|
||||
|
||||
dn->setOp((js_CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETNAME : JSOP_NAME);
|
||||
} else if (dn->kind() == Definition::FUNCTION) {
|
||||
JS_ASSERT(dn->isOp(JSOP_NOP));
|
||||
parser->prepareNodeForMutation(dn);
|
||||
dn->setKind(PNK_NAME);
|
||||
dn->setArity(PN_NAME);
|
||||
dn->pn_atom = atom;
|
||||
/*
|
||||
* In a function, dn must have been bound to an argument or local to be in
|
||||
* tc->decls. pn is going to take dn's place in tc->decls, so copy over the
|
||||
* cookie and op so that pn gets the same binding.
|
||||
*/
|
||||
if (tc->sc->inFunction()) {
|
||||
JS_ASSERT(!dn->pn_cookie.isFree());
|
||||
JS_ASSERT(dn->isBound());
|
||||
pn->pn_cookie = dn->pn_cookie;
|
||||
JS_ASSERT(JOF_OPTYPE(dn->getOp()) == JOF_QARG || JOF_OPTYPE(dn->getOp()) == JOF_LOCAL);
|
||||
pn->setOp(JOF_OPTYPE(dn->getOp()) == JOF_QARG ? JSOP_GETARG : JSOP_GETLOCAL);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
}
|
||||
|
||||
/* Now make dn no longer a definition, rather a use of pn. */
|
||||
JS_ASSERT(dn->isKind(PNK_NAME));
|
||||
JS_ASSERT(dn->isArity(PN_NAME));
|
||||
JS_ASSERT(dn->pn_atom == atom);
|
||||
/* Turn pn into a definition. */
|
||||
parser->tc->decls.updateFirst(atom, (Definition *) pn);
|
||||
pn->setDefn(true);
|
||||
|
||||
/* Change all uses of dn to be uses of pn. */
|
||||
for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
|
||||
JS_ASSERT(pnu->isUsed());
|
||||
JS_ASSERT(!pnu->isDefn());
|
||||
|
@ -891,38 +817,56 @@ MakeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *atom, Parser *parser)
|
|||
pn->pn_dflags |= dn->pn_dflags & PND_USE2DEF_FLAGS;
|
||||
pn->dn_uses = dn;
|
||||
|
||||
/*
|
||||
* A PNK_FUNCTION node must be a definition, so convert shadowed function
|
||||
* statements into nops. This is valid since all body-level function
|
||||
* statement initialization happens at the beginning of the function
|
||||
* (thus, only the last statement's effect is visible). E.g., in
|
||||
*
|
||||
* function outer() {
|
||||
* function g() { return 1 }
|
||||
* assertEq(g(), 2);
|
||||
* function g() { return 2 }
|
||||
* assertEq(g(), 2);
|
||||
* }
|
||||
*
|
||||
* both asserts are valid.
|
||||
*/
|
||||
if (dn->getKind() == PNK_FUNCTION) {
|
||||
JS_ASSERT(dn->functionIsHoisted());
|
||||
pn->dn_uses = dn->pn_link;
|
||||
parser->prepareNodeForMutation(dn);
|
||||
dn->setKind(PNK_NOP);
|
||||
dn->setArity(PN_NULLARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If dn is arg, or in [var, const, let] and has an initializer, then we
|
||||
* must rewrite it to be an assignment node, whose freshly allocated
|
||||
* left-hand side becomes a use of pn.
|
||||
*/
|
||||
if (dn->canHaveInitializer()) {
|
||||
if (ParseNode *rhs = dn->expr()) {
|
||||
ParseNode *lhs = MakeAssignment(dn, rhs, parser);
|
||||
if (!lhs)
|
||||
return false;
|
||||
pn->dn_uses = lhs;
|
||||
dn->pn_link = NULL;
|
||||
dn = (Definition *) lhs;
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn dn into a use of pn. */
|
||||
JS_ASSERT(dn->isKind(PNK_NAME));
|
||||
JS_ASSERT(dn->isArity(PN_NAME));
|
||||
JS_ASSERT(dn->pn_atom == atom);
|
||||
dn->setOp((js_CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETNAME : JSOP_NAME);
|
||||
dn->setDefn(false);
|
||||
dn->setUsed(true);
|
||||
dn->pn_lexdef = (Definition *) pn;
|
||||
dn->pn_cookie.makeFree();
|
||||
dn->pn_dflags &= ~PND_BOUND;
|
||||
return dn;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::DefineArg(ParseNode *pn, JSAtom *atom, unsigned i, Parser *parser)
|
||||
{
|
||||
/*
|
||||
* Make an argument definition node, distinguished by being in
|
||||
* parser->tc->decls but having PNK_NAME kind and JSOP_NOP op. Insert it in
|
||||
* a PNK_ARGSBODY list node returned via pn->pn_body.
|
||||
*/
|
||||
ParseNode *argpn = NameNode::create(PNK_NAME, atom, parser, parser->tc);
|
||||
if (!argpn)
|
||||
return false;
|
||||
JS_ASSERT(argpn->isKind(PNK_NAME) && argpn->isOp(JSOP_NOP));
|
||||
|
||||
/* Arguments are initialized by definition. */
|
||||
if (!Define(argpn, atom, parser->tc))
|
||||
return false;
|
||||
|
||||
ParseNode *argsbody = pn->pn_body;
|
||||
argsbody->append(argpn);
|
||||
|
||||
argpn->setOp(JSOP_GETARG);
|
||||
if (!argpn->pn_cookie.set(parser->context, parser->tc->staticLevel, i))
|
||||
return false;
|
||||
argpn->pn_dflags |= PND_BOUND;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -972,51 +916,6 @@ struct frontend::BindData {
|
|||
}
|
||||
};
|
||||
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
static bool
|
||||
BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
|
||||
{
|
||||
TreeContext *tc = parser->tc;
|
||||
JS_ASSERT(tc->sc->inFunction());
|
||||
|
||||
/*
|
||||
* NB: Check tc->decls rather than tc->sc->bindings, because destructuring
|
||||
* bindings aren't added to tc->sc->bindings until after all arguments have
|
||||
* been parsed.
|
||||
*/
|
||||
if (tc->decls.lookupFirst(atom)) {
|
||||
parser->reportError(NULL, JSMSG_DESTRUCT_DUP_ARG);
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode *pn = data->pn;
|
||||
|
||||
/*
|
||||
* Distinguish destructured-to binding nodes as vars, not args, by setting
|
||||
* pn_op to JSOP_SETLOCAL. Parser::functionDef checks for this pn_op value
|
||||
* when processing the destructuring-assignment AST prelude induced by such
|
||||
* destructuring args in Parser::functionArguments.
|
||||
*
|
||||
* We must set the PND_BOUND flag too to prevent pn_op from being reset to
|
||||
* JSOP_SETNAME by BindDestructuringVar. The only field not initialized is
|
||||
* pn_cookie; it gets set in functionDef in the first "if (prelude)" block.
|
||||
* We have to wait to set the cookie until we can call JSFunction::addLocal
|
||||
* with kind = JSLOCAL_VAR, after all JSLOCAL_ARG locals have been added.
|
||||
*
|
||||
* Thus a destructuring formal parameter binds an ARG (as in arguments[i]
|
||||
* element) with a null atom name for the object or array passed in to be
|
||||
* destructured, and zero or more VARs (as in named local variables) for
|
||||
* the destructured-to identifiers in the property value positions within
|
||||
* the object or array destructuring pattern, and all ARGs for the formal
|
||||
* parameter list bound as locals before any VAR for a destructured name.
|
||||
*/
|
||||
pn->setOp(JSOP_SETLOCAL);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
|
||||
return Define(pn, atom, tc);
|
||||
}
|
||||
#endif /* JS_HAS_DESTRUCTURING */
|
||||
|
||||
JSFunction *
|
||||
Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind)
|
||||
{
|
||||
|
@ -1124,6 +1023,7 @@ LeaveFunction(ParseNode *fn, Parser *parser, PropertyName *funName = NULL,
|
|||
return false;
|
||||
dn->pn_dflags |= PND_BOUND;
|
||||
foundCallee = 1;
|
||||
JS_ASSERT(dn->kind() == Definition::NAMED_LAMBDA);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1234,6 +1134,96 @@ LeaveFunction(ParseNode *fn, Parser *parser, PropertyName *funName = NULL,
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* DefineArg is called for both the formals of a regular function definition
|
||||
* and the formals specified by the Function constructor.
|
||||
*/
|
||||
bool
|
||||
frontend::DefineArg(ParseNode *pn, PropertyName *name, unsigned i, Parser *parser)
|
||||
{
|
||||
JSContext *cx = parser->context;
|
||||
TreeContext *tc = parser->tc;
|
||||
SharedContext *sc = tc->sc;
|
||||
|
||||
/*
|
||||
* Make an argument definition node, distinguished by being in
|
||||
* parser->tc->decls but having PNK_NAME kind and JSOP_NOP op. Insert it in
|
||||
* a PNK_ARGSBODY list node returned via pn->pn_body.
|
||||
*/
|
||||
ParseNode *argpn = NameNode::create(PNK_NAME, name, parser, tc);
|
||||
if (!argpn)
|
||||
return false;
|
||||
JS_ASSERT(argpn->isKind(PNK_NAME) && argpn->isOp(JSOP_NOP));
|
||||
|
||||
if (sc->needStrictChecks() && tc->decls.lookupFirst(name)) {
|
||||
if (!ReportBadParameter(cx, parser, name, JSMSG_DUPLICATE_FORMAL))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckStrictBinding(cx, parser, name, argpn))
|
||||
return false;
|
||||
|
||||
/* Arguments are initialized by definition. */
|
||||
if (!Define(argpn, name, tc))
|
||||
return false;
|
||||
|
||||
ParseNode *argsbody = pn->pn_body;
|
||||
argsbody->append(argpn);
|
||||
|
||||
argpn->setOp(JSOP_GETARG);
|
||||
if (!argpn->pn_cookie.set(cx, tc->staticLevel, i))
|
||||
return false;
|
||||
argpn->pn_dflags |= PND_BOUND;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
static bool
|
||||
BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
|
||||
{
|
||||
TreeContext *tc = parser->tc;
|
||||
JS_ASSERT(tc->sc->inFunction());
|
||||
|
||||
/*
|
||||
* NB: Check tc->decls rather than tc->sc->bindings, because destructuring
|
||||
* bindings aren't added to tc->sc->bindings until after all arguments have
|
||||
* been parsed.
|
||||
*/
|
||||
if (tc->decls.lookupFirst(atom)) {
|
||||
parser->reportError(NULL, JSMSG_DESTRUCT_DUP_ARG);
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode *pn = data->pn;
|
||||
if (!CheckStrictBinding(cx, parser, atom->asPropertyName(), pn))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Distinguish destructured-to binding nodes as vars, not args, by setting
|
||||
* pn_op to JSOP_SETLOCAL. Parser::functionDef checks for this pn_op value
|
||||
* when processing the destructuring-assignment AST prelude induced by such
|
||||
* destructuring args in Parser::functionArguments.
|
||||
*
|
||||
* We must set the PND_BOUND flag too to prevent pn_op from being reset to
|
||||
* JSOP_SETNAME by BindDestructuringVar. The only field not initialized is
|
||||
* pn_cookie; it gets set in functionDef in the first "if (prelude)" block.
|
||||
* We have to wait to set the cookie until we can call JSFunction::addLocal
|
||||
* with kind = JSLOCAL_VAR, after all JSLOCAL_ARG locals have been added.
|
||||
*
|
||||
* Thus a destructuring formal parameter binds an ARG (as in arguments[i]
|
||||
* element) with a null atom name for the object or array passed in to be
|
||||
* destructured, and zero or more VARs (as in named local variables) for
|
||||
* the destructured-to identifiers in the property value positions within
|
||||
* the object or array destructuring pattern, and all ARGs for the formal
|
||||
* parameter list bound as locals before any VAR for a destructured name.
|
||||
*/
|
||||
pn->setOp(JSOP_SETLOCAL);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
|
||||
return Define(pn, atom, tc);
|
||||
}
|
||||
#endif /* JS_HAS_DESTRUCTURING */
|
||||
|
||||
bool
|
||||
Parser::functionArguments(ParseNode **listp, bool &hasRest)
|
||||
{
|
||||
|
@ -1438,56 +1428,51 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
|||
pn->pn_cookie.makeFree();
|
||||
pn->pn_dflags = 0;
|
||||
|
||||
/*
|
||||
* Record names for function statements in tc->decls so we know when to
|
||||
* avoid optimizing variable references that might name a function.
|
||||
*/
|
||||
/* Function statements add a binding to the enclosing scope. */
|
||||
bool bodyLevel = tc->atBodyLevel();
|
||||
if (kind == Statement) {
|
||||
/*
|
||||
* Handle redeclaration and optimize cases where we can statically bind the
|
||||
* function (thereby avoiding JSOP_DEFFUN and dynamic name lookup).
|
||||
*/
|
||||
if (Definition *dn = tc->decls.lookupFirst(funName)) {
|
||||
Definition::Kind dn_kind = dn->kind();
|
||||
|
||||
JS_ASSERT(!dn->isUsed());
|
||||
JS_ASSERT(dn->isDefn());
|
||||
|
||||
if (context->hasStrictOption() || dn_kind == Definition::CONST) {
|
||||
if (context->hasStrictOption() || dn->kind() == Definition::CONST) {
|
||||
JSAutoByteString name;
|
||||
Reporter reporter = (dn_kind != Definition::CONST)
|
||||
Reporter reporter = (dn->kind() != Definition::CONST)
|
||||
? &Parser::reportStrictWarning
|
||||
: &Parser::reportError;
|
||||
if (!js_AtomToPrintableString(context, funName, &name) ||
|
||||
!(this->*reporter)(NULL, JSMSG_REDECLARED_VAR, Definition::kindString(dn_kind),
|
||||
!(this->*reporter)(NULL, JSMSG_REDECLARED_VAR, Definition::kindString(dn->kind()),
|
||||
name.ptr()))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (bodyLevel) {
|
||||
tc->decls.updateFirst(funName, (Definition *) pn);
|
||||
pn->setDefn(true);
|
||||
pn->dn_uses = dn; /* dn->dn_uses is now pn_link */
|
||||
|
||||
if (!MakeDefIntoUse(dn, pn, funName, this))
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Body-level function statements are effectively variable
|
||||
* declarations where the initialization is hoisted to the
|
||||
* beginning of the block. This means that any other variable
|
||||
* declaration with the same name is really just an assignment to
|
||||
* the function's binding (which is mutable), so turn any existing
|
||||
* declaration into a use.
|
||||
*/
|
||||
if (bodyLevel && !MakeDefIntoUse(dn, pn, funName, this))
|
||||
return NULL;
|
||||
} else if (bodyLevel) {
|
||||
/*
|
||||
* If this function was used before it was defined, claim the
|
||||
* pre-created definition node for this function that primaryExpr
|
||||
* put in tc->lexdeps on first forward reference, and recycle pn.
|
||||
*/
|
||||
|
||||
if (Definition *fn = tc->lexdeps.lookupDefn(funName)) {
|
||||
JS_ASSERT(fn->isDefn());
|
||||
fn->setKind(PNK_FUNCTION);
|
||||
fn->setArity(PN_FUNC);
|
||||
fn->pn_pos.begin = pn->pn_pos.begin;
|
||||
|
||||
/*
|
||||
* Set fn->pn_pos.end too, in case of error before we parse the
|
||||
* closing brace. See bug 640075.
|
||||
*/
|
||||
fn->pn_pos.end = pn->pn_pos.end;
|
||||
|
||||
fn->pn_body = NULL;
|
||||
|
@ -1500,41 +1485,64 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
|||
|
||||
if (!Define(pn, funName, tc))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* A function directly inside another's body needs only a local
|
||||
* variable to bind its name to its value, and not an activation object
|
||||
* property (it might also need the activation property, if the outer
|
||||
* function contains with statements, e.g., but the stack slot wins
|
||||
* when BytecodeEmitter.cpp's BindNameToSlot can optimize a JSOP_NAME
|
||||
* into a JSOP_GETLOCAL bytecode).
|
||||
*/
|
||||
if (tc->sc->inFunction()) {
|
||||
unsigned varIndex = tc->sc->bindings.numVars();
|
||||
if (!tc->sc->bindings.addVariable(context, funName))
|
||||
return NULL;
|
||||
if (!pn->pn_cookie.set(context, tc->staticLevel, varIndex))
|
||||
return NULL;
|
||||
pn->setOp(JSOP_GETLOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A function directly inside another's body needs only a local
|
||||
* variable to bind its name to its value, and not an activation object
|
||||
* property (it might also need the activation property, if the outer
|
||||
* function contains with statements, e.g., but the stack slot wins
|
||||
* when BytecodeEmitter.cpp's BindNameToSlot can optimize a JSOP_NAME
|
||||
* into a JSOP_GETLOCAL bytecode).
|
||||
* As a SpiderMonkey-specific extension, non-body-level function
|
||||
* statements (e.g., functions in an "if" or "while" block) are
|
||||
* dynamically bound when control flow reaches the statement. The
|
||||
* emitter normally emits functions in two passes (see PNK_ARGSBODY).
|
||||
* To distinguish
|
||||
*/
|
||||
if (bodyLevel && tc->sc->inFunction()) {
|
||||
/*
|
||||
* Define a local in the outer function so that BindNameToSlot
|
||||
* can properly optimize accesses. Note that we need a local
|
||||
* variable, not an argument, for the function statement. Thus
|
||||
* we add a variable even if a parameter with the given name
|
||||
* already exists.
|
||||
*/
|
||||
BindingIter bi(context, tc->sc->bindings.lookup(context, funName));
|
||||
if (!bi || bi->kind != CONSTANT) {
|
||||
unsigned varIndex;
|
||||
if (!bi || bi->kind == ARGUMENT) {
|
||||
varIndex = tc->sc->bindings.numVars();
|
||||
if (!tc->sc->bindings.addVariable(context, funName))
|
||||
return NULL;
|
||||
} else {
|
||||
JS_ASSERT(bi->kind == VARIABLE);
|
||||
varIndex = bi.frameIndex();
|
||||
}
|
||||
if (bodyLevel) {
|
||||
JS_ASSERT(pn->functionIsHoisted());
|
||||
JS_ASSERT_IF(tc->sc->inFunction(), !pn->pn_cookie.isFree());
|
||||
JS_ASSERT_IF(!tc->sc->inFunction(), pn->pn_cookie.isFree());
|
||||
} else {
|
||||
JS_ASSERT(tc->sc->strictModeState != StrictMode::STRICT);
|
||||
JS_ASSERT(pn->pn_cookie.isFree());
|
||||
tc->sc->setFunMightAliasLocals();
|
||||
tc->sc->setFunHasExtensibleScope();
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
pn->setOp(JSOP_DEFFUN);
|
||||
|
||||
if (!pn->pn_cookie.set(context, tc->staticLevel, varIndex))
|
||||
/*
|
||||
* Instead of setting bindingsAccessedDynamically, which would be
|
||||
* overly conservative, remember the names of all function
|
||||
* statements and mark any bindings with the same as aliased at the
|
||||
* end of functionBody.
|
||||
*/
|
||||
if (!tc->funcStmts) {
|
||||
tc->funcStmts = context->new_<FuncStmtSet>(context);
|
||||
if (!tc->funcStmts || !tc->funcStmts->init())
|
||||
return NULL;
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
}
|
||||
if (!tc->funcStmts->put(funName))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* No further binding (in BindNameToSlot) is needed for functions. */
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
} else {
|
||||
/* A function expression does not introduce any binding. */
|
||||
pn->setOp(JSOP_LAMBDA);
|
||||
}
|
||||
|
||||
TreeContext *outertc = tc;
|
||||
|
@ -1695,47 +1703,10 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
|||
outertc->sc->setFunIsHeavyweight();
|
||||
}
|
||||
|
||||
JSOp op = JSOP_NOP;
|
||||
if (kind == Expression) {
|
||||
op = JSOP_LAMBDA;
|
||||
} else {
|
||||
if (!bodyLevel) {
|
||||
/*
|
||||
* Extension: in non-strict mode code, a function statement not at
|
||||
* the top level of a function body or whole program, e.g., in a
|
||||
* compound statement such as the "then" part of an "if" statement,
|
||||
* binds a closure only if control reaches that sub-statement.
|
||||
*/
|
||||
JS_ASSERT(outertc->sc->strictModeState != StrictMode::STRICT);
|
||||
op = JSOP_DEFFUN;
|
||||
outertc->sc->setFunMightAliasLocals();
|
||||
outertc->sc->setFunHasExtensibleScope();
|
||||
outertc->sc->setFunIsHeavyweight();
|
||||
|
||||
/*
|
||||
* Instead of setting bindingsAccessedDynamically, which would be
|
||||
* overly conservative, remember the names of all function
|
||||
* statements and mark any bindings with the same as aliased at the
|
||||
* end of functionBody.
|
||||
*/
|
||||
if (!outertc->funcStmts) {
|
||||
outertc->funcStmts = context->new_<FuncStmtSet>(context);
|
||||
if (!outertc->funcStmts || !outertc->funcStmts->init())
|
||||
return NULL;
|
||||
}
|
||||
if (!outertc->funcStmts->put(funName))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pn->pn_funbox = funbox;
|
||||
pn->setOp(op);
|
||||
pn->pn_body->append(body);
|
||||
pn->pn_body->pn_pos = body->pn_pos;
|
||||
|
||||
JS_ASSERT_IF(!outertc->sc->inFunction() && bodyLevel && kind == Statement,
|
||||
pn->pn_cookie.isFree());
|
||||
|
||||
pn->pn_blockid = outertc->blockid();
|
||||
|
||||
if (!LeaveFunction(pn, this, funName, kind))
|
||||
|
|
|
@ -327,7 +327,7 @@ Parser::reportStrictModeError(ParseNode *pn, unsigned errorNumber, ...)
|
|||
}
|
||||
|
||||
bool
|
||||
DefineArg(ParseNode *pn, JSAtom *atom, unsigned i, Parser *parser);
|
||||
DefineArg(ParseNode *pn, PropertyName *name, unsigned i, Parser *parser);
|
||||
|
||||
} /* namespace frontend */
|
||||
} /* namespace js */
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
function f(x) {
|
||||
function x() {}
|
||||
arguments[0] = 42;
|
||||
return x;
|
||||
}
|
||||
assertEq(f(0), 42);
|
||||
|
||||
function g(x) {
|
||||
function x() {}
|
||||
assertEq(arguments[0], x);
|
||||
}
|
||||
g(0);
|
||||
|
||||
var caught = false;
|
||||
try {
|
||||
(function h(x) { function x() {} }).blah.baz;
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
}
|
||||
assertEq(caught, true);
|
|
@ -0,0 +1,44 @@
|
|||
function f1() {
|
||||
assertEq(g(), 3);
|
||||
function g() { return 1 }
|
||||
assertEq(g(), 3);
|
||||
function g() { return 2 }
|
||||
assertEq(g(), 3);
|
||||
function g() { return 3 }
|
||||
assertEq(g(), 3);
|
||||
}
|
||||
f1();
|
||||
|
||||
function f2() {
|
||||
assertEq(g(), 2);
|
||||
var g = 3;
|
||||
assertEq(g, 3);
|
||||
function g() { return 1 }
|
||||
function g() { return 2 }
|
||||
}
|
||||
f2();
|
||||
|
||||
function f3() {
|
||||
assertEq(g(), 2);
|
||||
var g = 3;
|
||||
assertEq(g, 3);
|
||||
function g() { return 1 }
|
||||
var g = 4;
|
||||
assertEq(g, 4);
|
||||
function g() { return 2 }
|
||||
}
|
||||
f3();
|
||||
|
||||
function f4() {
|
||||
assertEq(g(), 4);
|
||||
function g() { return 1 }
|
||||
assertEq(g(), 4);
|
||||
function g() { return 2 }
|
||||
var g = 9;
|
||||
assertEq(g, 9);
|
||||
function g() { return 3 }
|
||||
assertEq(g, 9);
|
||||
function g() { return 4 }
|
||||
assertEq(g, 9);
|
||||
}
|
||||
f4();
|
|
@ -1,15 +1,23 @@
|
|||
// |jit-test| error: ExitCleanly
|
||||
|
||||
// proxies can return primitives
|
||||
assertEq(new (Proxy.createFunction({}, function(){}, function(){})), undefined);
|
||||
x = Proxy.createFunction((function () {}), Uint16Array, wrap)
|
||||
new(wrap(x))
|
||||
assertEq((new (Proxy.createFunction({},
|
||||
function(){ this.x = 1 },
|
||||
function(){ this.x = 2 }))).x, 2);
|
||||
try {
|
||||
x = Proxy.createFunction((function () {}), Uint16Array, wrap)
|
||||
new(wrap(x))
|
||||
throw "Should not be reached"
|
||||
}
|
||||
catch (e) {
|
||||
assertEq(String(e.message).indexOf('is not a constructor') === -1, false);
|
||||
}
|
||||
// proxies can return the callee
|
||||
var x = Proxy.createFunction({}, function (q) { return q; });
|
||||
assertEq(new x(x), x);
|
||||
try {
|
||||
var x = (Proxy.createFunction({}, "".indexOf));
|
||||
new x;
|
||||
throw "Should not be reached"
|
||||
}
|
||||
catch (e) {
|
||||
assertEq(String(e.message).indexOf('is not a constructor') === -1, false);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jshash.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
|
@ -43,12 +42,6 @@ using namespace js::gc;
|
|||
|
||||
const size_t JSAtomState::commonAtomsOffset = offsetof(JSAtomState, emptyAtom);
|
||||
|
||||
/*
|
||||
* ATOM_HASH assumes that JSHashNumber is 32-bit even on 64-bit systems.
|
||||
*/
|
||||
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(JSAtom *) == JS_BYTES_PER_WORD);
|
||||
|
||||
const char *
|
||||
js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes)
|
||||
{
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
#include "jsalloc.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jshash.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jslock.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
|
||||
struct JSIdArray {
|
||||
int length;
|
||||
|
@ -83,23 +83,15 @@ JSID_TO_ATOM(jsid id)
|
|||
return (JSAtom *)JSID_TO_STRING(id);
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(js::HashNumber) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
|
||||
|
||||
namespace js {
|
||||
|
||||
static JS_ALWAYS_INLINE JSHashNumber
|
||||
static JS_ALWAYS_INLINE js::HashNumber
|
||||
HashId(jsid id)
|
||||
{
|
||||
JSHashNumber n =
|
||||
#if JS_BYTES_PER_WORD == 4
|
||||
JSHashNumber(JSID_BITS(id));
|
||||
#elif JS_BYTES_PER_WORD == 8
|
||||
JSHashNumber(JSID_BITS(id)) ^ JSHashNumber(JSID_BITS(id) >> 32);
|
||||
#else
|
||||
# error "Unsupported configuration"
|
||||
#endif
|
||||
return n * JS_GOLDEN_RATIO;
|
||||
return HashGeneric(JSID_BITS(id));
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
|
@ -135,15 +127,6 @@ struct DefaultHasher<jsid>
|
|||
|
||||
}
|
||||
|
||||
#if JS_BYTES_PER_WORD == 4
|
||||
# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2)
|
||||
#elif JS_BYTES_PER_WORD == 8
|
||||
# define ATOM_HASH(atom) (((JSHashNumber)(uintptr_t)(atom) >> 3) ^ \
|
||||
(JSHashNumber)((uintptr_t)(atom) >> 32))
|
||||
#else
|
||||
# error "Unsupported configuration"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return a printable, lossless char[] representation of a string-type atom.
|
||||
* The lifetime of the result matches the lifetime of bytes.
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jshash.h"
|
||||
#include "jsclist.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jshash.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsarray.h"
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "jsclass.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsinfer.h"
|
||||
#include "jshash.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jslock.h"
|
||||
|
|
|
@ -376,7 +376,7 @@ js_DumpPC(JSContext *cx)
|
|||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_DumpScript(JSContext *cx, JSScript *script_)
|
||||
{
|
||||
Sprinter sprinter(cx);
|
||||
|
@ -4819,7 +4819,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, int nb)
|
|||
* syntactically appear.
|
||||
*/
|
||||
jsbytecode *nextpc = pc + JSOP_LAMBDA_LENGTH;
|
||||
LOCAL_ASSERT(*nextpc == JSOP_SETLOCAL || *nextpc == JSOP_SETALIASEDVAR);
|
||||
LOCAL_ASSERT(*nextpc == JSOP_SETLOCAL || *nextpc == JSOP_SETALIASEDVAR || *nextpc == JSOP_SETARG);
|
||||
nextpc += js_CodeSpec[*nextpc].length;
|
||||
LOCAL_ASSERT(*nextpc == JSOP_POP);
|
||||
nextpc += JSOP_POP_LENGTH;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче