зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
4a6b9ecd83
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "8472f0c736660072799aaae60e4b6001a6aaceb4",
|
||||
"git_revision": "4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "e4b5ba76d5a4de0cd220310e0fe2ba334f0e250a",
|
||||
"revision": "0bdd0b54cb40d7e928e9e6de720c0506dc7e52db",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="828317e64d28138f24d578ab340c2a0ff8552df0"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8472f0c736660072799aaae60e4b6001a6aaceb4"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4bb17b24620818cbda0ba0c0d69e0ce3f914e1b7"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9465d16f95ab87636b2ae07538ee88e5aeff2d7d"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -14,6 +14,11 @@ var {
|
|||
// WeakMap[Extension -> BrowserAction]
|
||||
var browserActionMap = new WeakMap();
|
||||
|
||||
// WeakMap[Extension -> docshell]
|
||||
// This map is a cache of the windowless browser that's used to render ImageData
|
||||
// for the browser_action icon.
|
||||
let imageRendererMap = new WeakMap();
|
||||
|
||||
function browserActionOf(extension)
|
||||
{
|
||||
return browserActionMap.get(extension);
|
||||
|
@ -41,9 +46,6 @@ function BrowserAction(options, extension)
|
|||
this.icon = new DefaultWeakMap(options.default_icon);
|
||||
this.popup = new DefaultWeakMap(options.default_popup);
|
||||
|
||||
// Make the default something that won't compare equal to anything.
|
||||
this.prevPopups = new DefaultWeakMap({});
|
||||
|
||||
this.context = null;
|
||||
}
|
||||
|
||||
|
@ -63,12 +65,14 @@ BrowserAction.prototype = {
|
|||
this.updateTab(null, node);
|
||||
|
||||
let tabbrowser = document.defaultView.gBrowser;
|
||||
tabbrowser.ownerDocument.addEventListener("TabSelect", () => {
|
||||
this.updateTab(tabbrowser.selectedTab, node);
|
||||
});
|
||||
tabbrowser.tabContainer.addEventListener("TabSelect", this);
|
||||
|
||||
node.addEventListener("command", event => {
|
||||
if (node.getAttribute("type") != "panel") {
|
||||
let tab = tabbrowser.selectedTab;
|
||||
let popup = this.getProperty(tab, "popup");
|
||||
if (popup) {
|
||||
this.togglePopup(node, popup);
|
||||
} else {
|
||||
this.emit("click");
|
||||
}
|
||||
});
|
||||
|
@ -79,6 +83,81 @@ BrowserAction.prototype = {
|
|||
this.widget = widget;
|
||||
},
|
||||
|
||||
handleEvent(event) {
|
||||
if (event.type == "TabSelect") {
|
||||
let window = event.target.ownerDocument.defaultView;
|
||||
let tabbrowser = window.gBrowser;
|
||||
let instance = CustomizableUI.getWidget(this.id).forWindow(window);
|
||||
if (instance) {
|
||||
this.updateTab(tabbrowser.selectedTab, instance.node);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
togglePopup(node, popupResource) {
|
||||
let popupURL = this.extension.baseURI.resolve(popupResource);
|
||||
|
||||
let document = node.ownerDocument;
|
||||
let panel = document.createElement("panel");
|
||||
panel.setAttribute("class", "browser-action-panel");
|
||||
panel.setAttribute("type", "arrow");
|
||||
panel.setAttribute("flip", "slide");
|
||||
node.appendChild(panel);
|
||||
|
||||
panel.addEventListener("popuphidden", () => {
|
||||
this.context.unload();
|
||||
this.context = null;
|
||||
panel.remove();
|
||||
});
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let browser = document.createElementNS(XUL_NS, "browser");
|
||||
browser.setAttribute("type", "content");
|
||||
browser.setAttribute("disableglobalhistory", "true");
|
||||
panel.appendChild(browser);
|
||||
|
||||
let loadListener = () => {
|
||||
panel.removeEventListener("load", loadListener);
|
||||
|
||||
this.context = new ExtensionPage(this.extension, {
|
||||
type: "popup",
|
||||
contentWindow: browser.contentWindow,
|
||||
uri: Services.io.newURI(popupURL, null, null),
|
||||
docShell: browser.docShell,
|
||||
});
|
||||
GlobalManager.injectInDocShell(browser.docShell, this.extension, this.context);
|
||||
browser.setAttribute("src", popupURL);
|
||||
|
||||
let contentLoadListener = () => {
|
||||
browser.removeEventListener("load", contentLoadListener);
|
||||
|
||||
let contentViewer = browser.docShell.contentViewer;
|
||||
let width = {}, height = {};
|
||||
try {
|
||||
contentViewer.getContentSize(width, height);
|
||||
[width, height] = [width.value, height.value];
|
||||
} catch (e) {
|
||||
// getContentSize can throw
|
||||
[width, height] = [400, 400];
|
||||
}
|
||||
|
||||
let window = document.defaultView;
|
||||
width /= window.devicePixelRatio;
|
||||
height /= window.devicePixelRatio;
|
||||
width = Math.min(width, 800);
|
||||
height = Math.min(height, 800);
|
||||
|
||||
browser.setAttribute("width", width);
|
||||
browser.setAttribute("height", height);
|
||||
|
||||
let anchor = document.getAnonymousElementByAttribute(node, "class", "toolbarbutton-icon");
|
||||
panel.openPopup(anchor, "bottomcenter topright", 0, 0, false, false);
|
||||
};
|
||||
browser.addEventListener("load", contentLoadListener, true);
|
||||
};
|
||||
panel.addEventListener("load", loadListener);
|
||||
},
|
||||
|
||||
// Initialize the toolbar icon and popup given that |tab| is the
|
||||
// current tab and |node| is the CustomizableUI node. Note: |tab|
|
||||
// will be null if we don't know the current tab yet (during
|
||||
|
@ -118,57 +197,6 @@ BrowserAction.prototype = {
|
|||
|
||||
let iconURL = this.getIcon(tab, node);
|
||||
node.setAttribute("image", iconURL);
|
||||
|
||||
let popup = this.getProperty(tab, "popup");
|
||||
|
||||
if (popup != this.prevPopups.get(window)) {
|
||||
this.prevPopups.set(window, popup);
|
||||
|
||||
let panel = node.querySelector("panel");
|
||||
if (panel) {
|
||||
panel.remove();
|
||||
}
|
||||
|
||||
if (popup) {
|
||||
let popupURL = this.extension.baseURI.resolve(popup);
|
||||
node.setAttribute("type", "panel");
|
||||
|
||||
let document = node.ownerDocument;
|
||||
let panel = document.createElement("panel");
|
||||
panel.setAttribute("class", "browser-action-panel");
|
||||
panel.setAttribute("type", "arrow");
|
||||
panel.setAttribute("flip", "slide");
|
||||
node.appendChild(panel);
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
let browser = document.createElementNS(XUL_NS, "browser");
|
||||
browser.setAttribute("type", "content");
|
||||
browser.setAttribute("disableglobalhistory", "true");
|
||||
browser.setAttribute("width", "500");
|
||||
browser.setAttribute("height", "500");
|
||||
panel.appendChild(browser);
|
||||
|
||||
let loadListener = () => {
|
||||
panel.removeEventListener("load", loadListener);
|
||||
|
||||
if (this.context) {
|
||||
this.context.unload();
|
||||
}
|
||||
|
||||
this.context = new ExtensionPage(this.extension, {
|
||||
type: "popup",
|
||||
contentWindow: browser.contentWindow,
|
||||
uri: Services.io.newURI(popupURL, null, null),
|
||||
docShell: browser.docShell,
|
||||
});
|
||||
GlobalManager.injectInDocShell(browser.docShell, this.extension, this.context);
|
||||
browser.setAttribute("src", popupURL);
|
||||
};
|
||||
panel.addEventListener("load", loadListener);
|
||||
} else {
|
||||
node.removeAttribute("type");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Note: tab is allowed to be null here.
|
||||
|
@ -236,6 +264,13 @@ BrowserAction.prototype = {
|
|||
},
|
||||
|
||||
shutdown() {
|
||||
let widget = CustomizableUI.getWidget(this.id);
|
||||
for (let instance of widget.instances) {
|
||||
let window = instance.node.ownerDocument.defaultView;
|
||||
let tabbrowser = window.gBrowser;
|
||||
tabbrowser.tabContainer.removeEventListener("TabSelect", this);
|
||||
}
|
||||
|
||||
CustomizableUI.destroyWidget(this.id);
|
||||
},
|
||||
};
|
||||
|
@ -253,8 +288,37 @@ extensions.on("shutdown", (type, extension) => {
|
|||
browserActionMap.get(extension).shutdown();
|
||||
browserActionMap.delete(extension);
|
||||
}
|
||||
imageRendererMap.delete(extension);
|
||||
});
|
||||
|
||||
function convertImageDataToPNG(extension, imageData)
|
||||
{
|
||||
let webNav = imageRendererMap.get(extension);
|
||||
if (!webNav) {
|
||||
webNav = Services.appShell.createWindowlessBrowser(false);
|
||||
let principal = Services.scriptSecurityManager.createCodebasePrincipal(extension.baseURI,
|
||||
{addonId: extension.id});
|
||||
let interfaceRequestor = webNav.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||
let docShell = interfaceRequestor.getInterface(Ci.nsIDocShell);
|
||||
|
||||
GlobalManager.injectInDocShell(docShell, extension, null);
|
||||
|
||||
docShell.createAboutBlankContentViewer(principal);
|
||||
}
|
||||
|
||||
let document = webNav.document;
|
||||
let canvas = document.createElement("canvas");
|
||||
canvas.width = imageData.width;
|
||||
canvas.height = imageData.height;
|
||||
canvas.getContext("2d").putImageData(imageData, 0, 0);
|
||||
|
||||
let url = canvas.toDataURL("image/png");
|
||||
|
||||
canvas.remove();
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
extensions.registerAPI((extension, context) => {
|
||||
return {
|
||||
browserAction: {
|
||||
|
@ -283,10 +347,11 @@ extensions.registerAPI((extension, context) => {
|
|||
setIcon: function(details, callback) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
if (details.imageData) {
|
||||
// FIXME: Support the imageData attribute.
|
||||
return;
|
||||
let url = convertImageDataToPNG(extension, details.imageData);
|
||||
browserActionOf(extension).setProperty(tab, "icon", url);
|
||||
} else {
|
||||
browserActionOf(extension).setProperty(tab, "icon", details.path);
|
||||
}
|
||||
browserActionOf(extension).setProperty(tab, "icon", details.path);
|
||||
},
|
||||
|
||||
setBadgeText: function(details) {
|
||||
|
|
|
@ -42,11 +42,18 @@ var pageDataMap = new WeakMap();
|
|||
// in some tab-specific details and keep data around about the
|
||||
// ExtensionPage.
|
||||
extensions.on("page-load", (type, page, params, sender, delegate) => {
|
||||
if (params.type == "tab") {
|
||||
if (params.type == "tab" || params.type == "popup") {
|
||||
let browser = params.docShell.chromeEventHandler;
|
||||
|
||||
let parentWindow = browser.ownerDocument.defaultView;
|
||||
let tab = parentWindow.gBrowser.getTabForBrowser(browser);
|
||||
sender.tabId = TabManager.getId(tab);
|
||||
page.windowId = WindowManager.getId(parentWindow);
|
||||
|
||||
let tab = null;
|
||||
if (params.type == "tab") {
|
||||
tab = parentWindow.gBrowser.getTabForBrowser(browser);
|
||||
sender.tabId = TabManager.getId(tab);
|
||||
page.tabId = TabManager.getId(tab);
|
||||
}
|
||||
|
||||
pageDataMap.set(page, {tab, parentWindow});
|
||||
}
|
||||
|
@ -63,7 +70,9 @@ extensions.on("page-shutdown", (type, page) => {
|
|||
let {tab, parentWindow} = pageDataMap.get(page);
|
||||
pageDataMap.delete(page);
|
||||
|
||||
parentWindow.gBrowser.removeTab(tab);
|
||||
if (tab) {
|
||||
parentWindow.gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -77,6 +86,15 @@ extensions.on("fill-browser-data", (type, browser, data, result) => {
|
|||
data.tabId = tabId;
|
||||
});
|
||||
|
||||
global.currentWindow = function(context)
|
||||
{
|
||||
let pageData = pageDataMap.get(context);
|
||||
if (pageData) {
|
||||
return pageData.parentWindow;
|
||||
}
|
||||
return WindowManager.topWindow;
|
||||
}
|
||||
|
||||
// TODO: activeTab permission
|
||||
|
||||
extensions.registerAPI((extension, context) => {
|
||||
|
@ -257,7 +275,7 @@ extensions.registerAPI((extension, context) => {
|
|||
}
|
||||
}
|
||||
|
||||
let window = createProperties.windowId ?
|
||||
let window = "windowId" in createProperties ?
|
||||
WindowManager.getWindow(createProperties.windowId) :
|
||||
WindowManager.topWindow;
|
||||
if (!window.gBrowser) {
|
||||
|
@ -382,7 +400,7 @@ extensions.registerAPI((extension, context) => {
|
|||
|
||||
if ("windowId" in queryInfo) {
|
||||
if (queryInfo.windowId == WindowManager.WINDOW_ID_CURRENT) {
|
||||
if (context.contentWindow != window) {
|
||||
if (currentWindow(context) != window) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -393,7 +411,7 @@ extensions.registerAPI((extension, context) => {
|
|||
}
|
||||
|
||||
if ("currentWindow" in queryInfo) {
|
||||
let eq = window == context.contentWindow;
|
||||
let eq = window == currentWindow(context);
|
||||
if (queryInfo.currentWindow != eq) {
|
||||
return false;
|
||||
}
|
||||
|
@ -406,6 +424,9 @@ extensions.registerAPI((extension, context) => {
|
|||
let e = Services.wm.getEnumerator("navigator:browser");
|
||||
while (e.hasMoreElements()) {
|
||||
let window = e.getNext();
|
||||
if (window.document.readyState != "complete") {
|
||||
continue;
|
||||
}
|
||||
let tabs = TabManager.getTabs(extension, window);
|
||||
for (let tab of tabs) {
|
||||
if (matches(window, tab)) {
|
||||
|
|
|
@ -45,7 +45,11 @@ extensions.registerAPI((extension, context) => {
|
|||
},
|
||||
|
||||
getCurrent: function(getInfo, callback) {
|
||||
let window = context.contentWindow;
|
||||
if (!callback) {
|
||||
callback = getInfo;
|
||||
getInfo = {};
|
||||
}
|
||||
let window = currentWindow(context);
|
||||
runSafe(context, callback, WindowManager.convert(extension, window, getInfo));
|
||||
},
|
||||
|
||||
|
@ -65,7 +69,9 @@ extensions.registerAPI((extension, context) => {
|
|||
let windows = [];
|
||||
while (e.hasMoreElements()) {
|
||||
let window = e.getNext();
|
||||
windows.push(WindowManager.convert(extension, window, getInfo));
|
||||
if (window.document.readyState == "complete") {
|
||||
windows.push(WindowManager.convert(extension, window, getInfo));
|
||||
}
|
||||
}
|
||||
runSafe(context, callback, windows);
|
||||
},
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
[DEFAULT]
|
||||
skip-if = os == 'android' || buildapp == 'b2g' || os == 'mac'
|
||||
support-files =
|
||||
head.js
|
||||
|
||||
[browser_extensions_simple.js]
|
||||
[browser_ext_simple.js]
|
||||
[browser_ext_currentWindow.js]
|
||||
[browser_ext_browserAction_simple.js]
|
||||
[browser_ext_browserAction_icon.js]
|
||||
[browser_ext_getViews.js]
|
||||
[browser_ext_tabs_executeScript.js]
|
||||
[browser_ext_tabs_query.js]
|
||||
[browser_ext_tabs_update.js]
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
add_task(function* () {
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"browser_action": {},
|
||||
"background": {
|
||||
"page": "background.html",
|
||||
}
|
||||
},
|
||||
|
||||
files: {
|
||||
"background.html": `<canvas id="canvas" width="2" height="2">
|
||||
<script src="background.js"></script>`,
|
||||
|
||||
"background.js": function() {
|
||||
var canvas = document.getElementById("canvas");
|
||||
var canvasContext = canvas.getContext("2d");
|
||||
|
||||
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
|
||||
canvasContext.fillStyle = "green";
|
||||
canvasContext.fillRect(0, 0, 1, 1);
|
||||
|
||||
var url = canvas.toDataURL("image/png");
|
||||
var imageData = canvasContext.getImageData(0, 0, canvas.width, canvas.height);
|
||||
browser.browserAction.setIcon({imageData});
|
||||
|
||||
browser.test.sendMessage("imageURL", url);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
let [_, url] = yield Promise.all([extension.startup(), extension.awaitMessage("imageURL")]);
|
||||
|
||||
let widgetId = makeWidgetId(extension.id) + "-browser-action";
|
||||
let node = CustomizableUI.getWidget(widgetId).forWindow(window).node;
|
||||
|
||||
let image = node.getAttribute("image");
|
||||
is(image, url, "image is correct");
|
||||
|
||||
yield extension.unload();
|
||||
});
|
|
@ -22,15 +22,31 @@ add_task(function* () {
|
|||
background: function() {
|
||||
browser.runtime.onMessage.addListener(msg => {
|
||||
browser.test.assertEq(msg, "from-popup", "correct message received");
|
||||
browser.test.notifyPass("browser_action.simple");
|
||||
browser.test.sendMessage("popup");
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
yield extension.startup();
|
||||
|
||||
// FIXME: Should really test opening the popup here.
|
||||
let widgetId = makeWidgetId(extension.id) + "-browser-action";
|
||||
let node = CustomizableUI.getWidget(widgetId).forWindow(window).node;
|
||||
|
||||
// Do this a few times to make sure the pop-up is reloaded each time.
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let evt = new CustomEvent("command", {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
yield extension.awaitMessage("popup");
|
||||
|
||||
let panel = node.querySelector("panel");
|
||||
if (panel) {
|
||||
panel.hidePopup();
|
||||
}
|
||||
}
|
||||
|
||||
yield extension.awaitFinish("browser_action.simple");
|
||||
yield extension.unload();
|
||||
});
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
function* focusWindow(win)
|
||||
{
|
||||
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
||||
if (fm.activeWindow == win) {
|
||||
return;
|
||||
}
|
||||
|
||||
let promise = new Promise(resolve => {
|
||||
win.addEventListener("focus", function listener() {
|
||||
win.removeEventListener("focus", listener, true);
|
||||
resolve();
|
||||
}, true);
|
||||
});
|
||||
|
||||
win.focus();
|
||||
yield promise;
|
||||
}
|
||||
|
||||
function genericChecker()
|
||||
{
|
||||
var kind = "background";
|
||||
var path = window.location.pathname;
|
||||
if (path.indexOf("popup") != -1) {
|
||||
kind = "popup";
|
||||
} else if (path.indexOf("page") != -1) {
|
||||
kind = "page";
|
||||
}
|
||||
|
||||
browser.test.onMessage.addListener((msg, ...args) => {
|
||||
if (msg == kind + "-check-current1") {
|
||||
browser.tabs.query({
|
||||
currentWindow: true
|
||||
}, function(tabs) {
|
||||
browser.test.sendMessage("result", tabs[0].windowId);
|
||||
});
|
||||
} else if (msg == kind + "-check-current2") {
|
||||
browser.tabs.query({
|
||||
windowId: browser.windows.WINDOW_ID_CURRENT
|
||||
}, function(tabs) {
|
||||
browser.test.sendMessage("result", tabs[0].windowId);
|
||||
});
|
||||
} else if (msg == kind + "-check-current3") {
|
||||
browser.windows.getCurrent(function(window) {
|
||||
browser.test.sendMessage("result", window.id);
|
||||
});
|
||||
} else if (msg == kind + "-open-page") {
|
||||
browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("page.html")});
|
||||
} else if (msg == kind + "-close-page") {
|
||||
browser.tabs.query({
|
||||
windowId: args[0],
|
||||
}, tabs => {
|
||||
var tab = tabs.find(tab => tab.url.indexOf("page.html") != -1);
|
||||
browser.tabs.remove(tab.id, () => {
|
||||
browser.test.sendMessage("closed");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
browser.test.sendMessage(kind + "-ready");
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
let win2 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
yield focusWindow(win2);
|
||||
|
||||
yield BrowserTestUtils.loadURI(win1.gBrowser.selectedBrowser, "about:robots");
|
||||
yield BrowserTestUtils.browserLoaded(win1.gBrowser.selectedBrowser);
|
||||
|
||||
yield BrowserTestUtils.loadURI(win2.gBrowser.selectedBrowser, "about:config");
|
||||
yield BrowserTestUtils.browserLoaded(win2.gBrowser.selectedBrowser);
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"],
|
||||
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
"page.html": `
|
||||
<!DOCTYPE html>
|
||||
<html><body>
|
||||
<script src="page.js"></script>
|
||||
</body></html>
|
||||
`,
|
||||
|
||||
"page.js": genericChecker,
|
||||
|
||||
"popup.html": `
|
||||
<!DOCTYPE html>
|
||||
<html><body>
|
||||
<script src="popup.js"></script>
|
||||
</body></html>
|
||||
`,
|
||||
|
||||
"popup.js": genericChecker,
|
||||
},
|
||||
|
||||
background: genericChecker,
|
||||
});
|
||||
|
||||
yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
|
||||
|
||||
let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
||||
let winId1 = WindowManager.getId(win1);
|
||||
let winId2 = WindowManager.getId(win2);
|
||||
|
||||
function* checkWindow(kind, winId, name) {
|
||||
extension.sendMessage(kind + "-check-current1");
|
||||
is((yield extension.awaitMessage("result")), winId, `${name} is on top (check 1) [${kind}]`);
|
||||
extension.sendMessage(kind + "-check-current2");
|
||||
is((yield extension.awaitMessage("result")), winId, `${name} is on top (check 2) [${kind}]`);
|
||||
extension.sendMessage(kind + "-check-current3");
|
||||
is((yield extension.awaitMessage("result")), winId, `${name} is on top (check 3) [${kind}]`);
|
||||
}
|
||||
|
||||
yield focusWindow(win1);
|
||||
yield checkWindow("background", winId1, "win1");
|
||||
yield focusWindow(win2);
|
||||
yield checkWindow("background", winId2, "win2");
|
||||
|
||||
function* triggerPopup(win, callback) {
|
||||
let widgetId = makeWidgetId(extension.id) + "-browser-action";
|
||||
let node = CustomizableUI.getWidget(widgetId).forWindow(win).node;
|
||||
|
||||
let evt = new CustomEvent("command", {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
yield extension.awaitMessage("popup-ready");
|
||||
|
||||
yield callback();
|
||||
|
||||
let panel = node.querySelector("panel");
|
||||
if (panel) {
|
||||
panel.hidePopup();
|
||||
}
|
||||
}
|
||||
|
||||
// Set focus to some other window.
|
||||
yield focusWindow(window);
|
||||
|
||||
yield triggerPopup(win1, function*() {
|
||||
yield checkWindow("popup", winId1, "win1");
|
||||
});
|
||||
|
||||
yield triggerPopup(win2, function*() {
|
||||
yield checkWindow("popup", winId2, "win2");
|
||||
});
|
||||
|
||||
function* triggerPage(winId, name) {
|
||||
extension.sendMessage("background-open-page", winId);
|
||||
yield extension.awaitMessage("page-ready");
|
||||
yield checkWindow("page", winId, name);
|
||||
extension.sendMessage("background-close-page", winId);
|
||||
yield extension.awaitMessage("closed");
|
||||
}
|
||||
|
||||
yield triggerPage(winId1, "win1");
|
||||
yield triggerPage(winId2, "win2");
|
||||
|
||||
yield extension.unload();
|
||||
|
||||
yield BrowserTestUtils.closeWindow(win1);
|
||||
yield BrowserTestUtils.closeWindow(win2);
|
||||
});
|
|
@ -0,0 +1,178 @@
|
|||
function genericChecker()
|
||||
{
|
||||
var kind = "background";
|
||||
var path = window.location.pathname;
|
||||
if (path.indexOf("popup") != -1) {
|
||||
kind = "popup";
|
||||
} else if (path.indexOf("tab") != -1) {
|
||||
kind = "tab";
|
||||
}
|
||||
window.kind = kind;
|
||||
|
||||
browser.test.onMessage.addListener((msg, ...args) => {
|
||||
if (msg == kind + "-check-views") {
|
||||
var views = browser.extension.getViews();
|
||||
var counts = {
|
||||
"background": 0,
|
||||
"tab": 0,
|
||||
"popup": 0
|
||||
};
|
||||
for (var i = 0; i < views.length; i++) {
|
||||
var view = views[i];
|
||||
browser.test.assertTrue(view.kind in counts, "view type is valid");
|
||||
counts[view.kind]++;
|
||||
if (view.kind == "background") {
|
||||
browser.test.assertTrue(view === browser.extension.getBackgroundPage(),
|
||||
"background page is correct");
|
||||
}
|
||||
}
|
||||
browser.test.sendMessage("counts", counts);
|
||||
} else if (msg == kind + "-open-tab") {
|
||||
browser.tabs.create({windowId: args[0], url: chrome.runtime.getURL("tab.html")});
|
||||
} else if (msg == kind + "-close-tab") {
|
||||
browser.tabs.query({
|
||||
windowId: args[0],
|
||||
}, tabs => {
|
||||
var tab = tabs.find(tab => tab.url.indexOf("tab.html") != -1);
|
||||
browser.tabs.remove(tab.id, () => {
|
||||
browser.test.sendMessage("closed");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
browser.test.sendMessage(kind + "-ready");
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
let win1 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
let win2 = yield BrowserTestUtils.openNewBrowserWindow();
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
manifest: {
|
||||
"permissions": ["tabs"],
|
||||
|
||||
"browser_action": {
|
||||
"default_popup": "popup.html"
|
||||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
"tab.html": `
|
||||
<!DOCTYPE html>
|
||||
<html><body>
|
||||
<script src="tab.js"></script>
|
||||
</body></html>
|
||||
`,
|
||||
|
||||
"tab.js": genericChecker,
|
||||
|
||||
"popup.html": `
|
||||
<!DOCTYPE html>
|
||||
<html><body>
|
||||
<script src="popup.js"></script>
|
||||
</body></html>
|
||||
`,
|
||||
|
||||
"popup.js": genericChecker,
|
||||
},
|
||||
|
||||
background: genericChecker,
|
||||
});
|
||||
|
||||
yield Promise.all([extension.startup(), extension.awaitMessage("background-ready")]);
|
||||
|
||||
info("started");
|
||||
|
||||
let {TabManager, WindowManager} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
||||
let winId1 = WindowManager.getId(win1);
|
||||
let winId2 = WindowManager.getId(win2);
|
||||
|
||||
function* openTab(winId) {
|
||||
extension.sendMessage("background-open-tab", winId);
|
||||
yield extension.awaitMessage("tab-ready");
|
||||
}
|
||||
|
||||
function* checkViews(kind, tabCount, popupCount) {
|
||||
extension.sendMessage(kind + "-check-views");
|
||||
let counts = yield extension.awaitMessage("counts");
|
||||
is(counts.background, 1, "background count correct");
|
||||
is(counts.tab, tabCount, "tab count correct");
|
||||
is(counts.popup, popupCount, "popup count correct");
|
||||
}
|
||||
|
||||
yield checkViews("background", 0, 0);
|
||||
|
||||
yield openTab(winId1);
|
||||
|
||||
yield checkViews("background", 1, 0);
|
||||
yield checkViews("tab", 1, 0);
|
||||
|
||||
yield openTab(winId2);
|
||||
|
||||
yield checkViews("background", 2, 0);
|
||||
|
||||
function* triggerPopup(win, callback) {
|
||||
let widgetId = makeWidgetId(extension.id) + "-browser-action";
|
||||
let node = CustomizableUI.getWidget(widgetId).forWindow(win).node;
|
||||
|
||||
let evt = new CustomEvent("command", {
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
node.dispatchEvent(evt);
|
||||
|
||||
yield extension.awaitMessage("popup-ready");
|
||||
|
||||
yield callback();
|
||||
|
||||
let panel = node.querySelector("panel");
|
||||
if (panel) {
|
||||
panel.hidePopup();
|
||||
}
|
||||
}
|
||||
|
||||
yield triggerPopup(win1, function*() {
|
||||
yield checkViews("background", 2, 1);
|
||||
yield checkViews("popup", 2, 1);
|
||||
});
|
||||
|
||||
yield triggerPopup(win2, function*() {
|
||||
yield checkViews("background", 2, 1);
|
||||
yield checkViews("popup", 2, 1);
|
||||
});
|
||||
|
||||
info("checking counts after popups");
|
||||
|
||||
yield checkViews("background", 2, 0);
|
||||
|
||||
info("closing one tab");
|
||||
|
||||
extension.sendMessage("background-close-tab", winId1);
|
||||
yield extension.awaitMessage("closed");
|
||||
|
||||
info("one tab closed, one remains");
|
||||
|
||||
yield checkViews("background", 1, 0);
|
||||
|
||||
info("opening win1 popup");
|
||||
|
||||
yield triggerPopup(win1, function*() {
|
||||
yield checkViews("background", 1, 1);
|
||||
yield checkViews("tab", 1, 1);
|
||||
yield checkViews("popup", 1, 1);
|
||||
});
|
||||
|
||||
info("opening win2 popup");
|
||||
|
||||
yield triggerPopup(win2, function*() {
|
||||
yield checkViews("background", 1, 1);
|
||||
yield checkViews("tab", 1, 1);
|
||||
yield checkViews("popup", 1, 1);
|
||||
});
|
||||
|
||||
yield extension.unload();
|
||||
|
||||
yield BrowserTestUtils.closeWindow(win1);
|
||||
yield BrowserTestUtils.closeWindow(win2);
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
let {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
|
||||
function makeWidgetId(id)
|
||||
{
|
||||
id = id.toLowerCase();
|
||||
return id.replace(/[^a-z0-9_-]/g, "_");
|
||||
}
|
|
@ -7251,6 +7251,9 @@ if test -z "$MOZ_MEMORY"; then
|
|||
esac
|
||||
else
|
||||
AC_DEFINE(MOZ_MEMORY)
|
||||
if test -n "$NIGHTLY_BUILD"; then
|
||||
MOZ_JEMALLOC4=1
|
||||
fi
|
||||
if test -n "$MOZ_JEMALLOC4"; then
|
||||
AC_DEFINE(MOZ_JEMALLOC4)
|
||||
fi
|
||||
|
|
|
@ -9,17 +9,7 @@
|
|||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"test/test-console-workers.html";
|
||||
|
||||
function pushPrefEnv() {
|
||||
let deferred = promise.defer();
|
||||
let options = {
|
||||
set: [["dom.workers.sharedWorkers.enabled", true]]
|
||||
};
|
||||
SpecialPowers.pushPrefEnv(options, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
var test = asyncTest(function*() {
|
||||
yield pushPrefEnv();
|
||||
yield loadTab(TEST_URI);
|
||||
|
||||
let hud = yield openConsole();
|
||||
|
|
|
@ -108,8 +108,8 @@ class DeserializedEdgeRange : public EdgeRange
|
|||
}
|
||||
|
||||
public:
|
||||
explicit DeserializedEdgeRange(JSContext* cx)
|
||||
: edges(cx)
|
||||
explicit DeserializedEdgeRange()
|
||||
: edges()
|
||||
, i(0)
|
||||
{
|
||||
settle();
|
||||
|
@ -160,10 +160,10 @@ Concrete<DeserializedNode>::allocationStack() const
|
|||
|
||||
|
||||
UniquePtr<EdgeRange>
|
||||
Concrete<DeserializedNode>::edges(JSContext* cx, bool) const
|
||||
Concrete<DeserializedNode>::edges(JSRuntime* rt, bool) const
|
||||
{
|
||||
UniquePtr<DeserializedEdgeRange, JS::DeletePolicy<DeserializedEdgeRange>> range(
|
||||
js_new<DeserializedEdgeRange>(cx));
|
||||
js_new<DeserializedEdgeRange>());
|
||||
|
||||
if (!range || !range->init(get()))
|
||||
return nullptr;
|
||||
|
|
|
@ -265,7 +265,7 @@ public:
|
|||
|
||||
// We ignore the `bool wantNames` parameter because we can't control whether
|
||||
// the core dump was serialized with edge names or not.
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool) const override;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
@ -384,7 +384,7 @@ HeapSnapshot::TakeCensus(JSContext* cx, JS::HandleObject options,
|
|||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
|
||||
JS::ubi::CensusTraversal traversal(cx, handler, nogc);
|
||||
JS::ubi::CensusTraversal traversal(JS_GetRuntime(cx), handler, nogc);
|
||||
if (NS_WARN_IF(!traversal.init())) {
|
||||
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
|
@ -684,7 +684,7 @@ public:
|
|||
}
|
||||
|
||||
if (includeEdges) {
|
||||
auto edges = ubiNode.edges(cx, wantNames);
|
||||
auto edges = ubiNode.edges(JS_GetRuntime(cx), wantNames);
|
||||
if (NS_WARN_IF(!edges))
|
||||
return false;
|
||||
|
||||
|
@ -795,7 +795,7 @@ WriteHeapGraph(JSContext* cx,
|
|||
// core dump.
|
||||
|
||||
HeapSnapshotHandler handler(writer, zones);
|
||||
HeapSnapshotHandler::Traversal traversal(cx, handler, noGC);
|
||||
HeapSnapshotHandler::Traversal traversal(JS_GetRuntime(cx), handler, noGC);
|
||||
if (!traversal.init())
|
||||
return false;
|
||||
traversal.wantNames = wantNames;
|
||||
|
@ -960,7 +960,7 @@ ThreadSafeChromeUtils::SaveHeapSnapshot(GlobalObject& global,
|
|||
|
||||
{
|
||||
Maybe<AutoCheckCannotGC> maybeNoGC;
|
||||
ubi::RootList rootList(cx, maybeNoGC, wantNames);
|
||||
ubi::RootList rootList(JS_GetRuntime(cx), maybeNoGC, wantNames);
|
||||
if (!EstablishBoundaries(cx, rv, boundaries, rootList, zones))
|
||||
return;
|
||||
|
||||
|
|
|
@ -97,5 +97,5 @@ DEF_TEST(DeserializedNodeUbiNodes, {
|
|||
.Times(1)
|
||||
.WillOnce(Return(JS::ubi::Node(referent3.get())));
|
||||
|
||||
ubi.edges(cx);
|
||||
ubi.edges(JS_GetRuntime(cx));
|
||||
});
|
||||
|
|
|
@ -162,8 +162,8 @@ public:
|
|||
JS::Zone* zone;
|
||||
size_t size;
|
||||
|
||||
explicit FakeNode(JSContext* cx)
|
||||
: edges(cx),
|
||||
explicit FakeNode()
|
||||
: edges(),
|
||||
compartment(nullptr),
|
||||
zone(nullptr),
|
||||
size(1)
|
||||
|
@ -182,8 +182,8 @@ class Concrete<FakeNode> : public Base
|
|||
return concreteTypeName;
|
||||
}
|
||||
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override {
|
||||
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(cx, get().edges));
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override {
|
||||
return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
|
||||
}
|
||||
|
||||
Size size(mozilla::MallocSizeOf) const override {
|
||||
|
@ -233,8 +233,8 @@ void AddEdge(FakeNode& node, FakeNode& referent, const char16_t* edgeName = null
|
|||
namespace testing {
|
||||
|
||||
// Ensure that given node has the expected number of edges.
|
||||
MATCHER_P2(EdgesLength, cx, expectedLength, "") {
|
||||
auto edges = arg.edges(cx);
|
||||
MATCHER_P2(EdgesLength, rt, expectedLength, "") {
|
||||
auto edges = arg.edges(rt);
|
||||
if (!edges)
|
||||
return false;
|
||||
|
||||
|
@ -247,8 +247,8 @@ MATCHER_P2(EdgesLength, cx, expectedLength, "") {
|
|||
}
|
||||
|
||||
// Get the nth edge and match it with the given matcher.
|
||||
MATCHER_P3(Edge, cx, n, matcher, "") {
|
||||
auto edges = arg.edges(cx);
|
||||
MATCHER_P3(Edge, rt, n, matcher, "") {
|
||||
auto edges = arg.edges(rt);
|
||||
if (!edges)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -29,10 +29,10 @@ DEF_TEST(DoesCrossZoneBoundaries, {
|
|||
ASSERT_TRUE(targetZones.put(zone));
|
||||
ASSERT_TRUE(targetZones.put(newZone));
|
||||
|
||||
FakeNode nodeA(cx);
|
||||
FakeNode nodeB(cx);
|
||||
FakeNode nodeC(cx);
|
||||
FakeNode nodeD(cx);
|
||||
FakeNode nodeA;
|
||||
FakeNode nodeB;
|
||||
FakeNode nodeC;
|
||||
FakeNode nodeD;
|
||||
|
||||
nodeA.zone = zone;
|
||||
nodeB.zone = nullptr;
|
||||
|
|
|
@ -29,9 +29,9 @@ DEF_TEST(DoesntCrossZoneBoundaries, {
|
|||
ASSERT_TRUE(targetZones.init());
|
||||
ASSERT_TRUE(targetZones.put(zone));
|
||||
|
||||
FakeNode nodeA(cx);
|
||||
FakeNode nodeB(cx);
|
||||
FakeNode nodeC(cx);
|
||||
FakeNode nodeA;
|
||||
FakeNode nodeB;
|
||||
FakeNode nodeC;
|
||||
|
||||
nodeA.zone = zone;
|
||||
nodeB.zone = nullptr;
|
||||
|
|
|
@ -13,8 +13,8 @@ using testing::Property;
|
|||
using testing::Return;
|
||||
|
||||
DEF_TEST(SerializesEdgeNames, {
|
||||
FakeNode node(cx);
|
||||
FakeNode referent(cx);
|
||||
FakeNode node;
|
||||
FakeNode referent;
|
||||
|
||||
const char16_t edgeName[] = MOZ_UTF16("edge name");
|
||||
const char16_t emptyStr[] = MOZ_UTF16("");
|
||||
|
@ -28,12 +28,12 @@ DEF_TEST(SerializesEdgeNames, {
|
|||
// Should get the node with edges once.
|
||||
EXPECT_CALL(
|
||||
writer,
|
||||
writeNode(AllOf(EdgesLength(cx, 3),
|
||||
Edge(cx, 0, Field(&JS::ubi::Edge::name,
|
||||
writeNode(AllOf(EdgesLength(rt, 3),
|
||||
Edge(rt, 0, Field(&JS::ubi::Edge::name,
|
||||
UTF16StrEq(edgeName))),
|
||||
Edge(cx, 1, Field(&JS::ubi::Edge::name,
|
||||
Edge(rt, 1, Field(&JS::ubi::Edge::name,
|
||||
UTF16StrEq(emptyStr))),
|
||||
Edge(cx, 2, Field(&JS::ubi::Edge::name,
|
||||
Edge(rt, 2, Field(&JS::ubi::Edge::name,
|
||||
IsNull()))),
|
||||
_)
|
||||
)
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
#include "DevTools.h"
|
||||
|
||||
DEF_TEST(SerializesEverythingInHeapGraphOnce, {
|
||||
FakeNode nodeA(cx);
|
||||
FakeNode nodeB(cx);
|
||||
FakeNode nodeC(cx);
|
||||
FakeNode nodeD(cx);
|
||||
FakeNode nodeA;
|
||||
FakeNode nodeB;
|
||||
FakeNode nodeC;
|
||||
FakeNode nodeD;
|
||||
|
||||
AddEdge(nodeA, nodeB);
|
||||
AddEdge(nodeB, nodeC);
|
||||
|
|
|
@ -11,7 +11,7 @@ using testing::Property;
|
|||
using testing::Return;
|
||||
|
||||
DEF_TEST(SerializesTypeNames, {
|
||||
FakeNode node(cx);
|
||||
FakeNode node;
|
||||
|
||||
::testing::NiceMock<MockWriter> writer;
|
||||
EXPECT_CALL(writer, writeNode(Property(&JS::ubi::Node::typeName,
|
||||
|
|
|
@ -80,6 +80,7 @@ skip-if = os == 'linux' || os == 'mac' # Bug 1026815
|
|||
[test_bug690056.xul]
|
||||
[test_bug789773.xul]
|
||||
[test_bug846906.xul]
|
||||
skip-if = os == 'linux' && asan # Bug 1207161
|
||||
[test_bug89419.xul]
|
||||
[test_bug909218.html]
|
||||
[test_bug92598.xul]
|
||||
|
|
|
@ -44,7 +44,7 @@ function runTests() {
|
|||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.workers.sharedWorkers.enabled", true]]}, runTests);
|
||||
runTests();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -946,6 +946,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
|
|||
, mZero(false), mOpaque(false)
|
||||
, mResetLayer(true)
|
||||
, mIPC(false)
|
||||
, mIsSkiaGL(false)
|
||||
, mDrawObserver(nullptr)
|
||||
, mIsEntireFrameInvalid(false)
|
||||
, mPredictManyRedrawCalls(false)
|
||||
|
@ -1376,6 +1377,8 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
|||
}
|
||||
}
|
||||
|
||||
mIsSkiaGL = false;
|
||||
|
||||
// Check that the dimensions are sane
|
||||
IntSize size(mWidth, mHeight);
|
||||
if (size.width <= gfxPrefs::MaxCanvasSize() &&
|
||||
|
@ -1409,6 +1412,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
|||
if (mTarget) {
|
||||
AddDemotableContext(this);
|
||||
mBufferProvider = new PersistentBufferProviderBasic(mTarget);
|
||||
mIsSkiaGL = true;
|
||||
} else {
|
||||
printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
|
||||
mode = RenderingMode::SoftwareBackendMode;
|
||||
|
@ -5560,9 +5564,11 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
CanvasLayer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
{
|
||||
if (mOpaque) {
|
||||
if (mOpaque || mIsSkiaGL) {
|
||||
// If we're opaque then make sure we have a surface so we paint black
|
||||
// instead of transparent.
|
||||
// If we're using SkiaGL, then SkiaGLTex() below needs the target to
|
||||
// be accessible.
|
||||
EnsureTarget();
|
||||
}
|
||||
|
||||
|
|
|
@ -718,6 +718,9 @@ protected:
|
|||
bool mResetLayer;
|
||||
// This is needed for drawing in drawAsyncXULElement
|
||||
bool mIPC;
|
||||
// True if the current DrawTarget is using skia-gl, used so we can avoid
|
||||
// requesting the DT from mBufferProvider to check.
|
||||
bool mIsSkiaGL;
|
||||
|
||||
nsTArray<CanvasRenderingContext2DUserData*> mUserDatas;
|
||||
|
||||
|
|
|
@ -159,4 +159,4 @@ pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidV
|
|||
# Check that captureStream() displays in a local video element
|
||||
skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png
|
||||
|
||||
fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
|
||||
fuzzy-if(azureSkiaGL,1,2) fuzzy-if(Android,3,40) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),1,1) == 1177726-text-stroke-bounds.html 1177726-text-stroke-bounds-ref.html
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
#include "nsIClipboard.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsICycleCollectorListener.h"
|
||||
#include "nsIDocShellTreeOwner.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMGeoGeolocation.h"
|
||||
#include "nsIDOMGeoPositionError.h"
|
||||
|
@ -124,6 +125,7 @@
|
|||
#include "nsIFormProcessor.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsIIdleService.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIMemoryInfoDumper.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
|
@ -1234,7 +1236,18 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
|||
constructorSender->ChildID());
|
||||
}
|
||||
if (constructorSender) {
|
||||
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
||||
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
||||
if (!treeOwner) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebBrowserChrome> wbc = do_GetInterface(treeOwner);
|
||||
if (!wbc) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t chromeFlags = 0;
|
||||
wbc->GetChromeFlags(&chromeFlags);
|
||||
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
|
||||
if (loadContext && loadContext->UsePrivateBrowsing()) {
|
||||
|
@ -2189,7 +2202,7 @@ ContentParent::StartForceKillTimer()
|
|||
return;
|
||||
}
|
||||
|
||||
int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 0);
|
||||
int32_t timeoutSecs = Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5);
|
||||
if (timeoutSecs > 0) {
|
||||
mForceKillTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
MOZ_ASSERT(mForceKillTimer);
|
||||
|
@ -3471,6 +3484,14 @@ ContentParent::DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParen
|
|||
/* static */ void
|
||||
ContentParent::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
#ifdef ENABLE_TESTS
|
||||
// We don't want to time out the content process during XPCShell tests. This
|
||||
// is the easiest way to ensure that.
|
||||
if (PR_GetEnv("XPCSHELL_TEST_PROFILE_DIR")) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto self = static_cast<ContentParent*>(aClosure);
|
||||
self->KillHard("ShutDownKill");
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
// NSPR_LOG_MODULES=LoadManager:5
|
||||
PRLogModuleInfo *gLoadManagerLog = nullptr;
|
||||
|
@ -53,6 +55,11 @@ LoadManagerSingleton::LoadManagerSingleton(int aLoadMeasurementInterval,
|
|||
mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
|
||||
mLoadMonitor->Init(mLoadMonitor);
|
||||
mLoadMonitor->SetLoadChangeCallback(this);
|
||||
|
||||
mLastStateChange = TimeStamp::Now();
|
||||
for (auto &in_state : mTimeInState) {
|
||||
in_state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
LoadManagerSingleton::~LoadManagerSingleton()
|
||||
|
@ -100,21 +107,22 @@ LoadManagerSingleton::LoadChanged(float aSystemLoad, float aProcesLoad)
|
|||
if (mLoadSumMeasurements >= mAveragingMeasurements) {
|
||||
double averagedLoad = mLoadSum / (float)mLoadSumMeasurements;
|
||||
|
||||
webrtc::CPULoadState oldState = mCurrentState;
|
||||
webrtc::CPULoadState newState = mCurrentState;
|
||||
|
||||
if (mOveruseActive || averagedLoad > mHighLoadThreshold) {
|
||||
LOG(("LoadManager - LoadStressed"));
|
||||
mCurrentState = webrtc::kLoadStressed;
|
||||
newState = webrtc::kLoadStressed;
|
||||
} else if (averagedLoad < mLowLoadThreshold) {
|
||||
LOG(("LoadManager - LoadRelaxed"));
|
||||
mCurrentState = webrtc::kLoadRelaxed;
|
||||
newState = webrtc::kLoadRelaxed;
|
||||
} else {
|
||||
LOG(("LoadManager - LoadNormal"));
|
||||
mCurrentState = webrtc::kLoadNormal;
|
||||
newState = webrtc::kLoadNormal;
|
||||
}
|
||||
|
||||
if (oldState != mCurrentState)
|
||||
LoadHasChanged();
|
||||
if (newState != mCurrentState) {
|
||||
LoadHasChanged(newState);
|
||||
}
|
||||
|
||||
mLoadSum = 0;
|
||||
mLoadSumMeasurements = 0;
|
||||
|
@ -128,8 +136,7 @@ LoadManagerSingleton::OveruseDetected()
|
|||
MutexAutoLock lock(mLock);
|
||||
mOveruseActive = true;
|
||||
if (mCurrentState != webrtc::kLoadStressed) {
|
||||
mCurrentState = webrtc::kLoadStressed;
|
||||
LoadHasChanged();
|
||||
LoadHasChanged(webrtc::kLoadStressed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,10 +149,18 @@ LoadManagerSingleton::NormalUsage()
|
|||
}
|
||||
|
||||
void
|
||||
LoadManagerSingleton::LoadHasChanged()
|
||||
LoadManagerSingleton::LoadHasChanged(webrtc::CPULoadState aNewState)
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
LOG(("LoadManager - Signaling LoadHasChanged to %d listeners", mObservers.Length()));
|
||||
LOG(("LoadManager - Signaling LoadHasChanged from %d to %d to %d listeners",
|
||||
mCurrentState, aNewState, mObservers.Length()));
|
||||
|
||||
// Record how long we spent in this state for later Telemetry or display
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
|
||||
mLastStateChange = now;
|
||||
|
||||
mCurrentState = aNewState;
|
||||
for (size_t i = 0; i < mObservers.Length(); i++) {
|
||||
mObservers.ElementAt(i)->onLoadStateChanged(mCurrentState);
|
||||
}
|
||||
|
@ -162,6 +177,7 @@ LoadManagerSingleton::AddObserver(webrtc::CPULoadStateObserver * aObserver)
|
|||
mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
|
||||
mLoadMonitor->Init(mLoadMonitor);
|
||||
mLoadMonitor->SetLoadChangeCallback(this);
|
||||
mLastStateChange = TimeStamp::Now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,6 +192,35 @@ LoadManagerSingleton::RemoveObserver(webrtc::CPULoadStateObserver * aObserver)
|
|||
}
|
||||
if (mObservers.Length() == 0) {
|
||||
if (mLoadMonitor) {
|
||||
// Record how long we spent in the final state for later Telemetry or display
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
|
||||
|
||||
float total = 0;
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mTimeInState); i++) {
|
||||
total += mTimeInState[i];
|
||||
}
|
||||
// Don't include short calls; we don't have reasonable load data, and
|
||||
// such short calls rarely reach a stable state. Keep relatively
|
||||
// short calls separate from longer ones
|
||||
bool log = total > 5*PR_MSEC_PER_SEC;
|
||||
bool small = log && total < 30*PR_MSEC_PER_SEC;
|
||||
if (log) {
|
||||
// Note: We don't care about rounding here; thus total may be < 100
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_RELAXED_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_RELAXED,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadRelaxed]/total * 100));
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_NORMAL_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_NORMAL,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadNormal]/total * 100));
|
||||
Telemetry::Accumulate(small ? Telemetry::WEBRTC_LOAD_STATE_STRESSED_SHORT :
|
||||
Telemetry::WEBRTC_LOAD_STATE_STRESSED,
|
||||
(uint32_t) (mTimeInState[webrtc::CPULoadState::kLoadStressed]/total * 100));
|
||||
}
|
||||
for (auto &in_state : mTimeInState) {
|
||||
in_state = 0;
|
||||
}
|
||||
|
||||
// Dance to avoid deadlock on mLock!
|
||||
nsRefPtr<LoadMonitor> loadMonitor = mLoadMonitor.forget();
|
||||
MutexAutoUnlock unlock(mLock);
|
||||
|
|
|
@ -50,7 +50,7 @@ private:
|
|||
float aLowLoadThreshold);
|
||||
~LoadManagerSingleton();
|
||||
|
||||
void LoadHasChanged();
|
||||
void LoadHasChanged(webrtc::CPULoadState aNewState);
|
||||
|
||||
nsRefPtr<LoadMonitor> mLoadMonitor;
|
||||
|
||||
|
@ -59,6 +59,9 @@ private:
|
|||
Mutex mLock;
|
||||
nsTArray<webrtc::CPULoadStateObserver*> mObservers;
|
||||
webrtc::CPULoadState mCurrentState;
|
||||
TimeStamp mLastStateChange;
|
||||
float mTimeInState[static_cast<int>(webrtc::kLoadLast)];
|
||||
|
||||
// Set when overuse was signaled to us, and hasn't been un-signaled yet.
|
||||
bool mOveruseActive;
|
||||
float mLoadSum;
|
||||
|
|
|
@ -4,41 +4,24 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/dom/PresentationBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIPresentationDeviceManager.h"
|
||||
#include "nsIPresentationService.h"
|
||||
#include "nsIUUIDGenerator.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "Presentation.h"
|
||||
#include "PresentationCallbacks.h"
|
||||
#include "PresentationSession.h"
|
||||
#include "PresentationReceiver.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Presentation)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Presentation, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDefaultRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessions)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingGetSessionPromises)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Presentation, DOMEventTargetHelper)
|
||||
tmp->Shutdown();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDefaultRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessions)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingGetSessionPromises)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(Presentation, DOMEventTargetHelper,
|
||||
mDefaultRequest, mReceiver)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(Presentation, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(Presentation, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Presentation)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
/* static */ already_AddRefed<Presentation>
|
||||
|
@ -55,7 +38,6 @@ Presentation::Presentation(nsPIDOMWindow* aWindow)
|
|||
|
||||
Presentation::~Presentation()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -70,56 +52,25 @@ Presentation::Init()
|
|||
if (NS_WARN_IF(!GetOwner())) {
|
||||
return false;
|
||||
}
|
||||
mWindowId = GetOwner()->WindowID();
|
||||
|
||||
// Check if a session instance is required now. A session may already be
|
||||
// connecting before the web content gets loaded in a presenting browsing
|
||||
// context (receiver).
|
||||
// Check if a receiver instance is required now. A session may already be
|
||||
// connecting before the web content gets loaded in a receiving browsing
|
||||
// context.
|
||||
nsAutoString sessionId;
|
||||
nsresult rv = service->GetExistentSessionIdAtLaunch(mWindowId, sessionId);
|
||||
nsresult rv = service->GetExistentSessionIdAtLaunch(GetOwner()->WindowID(), sessionId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
if (!sessionId.IsEmpty()) {
|
||||
rv = NotifySessionConnect(mWindowId, sessionId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mReceiver = PresentationReceiver::Create(GetOwner(), sessionId);
|
||||
if (NS_WARN_IF(!mReceiver)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Register listener for incoming sessions.
|
||||
rv = service->RegisterRespondingListener(mWindowId, this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Presentation::Shutdown()
|
||||
{
|
||||
mDefaultRequest = nullptr;
|
||||
mSessions.Clear();
|
||||
mPendingGetSessionPromises.Clear();
|
||||
|
||||
// Unregister listener for incoming sessions.
|
||||
nsCOMPtr<nsIPresentationService> service =
|
||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!service)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = service->UnregisterRespondingListener(mWindowId);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
Presentation::DisconnectFromOwner()
|
||||
{
|
||||
Shutdown();
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
}
|
||||
|
||||
/* virtual */ JSObject*
|
||||
Presentation::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
|
@ -140,81 +91,9 @@ Presentation::GetDefaultRequest() const
|
|||
return request.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Presentation::GetSession(ErrorResult& aRv)
|
||||
already_AddRefed<PresentationReceiver>
|
||||
Presentation::GetReceiver() const
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||
if (NS_WARN_IF(!global)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If there's no existing session, leave the promise pending until a
|
||||
// connecting request arrives from the controlling browsing context (sender).
|
||||
// http://w3c.github.io/presentation-api/#dom-presentation-getsession
|
||||
if (!mSessions.IsEmpty()) {
|
||||
promise->MaybeResolve(mSessions[0]);
|
||||
} else {
|
||||
mPendingGetSessionPromises.AppendElement(promise);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
Presentation::GetSessions(ErrorResult& aRv) const
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||
if (NS_WARN_IF(!global)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
promise->MaybeResolve(mSessions);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Presentation::NotifySessionConnect(uint64_t aWindowId,
|
||||
const nsAString& aSessionId)
|
||||
{
|
||||
if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsRefPtr<PresentationSession> session =
|
||||
PresentationSession::Create(GetOwner(), aSessionId,
|
||||
PresentationSessionState::Disconnected);
|
||||
if (NS_WARN_IF(!session)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
mSessions.AppendElement(session);
|
||||
|
||||
// Resolve pending |GetSession| promises if any.
|
||||
if (!mPendingGetSessionPromises.IsEmpty()) {
|
||||
for(uint32_t i = 0; i < mPendingGetSessionPromises.Length(); i++) {
|
||||
mPendingGetSessionPromises[i]->MaybeResolve(session);
|
||||
}
|
||||
mPendingGetSessionPromises.Clear();
|
||||
}
|
||||
|
||||
return DispatchSessionAvailableEvent();
|
||||
}
|
||||
|
||||
nsresult
|
||||
Presentation::DispatchSessionAvailableEvent()
|
||||
{
|
||||
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(this, NS_LITERAL_STRING("sessionavailable"), false);
|
||||
return asyncDispatcher->PostDOMEvent();
|
||||
nsRefPtr<PresentationReceiver> receiver = mReceiver;
|
||||
return receiver.forget();
|
||||
}
|
||||
|
|
|
@ -8,28 +8,23 @@
|
|||
#define mozilla_dom_Presentation_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "nsIPresentationListener.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
class PresentationReceiver;
|
||||
class PresentationRequest;
|
||||
class PresentationSession;
|
||||
|
||||
class Presentation final : public DOMEventTargetHelper
|
||||
, public nsIPresentationRespondingListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Presentation,
|
||||
DOMEventTargetHelper)
|
||||
NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
|
||||
|
||||
static already_AddRefed<Presentation> Create(nsPIDOMWindow* aWindow);
|
||||
|
||||
virtual void DisconnectFromOwner() override;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
|
@ -38,11 +33,7 @@ public:
|
|||
|
||||
already_AddRefed<PresentationRequest> GetDefaultRequest() const;
|
||||
|
||||
already_AddRefed<Promise> GetSession(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> GetSessions(ErrorResult& aRv) const;
|
||||
|
||||
IMPL_EVENT_HANDLER(sessionavailable);
|
||||
already_AddRefed<PresentationReceiver> GetReceiver() const;
|
||||
|
||||
private:
|
||||
explicit Presentation(nsPIDOMWindow* aWindow);
|
||||
|
@ -51,17 +42,8 @@ private:
|
|||
|
||||
bool Init();
|
||||
|
||||
void Shutdown();
|
||||
|
||||
nsresult DispatchSessionAvailableEvent();
|
||||
|
||||
// Store the inner window ID for |UnregisterRespondingListener| call in
|
||||
// |Shutdown| since the inner window may not exist at that moment.
|
||||
uint64_t mWindowId;
|
||||
|
||||
nsRefPtr<PresentationRequest> mDefaultRequest;
|
||||
nsTArray<nsRefPtr<PresentationSession>> mSessions;
|
||||
nsTArray<nsRefPtr<Promise>> mPendingGetSessionPromises;
|
||||
nsRefPtr<PresentationReceiver> mReceiver;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/dom/PresentationReceiverBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIPresentationService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "PresentationReceiver.h"
|
||||
#include "PresentationSession.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationReceiver)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PresentationReceiver, DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessions)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingGetSessionPromises)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationReceiver, DOMEventTargetHelper)
|
||||
tmp->Shutdown();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessions)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingGetSessionPromises)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(PresentationReceiver, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(PresentationReceiver, DOMEventTargetHelper)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationReceiver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
/* static */ already_AddRefed<PresentationReceiver>
|
||||
PresentationReceiver::Create(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aSessionId)
|
||||
{
|
||||
nsRefPtr<PresentationReceiver> receiver = new PresentationReceiver(aWindow);
|
||||
return NS_WARN_IF(!receiver->Init(aSessionId)) ? nullptr : receiver.forget();
|
||||
}
|
||||
|
||||
PresentationReceiver::PresentationReceiver(nsPIDOMWindow* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
{
|
||||
}
|
||||
|
||||
PresentationReceiver::~PresentationReceiver()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
PresentationReceiver::Init(const nsAString& aSessionId)
|
||||
{
|
||||
if (NS_WARN_IF(!GetOwner())) {
|
||||
return false;
|
||||
}
|
||||
mWindowId = GetOwner()->WindowID();
|
||||
|
||||
if (!aSessionId.IsEmpty()) {
|
||||
nsresult rv = NotifySessionConnect(mWindowId, aSessionId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Register listener for incoming sessions.
|
||||
nsCOMPtr<nsIPresentationService> service =
|
||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!service)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv = service->RegisterRespondingListener(mWindowId, this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PresentationReceiver::Shutdown()
|
||||
{
|
||||
mSessions.Clear();
|
||||
mPendingGetSessionPromises.Clear();
|
||||
|
||||
// Unregister listener for incoming sessions.
|
||||
nsCOMPtr<nsIPresentationService> service =
|
||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!service)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = service->UnregisterRespondingListener(mWindowId);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
PresentationReceiver::DisconnectFromOwner()
|
||||
{
|
||||
Shutdown();
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
}
|
||||
|
||||
/* virtual */ JSObject*
|
||||
PresentationReceiver::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return PresentationReceiverBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
PresentationReceiver::GetSession(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||
if (NS_WARN_IF(!global)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If there's no existing session, leave the promise pending until a
|
||||
// connecting request arrives from the controlling browsing context (sender).
|
||||
// http://w3c.github.io/presentation-api/#dom-presentation-getsession
|
||||
if (!mSessions.IsEmpty()) {
|
||||
promise->MaybeResolve(mSessions[0]);
|
||||
} else {
|
||||
mPendingGetSessionPromises.AppendElement(promise);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
PresentationReceiver::GetSessions(ErrorResult& aRv) const
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||
if (NS_WARN_IF(!global)) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
promise->MaybeResolve(mSessions);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationReceiver::NotifySessionConnect(uint64_t aWindowId,
|
||||
const nsAString& aSessionId)
|
||||
{
|
||||
if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsRefPtr<PresentationSession> session =
|
||||
PresentationSession::Create(GetOwner(), aSessionId,
|
||||
PresentationSessionState::Disconnected);
|
||||
if (NS_WARN_IF(!session)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
mSessions.AppendElement(session);
|
||||
|
||||
// Resolve pending |GetSession| promises if any.
|
||||
if (!mPendingGetSessionPromises.IsEmpty()) {
|
||||
for(uint32_t i = 0; i < mPendingGetSessionPromises.Length(); i++) {
|
||||
mPendingGetSessionPromises[i]->MaybeResolve(session);
|
||||
}
|
||||
mPendingGetSessionPromises.Clear();
|
||||
}
|
||||
|
||||
return DispatchSessionAvailableEvent();
|
||||
}
|
||||
|
||||
nsresult
|
||||
PresentationReceiver::DispatchSessionAvailableEvent()
|
||||
{
|
||||
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(this, NS_LITERAL_STRING("sessionavailable"), false);
|
||||
return asyncDispatcher->PostDOMEvent();
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PresentationReceiver_h
|
||||
#define mozilla_dom_PresentationReceiver_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "nsIPresentationListener.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Promise;
|
||||
class PresentationSession;
|
||||
|
||||
class PresentationReceiver final : public DOMEventTargetHelper
|
||||
, public nsIPresentationRespondingListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationReceiver,
|
||||
DOMEventTargetHelper)
|
||||
NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
|
||||
|
||||
static already_AddRefed<PresentationReceiver> Create(nsPIDOMWindow* aWindow,
|
||||
const nsAString& aSessionId);
|
||||
|
||||
virtual void DisconnectFromOwner() override;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
// WebIDL (public APIs)
|
||||
already_AddRefed<Promise> GetSession(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> GetSessions(ErrorResult& aRv) const;
|
||||
|
||||
IMPL_EVENT_HANDLER(sessionavailable);
|
||||
|
||||
private:
|
||||
explicit PresentationReceiver(nsPIDOMWindow* aWindow);
|
||||
|
||||
~PresentationReceiver();
|
||||
|
||||
bool Init(const nsAString& aSessionId);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
nsresult DispatchSessionAvailableEvent();
|
||||
|
||||
// Store the inner window ID for |UnregisterRespondingListener| call in
|
||||
// |Shutdown| since the inner window may not exist at that moment.
|
||||
uint64_t mWindowId;
|
||||
|
||||
nsTArray<nsRefPtr<PresentationSession>> mSessions;
|
||||
nsTArray<nsRefPtr<Promise>> mPendingGetSessionPromises;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PresentationReceiver_h
|
|
@ -50,6 +50,11 @@ PresentationParent::ActorDestroy(ActorDestroyReason aWhy)
|
|||
}
|
||||
mSessionIds.Clear();
|
||||
|
||||
for (uint32_t i = 0; i < mWindowIds.Length(); i++) {
|
||||
NS_WARN_IF(NS_FAILED(mService->UnregisterRespondingListener(mWindowIds[i])));
|
||||
}
|
||||
mWindowIds.Clear();
|
||||
|
||||
mService->UnregisterAvailabilityListener(this);
|
||||
mService = nullptr;
|
||||
}
|
||||
|
@ -149,6 +154,8 @@ PresentationParent::RecvUnregisterSessionHandler(const nsString& aSessionId)
|
|||
PresentationParent::RecvRegisterRespondingHandler(const uint64_t& aWindowId)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
|
||||
mWindowIds.AppendElement(aWindowId);
|
||||
NS_WARN_IF(NS_FAILED(mService->RegisterRespondingListener(aWindowId, this)));
|
||||
return true;
|
||||
}
|
||||
|
@ -157,6 +164,7 @@ PresentationParent::RecvRegisterRespondingHandler(const uint64_t& aWindowId)
|
|||
PresentationParent::RecvUnregisterRespondingHandler(const uint64_t& aWindowId)
|
||||
{
|
||||
MOZ_ASSERT(mService);
|
||||
mWindowIds.RemoveElement(aWindowId);
|
||||
NS_WARN_IF(NS_FAILED(mService->UnregisterRespondingListener(aWindowId)));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ private:
|
|||
bool mActorDestroyed;
|
||||
nsCOMPtr<nsIPresentationService> mService;
|
||||
nsTArray<nsString> mSessionIds;
|
||||
nsTArray<uint64_t> mWindowIds;
|
||||
};
|
||||
|
||||
class PresentationRequestParent final : public PPresentationRequestParent
|
||||
|
|
|
@ -17,6 +17,7 @@ EXPORTS.mozilla.dom += [
|
|||
'PresentationAvailability.h',
|
||||
'PresentationCallbacks.h',
|
||||
'PresentationDeviceManager.h',
|
||||
'PresentationReceiver.h',
|
||||
'PresentationRequest.h',
|
||||
'PresentationService.h',
|
||||
'PresentationSession.h',
|
||||
|
@ -32,6 +33,7 @@ UNIFIED_SOURCES += [
|
|||
'PresentationAvailability.cpp',
|
||||
'PresentationCallbacks.cpp',
|
||||
'PresentationDeviceManager.cpp',
|
||||
'PresentationReceiver.cpp',
|
||||
'PresentationRequest.cpp',
|
||||
'PresentationService.cpp',
|
||||
'PresentationSession.cpp',
|
||||
|
|
|
@ -29,18 +29,8 @@ function finish() {
|
|||
function testSessionAvailable() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(navigator.presentation, "navigator.presentation should be available in OOP pages.");
|
||||
|
||||
navigator.presentation.getSessions().then(
|
||||
function(aSessions) {
|
||||
is(aSessions.length, 0, "Non-receiving OOP pages shouldn't get a predefined presentation session instance.");
|
||||
aResolve();
|
||||
},
|
||||
function(aError) {
|
||||
ok(false, "Error occurred when getting sessions: " + aError);
|
||||
teardown();
|
||||
aReject();
|
||||
}
|
||||
);
|
||||
ok(!navigator.presentation.receiver, "Non-receiving OOP pages shouldn't get a presentation receiver instance.");
|
||||
aResolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -35,8 +35,9 @@ var session;
|
|||
function testSessionAvailable() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(navigator.presentation, "navigator.presentation should be available.");
|
||||
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
|
||||
|
||||
navigator.presentation.getSession().then(
|
||||
navigator.presentation.receiver.getSession().then(
|
||||
function(aSession) {
|
||||
session = aSession;
|
||||
|
||||
|
|
|
@ -35,8 +35,9 @@ var session;
|
|||
function testSessionAvailable() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(navigator.presentation, "navigator.presentation should be available.");
|
||||
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
|
||||
|
||||
navigator.presentation.getSession().then(
|
||||
navigator.presentation.receiver.getSession().then(
|
||||
function(aSession) {
|
||||
session = aSession;
|
||||
|
||||
|
|
|
@ -35,8 +35,9 @@ var session;
|
|||
function testSessionAvailable() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
ok(navigator.presentation, "navigator.presentation should be available.");
|
||||
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
|
||||
|
||||
navigator.presentation.getSession().then(
|
||||
navigator.presentation.receiver.getSession().then(
|
||||
function(aSession) {
|
||||
session = aSession;
|
||||
|
||||
|
|
|
@ -93,18 +93,8 @@ function testIncomingSessionRequest() {
|
|||
info("Trying to launch receiver page.");
|
||||
|
||||
ok(navigator.presentation, "navigator.presentation should be available in in-process pages.");
|
||||
|
||||
navigator.presentation.getSessions().then(
|
||||
function(aSessions) {
|
||||
is(aSessions.length, 0, "Non-receiving in-process pages shouldn't get a predefined presentation session instance.");
|
||||
aResolve();
|
||||
},
|
||||
function(aError) {
|
||||
ok(false, "Error occurred when getting sessions: " + aError);
|
||||
teardown();
|
||||
aReject();
|
||||
}
|
||||
);
|
||||
ok(!navigator.presentation.receiver, "Non-receiving in-process pages shouldn't get a presentation receiver instance.");
|
||||
aResolve();
|
||||
});
|
||||
|
||||
gScript.sendAsyncMessage('trigger-incoming-session-request', receiverUrl);
|
||||
|
|
|
@ -81,6 +81,8 @@ function testStartSession() {
|
|||
gScript.sendAsyncMessage('trigger-incoming-answer');
|
||||
});
|
||||
|
||||
ok(!navigator.presentation.receiver, "Sender shouldn't get a presentation receiver instance.");
|
||||
|
||||
navigator.presentation.defaultRequest.onsessionconnect = function(aEvent) {
|
||||
navigator.presentation.defaultRequest.onsessionconnect = null;
|
||||
session = aEvent.session;
|
||||
|
|
|
@ -7,5 +7,6 @@ support-files =
|
|||
[test_app_uninstall.html]
|
||||
[test_clear_browser_data.html]
|
||||
[test_localStorageBasePrivateBrowsing_perwindowpb.html]
|
||||
skip-if = true # bug 1156725
|
||||
[test_localStorageFromChrome.xhtml]
|
||||
[test_localStorageQuotaPrivateBrowsing_perwindowpb.html]
|
||||
|
|
|
@ -18,26 +18,9 @@ interface Presentation : EventTarget {
|
|||
attribute PresentationRequest? defaultRequest;
|
||||
|
||||
/*
|
||||
* Get the first connected presentation session in a presenting browsing
|
||||
* context.
|
||||
*
|
||||
* Only used by presenting browsing context (receivers).
|
||||
* This should be available on the receiving browsing context in order to
|
||||
* access the controlling browsing context and communicate with them.
|
||||
*/
|
||||
[Throws]
|
||||
Promise<PresentationSession> getSession();
|
||||
|
||||
/*
|
||||
* Get all connected presentation sessions in a presenting browsing context.
|
||||
*
|
||||
* Only used by presenting browsing context (receivers).
|
||||
*/
|
||||
[Throws]
|
||||
Promise<sequence<PresentationSession>> getSessions();
|
||||
|
||||
/*
|
||||
* It is called when an incoming session is connecting.
|
||||
*
|
||||
* Only used by presenting browsing context (receivers).
|
||||
*/
|
||||
attribute EventHandler onsessionavailable;
|
||||
[SameObject]
|
||||
readonly attribute PresentationReceiver? receiver;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Pref="dom.presentation.enabled",
|
||||
CheckAnyPermissions="presentation"]
|
||||
interface PresentationReceiver : EventTarget {
|
||||
/*
|
||||
* Get the first connected presentation session in a receiving browsing
|
||||
* context.
|
||||
*/
|
||||
[Throws]
|
||||
Promise<PresentationSession> getSession();
|
||||
|
||||
/*
|
||||
* Get all connected presentation sessions in a receiving browsing context.
|
||||
*/
|
||||
[Throws]
|
||||
Promise<sequence<PresentationSession>> getSessions();
|
||||
|
||||
/*
|
||||
* It is called when an incoming session is connecting.
|
||||
*/
|
||||
attribute EventHandler onsessionavailable;
|
||||
};
|
|
@ -4,8 +4,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
[Pref="dom.workers.sharedWorkers.enabled",
|
||||
Constructor(DOMString scriptURL, optional DOMString name)]
|
||||
[Constructor(DOMString scriptURL, optional DOMString name)]
|
||||
interface SharedWorker : EventTarget {
|
||||
readonly attribute MessagePort port;
|
||||
};
|
||||
|
|
|
@ -373,6 +373,7 @@ WEBIDL_FILES = [
|
|||
'Presentation.webidl',
|
||||
'PresentationAvailability.webidl',
|
||||
'PresentationDeviceInfoManager.webidl',
|
||||
'PresentationReceiver.webidl',
|
||||
'PresentationRequest.webidl',
|
||||
'PresentationSession.webidl',
|
||||
'ProcessingInstruction.webidl',
|
||||
|
|
|
@ -3376,7 +3376,6 @@ ServiceWorkerManager::FindScopeForPath(const nsACString& aScopeKey,
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* static */ bool
|
||||
ServiceWorkerManager::HasScope(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope)
|
||||
|
@ -3397,7 +3396,6 @@ ServiceWorkerManager::HasScope(nsIPrincipal* aPrincipal,
|
|||
|
||||
return data->mOrderedScopes.Contains(aScope);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* static */ void
|
||||
ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo* aRegistration)
|
||||
|
@ -4636,7 +4634,8 @@ ServiceWorkerManager::MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRe
|
|||
{
|
||||
MOZ_ASSERT(aRegistration);
|
||||
nsRefPtr<ServiceWorkerInfo> newest = aRegistration->Newest();
|
||||
if (!newest) {
|
||||
if (!newest && HasScope(aRegistration->mPrincipal, aRegistration->mScope)) {
|
||||
aRegistration->Clear();
|
||||
RemoveRegistration(aRegistration);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -520,10 +520,8 @@ private:
|
|||
const nsACString& aPath,
|
||||
RegistrationDataPerPrincipal** aData, nsACString& aMatch);
|
||||
|
||||
#ifdef DEBUG
|
||||
static bool
|
||||
HasScope(nsIPrincipal* aPrincipal, const nsACString& aScope);
|
||||
#endif
|
||||
|
||||
static void
|
||||
RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo* aRegistration);
|
||||
|
|
|
@ -16,23 +16,21 @@
|
|||
// This test is full of dummy debug messages. This is because I need to follow
|
||||
// an hard-to-reproduce timeout failure.
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]] }, function() {
|
||||
info("test started");
|
||||
var sw = new SharedWorker('bug1132395_sharedWorker.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
info("sw.onmessage received");
|
||||
ok(true, "We didn't crash.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
info("test started");
|
||||
var sw = new SharedWorker('bug1132395_sharedWorker.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
info("sw.onmessage received");
|
||||
ok(true, "We didn't crash.");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
sw.onerror = function(event) {
|
||||
ok(false, "Failed to create a ServiceWorker");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
sw.onerror = function(event) {
|
||||
ok(false, "Failed to create a ServiceWorker");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
info("sw.postmessage called");
|
||||
sw.port.postMessage('go');
|
||||
});
|
||||
info("sw.postmessage called");
|
||||
sw.port.postMessage('go');
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
|
|
|
@ -15,15 +15,10 @@
|
|||
<pre id="test"></pre>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]] }, function() {
|
||||
new SharedWorker('sharedWorker_sharedWorker.js');
|
||||
new SharedWorker('sharedWorker_sharedWorker.js', ':');
|
||||
new SharedWorker('sharedWorker_sharedWorker.js', '|||');
|
||||
ok(true, "3 SharedWorkers created!");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
new SharedWorker('sharedWorker_sharedWorker.js');
|
||||
new SharedWorker('sharedWorker_sharedWorker.js', ':');
|
||||
new SharedWorker('sharedWorker_sharedWorker.js', '|||');
|
||||
ok(true, "3 SharedWorkers created!");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -47,10 +47,7 @@
|
|||
}
|
||||
|
||||
var cl = new consoleListener();
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]] }, function() {
|
||||
new SharedWorker('sharedWorker_console.js');
|
||||
});
|
||||
new SharedWorker('sharedWorker_console.js');
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
const swPref = "dom.workers.sharedWorkers.enabled";
|
||||
|
||||
const basePath =
|
||||
location.pathname.substring(0,
|
||||
location.pathname.lastIndexOf("/") + 1);
|
||||
|
@ -30,13 +28,6 @@
|
|||
let testGenerator = (function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
if (!SpecialPowers.getBoolPref(swPref)) {
|
||||
ok(!("SharedWorker" in window), "No SharedWorker without pref set");
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [[swPref, true]] }, sendToGenerator);
|
||||
yield undefined;
|
||||
|
||||
window.addEventListener("message", function(event) {
|
||||
if (typeof(event.data) == "string") {
|
||||
info(event.data);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
const swPref = "dom.workers.sharedWorkers.enabled";
|
||||
const scrollbarPref = "layout.testing.overlay-scrollbars.always-visible";
|
||||
const bfCacheEnabledPref = "browser.sessionhistory.cache_subframes";
|
||||
const bfCacheDepthPref = "browser.sessionhistory.max_total_viewers";
|
||||
|
@ -23,16 +22,11 @@
|
|||
let testGenerator = (function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
if (!SpecialPowers.getBoolPref(swPref)) {
|
||||
ok(!("SharedWorker" in window), "No SharedWorker without pref set");
|
||||
}
|
||||
|
||||
// Enable SharedWorkers and force scrollbar to always be shown. The
|
||||
// scrollbar setting is necessary to avoid the fade-in/fade-out from
|
||||
// evicting our document from the BF cache below. If bug 1049277
|
||||
// is fixed, then we can stop setting the scrollbar pref here.
|
||||
SpecialPowers.pushPrefEnv({ set: [[swPref, true],
|
||||
[scrollbarPref, true]] },
|
||||
// Force scrollbar to always be shown. The scrollbar setting is
|
||||
// necessary to avoid the fade-in/fade-out from evicting our document
|
||||
// from the BF cache below. If bug 1049277 is fixed, then we can
|
||||
// stop setting the scrollbar pref here.
|
||||
SpecialPowers.pushPrefEnv({ set: [[scrollbarPref, true]] },
|
||||
sendToGenerator);
|
||||
yield undefined;
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
<script class="testbody">
|
||||
"use strict";
|
||||
|
||||
const swPref = "dom.workers.sharedWorkers.enabled";
|
||||
|
||||
const href = window.location.href;
|
||||
const filename = "sharedWorker_sharedWorker.js";
|
||||
const sentMessage = "ping";
|
||||
|
@ -27,49 +25,43 @@
|
|||
const errorLine = 86;
|
||||
const errorColumn = 0;
|
||||
|
||||
if (!SpecialPowers.getBoolPref(swPref)) {
|
||||
ok(!("SharedWorker" in window), "No SharedWorker without pref set");
|
||||
}
|
||||
var worker = new SharedWorker(filename);
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [[swPref, true]] }, function() {
|
||||
var worker = new SharedWorker(filename);
|
||||
ok(worker instanceof SharedWorker, "Got SharedWorker instance");
|
||||
ok(!("postMessage" in worker), "SharedWorker has no 'postMessage'");
|
||||
ok(worker.port instanceof MessagePort,
|
||||
"Shared worker has MessagePort");
|
||||
|
||||
ok(worker instanceof SharedWorker, "Got SharedWorker instance");
|
||||
ok(!("postMessage" in worker), "SharedWorker has no 'postMessage'");
|
||||
ok(worker.port instanceof MessagePort,
|
||||
"Shared worker has MessagePort");
|
||||
var receivedMessage;
|
||||
var receivedError;
|
||||
|
||||
var receivedMessage;
|
||||
var receivedError;
|
||||
worker.port.onmessage = function(event) {
|
||||
ok(event instanceof MessageEvent, "Got a MessageEvent");
|
||||
ok(event.target === worker.port,
|
||||
"MessageEvent has correct 'target' property");
|
||||
is(event.data, sentMessage, "Got correct message");
|
||||
ok(receivedMessage === undefined, "Haven't gotten message yet");
|
||||
receivedMessage = event.data;
|
||||
if (receivedError) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
|
||||
worker.port.onmessage = function(event) {
|
||||
ok(event instanceof MessageEvent, "Got a MessageEvent");
|
||||
ok(event.target === worker.port,
|
||||
"MessageEvent has correct 'target' property");
|
||||
is(event.data, sentMessage, "Got correct message");
|
||||
ok(receivedMessage === undefined, "Haven't gotten message yet");
|
||||
receivedMessage = event.data;
|
||||
if (receivedError) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
worker.onerror = function(event) {
|
||||
ok(event instanceof ErrorEvent, "Got an ErrorEvent");
|
||||
is(event.message, "Error: " + sentMessage, "Got correct error");
|
||||
is(event.filename, errorFilename, "Got correct filename");
|
||||
is(event.lineno, errorLine, "Got correct lineno");
|
||||
is(event.colno, errorColumn, "Got correct column");
|
||||
ok(receivedError === undefined, "Haven't gotten error yet");
|
||||
receivedError = event.message;
|
||||
event.preventDefault();
|
||||
if (receivedMessage) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
|
||||
worker.onerror = function(event) {
|
||||
ok(event instanceof ErrorEvent, "Got an ErrorEvent");
|
||||
is(event.message, "Error: " + sentMessage, "Got correct error");
|
||||
is(event.filename, errorFilename, "Got correct filename");
|
||||
is(event.lineno, errorLine, "Got correct lineno");
|
||||
is(event.colno, errorColumn, "Got correct column");
|
||||
ok(receivedError === undefined, "Haven't gotten error yet");
|
||||
receivedError = event.message;
|
||||
event.preventDefault();
|
||||
if (receivedMessage) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
|
||||
worker.port.postMessage(sentMessage);
|
||||
});
|
||||
worker.port.postMessage(sentMessage);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
|
|
|
@ -13,18 +13,16 @@
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var gced = false;
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
|
||||
function() {
|
||||
var sw = new SharedWorker('sharedWorker_lifetime.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
ok(gced, "The SW is still alive also after GC");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
sw = null;
|
||||
SpecialPowers.forceGC();
|
||||
gced = true;
|
||||
});
|
||||
var sw = new SharedWorker('sharedWorker_lifetime.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
ok(gced, "The SW is still alive also after GC");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
sw = null;
|
||||
SpecialPowers.forceGC();
|
||||
gced = true;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
|
|
|
@ -12,17 +12,14 @@
|
|||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
|
||||
function() {
|
||||
var sw = new SharedWorker('sharedworker_performance_user_timing.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
if (event.data.type == 'finish') {
|
||||
SimpleTest.finish();
|
||||
} else if (event.data.type == 'status') {
|
||||
ok(event.data.status, event.data.msg);
|
||||
}
|
||||
var sw = new SharedWorker('sharedworker_performance_user_timing.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
if (event.data.type == 'finish') {
|
||||
SimpleTest.finish();
|
||||
} else if (event.data.type == 'status') {
|
||||
ok(event.data.status, event.data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
|
|
|
@ -12,28 +12,25 @@
|
|||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
|
||||
function() {
|
||||
var sw1 = new SharedWorker('sharedWorker_ports.js');
|
||||
sw1.port.onmessage = function(event) {
|
||||
if (event.data.type == "connected") {
|
||||
ok(true, "The SharedWorker is alive.");
|
||||
var sw1 = new SharedWorker('sharedWorker_ports.js');
|
||||
sw1.port.onmessage = function(event) {
|
||||
if (event.data.type == "connected") {
|
||||
ok(true, "The SharedWorker is alive.");
|
||||
|
||||
var sw2 = new SharedWorker('sharedWorker_ports.js');
|
||||
sw1.port.postMessage("Port from the main-thread!", [sw2.port]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type == "status") {
|
||||
ok(event.data.test, event.data.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type == "finish") {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
var sw2 = new SharedWorker('sharedWorker_ports.js');
|
||||
sw1.port.postMessage("Port from the main-thread!", [sw2.port]);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (event.data.type == "status") {
|
||||
ok(event.data.test, event.data.msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.data.type == "finish") {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
|
|
|
@ -92,7 +92,6 @@ function runTest() {
|
|||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.workers.sharedWorkers.enabled", true],
|
||||
["browser.startup.page", 0],
|
||||
["browser.startup.homepage_override.mstone", "ignore"],
|
||||
]}, runTest);
|
||||
|
|
|
@ -13,17 +13,14 @@
|
|||
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]]},
|
||||
function() {
|
||||
var sw = new SharedWorker('webSocket_sharedWorker.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
if (event.data.type == 'finish') {
|
||||
SimpleTest.finish();
|
||||
} else if (event.data.type == 'status') {
|
||||
ok(event.data.status, event.data.msg);
|
||||
}
|
||||
var sw = new SharedWorker('webSocket_sharedWorker.js');
|
||||
sw.port.onmessage = function(event) {
|
||||
if (event.data.type == 'finish') {
|
||||
SimpleTest.finish();
|
||||
} else if (event.data.type == 'status') {
|
||||
ok(event.data.status, event.data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "nsXBLProtoImplMethod.h"
|
||||
#include "nsXBLPrototypeHandler.h"
|
||||
#include "nsXBLPrototypeResources.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIContent;
|
||||
|
@ -36,9 +37,12 @@ class CSSStyleSheet;
|
|||
// Instances of this class are owned by the nsXBLDocumentInfo object returned
|
||||
// by XBLDocumentInfo(). Consumers who want to refcount things should refcount
|
||||
// that.
|
||||
class nsXBLPrototypeBinding final
|
||||
class nsXBLPrototypeBinding final :
|
||||
public mozilla::SupportsWeakPtr<nsXBLPrototypeBinding>
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsXBLPrototypeBinding)
|
||||
|
||||
nsIContent* GetBindingElement() const { return mBinding; }
|
||||
void SetBindingElement(nsIContent* aElement);
|
||||
|
||||
|
@ -290,7 +294,8 @@ protected:
|
|||
nsXBLProtoImpl* mImplementation; // Our prototype implementation (includes methods, properties, fields,
|
||||
// the constructor, and the destructor).
|
||||
|
||||
nsXBLPrototypeBinding* mBaseBinding; // Weak. The docinfo will own our base binding.
|
||||
// Weak. The docinfo will own our base binding.
|
||||
mozilla::WeakPtr<nsXBLPrototypeBinding> mBaseBinding;
|
||||
bool mInheritStyle;
|
||||
bool mCheckedBaseProto;
|
||||
bool mKeyHandlersRegistered;
|
||||
|
|
|
@ -730,7 +730,8 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
|
|||
if (!docInfo)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsXBLPrototypeBinding* protoBinding = docInfo->GetPrototypeBinding(ref);
|
||||
WeakPtr<nsXBLPrototypeBinding> protoBinding =
|
||||
docInfo->GetPrototypeBinding(ref);
|
||||
|
||||
if (!protoBinding) {
|
||||
#ifdef DEBUG
|
||||
|
@ -781,7 +782,7 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> baseBindingURI;
|
||||
nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype();
|
||||
WeakPtr<nsXBLPrototypeBinding> baseProto = protoBinding->GetBasePrototype();
|
||||
if (baseProto) {
|
||||
baseBindingURI = baseProto->BindingURI();
|
||||
}
|
||||
|
@ -826,7 +827,6 @@ nsXBLService::GetBinding(nsIContent* aBoundElement, nsIURI* aURI,
|
|||
|
||||
if (!aPeekOnly) {
|
||||
// Make a new binding
|
||||
protoBinding = docInfo->GetPrototypeBinding(ref);
|
||||
NS_ENSURE_STATE(protoBinding);
|
||||
nsXBLBinding *newBinding = new nsXBLBinding(protoBinding);
|
||||
|
||||
|
|
|
@ -918,6 +918,23 @@ XULDocument::AttributeWillChange(nsIDocument* aDocument,
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
ShouldPersistAttribute(nsIDocument* aDocument, Element* aElement)
|
||||
{
|
||||
if (aElement->IsXULElement(nsGkAtoms::window)) {
|
||||
if (nsCOMPtr<nsPIDOMWindow> window = aDocument->GetWindow()) {
|
||||
bool isFullscreen;
|
||||
window->GetFullScreen(&isFullscreen);
|
||||
if (isFullscreen) {
|
||||
// Don't persist attributes if it is window element and
|
||||
// we are in fullscreen state.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
XULDocument::AttributeChanged(nsIDocument* aDocument,
|
||||
Element* aElement, int32_t aNameSpaceID,
|
||||
|
@ -992,18 +1009,19 @@ XULDocument::AttributeChanged(nsIDocument* aDocument,
|
|||
bool listener, resolved;
|
||||
CheckBroadcasterHookup(aElement, &listener, &resolved);
|
||||
|
||||
// See if there is anything we need to persist in the localstore.
|
||||
//
|
||||
// XXX Namespace handling broken :-(
|
||||
nsAutoString persist;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
|
||||
if (!persist.IsEmpty()) {
|
||||
// XXXldb This should check that it's a token, not just a substring.
|
||||
if (persist.Find(nsDependentAtomString(aAttribute)) >= 0) {
|
||||
if (ShouldPersistAttribute(aDocument, aElement)) {
|
||||
// See if there is anything we need to persist in the localstore.
|
||||
//
|
||||
// XXX Namespace handling broken :-(
|
||||
nsString persist;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
|
||||
if (!persist.IsEmpty() &&
|
||||
// XXXldb This should check that it's a token, not just a substring.
|
||||
persist.Find(nsDependentAtomString(aAttribute)) >= 0) {
|
||||
nsContentUtils::AddScriptRunner(NS_NewRunnableMethodWithArgs
|
||||
<nsIContent*, int32_t, nsIAtom*>
|
||||
(this, &XULDocument::DoPersist, aElement, kNameSpaceID_None,
|
||||
aAttribute));
|
||||
<nsIContent*, int32_t, nsIAtom*>
|
||||
(this, &XULDocument::DoPersist, aElement,
|
||||
kNameSpaceID_None, aAttribute));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ SourceSurfaceSkia::InitFromTexture(DrawTargetSkia* aOwner,
|
|||
mSize.width = skiaTexGlue.fWidth = aSize.width;
|
||||
mSize.height = skiaTexGlue.fHeight = aSize.height;
|
||||
skiaTexGlue.fFlags = kNone_GrBackendTextureFlag;
|
||||
skiaTexGlue.fOrigin = kBottomLeft_GrSurfaceOrigin;
|
||||
skiaTexGlue.fOrigin = kTopLeft_GrSurfaceOrigin;
|
||||
skiaTexGlue.fConfig = GfxFormatToGrConfig(aFormat);
|
||||
skiaTexGlue.fSampleCnt = 0;
|
||||
skiaTexGlue.fTextureHandle = aTexture;
|
||||
|
|
|
@ -78,7 +78,8 @@ WheelScrollAnimation::InitPreferences(TimeStamp aTime)
|
|||
mOriginMaxMS = clamped(gfxPrefs::WheelSmoothScrollMaxDurationMs(), 0, 10000);
|
||||
mOriginMinMS = clamped(gfxPrefs::WheelSmoothScrollMinDurationMs(), 0, mOriginMaxMS);
|
||||
|
||||
mIntervalRatio = (gfxPrefs::SmoothScrollDurationToIntervalRatio() * 100) / 100.0;
|
||||
// The pref is 100-based int percentage, while mIntervalRatio is 1-based ratio
|
||||
mIntervalRatio = ((double)gfxPrefs::SmoothScrollDurationToIntervalRatio()) / 100.0;
|
||||
mIntervalRatio = std::max(1.0, mIntervalRatio);
|
||||
|
||||
InitializeHistory(aTime);
|
||||
|
|
|
@ -169,12 +169,17 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
|||
|
||||
AddUniforms(result);
|
||||
|
||||
vs << "#ifdef GL_ES" << endl;
|
||||
vs << "#define EDGE_PRECISION mediump" << endl;
|
||||
vs << "#else" << endl;
|
||||
vs << "#define EDGE_PRECISION" << endl;
|
||||
vs << "#endif" << endl;
|
||||
vs << "uniform mat4 uMatrixProj;" << endl;
|
||||
vs << "uniform vec4 uLayerRects[4];" << endl;
|
||||
vs << "uniform mat4 uLayerTransform;" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
vs << "uniform mat4 uLayerTransformInverse;" << endl;
|
||||
vs << "uniform vec3 uSSEdges[4];" << endl;
|
||||
vs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl;
|
||||
vs << "uniform vec2 uVisibleCenter;" << endl;
|
||||
vs << "uniform vec2 uViewportSize;" << endl;
|
||||
}
|
||||
|
@ -282,8 +287,10 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
|||
fs << "#ifdef GL_ES" << endl;
|
||||
fs << "precision mediump float;" << endl;
|
||||
fs << "#define COLOR_PRECISION lowp" << endl;
|
||||
fs << "#define EDGE_PRECISION mediump" << endl;
|
||||
fs << "#else" << endl;
|
||||
fs << "#define COLOR_PRECISION" << endl;
|
||||
fs << "#define EDGE_PRECISION" << endl;
|
||||
fs << "#endif" << endl;
|
||||
if (aConfig.mFeatures & ENABLE_RENDER_COLOR) {
|
||||
fs << "uniform COLOR_PRECISION vec4 uRenderColor;" << endl;
|
||||
|
@ -344,7 +351,7 @@ ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig)
|
|||
}
|
||||
|
||||
if (aConfig.mFeatures & ENABLE_DEAA) {
|
||||
fs << "uniform vec3 uSSEdges[4];" << endl;
|
||||
fs << "uniform EDGE_PRECISION vec3 uSSEdges[4];" << endl;
|
||||
}
|
||||
|
||||
if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) {
|
||||
|
|
|
@ -66,7 +66,7 @@ private:
|
|||
case NS_STYLE_TEXT_ORIENTATION_UPRIGHT:
|
||||
flags |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
|
||||
break;
|
||||
case NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_RIGHT:
|
||||
case NS_STYLE_TEXT_ORIENTATION_SIDEWAYS:
|
||||
flags |= gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
-->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%" height="100%">
|
||||
<!-- There is a bug with MultiTiledContentClient that causes improper painting;
|
||||
bug 1204076 is on file for this issue. As a temporary workaround, we set
|
||||
user-scalable=no here so that WantAsyncZoom() returns false and we don't
|
||||
use a MultiTiledContentClient. Once bug 1204076 is fixed, we can remove this. -->
|
||||
<meta xmlns="http://www.w3.org/1999/xhtml" name="viewport" content="user-scalable=no"/>
|
||||
|
||||
<title>Testcase for small circles</title>
|
||||
<!--From https://bugzilla.mozilla.org/show_bug.cgi?id=1143303 -->
|
||||
|
||||
|
|
До Ширина: | Высота: | Размер: 1.2 KiB После Ширина: | Высота: | Размер: 769 B |
|
@ -4,36 +4,8 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
os_win = 0
|
||||
os_posix = 0
|
||||
os_macosx = 0
|
||||
os_dragonfly = 0
|
||||
os_freebsd = 0
|
||||
os_netbsd = 0
|
||||
os_openbsd = 0
|
||||
os_bsd = 0
|
||||
os_linux = 0
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
os_win = 1
|
||||
else:
|
||||
os_posix = 1
|
||||
if CONFIG['OS_ARCH'] == 'Darwin':
|
||||
os_macosx = 1
|
||||
elif CONFIG['OS_ARCH'] == 'DragonFly':
|
||||
os_dragonfly = 1
|
||||
os_bsd = 1
|
||||
elif CONFIG['OS_ARCH'] in ['FreeBSD', 'GNU_kFreeBSD']:
|
||||
os_freebsd = 1
|
||||
os_bsd = 1
|
||||
elif CONFIG['OS_ARCH'] == 'NetBSD':
|
||||
os_netbsd = 1
|
||||
os_bsd = 1
|
||||
elif CONFIG['OS_ARCH'] == 'OpenBSD':
|
||||
os_openbsd = 1
|
||||
os_bsd = 1
|
||||
else:
|
||||
os_linux = 1
|
||||
libevent_path_prefix = 'src/third_party'
|
||||
include(libevent_path_prefix + '/libeventcommon.mozbuild')
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'src/base/at_exit.cc',
|
||||
|
@ -102,36 +74,7 @@ if os_win:
|
|||
'src/chrome/common/transport_dib_win.cc',
|
||||
]
|
||||
elif not CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
UNIFIED_SOURCES += [
|
||||
'src/third_party/libevent/buffer.c',
|
||||
'src/third_party/libevent/bufferevent.c',
|
||||
'src/third_party/libevent/bufferevent_ratelim.c',
|
||||
'src/third_party/libevent/bufferevent_sock.c',
|
||||
'src/third_party/libevent/event.c',
|
||||
'src/third_party/libevent/event_tagging.c',
|
||||
'src/third_party/libevent/evmap.c',
|
||||
'src/third_party/libevent/evrpc.c',
|
||||
'src/third_party/libevent/evthread.c',
|
||||
'src/third_party/libevent/evthread_pthread.c',
|
||||
'src/third_party/libevent/evutil.c',
|
||||
'src/third_party/libevent/evutil_rand.c',
|
||||
'src/third_party/libevent/http.c',
|
||||
'src/third_party/libevent/listener.c',
|
||||
'src/third_party/libevent/log.c',
|
||||
'src/third_party/libevent/poll.c',
|
||||
'src/third_party/libevent/select.c',
|
||||
'src/third_party/libevent/signal.c',
|
||||
'src/third_party/libevent/strlcpy.c',
|
||||
]
|
||||
SOURCES += [
|
||||
# This file cannot be built in unified mode because of strtotimeval symbol clash.
|
||||
'src/third_party/libevent/evdns.c',
|
||||
]
|
||||
DEFINES['HAVE_CONFIG_H'] = True
|
||||
LOCAL_INCLUDES += [
|
||||
'src/third_party/libevent',
|
||||
'src/third_party/libevent/include',
|
||||
]
|
||||
DIRS += ['src/third_party']
|
||||
|
||||
if os_posix:
|
||||
UNIFIED_SOURCES += [
|
||||
|
@ -156,12 +99,6 @@ if os_posix:
|
|||
'src/chrome/common/ipc_channel_posix.cc',
|
||||
'src/chrome/common/process_watcher_posix_sigchld.cc',
|
||||
]
|
||||
if CONFIG['OS_TARGET'] == 'Android':
|
||||
UNIFIED_SOURCES += [
|
||||
'src/base/message_pump_android.cc',
|
||||
]
|
||||
DEFINES['ANDROID'] = True
|
||||
DEFINES['_POSIX_MONOTONIC_CLOCK'] = 0
|
||||
|
||||
if os_macosx:
|
||||
UNIFIED_SOURCES += [
|
||||
|
@ -180,43 +117,10 @@ if os_macosx:
|
|||
'src/chrome/common/transport_dib_mac.cc',
|
||||
]
|
||||
SOURCES += [
|
||||
# This file cannot be built in unified mode because of the redefinition of NoOp.
|
||||
# This file cannot be built in unified mode because of the redefinition
|
||||
# of NoOp.
|
||||
'src/base/platform_thread_mac.mm',
|
||||
]
|
||||
if not CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
UNIFIED_SOURCES += [
|
||||
'src/third_party/libevent/kqueue.c',
|
||||
]
|
||||
LOCAL_INCLUDES += ['src/third_party/libevent/mac']
|
||||
|
||||
if os_linux:
|
||||
SOURCES += [
|
||||
'src/base/atomicops_internals_x86_gcc.cc',
|
||||
'src/base/idle_timer_none.cc',
|
||||
'src/base/process_util_linux.cc',
|
||||
'src/base/time_posix.cc',
|
||||
]
|
||||
if CONFIG['MOZ_WIDGET_GTK']:
|
||||
SOURCES += [
|
||||
'src/base/message_pump_glib.cc',
|
||||
]
|
||||
if CONFIG['MOZ_ENABLE_QT']:
|
||||
SOURCES += [
|
||||
'!moc_message_pump_qt.cc',
|
||||
'src/base/message_pump_qt.cc',
|
||||
]
|
||||
if not CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
if CONFIG['OS_TARGET'] != 'Android':
|
||||
SOURCES += [
|
||||
'src/third_party/libevent/epoll_sub.c',
|
||||
]
|
||||
SOURCES += [
|
||||
'src/third_party/libevent/epoll.c',
|
||||
]
|
||||
if CONFIG['OS_TARGET'] == 'Android':
|
||||
LOCAL_INCLUDES += ['src/third_party/libevent/android']
|
||||
else:
|
||||
LOCAL_INCLUDES += ['src/third_party/libevent/linux']
|
||||
|
||||
if os_bsd:
|
||||
SOURCES += [
|
||||
|
@ -231,6 +135,22 @@ if os_bsd:
|
|||
SOURCES += [
|
||||
'src/base/process_util_bsd.cc'
|
||||
]
|
||||
|
||||
if os_linux:
|
||||
SOURCES += [
|
||||
'src/base/atomicops_internals_x86_gcc.cc',
|
||||
'src/base/idle_timer_none.cc',
|
||||
'src/base/process_util_linux.cc',
|
||||
'src/base/time_posix.cc',
|
||||
]
|
||||
if CONFIG['OS_TARGET'] == 'Android':
|
||||
UNIFIED_SOURCES += [
|
||||
'src/base/message_pump_android.cc',
|
||||
]
|
||||
DEFINES['ANDROID'] = True
|
||||
DEFINES['_POSIX_MONOTONIC_CLOCK'] = 0
|
||||
|
||||
if os_bsd or os_linux:
|
||||
if CONFIG['MOZ_WIDGET_GTK']:
|
||||
SOURCES += [
|
||||
'src/base/message_pump_glib.cc',
|
||||
|
@ -240,11 +160,6 @@ if os_bsd:
|
|||
'!moc_message_pump_qt.cc',
|
||||
'src/base/message_pump_qt.cc',
|
||||
]
|
||||
if not CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
SOURCES += [
|
||||
'src/third_party/libevent/kqueue.c',
|
||||
]
|
||||
LOCAL_INCLUDES += ['src/third_party/libevent/bsd']
|
||||
|
||||
ost = CONFIG['OS_TEST']
|
||||
if '86' not in ost and 'arm' not in ost and 'mips' not in ost:
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
os_win = 0
|
||||
os_posix = 0
|
||||
os_macosx = 0
|
||||
os_bsd = 0
|
||||
os_linux = 0
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
os_win = 1
|
||||
else:
|
||||
os_posix = 1
|
||||
if CONFIG['OS_ARCH'] == 'Darwin':
|
||||
os_macosx = 1
|
||||
libevent_include_suffix = 'mac'
|
||||
elif CONFIG['OS_ARCH'] in ['DragonFly', 'FreeBSD', 'GNU_kFreeBSD',
|
||||
'NetBSD', 'OpenBSD']:
|
||||
os_bsd = 1
|
||||
libevent_include_suffix = 'bsd'
|
||||
else:
|
||||
os_linux = 1
|
||||
if CONFIG['OS_TARGET'] == 'Android':
|
||||
libevent_include_suffix = 'android'
|
||||
else:
|
||||
libevent_include_suffix = 'linux'
|
||||
|
||||
if os_posix and not CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
DEFINES['HAVE_CONFIG_H'] = True
|
||||
LOCAL_INCLUDES += sorted([
|
||||
libevent_path_prefix + '/libevent',
|
||||
libevent_path_prefix + '/libevent/include',
|
||||
libevent_path_prefix + '/libevent/' + libevent_include_suffix,
|
||||
])
|
|
@ -0,0 +1,59 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
libevent_path_prefix = '.'
|
||||
include(libevent_path_prefix + '/libeventcommon.mozbuild')
|
||||
|
||||
if os_win:
|
||||
error('should not reach here on Windows')
|
||||
|
||||
if CONFIG['MOZ_NATIVE_LIBEVENT']:
|
||||
error('should not reach here if we are using a native libevent')
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'libevent/buffer.c',
|
||||
'libevent/bufferevent.c',
|
||||
'libevent/bufferevent_ratelim.c',
|
||||
'libevent/bufferevent_sock.c',
|
||||
'libevent/event.c',
|
||||
'libevent/event_tagging.c',
|
||||
'libevent/evmap.c',
|
||||
'libevent/evrpc.c',
|
||||
'libevent/evthread.c',
|
||||
'libevent/evthread_pthread.c',
|
||||
'libevent/evutil.c',
|
||||
'libevent/evutil_rand.c',
|
||||
'libevent/http.c',
|
||||
'libevent/listener.c',
|
||||
'libevent/log.c',
|
||||
'libevent/poll.c',
|
||||
'libevent/select.c',
|
||||
'libevent/signal.c',
|
||||
'libevent/strlcpy.c',
|
||||
]
|
||||
SOURCES += [
|
||||
# This file cannot be built in unified mode because of strtotimeval
|
||||
# symbol clash.
|
||||
'libevent/evdns.c',
|
||||
]
|
||||
|
||||
if os_macosx or os_bsd:
|
||||
UNIFIED_SOURCES += [
|
||||
'libevent/kqueue.c',
|
||||
]
|
||||
|
||||
if os_linux:
|
||||
SOURCES += [
|
||||
'libevent/epoll.c',
|
||||
]
|
||||
if CONFIG['OS_TARGET'] != 'Android':
|
||||
SOURCES += [
|
||||
'libevent/epoll_sub.c',
|
||||
]
|
||||
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
|
@ -9,7 +9,7 @@
|
|||
#include "base/process.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_MACOSX)
|
||||
#if defined(OS_LINUX) || defined(XP_DARWIN)
|
||||
#include <pthread.h>
|
||||
#include "SharedMemoryBasic.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
%/SharedMemoryBasic_mach.cpp: ;
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#ifdef ANDROID
|
||||
# include "mozilla/ipc/SharedMemoryBasic_android.h"
|
||||
#elif defined(XP_MACOSX)
|
||||
#elif defined(XP_DARWIN)
|
||||
# include "mozilla/ipc/SharedMemoryBasic_mach.h"
|
||||
#else
|
||||
# include "mozilla/ipc/SharedMemoryBasic_chromium.h"
|
||||
|
|
|
@ -9,7 +9,18 @@
|
|||
|
||||
#include <mach/vm_map.h>
|
||||
#include <mach/mach_port.h>
|
||||
#if defined(XP_IOS)
|
||||
#include <mach/vm_map.h>
|
||||
#define mach_vm_address_t vm_address_t
|
||||
#define mach_vm_allocate vm_allocate
|
||||
#define mach_vm_deallocate vm_deallocate
|
||||
#define mach_vm_map vm_map
|
||||
#define mach_vm_read vm_read
|
||||
#define mach_vm_region_recurse vm_region_recurse_64
|
||||
#define mach_vm_size_t vm_size_t
|
||||
#else
|
||||
#include <mach/mach_vm.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include "SharedMemoryBasic.h"
|
|
@ -80,7 +80,7 @@ if CONFIG['OS_TARGET'] == 'Android':
|
|||
elif CONFIG['OS_ARCH'] == 'Darwin':
|
||||
EXPORTS.mozilla.ipc += ['SharedMemoryBasic_mach.h']
|
||||
SOURCES += [
|
||||
'SharedMemoryBasic_mach.cpp',
|
||||
'SharedMemoryBasic_mach.mm',
|
||||
]
|
||||
else:
|
||||
EXPORTS.mozilla.ipc += ['SharedMemoryBasic_chromium.h']
|
||||
|
|
|
@ -703,7 +703,8 @@ struct JSClass {
|
|||
// the beginning of every global object's slots for use by the
|
||||
// application.
|
||||
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 32)
|
||||
#define JSCLASS_GLOBAL_SLOT_COUNT \
|
||||
(JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 33)
|
||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||
#define JSCLASS_GLOBAL_FLAGS \
|
||||
|
|
|
@ -569,7 +569,7 @@ class Base {
|
|||
//
|
||||
// If wantNames is true, compute names for edges. Doing so can be expensive
|
||||
// in time and memory.
|
||||
virtual UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const = 0;
|
||||
virtual UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const = 0;
|
||||
|
||||
// Return the Zone to which this node's referent belongs, or nullptr if the
|
||||
// referent is not of a type allocated in SpiderMonkey Zones.
|
||||
|
@ -756,8 +756,8 @@ class Node {
|
|||
return base()->size(mallocSizeof);
|
||||
}
|
||||
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames = true) const {
|
||||
return base()->edges(cx, wantNames);
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames = true) const {
|
||||
return base()->edges(rt, wantNames);
|
||||
}
|
||||
|
||||
bool hasAllocationStack() const { return base()->hasAllocationStack(); }
|
||||
|
@ -868,7 +868,7 @@ class EdgeRange {
|
|||
};
|
||||
|
||||
|
||||
typedef mozilla::Vector<Edge, 8, js::TempAllocPolicy> EdgeVector;
|
||||
typedef mozilla::Vector<Edge, 8, js::SystemAllocPolicy> EdgeVector;
|
||||
|
||||
// An EdgeRange concrete class that holds a pre-existing vector of
|
||||
// Edges. A PreComputedEdgeRange does not take ownership of its
|
||||
|
@ -883,7 +883,7 @@ class PreComputedEdgeRange : public EdgeRange {
|
|||
}
|
||||
|
||||
public:
|
||||
explicit PreComputedEdgeRange(JSContext* cx, EdgeVector& edges)
|
||||
explicit PreComputedEdgeRange(EdgeVector& edges)
|
||||
: edges(edges),
|
||||
i(0)
|
||||
{
|
||||
|
@ -916,7 +916,7 @@ class PreComputedEdgeRange : public EdgeRange {
|
|||
//
|
||||
// {
|
||||
// mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
|
||||
// JS::ubi::RootList rootList(cx, maybeNoGC);
|
||||
// JS::ubi::RootList rootList(rt, maybeNoGC);
|
||||
// if (!rootList.init())
|
||||
// return false;
|
||||
//
|
||||
|
@ -929,13 +929,13 @@ class PreComputedEdgeRange : public EdgeRange {
|
|||
// }
|
||||
class MOZ_STACK_CLASS RootList {
|
||||
Maybe<AutoCheckCannotGC>& noGC;
|
||||
JSContext* cx;
|
||||
|
||||
public:
|
||||
JSRuntime* rt;
|
||||
EdgeVector edges;
|
||||
bool wantNames;
|
||||
|
||||
RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
|
||||
RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
|
||||
|
||||
// Find all GC roots.
|
||||
bool init();
|
||||
|
@ -959,7 +959,7 @@ class MOZ_STACK_CLASS RootList {
|
|||
|
||||
template<>
|
||||
struct Concrete<RootList> : public Base {
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
|
||||
const char16_t* typeName() const override { return concreteTypeName; }
|
||||
|
||||
protected:
|
||||
|
@ -976,7 +976,7 @@ struct Concrete<RootList> : public Base {
|
|||
template<typename Referent>
|
||||
class TracerConcrete : public Base {
|
||||
const char16_t* typeName() const override { return concreteTypeName; }
|
||||
UniquePtr<EdgeRange> edges(JSContext*, bool wantNames) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
|
||||
JS::Zone* zone() const override;
|
||||
|
||||
protected:
|
||||
|
@ -1069,7 +1069,7 @@ template<>
|
|||
class Concrete<void> : public Base {
|
||||
const char16_t* typeName() const override;
|
||||
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
|
||||
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
|
||||
UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
|
||||
JS::Zone* zone() const override;
|
||||
JSCompartment* compartment() const override;
|
||||
CoarseType coarseType() const final;
|
||||
|
|
|
@ -78,13 +78,13 @@ template<typename Handler>
|
|||
struct BreadthFirst {
|
||||
|
||||
// Construct a breadth-first traversal object that reports the nodes it
|
||||
// reaches to |handler|. The traversal object reports OOM on |cx|, and
|
||||
// asserts that no GC happens in |cx|'s runtime during its lifetime.
|
||||
// reaches to |handler|. The traversal asserts that no GC happens in its
|
||||
// runtime during its lifetime.
|
||||
//
|
||||
// We do nothing with noGC, other than require it to exist, with a lifetime
|
||||
// that encloses our own.
|
||||
BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoCheckCannotGC& noGC)
|
||||
: wantNames(true), cx(cx), visited(cx), handler(handler), pending(cx),
|
||||
BreadthFirst(JSRuntime* rt, Handler& handler, const JS::AutoCheckCannotGC& noGC)
|
||||
: wantNames(true), rt(rt), visited(), handler(handler), pending(),
|
||||
traversalBegun(false), stopRequested(false), abandonRequested(false)
|
||||
{ }
|
||||
|
||||
|
@ -126,7 +126,7 @@ struct BreadthFirst {
|
|||
pending.popFront();
|
||||
|
||||
// Get a range containing all origin's outgoing edges.
|
||||
auto range = origin.edges(cx, wantNames);
|
||||
auto range = origin.edges(rt, wantNames);
|
||||
if (!range)
|
||||
return false;
|
||||
|
||||
|
@ -181,13 +181,14 @@ struct BreadthFirst {
|
|||
// Other edges *to* that referent will still be traversed.
|
||||
void abandonReferent() { abandonRequested = true; }
|
||||
|
||||
// The context with which we were constructed.
|
||||
JSContext* cx;
|
||||
// The runtime with which we were constructed.
|
||||
JSRuntime* rt;
|
||||
|
||||
// A map associating each node N that we have reached with a
|
||||
// Handler::NodeData, for |handler|'s use. This is public, so that
|
||||
// |handler| can access it to see the traversal thus far.
|
||||
typedef js::HashMap<Node, typename Handler::NodeData> NodeMap;
|
||||
using NodeMap = js::HashMap<Node, typename Handler::NodeData, js::DefaultHasher<Node>,
|
||||
js::SystemAllocPolicy>;
|
||||
NodeMap visited;
|
||||
|
||||
private:
|
||||
|
@ -199,10 +200,10 @@ struct BreadthFirst {
|
|||
// current population.
|
||||
template <typename T>
|
||||
class Queue {
|
||||
js::Vector<T, 0> head, tail;
|
||||
js::Vector<T, 0, js::SystemAllocPolicy> head, tail;
|
||||
size_t frontIndex;
|
||||
public:
|
||||
explicit Queue(JSContext* cx) : head(cx), tail(cx), frontIndex(0) { }
|
||||
Queue() : head(), tail(), frontIndex(0) { }
|
||||
bool empty() { return frontIndex >= head.length(); }
|
||||
T& front() {
|
||||
MOZ_ASSERT(!empty());
|
||||
|
|
|
@ -291,6 +291,7 @@ selfhosting_srcs := \
|
|||
$(srcdir)/builtin/IntlData.js \
|
||||
$(srcdir)/builtin/Iterator.js \
|
||||
$(srcdir)/builtin/Map.js \
|
||||
$(srcdir)/builtin/Module.js \
|
||||
$(srcdir)/builtin/Number.js \
|
||||
$(srcdir)/builtin/Object.js \
|
||||
$(srcdir)/builtin/Reflect.js \
|
||||
|
|
|
@ -201,6 +201,7 @@ class AutoSetHandlingSignal
|
|||
#elif defined(XP_DARWIN)
|
||||
# define EIP_sig(p) ((p)->uc_mcontext->__ss.__eip)
|
||||
# define RIP_sig(p) ((p)->uc_mcontext->__ss.__rip)
|
||||
# define R15_sig(p) ((p)->uc_mcontext->__ss.__pc)
|
||||
#else
|
||||
# error "Don't know how to read/write to the thread state via the mcontext_t."
|
||||
#endif
|
||||
|
@ -320,12 +321,20 @@ struct macos_x64_context {
|
|||
x86_float_state64_t float_;
|
||||
};
|
||||
# define EMULATOR_CONTEXT macos_x64_context
|
||||
# else
|
||||
# elif defined(JS_CODEGEN_X86)
|
||||
struct macos_x86_context {
|
||||
x86_thread_state_t thread;
|
||||
x86_float_state_t float_;
|
||||
};
|
||||
# define EMULATOR_CONTEXT macos_x86_context
|
||||
# elif defined(JS_CODEGEN_ARM)
|
||||
struct macos_arm_context {
|
||||
arm_thread_state_t thread;
|
||||
arm_neon_state_t float_;
|
||||
};
|
||||
# define EMULATOR_CONTEXT macos_arm_context
|
||||
# else
|
||||
# error Unsupported architecture
|
||||
# endif
|
||||
#else
|
||||
# define EMULATOR_CONTEXT CONTEXT
|
||||
|
@ -803,10 +812,16 @@ ContextToPC(EMULATOR_CONTEXT* context)
|
|||
static_assert(sizeof(context->thread.__rip) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.__rip);
|
||||
# else
|
||||
# elif defined(JS_CPU_X86)
|
||||
static_assert(sizeof(context->thread.uts.ts32.__eip) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.uts.ts32.__eip);
|
||||
# elif defined(JS_CPU_ARM)
|
||||
static_assert(sizeof(context->thread.__pc) == sizeof(void*),
|
||||
"stored IP should be compile-time pointer-sized");
|
||||
return reinterpret_cast<uint8_t**>(&context->thread.__pc);
|
||||
# else
|
||||
# error Unsupported architecture
|
||||
# endif
|
||||
}
|
||||
|
||||
|
@ -852,11 +867,18 @@ HandleMachException(JSRuntime* rt, const ExceptionRequest& request)
|
|||
unsigned int float_state_count = x86_FLOAT_STATE64_COUNT;
|
||||
int thread_state = x86_THREAD_STATE64;
|
||||
int float_state = x86_FLOAT_STATE64;
|
||||
# else
|
||||
# elif defined(JS_CODEGEN_X86)
|
||||
unsigned int thread_state_count = x86_THREAD_STATE_COUNT;
|
||||
unsigned int float_state_count = x86_FLOAT_STATE_COUNT;
|
||||
int thread_state = x86_THREAD_STATE;
|
||||
int float_state = x86_FLOAT_STATE;
|
||||
# elif defined(JS_CODEGEN_ARM)
|
||||
unsigned int thread_state_count = ARM_THREAD_STATE_COUNT;
|
||||
unsigned int float_state_count = ARM_NEON_STATE_COUNT;
|
||||
int thread_state = ARM_THREAD_STATE;
|
||||
int float_state = ARM_NEON_STATE;
|
||||
# else
|
||||
# error Unsupported architecture
|
||||
# endif
|
||||
kern_return_t kret;
|
||||
kret = thread_get_state(rtThread, thread_state,
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/* 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/. */
|
||||
|
||||
function ModuleResolveExport(exportName, resolveSet = [], exportStarSet = [])
|
||||
{
|
||||
// 15.2.1.16.3 ResolveExport(exportName, resolveSet, exportStarSet)
|
||||
|
||||
if (!IsObject(this) || !IsModule(this)) {
|
||||
return callFunction(CallModuleMethodIfWrapped, this, exportName, resolveSet,
|
||||
exportStarSet, "ModuleResolveExport");
|
||||
}
|
||||
|
||||
// Step 1
|
||||
let module = this;
|
||||
|
||||
// Step 2
|
||||
for (let i = 0; i < resolveSet.length; i++) {
|
||||
let r = resolveSet[i];
|
||||
if (r.module === module && r.exportName === exportName)
|
||||
return null;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
resolveSet.push({module: module, exportName: exportName});
|
||||
|
||||
// Step 4
|
||||
let localExportEntries = module.localExportEntries;
|
||||
for (let i = 0; i < localExportEntries.length; i++) {
|
||||
let e = localExportEntries[i];
|
||||
if (exportName === e.exportName)
|
||||
return {module: module, bindingName: e.localName};
|
||||
}
|
||||
|
||||
// Step 5
|
||||
let indirectExportEntries = module.indirectExportEntries;
|
||||
for (let i = 0; i < indirectExportEntries.length; i++) {
|
||||
let e = indirectExportEntries[i];
|
||||
if (exportName === e.exportName) {
|
||||
let importedModule = HostResolveImportedModule(module, e.moduleRequest);
|
||||
let indirectResolution = importedModule.resolveExport(e.importName,
|
||||
resolveSet,
|
||||
exportStarSet);
|
||||
if (indirectResolution !== null)
|
||||
return indirectResolution;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6
|
||||
if (exportName === "default") {
|
||||
// A default export cannot be provided by an export *.
|
||||
ThrowSyntaxError(JSMSG_BAD_DEFAULT_EXPORT);
|
||||
}
|
||||
|
||||
// Step 7
|
||||
if (module in exportStarSet)
|
||||
return null;
|
||||
|
||||
// Step 8
|
||||
exportStarSet.push(module);
|
||||
|
||||
// Step 9
|
||||
let starResolution = null;
|
||||
|
||||
// Step 10
|
||||
let starExportEntries = module.starExportEntries;
|
||||
for (let i = 0; i < starExportEntries.length; i++) {
|
||||
let e = starExportEntries[i];
|
||||
let importedModule = HostResolveImportedModule(module, e.moduleRequest);
|
||||
let resolution = importedModule.resolveExport(exportName, resolveSet, exportStarSet);
|
||||
if (resolution === "ambiguous")
|
||||
return resolution;
|
||||
|
||||
if (resolution !== null) {
|
||||
if (starResolution === null) {
|
||||
starResolution = resolution;
|
||||
} else {
|
||||
if (resolution.module !== starResolution.module ||
|
||||
resolution.exportName !== starResolution.exportName)
|
||||
{
|
||||
return "ambiguous";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return starResolution;
|
||||
}
|
||||
|
||||
// 15.2.1.16.4 ModuleDeclarationInstantiation()
|
||||
function ModuleDeclarationInstantiation()
|
||||
{
|
||||
if (!IsObject(this) || !IsModule(this))
|
||||
return callFunction(CallModuleMethodIfWrapped, this, "ModuleDeclarationInstantiation");
|
||||
|
||||
// Step 1
|
||||
let module = this;
|
||||
|
||||
// Step 5
|
||||
if (module.environment !== undefined)
|
||||
return;
|
||||
|
||||
// Step 7
|
||||
CreateModuleEnvironment(module);
|
||||
let env = module.environment;
|
||||
|
||||
// Step 8
|
||||
let requestedModules = module.requestedModules;
|
||||
for (let i = 0; i < requestedModules.length; i++) {
|
||||
let required = requestedModules[i];
|
||||
let requiredModule = HostResolveImportedModule(module, required);
|
||||
requiredModule.declarationInstantiation();
|
||||
}
|
||||
|
||||
// Step 9
|
||||
let indirectExportEntries = module.indirectExportEntries;
|
||||
for (let i = 0; i < indirectExportEntries.length; i++) {
|
||||
let e = indirectExportEntries[i];
|
||||
let resolution = module.resolveExport(e.exportName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT);
|
||||
}
|
||||
|
||||
// Step 12
|
||||
let importEntries = module.importEntries;
|
||||
for (let i = 0; i < importEntries.length; i++) {
|
||||
let imp = importEntries[i];
|
||||
let importedModule = HostResolveImportedModule(module, imp.moduleRequest);
|
||||
if (imp.importName === "*") {
|
||||
// TODO
|
||||
// let namespace = GetModuleNamespace(importedModule);
|
||||
// CreateNamespaceBinding(module.environment, imp.localName, namespace);
|
||||
} else {
|
||||
let resolution = importedModule.resolveExport(imp.importName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_IMPORT);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT);
|
||||
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 15.2.1.16.5 ModuleEvaluation()
|
||||
function ModuleEvaluation()
|
||||
{
|
||||
if (!IsObject(this) || !IsModule(this))
|
||||
return callFunction(CallModuleMethodIfWrapped, this, "ModuleEvaluation");
|
||||
|
||||
// Step 1
|
||||
let module = this;
|
||||
|
||||
// Step 4
|
||||
if (module.evaluated)
|
||||
return undefined;
|
||||
|
||||
// Step 5
|
||||
SetModuleEvaluated(this);
|
||||
|
||||
// Step 6
|
||||
let requestedModules = module.requestedModules;
|
||||
for (let i = 0; i < requestedModules.length; i++) {
|
||||
let required = requestedModules[i];
|
||||
let requiredModule = HostResolveImportedModule(module, required);
|
||||
requiredModule.evaluation();
|
||||
}
|
||||
|
||||
return EvaluateModule(module);
|
||||
}
|
|
@ -211,6 +211,13 @@ ExportEntryObject::create(JSContext* cx,
|
|||
return self;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IndirectBinding
|
||||
|
||||
IndirectBinding::IndirectBinding(Handle<ModuleEnvironmentObject*> environment, HandleId localName)
|
||||
: environment(environment), localName(localName)
|
||||
{}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ModuleObject
|
||||
|
||||
|
@ -228,7 +235,7 @@ ModuleObject::class_ = {
|
|||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
nullptr, /* convert */
|
||||
nullptr, /* finalize */
|
||||
ModuleObject::finalize,
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
|
@ -257,7 +264,39 @@ ModuleObject::isInstance(HandleValue value)
|
|||
/* static */ ModuleObject*
|
||||
ModuleObject::create(ExclusiveContext* cx)
|
||||
{
|
||||
return NewBuiltinClassInstance<ModuleObject>(cx, TenuredObject);
|
||||
Rooted<ModuleObject*> self(cx, NewBuiltinClassInstance<ModuleObject>(cx, TenuredObject));
|
||||
|
||||
IndirectBindingMap* bindings = cx->new_<IndirectBindingMap>();
|
||||
if (!bindings || !bindings->init()) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
self->setReservedSlot(ImportBindingsSlot, PrivateValue(bindings));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ModuleObject::finalize(js::FreeOp* fop, JSObject* obj)
|
||||
{
|
||||
fop->delete_(&obj->as<ModuleObject>().importBindings());
|
||||
}
|
||||
|
||||
ModuleEnvironmentObject*
|
||||
ModuleObject::environment() const
|
||||
{
|
||||
Value value = getReservedSlot(EnvironmentSlot);
|
||||
if (value.isUndefined())
|
||||
return nullptr;
|
||||
|
||||
return &value.toObject().as<ModuleEnvironmentObject>();
|
||||
}
|
||||
|
||||
IndirectBindingMap&
|
||||
ModuleObject::importBindings()
|
||||
{
|
||||
return *static_cast<IndirectBindingMap*>(getReservedSlot(ImportBindingsSlot).toPrivate());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -265,6 +304,7 @@ ModuleObject::init(HandleScript script)
|
|||
{
|
||||
MOZ_ASSERT(!script->enclosingStaticScope());
|
||||
initReservedSlot(ScriptSlot, PrivateValue(script));
|
||||
initReservedSlot(EvaluatedSlot, BooleanValue(false));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -301,6 +341,12 @@ ModuleObject::script() const
|
|||
return static_cast<JSScript*>(getReservedSlot(ScriptSlot).toPrivate());
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleObject::evaluated() const
|
||||
{
|
||||
return getReservedSlot(EvaluatedSlot).toBoolean();
|
||||
}
|
||||
|
||||
ModuleEnvironmentObject&
|
||||
ModuleObject::initialEnvironment() const
|
||||
{
|
||||
|
@ -325,9 +371,45 @@ ModuleObject::trace(JSTracer* trc, JSObject* obj)
|
|||
TraceManuallyBarrieredEdge(trc, &script, "Module script");
|
||||
module.setReservedSlot(ScriptSlot, PrivateValue(script));
|
||||
}
|
||||
|
||||
IndirectBindingMap& bindings = module.importBindings();
|
||||
for (IndirectBindingMap::Enum e(bindings); !e.empty(); e.popFront()) {
|
||||
IndirectBinding& b = e.front().value();
|
||||
TraceEdge(trc, &b.environment, "module import environment");
|
||||
TraceEdge(trc, &b.localName, "module import local name");
|
||||
jsid bindingName = e.front().key();
|
||||
TraceManuallyBarrieredEdge(trc, &bindingName, "module import binding name");
|
||||
MOZ_ASSERT(bindingName == e.front().key());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ModuleObject::createEnvironment()
|
||||
{
|
||||
// The environment has already been created, we just neet to set it in the
|
||||
// right slot.
|
||||
MOZ_ASSERT(!getReservedSlot(InitialEnvironmentSlot).isUndefined());
|
||||
MOZ_ASSERT(getReservedSlot(EnvironmentSlot).isUndefined());
|
||||
setReservedSlot(EnvironmentSlot, getReservedSlot(InitialEnvironmentSlot));
|
||||
}
|
||||
|
||||
void
|
||||
ModuleObject::setEvaluated()
|
||||
{
|
||||
MOZ_ASSERT(!evaluated());
|
||||
setReservedSlot(EvaluatedSlot, TrueHandleValue);
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleObject::evaluate(JSContext* cx, MutableHandleValue rval)
|
||||
{
|
||||
RootedScript script(cx, this->script());
|
||||
return JS_ExecuteScript(cx, script, rval);
|
||||
}
|
||||
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, initialEnvironment, InitialEnvironmentSlot)
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, environment, EnvironmentSlot)
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluated, EvaluatedSlot)
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
|
||||
DEFINE_GETTER_FUNCTIONS(ModuleObject, localExportEntries, LocalExportEntriesSlot)
|
||||
|
@ -339,6 +421,8 @@ js::InitModuleClass(JSContext* cx, HandleObject obj)
|
|||
{
|
||||
static const JSPropertySpec protoAccessors[] = {
|
||||
JS_PSG("initialEnvironment", ModuleObject_initialEnvironmentGetter, 0),
|
||||
JS_PSG("environment", ModuleObject_environmentGetter, 0),
|
||||
JS_PSG("evaluated", ModuleObject_evaluatedGetter, 0),
|
||||
JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
|
||||
JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),
|
||||
JS_PSG("localExportEntries", ModuleObject_localExportEntriesGetter, 0),
|
||||
|
@ -347,13 +431,20 @@ js::InitModuleClass(JSContext* cx, HandleObject obj)
|
|||
JS_PS_END
|
||||
};
|
||||
|
||||
static const JSFunctionSpec protoFunctions[] = {
|
||||
JS_SELF_HOSTED_FN("resolveExport", "ModuleResolveExport", 3, 0),
|
||||
JS_SELF_HOSTED_FN("declarationInstantiation", "ModuleDeclarationInstantiation", 0, 0),
|
||||
JS_SELF_HOSTED_FN("evaluation", "ModuleEvaluation", 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
|
||||
|
||||
RootedObject proto(cx, global->createBlankPrototype<PlainObject>(cx));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, nullptr))
|
||||
if (!DefinePropertiesAndFunctions(cx, proto, protoAccessors, protoFunctions))
|
||||
return nullptr;
|
||||
|
||||
global->setPrototype(JSProto_Module, ObjectValue(*proto));
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define builtin_ModuleObject_h
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
|
||||
#include "js/TraceableVector.h"
|
||||
|
||||
|
@ -70,6 +71,15 @@ class ExportEntryObject : public NativeObject
|
|||
JSAtom* localName();
|
||||
};
|
||||
|
||||
struct IndirectBinding
|
||||
{
|
||||
IndirectBinding(Handle<ModuleEnvironmentObject*> environment, HandleId localName);
|
||||
RelocatablePtr<ModuleEnvironmentObject*> environment;
|
||||
RelocatableId localName;
|
||||
};
|
||||
|
||||
typedef HashMap<jsid, IndirectBinding, JsidHasher, SystemAllocPolicy> IndirectBindingMap;
|
||||
|
||||
class ModuleObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
|
@ -77,11 +87,14 @@ class ModuleObject : public NativeObject
|
|||
{
|
||||
ScriptSlot = 0,
|
||||
InitialEnvironmentSlot,
|
||||
EnvironmentSlot,
|
||||
EvaluatedSlot,
|
||||
RequestedModulesSlot,
|
||||
ImportEntriesSlot,
|
||||
LocalExportEntriesSlot,
|
||||
IndirectExportEntriesSlot,
|
||||
StarExportEntriesSlot,
|
||||
ImportBindingsSlot,
|
||||
SlotCount
|
||||
};
|
||||
|
||||
|
@ -100,15 +113,24 @@ class ModuleObject : public NativeObject
|
|||
|
||||
JSScript* script() const;
|
||||
ModuleEnvironmentObject& initialEnvironment() const;
|
||||
ModuleEnvironmentObject* environment() const;
|
||||
bool evaluated() const;
|
||||
ArrayObject& requestedModules() const;
|
||||
ArrayObject& importEntries() const;
|
||||
ArrayObject& localExportEntries() const;
|
||||
ArrayObject& indirectExportEntries() const;
|
||||
ArrayObject& starExportEntries() const;
|
||||
JSObject* enclosingStaticScope() const;
|
||||
IndirectBindingMap& importBindings();
|
||||
|
||||
void createEnvironment();
|
||||
|
||||
void setEvaluated();
|
||||
bool evaluate(JSContext*cx, MutableHandleValue rval);
|
||||
|
||||
private:
|
||||
static void trace(JSTracer* trc, JSObject* obj);
|
||||
static void finalize(js::FreeOp* fop, JSObject* obj);
|
||||
|
||||
bool hasScript() const;
|
||||
};
|
||||
|
@ -135,6 +157,7 @@ class MOZ_STACK_CLASS ModuleBuilder
|
|||
|
||||
JSContext* cx_;
|
||||
RootedAtomVector requestedModules_;
|
||||
|
||||
RootedAtomVector importedBoundNames_;
|
||||
RootedImportEntryVector importEntries_;
|
||||
RootedExportEntryVector exportEntries_;
|
||||
|
|
|
@ -2127,9 +2127,9 @@ struct FindPathHandler {
|
|||
typedef BackEdge NodeData;
|
||||
typedef JS::ubi::BreadthFirst<FindPathHandler> Traversal;
|
||||
|
||||
FindPathHandler(JS::ubi::Node start, JS::ubi::Node target,
|
||||
FindPathHandler(JSContext*cx, JS::ubi::Node start, JS::ubi::Node target,
|
||||
AutoValueVector& nodes, Vector<EdgeName>& edges)
|
||||
: start(start), target(target), foundPath(false),
|
||||
: cx(cx), start(start), target(target), foundPath(false),
|
||||
nodes(nodes), edges(edges) { }
|
||||
|
||||
bool
|
||||
|
@ -2143,7 +2143,7 @@ struct FindPathHandler {
|
|||
|
||||
// Record how we reached this node. This is the last edge on a
|
||||
// shortest path to this node.
|
||||
EdgeName edgeName = DuplicateString(traversal.cx, edge.name);
|
||||
EdgeName edgeName = DuplicateString(cx, edge.name);
|
||||
if (!edgeName)
|
||||
return false;
|
||||
*backEdge = mozilla::Move(BackEdge(origin, Move(edgeName)));
|
||||
|
@ -2180,6 +2180,8 @@ struct FindPathHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
JSContext* cx;
|
||||
|
||||
// The node we're starting from.
|
||||
JS::ubi::Node start;
|
||||
|
||||
|
@ -2238,8 +2240,8 @@ FindPath(JSContext* cx, unsigned argc, Value* vp)
|
|||
|
||||
JS::ubi::Node start(args[0]), target(args[1]);
|
||||
|
||||
heaptools::FindPathHandler handler(start, target, nodes, edges);
|
||||
heaptools::FindPathHandler::Traversal traversal(cx, handler, autoCannotGC);
|
||||
heaptools::FindPathHandler handler(cx, start, target, nodes, edges);
|
||||
heaptools::FindPathHandler::Traversal traversal(cx->runtime(), handler, autoCannotGC);
|
||||
if (!traversal.init() || !traversal.addStart(start))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -673,7 +673,7 @@ class GCRuntime
|
|||
bool onBackgroundThread() { return helperState.onBackgroundThread(); }
|
||||
|
||||
bool currentThreadOwnsGCLock() {
|
||||
return lockOwner == PR_GetCurrentThread();
|
||||
return lockOwner.value == PR_GetCurrentThread();
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
||||
|
@ -684,15 +684,17 @@ class GCRuntime
|
|||
|
||||
void lockGC() {
|
||||
PR_Lock(lock);
|
||||
MOZ_ASSERT(!lockOwner);
|
||||
#ifdef DEBUG
|
||||
lockOwner = PR_GetCurrentThread();
|
||||
MOZ_ASSERT(!lockOwner.value);
|
||||
lockOwner.value = PR_GetCurrentThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlockGC() {
|
||||
MOZ_ASSERT(lockOwner == PR_GetCurrentThread());
|
||||
lockOwner = nullptr;
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(lockOwner.value == PR_GetCurrentThread());
|
||||
lockOwner.value = nullptr;
|
||||
#endif
|
||||
PR_Unlock(lock);
|
||||
}
|
||||
|
||||
|
@ -1298,7 +1300,7 @@ class GCRuntime
|
|||
|
||||
/* Synchronize GC heap access between main thread and GCHelperState. */
|
||||
PRLock* lock;
|
||||
mozilla::DebugOnly<PRThread*> lockOwner;
|
||||
mozilla::DebugOnly<mozilla::Atomic<PRThread*>> lockOwner;
|
||||
|
||||
BackgroundAllocTask allocTask;
|
||||
GCHelperState helperState;
|
||||
|
|
|
@ -370,7 +370,8 @@ AssertRootMarkingPhase(JSTracer* trc)
|
|||
D(GlobalObject*) \
|
||||
D(JSObject*) \
|
||||
D(JSFunction*) \
|
||||
D(ModuleObject*) \
|
||||
D(ModuleObject*) \
|
||||
D(ModuleEnvironmentObject*) \
|
||||
D(NestedScopeObject*) \
|
||||
D(PlainObject*) \
|
||||
D(SavedFrame*) \
|
||||
|
|
|
@ -133,6 +133,14 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
|
|||
pushedNonVolatileRegisters++;
|
||||
}
|
||||
|
||||
#if defined(XP_IOS) && defined(JS_CODEGEN_ARM)
|
||||
// The stack is 4-byte aligned on iOS, force 8-byte alignment.
|
||||
masm.movePtr(StackPointer, temp0);
|
||||
masm.andPtr(Imm32(~7), StackPointer);
|
||||
masm.push(temp0);
|
||||
masm.push(temp0);
|
||||
#endif
|
||||
|
||||
#ifndef JS_CODEGEN_X86
|
||||
// The InputOutputData* is stored as an argument, save it on the stack
|
||||
// above the frame.
|
||||
|
@ -369,6 +377,11 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only)
|
|||
masm.freeStack(frameSize);
|
||||
#endif
|
||||
|
||||
#if defined(XP_IOS) && defined(JS_CODEGEN_ARM)
|
||||
masm.pop(temp0);
|
||||
masm.movePtr(temp0, StackPointer);
|
||||
#endif
|
||||
|
||||
// Restore non-volatile registers which were saved on entry.
|
||||
for (GeneralRegisterBackwardIterator iter(savedNonVolatileRegisters); iter.more(); ++iter)
|
||||
masm.Pop(*iter);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче