Merge inbound to m-c. a=merge
Merge inbound to m-c. a=merge
--- a/.eslintignore
+++ b/.eslintignore
@@ -212,16 +212,17 @@ dom/jsurl/**
dom/locales/**
dom/manifest/**
dom/mathml/**
dom/media/**
dom/messagechannel/**
dom/network/**
dom/notification/**
dom/offline/**
+dom/payments/**
dom/performance/**
dom/permission/**
dom/plugins/**
dom/power/**
dom/presentation/**
dom/promise/**
dom/push/**
dom/quota/**
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -208,16 +208,17 @@
@RESPATH@/components/dom_events.xpt
@RESPATH@/components/dom_geolocation.xpt
@RESPATH@/components/dom_media.xpt
@RESPATH@/components/dom_network.xpt
@RESPATH@/components/dom_notification.xpt
@RESPATH@/components/dom_html.xpt
@RESPATH@/components/dom_offline.xpt
@RESPATH@/components/dom_json.xpt
+@RESPATH@/components/dom_payments.xpt
@RESPATH@/components/dom_power.xpt
@RESPATH@/components/dom_push.xpt
@RESPATH@/components/dom_quota.xpt
@RESPATH@/components/dom_range.xpt
@RESPATH@/components/dom_security.xpt
@RESPATH@/components/dom_sidebar.xpt
@RESPATH@/components/dom_storage.xpt
@RESPATH@/components/dom_stylesheets.xpt
--- a/devtools/client/jsonview/converter-child.js
+++ b/devtools/client/jsonview/converter-child.js
@@ -14,20 +14,16 @@ loader.lazyRequireGetter(this, "NetworkH
"devtools/shared/webconsole/network-helper");
loader.lazyRequireGetter(this, "JsonViewUtils",
"devtools/client/jsonview/utils");
const childProcessMessageManager =
Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsISyncMessageSender);
-// Amount of space that will be allocated for the stream's backing-store.
-// Must be power of 2. Used to copy the data stream in onStopRequest.
-const SEGMENT_SIZE = Math.pow(2, 17);
-
// Localization
loader.lazyGetter(this, "jsonViewStrings", () => {
return Services.strings.createBundle(
"chrome://devtools/locale/jsonview.properties");
});
/**
* This object detects 'application/vnd.mozilla.json.view' content type
@@ -49,300 +45,217 @@ Converter.prototype = {
return this;
},
/**
* This component works as such:
* 1. asyncConvertData captures the listener
* 2. onStartRequest fires, initializes stuff, modifies the listener
* to match our output type
- * 3. onDataAvailable transcodes the data into a UTF-8 string
- * 4. onStopRequest gets the collected data and converts it,
- * spits it to the listener
+ * 3. onDataAvailable spits it back to the listener
+ * 4. onStopRequest spits it back to the listener and initializes
+ the JSON Viewer
* 5. convert does nothing, it's just the synchronous version
* of asyncConvertData
*/
convert: function (fromStream, fromType, toType, ctx) {
return fromStream;
},
asyncConvertData: function (fromType, toType, listener, ctx) {
this.listener = listener;
},
onDataAvailable: function (request, context, inputStream, offset, count) {
- // From https://developer.mozilla.org/en/Reading_textual_data
- let is = Cc["@mozilla.org/intl/converter-input-stream;1"]
- .createInstance(Ci.nsIConverterInputStream);
- is.init(inputStream, this.charset, -1,
- Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
-
- // Seed it with something positive
- while (count) {
- let str = {};
- let bytesRead = is.readString(count, str);
- if (!bytesRead) {
- break;
- }
- count -= bytesRead;
- this.data += str.value;
- }
+ this.listener.onDataAvailable(...arguments);
},
onStartRequest: function (request, context) {
- this.data = "";
- this.uri = request.QueryInterface(Ci.nsIChannel).URI.spec;
-
- // Sets the charset if it is available. (For documents loaded from the
- // filesystem, this is not set.)
- this.charset =
- request.QueryInterface(Ci.nsIChannel).contentCharset || "UTF-8";
+ this.channel = request;
// Let "save as" save the original JSON, not the viewer.
// To save with the proper extension we need the original content type,
// which has been replaced by application/vnd.mozilla.json.view
let originalType;
if (request instanceof Ci.nsIHttpChannel) {
try {
- originalType = request.getResponseHeader("Content-Type");
+ let header = request.getResponseHeader("Content-Type");
+ originalType = header.split(";")[0];
} catch (err) {
// Handled below
}
} else {
- let match = this.uri.match(/^data:(.*?)[,;]/);
+ let uri = request.QueryInterface(Ci.nsIChannel).URI.spec;
+ let match = uri.match(/^data:(.*?)[,;]/);
if (match) {
originalType = match[1];
}
}
const JSON_TYPES = ["application/json", "application/manifest+json"];
if (!JSON_TYPES.includes(originalType)) {
originalType = JSON_TYPES[0];
}
request.QueryInterface(Ci.nsIWritablePropertyBag);
request.setProperty("contentType", originalType);
- this.channel = request;
- this.channel.contentType = "text/html";
- this.channel.contentCharset = "UTF-8";
+ // Parse source as JSON. This is like text/plain, but enforcing
+ // UTF-8 charset (see bug 741776).
+ request.QueryInterface(Ci.nsIChannel);
+ request.contentType = JSON_TYPES[0];
+ this.charset = request.contentCharset = "UTF-8";
+
// Because content might still have a reference to this window,
// force setting it to a null principal to avoid it being same-
// origin with (other) content.
- this.channel.loadInfo.resetPrincipalToInheritToNullPrincipal();
+ request.loadInfo.resetPrincipalToInheritToNullPrincipal();
- this.listener.onStartRequest(this.channel, context);
+ this.listener.onStartRequest(request, context);
},
- /**
- * This should go something like this:
- * 1. Make sure we have a unicode string.
- * 2. Convert it to a Javascript object.
- * 2.1 Removes the callback
- * 3. Convert that to HTML? Or XUL?
- * 4. Spit it back out at the listener
- */
onStopRequest: function (request, context, statusCode) {
- let headers = {
- response: [],
- request: []
- };
-
- let win = NetworkHelper.getWindowForRequest(request);
-
let Locale = {
$STR: key => {
try {
return jsonViewStrings.GetStringFromName(key);
} catch (err) {
console.error(err);
return undefined;
}
}
};
- JsonViewUtils.exportIntoContentScope(win, Locale, "Locale");
-
- win.addEventListener("DOMContentLoaded", event => {
- win.addEventListener("contentMessage",
- this.onContentMessage.bind(this), false, true);
- }, {once: true});
-
+ let headers = {
+ response: [],
+ request: []
+ };
// The request doesn't have to be always nsIHttpChannel
// (e.g. in case of data: URLs)
if (request instanceof Ci.nsIHttpChannel) {
request.visitResponseHeaders({
visitHeader: function (name, value) {
headers.response.push({name: name, value: value});
}
});
-
request.visitRequestHeaders({
visitHeader: function (name, value) {
headers.request.push({name: name, value: value});
}
});
}
- let outputDoc = "";
-
- try {
- headers = JSON.stringify(headers);
- outputDoc = this.toHTML(this.data, headers);
- } catch (e) {
- console.error("JSON Viewer ERROR " + e);
- outputDoc = this.toErrorPage(e, this.data);
- }
-
- let storage = Cc["@mozilla.org/storagestream;1"]
- .createInstance(Ci.nsIStorageStream);
+ let win = NetworkHelper.getWindowForRequest(request);
+ JsonViewUtils.exportIntoContentScope(win, Locale, "Locale");
+ JsonViewUtils.exportIntoContentScope(win, headers, "headers");
- storage.init(SEGMENT_SIZE, 0xffffffff, null);
- let out = storage.getOutputStream(0);
-
- let binout = Cc["@mozilla.org/binaryoutputstream;1"]
- .createInstance(Ci.nsIBinaryOutputStream);
-
- binout.setOutputStream(out);
- binout.writeUtf8Z(outputDoc);
- binout.close();
-
- // We need to trim 4 bytes off the front (this could be underlying bug).
- let trunc = 4;
- let instream = storage.newInputStream(trunc);
-
- // Pass the data to the main content listener
- this.listener.onDataAvailable(this.channel, context, instream, 0,
- instream.available());
+ win.addEventListener("DOMContentLoaded", event => {
+ win.addEventListener("contentMessage",
+ onContentMessage.bind(this), false, true);
+ loadJsonViewer(win.document);
+ }, {once: true});
this.listener.onStopRequest(this.channel, context, statusCode);
-
this.listener = null;
- },
-
- htmlEncode: function (t) {
- return t !== null ? t.toString()
- .replace(/&/g, "&")
- .replace(/"/g, """)
- .replace(/</g, "<")
- .replace(/>/g, ">") : "";
- },
-
- toHTML: function (json, headers) {
- let themeClassName = "theme-" + JsonViewUtils.getCurrentTheme();
- let clientBaseUrl = "resource://devtools/client/";
- let baseUrl = clientBaseUrl + "jsonview/";
- let themeVarsUrl = clientBaseUrl + "themes/variables.css";
- let commonUrl = clientBaseUrl + "themes/common.css";
- let toolbarsUrl = clientBaseUrl + "themes/toolbars.css";
-
- let os;
- let platform = Services.appinfo.OS;
- if (platform.startsWith("WINNT")) {
- os = "win";
- } else if (platform.startsWith("Darwin")) {
- os = "mac";
- } else {
- os = "linux";
- }
-
- let dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
-
- return "<!DOCTYPE html>\n" +
- "<html platform=\"" + os + "\" class=\"" + themeClassName +
- "\" dir=\"" + dir + "\">" +
- "<head>" +
- "<base href=\"" + this.htmlEncode(baseUrl) + "\">" +
- "<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
- themeVarsUrl + "\">" +
- "<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
- commonUrl + "\">" +
- "<link rel=\"stylesheet\" type=\"text/css\" href=\"" +
- toolbarsUrl + "\">" +
- "<link rel=\"stylesheet\" type=\"text/css\" href=\"css/main.css\">" +
- "<script data-main=\"viewer-config\" src=\"lib/require.js\"></script>" +
- "</head><body>" +
- "<div id=\"content\">" +
- "<pre id=\"json\">" + this.htmlEncode(json) + "</pre>" +
- "</div><div id=\"headers\">" + this.htmlEncode(headers) + "</div>" +
- "</body></html>";
- },
-
- toErrorPage: function (error, data) {
- // Escape unicode nulls
- data = data.replace("\u0000", "\uFFFD");
-
- let errorInfo = error + "";
-
- let output = "<div id=\"error\">" + "error parsing";
- if (errorInfo.message) {
- output += "<div class=\"errormessage\">" + errorInfo.message + "</div>";
- }
-
- output += "</div><div id=\"json\">" + this.highlightError(data,
- errorInfo.line, errorInfo.column) + "</div>";
-
- let dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
-
- return "<!DOCTYPE html>\n" +
- "<html><head>" +
- "<base href=\"" + this.htmlEncode(this.data.url()) + "\">" +
- "</head><body dir=\"" + dir + "\">" +
- output +
- "</body></html>";
- },
-
- // Chrome <-> Content communication
-
- onContentMessage: function (e) {
- // Do not handle events from different documents.
- let win = NetworkHelper.getWindowForRequest(this.channel);
- if (win != e.target) {
- return;
- }
-
- let value = e.detail.value;
- switch (e.detail.type) {
- case "copy":
- copyString(win, value);
- break;
-
- case "copy-headers":
- this.copyHeaders(win, value);
- break;
-
- case "save":
- // The window ID is needed when the JSON Viewer is inside an iframe.
- let windowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
- childProcessMessageManager.sendAsyncMessage(
- "devtools:jsonview:save", {url: value, windowID: windowID});
- }
- },
-
- copyHeaders: function (win, headers) {
- let value = "";
- let eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n";
-
- let responseHeaders = headers.response;
- for (let i = 0; i < responseHeaders.length; i++) {
- let header = responseHeaders[i];
- value += header.name + ": " + header.value + eol;
- }
-
- value += eol;
-
- let requestHeaders = headers.request;
- for (let i = 0; i < requestHeaders.length; i++) {
- let header = requestHeaders[i];
- value += header.name + ": " + header.value + eol;
- }
-
- copyString(win, value);
}
};
+// Chrome <-> Content communication
+function onContentMessage(e) {
+ // Do not handle events from different documents.
+ let win = NetworkHelper.getWindowForRequest(this.channel);
+ if (win != e.target) {
+ return;
+ }
+
+ let value = e.detail.value;
+ switch (e.detail.type) {
+ case "copy":
+ copyString(win, value);
+ break;
+
+ case "copy-headers":
+ copyHeaders(win, value);
+ break;
+
+ case "save":
+ // The window ID is needed when the JSON Viewer is inside an iframe.
+ let windowID = win.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
+ childProcessMessageManager.sendAsyncMessage(
+ "devtools:jsonview:save", {url: value, windowID: windowID});
+ }
+}
+
+// Loads the JSON Viewer into a text/plain document
+function loadJsonViewer(doc) {
+ function addStyleSheet(url) {
+ let link = doc.createElement("link");
+ link.rel = "stylesheet";
+ link.type = "text/css";
+ link.href = url;
+ doc.head.appendChild(link);
+ }
+
+ let os;
+ let platform = Services.appinfo.OS;
+ if (platform.startsWith("WINNT")) {
+ os = "win";
+ } else if (platform.startsWith("Darwin")) {
+ os = "mac";
+ } else {
+ os = "linux";
+ }
+
+ doc.documentElement.setAttribute("platform", os);
+ doc.documentElement.dataset.contentType = doc.contentType;
+ doc.documentElement.classList.add("theme-" + JsonViewUtils.getCurrentTheme());
+ doc.documentElement.dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
+
+ let base = doc.createElement("base");
+ base.href = "resource://devtools/client/jsonview/";
+ doc.head.appendChild(base);
+
+ addStyleSheet("../themes/variables.css");
+ addStyleSheet("../themes/common.css");
+ addStyleSheet("../themes/toolbars.css");
+ addStyleSheet("css/main.css");
+
+ let json = doc.querySelector("pre");
+ json.id = "json";
+ let content = doc.createElement("div");
+ content.id = "content";
+ content.appendChild(json);
+ doc.body.appendChild(content);
+
+ let script = doc.createElement("script");
+ script.src = "lib/require.js";
+ script.dataset.main = "viewer-config";
+ doc.body.appendChild(script);
+}
+
+function copyHeaders(win, headers) {
+ let value = "";
+ let eol = (Services.appinfo.OS !== "WINNT") ? "\n" : "\r\n";
+
+ let responseHeaders = headers.response;
+ for (let i = 0; i < responseHeaders.length; i++) {
+ let header = responseHeaders[i];
+ value += header.name + ": " + header.value + eol;
+ }
+
+ value += eol;
+
+ let requestHeaders = headers.request;
+ for (let i = 0; i < requestHeaders.length; i++) {
+ let header = requestHeaders[i];
+ value += header.name + ": " + header.value + eol;
+ }
+
+ copyString(win, value);
+}
+
function copyString(win, string) {
win.document.addEventListener("copy", event => {
event.clipboardData.setData("text/plain", string);
event.preventDefault();
}, {once: true});
win.document.execCommand("copy", false, null);
}
--- a/devtools/client/jsonview/css/general.css
+++ b/devtools/client/jsonview/css/general.css
@@ -30,23 +30,26 @@ pre {
#content {
display: flow-root;
}
#json {
margin: 8px;
}
-#headers {
- display: none;
-}
-
/******************************************************************************/
/* Dark Theme */
body.theme-dark {
color: var(--theme-body-color);
background-color: var(--theme-body-background);
}
.theme-dark pre {
background-color: var(--theme-body-background);
}
+
+/******************************************************************************/
+/* Fixes for quirks mode */
+
+table {
+ font: inherit;
+}
--- a/devtools/client/jsonview/json-viewer.js
+++ b/devtools/client/jsonview/json-viewer.js
@@ -7,39 +7,37 @@
"use strict";
define(function (require, exports, module) {
const { render } = require("devtools/client/shared/vendor/react-dom");
const { createFactories } = require("devtools/client/shared/react-utils");
const { MainTabbedArea } = createFactories(require("./components/main-tabbed-area"));
const json = document.getElementById("json");
- const headers = document.getElementById("headers");
let jsonData;
let prettyURL;
try {
jsonData = JSON.parse(json.textContent);
} catch (err) {
jsonData = err + "";
}
// Application state object.
let input = {
jsonText: json.textContent,
jsonPretty: null,
json: jsonData,
- headers: JSON.parse(headers.textContent),
+ headers: window.headers,
tabActive: 0,
prettified: false
};
json.remove();
- headers.remove();
/**
* Application actions/commands. This list implements all commands
* available for the JSON viewer.
*/
input.actions = {
onCopyJson: function () {
dispatchEvent("copy", input.prettified ? input.jsonPretty : input.jsonText);
--- a/devtools/client/jsonview/utils.js
+++ b/devtools/client/jsonview/utils.js
@@ -27,11 +27,13 @@ exports.exportIntoContentScope = functio
let props = Object.getOwnPropertyNames(obj);
for (let i = 0; i < props.length; i++) {
let propName = props[i];
let propValue = obj[propName];
if (typeof propValue == "function") {
Cu.exportFunction(propValue, clone, {
defineAs: propName
});
+ } else {
+ clone[propName] = Cu.cloneInto(propValue, win);
}
}
};
--- a/devtools/server/actors/environment.js
+++ b/devtools/server/actors/environment.js
@@ -23,16 +23,25 @@ const { environmentSpec } = require("dev
*/
let EnvironmentActor = ActorClassWithSpec(environmentSpec, {
initialize: function (environment, threadActor) {
this.obj = environment;
this.threadActor = threadActor;
},
/**
+ * When the Environment Actor is destroyed it removes the
+ * Debugger.Environment.actor field so that environment does not
+ * reference a destroyed actor.
+ */
+ destroy: function () {
+ this.obj.actor = null;
+ },
+
+ /**
* Return an environment form for use in a protocol message.
*/
form: function () {
let form = { actor: this.actorID };
// What is this environment's type?
if (this.obj.type == "declarative") {
form.type = this.obj.callee ? "function" : "block";
--- a/devtools/server/tests/unit/head_dbg.js
+++ b/devtools/server/tests/unit/head_dbg.js
@@ -226,16 +226,24 @@ function waitForPause(threadClient) {
return waitForEvent(threadClient, "paused");
}
function setBreakpoint(sourceClient, location) {
dump("Setting breakpoint.\n");
return sourceClient.setBreakpoint(location);
}
+function getPrototypeAndProperties(objClient) {
+ dump("getting prototype and properties.\n");
+
+ return new Promise(resolve => {
+ objClient.getPrototypeAndProperties(response => resolve(response));
+ });
+}
+
function dumpn(msg) {
dump("DBG-TEST: " + msg + "\n");
}
function testExceptionHook(ex) {
try {
do_report_unexpected_exception(ex);
} catch (e) {
@@ -689,16 +697,26 @@ function waitForEvent(client, type, pred
* @returns Promise
*/
function executeOnNextTickAndWaitForPause(action, client) {
const paused = waitForPause(client);
executeSoon(action);
return paused;
}
+function evalCallback(debuggeeGlobal, func) {
+ Components.utils.evalInSandbox(
+ "(" + func + ")()",
+ debuggeeGlobal,
+ "1.8",
+ "test.js",
+ 1
+ );
+}
+
/**
* Interrupt JS execution for the specified thread.
*
* @param ThreadClient threadClient
* @returns Promise
*/
function interrupt(threadClient) {
dumpn("Interrupting.");
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_objectgrips-14.js
@@ -0,0 +1,61 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Test out of scope objects with synchronous functions.
+ */
+
+var gDebuggee;
+var gClient;
+var gThreadClient;
+
+function run_test() {
+ initTestDebuggerServer();
+ gDebuggee = addTestGlobal("test-object-grip");
+ gClient = new DebuggerClient(DebuggerServer.connectPipe());
+ gClient.connect().then(function () {
+ attachTestTabAndResume(gClient, "test-object-grip",
+ function (response, tabClient, threadClient) {
+ gThreadClient = threadClient;
+ testObjectGroup();
+ });
+ });
+ do_test_pending();
+}
+
+function evalCode() {
+ evalCallback(gDebuggee, function runTest() {
+ let ugh = [];
+ let i = 0;
+
+ (function () {
+ (function () {
+ ugh.push(i++);
+ debugger;
+ })();
+ })();
+
+ debugger;
+ });
+}
+
+const testObjectGroup = Task.async(function* () {
+ let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
+
+ const ugh = packet.frame.environment.parent.parent.bindings.variables.ugh;
+ const ughClient = yield gThreadClient.pauseGrip(ugh.value);
+
+ packet = yield getPrototypeAndProperties(ughClient);
+ packet = yield resumeAndWaitForPause(gClient, gThreadClient);
+
+ const ugh2 = packet.frame.environment.bindings.variables.ugh;
+ const ugh2Client = gThreadClient.pauseGrip(ugh2.value);
+
+ packet = yield getPrototypeAndProperties(ugh2Client);
+ do_check_eq(packet.ownProperties.length.value, 1);
+
+ yield resume(gThreadClient);
+ finishClient(gClient);
+});
new file mode 100644
--- /dev/null
+++ b/devtools/server/tests/unit/test_objectgrips-15.js
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Test out of scope objects with async functions.
+ */
+
+var gDebuggee;
+var gClient;
+var gThreadClient;
+
+function run_test() {
+ initTestDebuggerServer();
+ gDebuggee = addTestGlobal("test-object-grip");
+ gClient = new DebuggerClient(DebuggerServer.connectPipe());
+ gClient.connect().then(function () {
+ attachTestTabAndResume(gClient, "test-object-grip",
+ function (response, tabClient, threadClient) {
+ gThreadClient = threadClient;
+ testObjectGroup();
+ });
+ });
+ do_test_pending();
+}
+
+function evalCode() {
+ evalCallback(gDebuggee, function runTest() {
+ let ugh = [];
+ let i = 0;
+
+ function foo() {
+ ugh.push(i++);
+ debugger;
+ }
+
+ Promise.resolve().then(foo).then(foo);
+ });
+}
+
+const testObjectGroup = Task.async(function* () {
+ let packet = yield executeOnNextTickAndWaitForPause(evalCode, gClient);
+
+ const ugh = packet.frame.environment.parent.bindings.variables.ugh;
+ const ughClient = yield gThreadClient.pauseGrip(ugh.value);
+
+ packet = yield getPrototypeAndProperties(ughClient);
+
+ packet = yield resumeAndWaitForPause(gClient, gThreadClient);
+ const ugh2 = packet.frame.environment.parent.bindings.variables.ugh;
+ const ugh2Client = gThreadClient.pauseGrip(ugh2.value);
+
+ packet = yield getPrototypeAndProperties(ugh2Client);
+ do_check_eq(packet.ownProperties.length.value, 2);
+
+ yield resume(gThreadClient);
+ finishClient(gClient);
+});
--- a/devtools/server/tests/unit/xpcshell.ini
+++ b/devtools/server/tests/unit/xpcshell.ini
@@ -164,16 +164,18 @@ reason = only ran on B2G
[test_objectgrips-06.js]
[test_objectgrips-07.js]
[test_objectgrips-08.js]
[test_objectgrips-09.js]
[test_objectgrips-10.js]
[test_objectgrips-11.js]
[test_objectgrips-12.js]
[test_objectgrips-13.js]
+[test_objectgrips-14.js]
+[test_objectgrips-15.js]
[test_promise_state-01.js]
[test_promise_state-02.js]
[test_promise_state-03.js]
[test_interrupt.js]
[test_stepping-01.js]
[test_stepping-02.js]
[test_stepping-03.js]
[test_stepping-04.js]
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -953,16 +953,18 @@ GK_ATOM(onscanningstatechanged, "onscann
GK_ATOM(onscostatuschanged, "onscostatuschanged")
GK_ATOM(onscroll, "onscroll")
GK_ATOM(onselect, "onselect")
GK_ATOM(onselectionchange, "onselectionchange")
GK_ATOM(onselectstart, "onselectstart")
GK_ATOM(onsending, "onsending")
GK_ATOM(onsent, "onsent")
GK_ATOM(onset, "onset")
+GK_ATOM(onshippingaddresschange, "onshippingaddresschange")
+GK_ATOM(onshippingoptionchange, "onshippingoptionchange")
GK_ATOM(onshow, "onshow")
GK_ATOM(onstatechange, "onstatechange")
GK_ATOM(onstatuschanged, "onstatuschanged")
GK_ATOM(onstkcommand, "onstkcommand")
GK_ATOM(onstksessionend, "onstksessionend")
GK_ATOM(onstorage, "onstorage")
GK_ATOM(onstorageareachanged, "onstorageareachanged")
GK_ATOM(onsubmit, "onsubmit")
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1570,17 +1570,17 @@ nsJSContext::BeginCycleCollectionCallbac
// Create an ICC timer even if ICC is globally disabled, because we could be manually triggering
// an incremental collection, and we want to be sure to finish it.
CallCreateInstance("@mozilla.org/timer;1", &sICCTimer);
if (sICCTimer) {
sICCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sICCTimer->InitWithNamedFuncCallback(ICCTimerFired, nullptr,
kICCIntersliceDelay,
- nsITimer::TYPE_REPEATING_SLACK,
+ nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
"ICCTimerFired");
}
}
static_assert(NS_GC_DELAY > kMaxICCDuration, "A max duration ICC shouldn't reduce GC delay to 0");
//static
void
@@ -1984,17 +1984,17 @@ nsJSContext::PokeGC(JS::gcreason::Reason
sGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sGCTimer->InitWithNamedFuncCallback(GCTimerFired,
reinterpret_cast<void *>(aReason),
aDelay
? aDelay
: (first
? NS_FIRST_GC_DELAY
: NS_GC_DELAY),
- nsITimer::TYPE_ONE_SHOT,
+ nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
"GCTimerFired");
first = false;
}
// static
void
nsJSContext::PokeShrinkingGC()
{
@@ -2007,17 +2007,17 @@ nsJSContext::PokeShrinkingGC()
if (!sShrinkingGCTimer) {
// Failed to create timer (probably because we're in XPCOM shutdown)
return;
}
sShrinkingGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sShrinkingGCTimer->InitWithNamedFuncCallback(ShrinkingGCTimerFired, nullptr,
sCompactOnUserInactiveDelay,
- nsITimer::TYPE_ONE_SHOT,
+ nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
"ShrinkingGCTimerFired");
}
// static
void
nsJSContext::MaybePokeCC()
{
if (sCCTimer || sICCTimer || sShuttingDown || !sHasRunGC) {
@@ -2031,17 +2031,17 @@ nsJSContext::MaybePokeCC()
return;
}
// We can kill some objects before running forgetSkippable.
nsCycleCollector_dispatchDeferredDeletion();
sCCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sCCTimer->InitWithNamedFuncCallback(CCTimerFired, nullptr,
NS_CC_SKIPPABLE_DELAY,
- nsITimer::TYPE_REPEATING_SLACK,
+ nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
"CCTimerFired");
}
}
//static
void
nsJSContext::KillGCTimer()
{
@@ -2183,17 +2183,17 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
if (aDesc.isZone_) {
if (!sFullGCTimer && !sShuttingDown) {
CallCreateInstance("@mozilla.org/timer;1", &sFullGCTimer);
sFullGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sFullGCTimer->InitWithNamedFuncCallback(FullGCTimerFired,
nullptr,
NS_FULL_GC_DELAY,
- nsITimer::TYPE_ONE_SHOT,
+ nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
"FullGCTimerFired");
}
} else {
nsJSContext::KillFullGCTimer();
}
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
nsCycleCollector_dispatchDeferredDeletion();
@@ -2214,17 +2214,17 @@ DOMGCSliceCallback(JSContext* aCx, JS::G
// Schedule another GC slice if the GC has more work to do.
nsJSContext::KillInterSliceGCTimer();
if (!sShuttingDown && !aDesc.isComplete_) {
CallCreateInstance("@mozilla.org/timer;1", &sInterSliceGCTimer);
sInterSliceGCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sInterSliceGCTimer->InitWithNamedFuncCallback(InterSliceGCTimerFired,
nullptr,
NS_INTERSLICE_GC_DELAY,
- nsITimer::TYPE_ONE_SHOT,
+ nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
"InterSliceGCTimerFired");
}
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
nsCycleCollector_dispatchDeferredDeletion();
}
if (sPostGCEventsToConsole) {
@@ -2625,17 +2625,17 @@ nsJSContext::NotifyDidPaint()
}
sICCTimer->Cancel();
ICCTimerFired(nullptr, nullptr);
if (sICCTimer) {
sICCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sICCTimer->InitWithNamedFuncCallback(ICCTimerFired, nullptr,
kICCIntersliceDelay,
- nsITimer::TYPE_REPEATING_SLACK,
+ nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
"ICCTimerFired");
}
} else if (sCCTimer) {
static uint32_t sCount = 0;
static const uint32_t kTicksPerForgetSkippableDelay =
NS_CC_SKIPPABLE_DELAY / 16;
if (++sCount % kTicksPerForgetSkippableDelay != 0) {
// The comment above about triggering CC slice applies to forget skippable
@@ -2644,17 +2644,17 @@ nsJSContext::NotifyDidPaint()
}
sCCTimer->Cancel();
CCTimerFired(nullptr, nullptr);
if (sCCTimer) {
sCCTimer->SetTarget(SystemGroup::EventTargetFor(TaskCategory::GarbageCollection));
sCCTimer->InitWithNamedFuncCallback(CCTimerFired, nullptr,
NS_CC_SKIPPABLE_DELAY,
- nsITimer::TYPE_REPEATING_SLACK,
+ nsITimer::TYPE_REPEATING_SLACK_LOW_PRIORITY,
"CCTimerFired");
}
}
}
nsScriptNameSpaceManager*
mozilla::dom::GetNameSpaceManager()
{
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -402,32 +402,34 @@ CollectWindowReports(nsGlobalWindow *aWi
// There are many different kinds of frames, but it is very likely
// that only a few matter. Implement a cutoff so we don't bloat
// about:memory with many uninteresting entries.
const size_t FRAME_SUNDRIES_THRESHOLD =
js::MemoryReportingSundriesThreshold();
size_t frameSundriesSize = 0;
-#define FRAME_ID(classname) \
+#define FRAME_ID(classname, ...) \
{ \
size_t frameSize \
= windowSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname); \
if (frameSize < FRAME_SUNDRIES_THRESHOLD) { \
frameSundriesSize += frameSize; \
} else { \
REPORT_SIZE("/layout/frames/" # classname, frameSize, \
"Memory used by frames of " \
"type " #classname " within a window."); \
} \
aWindowTotalSizes->mArenaStats.FRAME_ID_STAT_FIELD(classname) \
+= frameSize; \
}
+#define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
if (frameSundriesSize > 0) {
REPORT_SIZE("/layout/frames/sundries", frameSundriesSize,
"The sum of all memory used by frames which were too small "
"to be shown individually.");
}
#undef REPORT_SIZE
@@ -559,20 +561,22 @@ nsWindowMemoryReporter::CollectReports(n
REPORT("window-objects/layout/text-runs", windowTotalSizes.mLayoutTextRunsSize,
"This is the sum of all windows' 'layout/text-runs' numbers.");
REPORT("window-objects/layout/pres-contexts", windowTotalSizes.mLayoutPresContextSize,
"This is the sum of all windows' 'layout/pres-contexts' numbers.");
size_t frameTotal = 0;
-#define FRAME_ID(classname) \
+#define FRAME_ID(classname, ...) \
frameTotal += windowTotalSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname);
+#define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
REPORT("window-objects/layout/frames", frameTotal,
"Memory used for layout frames within windows. "
"This is the sum of all windows' 'layout/frames/' numbers.");
#undef REPORT
return NS_OK;
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -28,16 +28,17 @@ MSG_DEF(MSG_NOT_OBJECT, 1, JSEXN_TYPEERR
MSG_DEF(MSG_NOT_CALLABLE, 1, JSEXN_TYPEERR, "{0} is not callable.")
MSG_DEF(MSG_NOT_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} is not a constructor.")
MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 2, JSEXN_TYPEERR, "{0} does not implement interface {1}.")
MSG_DEF(MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 2, JSEXN_TYPEERR, "'{0}' called on an object that does not implement interface {1}.")
MSG_DEF(MSG_METHOD_THIS_UNWRAPPING_DENIED, 1, JSEXN_TYPEERR, "Permission to call '{0}' denied.")
MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, JSEXN_TYPEERR, "\"this\" object does not implement interface {0}.")
MSG_DEF(MSG_NOT_IN_UNION, 2, JSEXN_TYPEERR, "{0} could not be converted to any of: {1}.")
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Illegal constructor.")
+MSG_DEF(MSG_ILLEGAL_PR_CONSTRUCTOR, 1, JSEXN_TYPEERR, "TypeError:{0}")
MSG_DEF(MSG_CONSTRUCTOR_WITHOUT_NEW, 1, JSEXN_TYPEERR, "Constructor {0} requires 'new'")
MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, JSEXN_TYPEERR, "Non-finite value is out of range for {0}.")
MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "Value is out of range for {0}.")
MSG_DEF(MSG_NOT_SEQUENCE, 1, JSEXN_TYPEERR, "{0} can't be converted to a sequence.")
MSG_DEF(MSG_NOT_DICTIONARY, 1, JSEXN_TYPEERR, "{0} can't be converted to a dictionary.")
MSG_DEF(MSG_OVERLOAD_RESOLUTION_FAILED, 3, JSEXN_TYPEERR, "Argument {0} is not valid for any of the {1}-argument overloads of {2}.")
MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, JSEXN_TYPEERR, "Global is not a native object.")
MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, JSEXN_RANGEERR, "The given encoding '{0}' is not supported.")
--- a/dom/browser-element/mochitest/browserElementTestHelpers.js
+++ b/dom/browser-element/mochitest/browserElementTestHelpers.js
@@ -45,18 +45,16 @@ const browserElementTestHelpers = {
if (this._testReadyLockCount == 0 && !this._firedTestReady) {
this._firedTestReady = true;
dispatchEvent(new Event("testready"));
}
},
enableProcessPriorityManager: function() {
this._setPrefs(
- ['dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels', 2],
- ['dom.ipc.processPriorityManager.BACKGROUND_PERCEIVABLE.LRUPoolLevels', 2],
['dom.ipc.processPriorityManager.testMode', true],
['dom.ipc.processPriorityManager.enabled', true]
);
},
setClipboardPlainTextOnlyPref: function(value) {
this._setPref('clipboard.plainTextOnly', value);
},
@@ -192,56 +190,16 @@ function expectPriorityChange(childID, e
} else {
reject();
}
}
);
});
}
-// Returns a promise which is resolved or rejected the next time the
-// process childID changes its priority. We resolve if the expectedPriority
-// matches the priority and the LRU parameter matches expectedLRU and we
-// reject otherwise.
-
-function expectPriorityWithLRUSet(childID, expectedPriority, expectedLRU) {
- return new Promise(function(resolve, reject) {
- var observed = false;
- browserElementTestHelpers.addProcessPriorityObserver(
- 'process-priority-with-LRU-set',
- function(subject, topic, data) {
- if (observed) {
- return;
- }
-
- var [id, priority, lru] = data.split(":");
- if (id != childID) {
- return;
- }
-
- // Make sure we run the is() calls in this observer only once,
- // otherwise we'll expect /every/ priority/LRU change to match
- // expectedPriority/expectedLRU.
- observed = true;
-
- is(lru, expectedLRU,
- 'Expected LRU ' + lru +
- ' of childID ' + childID +
- ' to change to ' + expectedLRU);
-
- if ((priority == expectedPriority) && (lru == expectedLRU)) {
- resolve();
- } else {
- reject();
- }
- }
- );
- });
-}
-
// Returns a promise which is resolved the first time the given iframe fires
// the mozbrowser##eventName event.
function expectMozbrowserEvent(iframe, eventName) {
return new Promise(function(resolve, reject) {
iframe.addEventListener('mozbrowser' + eventName, function handler(e) {
iframe.removeEventListener('mozbrowser' + eventName, handler);
resolve(e);
});
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/moz.build
@@ -0,0 +1,13 @@
+# -*- Mode: python; 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/.
+
+XPIDL_SOURCES += [
+ 'nsIPaymentActionRequest.idl',
+ 'nsIPaymentRequest.idl',
+ 'nsIPaymentRequestService.idl',
+]
+
+XPIDL_MODULE = 'dom_payments'
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/nsIPaymentActionRequest.idl
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+#include "nsIPaymentRequest.idl"
+
+interface nsIArray;
+
+[builtinclass, uuid(7ddbe8be-beac-4952-96f6-619981dff7a6)]
+interface nsIPaymentActionRequest : nsISupports
+{
+ const uint32_t CREATE_ACTION = 1;
+ /*
+ * The payment request identifier.
+ */
+ readonly attribute AString requestId;
+
+ /*
+ * The type of the requested task.
+ */
+ readonly attribute uint32_t type;
+
+ /*
+ * Initialize function for this request.
+ */
+ void init(in AString aRequestId,
+ in uint32_t aType);
+};
+
+[builtinclass, uuid(1d38dce6-8bcd-441b-aa94-68e300b6e175)]
+interface nsIPaymentCreateActionRequest : nsIPaymentActionRequest
+{
+ /*
+ * The tab identifier
+ */
+ readonly attribute uint64_t tabId;
+
+ /*
+ * The methodData information of the payment request.
+ */
+ readonly attribute nsIArray methodData;
+
+ /*
+ * The Details information of the payment request.
+ */
+ readonly attribute nsIPaymentDetails details;
+
+ /*
+ * The Options information of the payment request.
+ */
+ readonly attribute nsIPaymentOptions options;
+
+ /*
+ * Initialize function the this request.
+ */
+ void initRequest(in AString aRequestId,
+ in uint64_t aTabId,
+ in nsIArray aMethodData,
+ in nsIPaymentDetails aDetails,
+ in nsIPaymentOptions aOptions);
+};
+
+%{C++
+#define NS_PAYMENT_ACTION_REQUEST_CID \
+ { 0x7ddbe8be, 0xbeac, 0x4952, { 0x96, 0xf6, 0x61, 0x99, 0x81, 0xdf, 0xf7, 0xa6 } }
+#define NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID \
+ "@mozilla.org/dom/payments/payment-action-request;1"
+
+#define NS_PAYMENT_CREATE_ACTION_REQUEST_CID \
+ { 0x1d38dce6, 0x8bcd, 0x441b, { 0xaa, 0x94, 0x68, 0xe3, 0x00, 0xb6, 0xe1, 0x75 } }
+#define NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID \
+ "@mozilla.org/dom/payments/payment-create-action-request;1"
+%}
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/nsIPaymentRequest.idl
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+
+interface nsIArray;
+
+[scriptable, builtinclass, uuid(2fe296cc-d917-4820-b492-aa42df23f9b4)]
+interface nsIPaymentMethodData : nsISupports
+{
+ readonly attribute nsIArray supportedMethods;
+ readonly attribute AString data;
+};
+
+[scriptable, builtinclass, uuid(d22a6f5f-767b-4fea-bf92-68b0b8003eba)]
+interface nsIPaymentCurrencyAmount : nsISupports
+{
+ readonly attribute AString currency;
+ readonly attribute AString value;
+};
+
+[scriptable, builtinclass, uuid(4f78a59f-b5ff-4fb5-ab48-3b37d0101b02)]
+interface nsIPaymentItem : nsISupports
+{
+ readonly attribute AString label;
+ readonly attribute nsIPaymentCurrencyAmount amount;
+ readonly attribute boolean pending;
+};
+
+[scriptable, builtinclass, uuid(74259861-c318-40e8-b3d5-518e701bed80)]
+interface nsIPaymentDetailsModifier : nsISupports
+{
+ readonly attribute nsIArray supportedMethods;
+ readonly attribute nsIPaymentItem total;
+ readonly attribute nsIArray additionalDisplayItems;
+ readonly attribute AString data;
+};
+
+[scriptable, builtinclass, uuid(68341551-3605-4381-b936-41e830aa88fb)]
+interface nsIPaymentShippingOption : nsISupports
+{
+ readonly attribute AString id;
+ readonly attribute AString label;
+ readonly attribute nsIPaymentCurrencyAmount amount;
+ attribute boolean selected;
+};
+
+[scriptable, builtinclass, uuid(73a5a3f1-45b9-4605-a6e6-7aa60daa9039)]
+interface nsIPaymentDetails : nsISupports
+{
+ readonly attribute AString id;
+ readonly attribute nsIPaymentItem totalItem;
+ readonly attribute nsIArray displayItems;
+ readonly attribute nsIArray shippingOptions;
+ readonly attribute nsIArray modifiers;
+ readonly attribute AString error;
+
+ void update(in nsIPaymentDetails aDetails);
+};
+
+[scriptable, builtinclass, uuid(d53f9f20-138e-47cc-9fd5-db16a3f6d301)]
+interface nsIPaymentOptions : nsISupports
+{
+ readonly attribute boolean requestPayerName;
+ readonly attribute boolean requestPayerEmail;
+ readonly attribute boolean requestPayerPhone;
+ readonly attribute boolean requestShipping;
+ readonly attribute AString shippingType;
+};
+
+[scriptable, builtinclass, uuid(2fa36783-d684-4487-b7a8-9def6ae3128f)]
+interface nsIPaymentRequest : nsISupports
+{
+ readonly attribute uint64_t tabId;
+ readonly attribute AString requestId;
+ readonly attribute nsIArray paymentMethods;
+ readonly attribute nsIPaymentDetails paymentDetails;
+ readonly attribute nsIPaymentOptions paymentOptions;
+
+ void updatePaymentDetails(in nsIPaymentDetails aDetails);
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/payments/nsIPaymentRequestService.idl
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+#include "nsIVariant.idl"
+#include "nsIPaymentRequest.idl"
+#include "nsIPaymentActionRequest.idl"
+#include "nsISimpleEnumerator.idl"
+
+/*
+ * nsPaymentRequestService is used to manage the created PaymentRequest in the
+ * chrome process. It is also the IPC agent for payment UI to communicate with
+ * merchant side.
+ */
+[scriptable, builtinclass, uuid(cccd665f-edf3-41fc-ab9b-fc55b37340aa)]
+interface nsIPaymentRequestService : nsISupports
+{
+ nsIPaymentRequest getPaymentRequestById(in AString requestId);
+ nsISimpleEnumerator enumerate();
+
+ /*
+ * This method is only for testing.
+ */
+ void cleanup();
+
+ /*
+ * requestPayment is used to handle the asked action request of the payment
+ * from content process.
+ */
+ void requestPayment(in nsIPaymentActionRequest aRequest);
+};
+
+%{C++
+#define NS_PAYMENT_REQUEST_SERVICE_CID \
+ { 0xcccd665f, 0xedf3, 0x41fc, { 0xab, 0x9b, 0xfc, 0x55, 0xb3, 0x73, 0x40, 0xaa } }
+#define NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID \
+ "@mozilla.org/dom/payments/payment-request-service;1"
+%}
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -14,16 +14,17 @@ include protocol PFilePicker;
include protocol PIndexedDBPermissionRequest;
include protocol PRenderFrame;
include protocol PPluginWidget;
include protocol PRemotePrintJob;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include protocol PFileDescriptorSet;
include protocol PIPCBlobInputStream;
+include protocol PPaymentRequest;
include DOMTypes;
include IPCBlob;
include IPCStream;
include JavaScriptTypes;
include URIParams;
include PPrintingTypes;
include PTabContext;
@@ -110,16 +111,17 @@ nested(upto inside_cpow) sync protocol P
manages PColorPicker;
manages PDocAccessible;
manages PDocumentRenderer;
manages PFilePicker;
manages PIndexedDBPermissionRequest;
manages PRenderFrame;
manages PPluginWidget;
+ manages PPaymentRequest;
both:
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
Principal aPrincipal, ClonedMessageData aData);
/**
* Create a layout frame (encapsulating a remote layer tree) for
* the page that is currently loaded in the <browser>.
@@ -140,16 +142,18 @@ parent:
/*
* Creates a new remoted nsIWidget connection for windowed plugins
* in e10s mode. This is always initiated from the child in response
* to windowed plugin creation.
*/
sync PPluginWidget();
+ async PPaymentRequest();
+
/**
* Return native data of root widget
*/
nested(inside_cpow) sync GetWidgetNativeData() returns (WindowsHandle value);
/**
* Sends an NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW to be adopted by the
* widget's shareable window on the chrome side. Only used on Windows.
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -87,50 +87,16 @@ using namespace mozilla::hal;
NameWithComma().get(), \
static_cast<uint64_t>(ChildID()), Pid(), ##__VA_ARGS__))
#endif
namespace {
class ParticularProcessPriorityManager;
-class ProcessLRUPool final
-{
-public:
- /**
- * Creates a new process LRU pool for the specified priority.
- */
- explicit ProcessLRUPool(ProcessPriority aPriority);
-
- /**
- * Used to remove a particular process priority manager from the LRU pool
- * when the associated ContentParent is destroyed or its priority changes.
- */
- void Remove(ParticularProcessPriorityManager* aParticularManager);
-
- /**
- * Used to add a particular process priority manager into the LRU pool when
- * the associated ContentParent's priority changes.
- */
- void Add(ParticularProcessPriorityManager* aParticularManager);
-
-private:
- ProcessPriority mPriority;
- uint32_t mLRUPoolLevels;
- nsTArray<ParticularProcessPriorityManager*> mLRUPool;
-
- uint32_t CalculateLRULevel(uint32_t aLRUPoolIndex);
-
- void AdjustLRUValues(
- nsTArray<ParticularProcessPriorityManager*>::index_type aStart,
- bool removed);
-
- DISALLOW_EVIL_CONSTRUCTORS(ProcessLRUPool);
-};
-
/**
* This singleton class does the work to implement the process priority manager
* in the main process. This class may not be used in child processes. (You
* can call StaticInit, but it won't do anything, and GetSingleton() will
* return null.)
*
* ProcessPriorityManager::CurrentProcessIsForeground() and
* ProcessPriorityManager::AnyProcessHasHighPriority() which can be called in
@@ -155,18 +121,17 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
/**
* This function implements ProcessPriorityManager::SetProcessPriority.
*/
void SetProcessPriority(ContentParent* aContentParent,
- ProcessPriority aPriority,
- uint32_t aLRU = 0);
+ ProcessPriority aPriority);
/**
* If a magic testing-only pref is set, notify the observer service on the
* given topic with the given data. This is used for testing
*/
void FireTestOnlyObserverNotification(const char* aTopic,
const nsACString& aData = EmptyCString());
@@ -233,22 +198,16 @@ private:
nsDataHashtable<nsUint64HashKey, RefPtr<ParticularProcessPriorityManager> >
mParticularManagers;
/** True if the main process is holding a high-priority wakelock */
bool mHighPriority;
/** Contains the PIDs of child processes holding high-priority wakelocks */
nsTHashtable<nsUint64HashKey> mHighPriorityChildIDs;
-
- /** Contains a pseudo-LRU list of background processes */
- ProcessLRUPool mBackgroundLRUPool;
-
- /** Contains a pseudo-LRU list of background-perceivable processes */
- ProcessLRUPool mBackgroundPerceivableLRUPool;
};
/**
* This singleton class implements the parts of the process priority manager
* that are available from all processes.
*/
class ProcessPriorityManagerChild final
: public nsIObserver
@@ -309,17 +268,16 @@ public:
* The reference returned here is guaranteed to be live until the next call
* to NameWithComma() or until the ParticularProcessPriorityManager is
* destroyed, whichever comes first.
*/
const nsAutoCString& NameWithComma();
bool IsExpectingSystemMessage();
- void OnAudioChannelProcessChanged(nsISupports* aSubject);
void OnRemoteBrowserFrameShown(nsISupports* aSubject);
void OnTabParentDestroyed(nsISupports* aSubject);
void OnFrameloaderVisibleChanged(nsISupports* aSubject);
void OnActivityOpened(const char16_t* aData);
void OnActivityClosed(const char16_t* aData);
ProcessPriority CurrentPriority();
ProcessPriority ComputePriority();
@@ -327,17 +285,17 @@ public:
enum TimeoutPref {
BACKGROUND_PERCEIVABLE_GRACE_PERIOD,
BACKGROUND_GRACE_PERIOD,
};
void ScheduleResetPriority(TimeoutPref aTimeoutPref);
void ResetPriority();
void ResetPriorityNow();
- void SetPriorityNow(ProcessPriority aPriority, uint32_t aLRU = 0);
+ void SetPriorityNow(ProcessPriority aPriority);
void Freeze();
void Unfreeze();
void ShutDown();
private:
static uint32_t sBackgroundPerceivableGracePeriodMS;
static uint32_t sBackgroundGracePeriodMS;
@@ -348,17 +306,16 @@ private:
void FireTestOnlyObserverNotification(
const char* aTopic,
const char* aData = nullptr);
ContentParent* mContentParent;
uint64_t mChildID;
ProcessPriority mPriority;
- uint32_t mLRU;
bool mHoldsCPUWakeLock;
bool mHoldsHighPriorityWakeLock;
bool mIsActivityOpener;
bool mFrozen;
/**
* Used to implement NameWithComma().
*/
@@ -457,19 +414,17 @@ ProcessPriorityManagerImpl::GetSingleton
if (!sSingleton) {
StaticInit();
}
return sSingleton;
}
ProcessPriorityManagerImpl::ProcessPriorityManagerImpl()
- : mHighPriority(false)
- , mBackgroundLRUPool(PROCESS_PRIORITY_BACKGROUND)
- , mBackgroundPerceivableLRUPool(PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE)
+ : mHighPriority(false)
{
MOZ_ASSERT(XRE_IsParentProcess());
RegisterWakeLockObserver(this);
}
ProcessPriorityManagerImpl::~ProcessPriorityManagerImpl()
{
ShutDown();
@@ -535,24 +490,23 @@ ProcessPriorityManagerImpl::GetParticula
nsPrintfCString("%" PRIu64, cpId));
}
return pppm.forget();
}
void
ProcessPriorityManagerImpl::SetProcessPriority(ContentParent* aContentParent,
- ProcessPriority aPriority,
- uint32_t aLRU)
+ ProcessPriority aPriority)
{
MOZ_ASSERT(aContentParent);
RefPtr<ParticularProcessPriorityManager> pppm =
GetParticularProcessPriorityManager(aContentParent);
if (pppm) {
- pppm->SetPriorityNow(aPriority, aLRU);
+ pppm->SetPriorityNow(aPriority);
}
}
void
ProcessPriorityManagerImpl::ObserveContentParentCreated(
nsISupports* aContentParent)
{
// Do nothing; it's sufficient to get the PPPM. But assign to nsRefPtr so we
@@ -570,20 +524,16 @@ ProcessPriorityManagerImpl::ObserveConte
uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
NS_ENSURE_TRUE_VOID(childID != CONTENT_PROCESS_ID_UNKNOWN);
RefPtr<ParticularProcessPriorityManager> pppm;
mParticularManagers.Get(childID, &pppm);
if (pppm) {
- // Unconditionally remove the manager from the pools
- mBackgroundLRUPool.Remove(pppm);
- mBackgroundPerceivableLRUPool.Remove(pppm);
-
pppm->ShutDown();
mParticularManagers.Remove(childID);
mHighPriorityChildIDs.RemoveEntry(childID);
}
}
@@ -611,32 +561,16 @@ ProcessPriorityManagerImpl::ChildProcess
void
ProcessPriorityManagerImpl::NotifyProcessPriorityChanged(
ParticularProcessPriorityManager* aParticularManager,
ProcessPriority aOldPriority)
{
ProcessPriority newPriority = aParticularManager->CurrentPriority();
- if (newPriority == PROCESS_PRIORITY_BACKGROUND &&
- aOldPriority != PROCESS_PRIORITY_BACKGROUND) {
- mBackgroundLRUPool.Add(aParticularManager);
- } else if (newPriority != PROCESS_PRIORITY_BACKGROUND &&
- aOldPriority == PROCESS_PRIORITY_BACKGROUND) {
- mBackgroundLRUPool.Remove(aParticularManager);
- }
-
- if (newPriority == PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE &&
- aOldPriority != PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE) {
- mBackgroundPerceivableLRUPool.Add(aParticularManager);
- } else if (newPriority != PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE &&
- aOldPriority == PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE) {
- mBackgroundPerceivableLRUPool.Remove(aParticularManager);
- }
-
if (newPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH &&
aOldPriority < PROCESS_PRIORITY_FOREGROUND_HIGH) {
mHighPriorityChildIDs.PutEntry(aParticularManager->ChildID());
} else if (newPriority < PROCESS_PRIORITY_FOREGROUND_HIGH &&
aOldPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) {
mHighPriorityChildIDs.RemoveEntry(aParticularManager->ChildID());
}
}
@@ -664,17 +598,16 @@ NS_IMPL_ISUPPORTS(ParticularProcessPrior
nsITimerCallback,
nsISupportsWeakReference);
ParticularProcessPriorityManager::ParticularProcessPriorityManager(
ContentParent* aContentParent, bool aFrozen)
: mContentParent(aContentParent)
, mChildID(aContentParent->ChildID())
, mPriority(PROCESS_PRIORITY_UNKNOWN)
- , mLRU(0)
, mHoldsCPUWakeLock(false)
, mHoldsHighPriorityWakeLock(false)
, mIsActivityOpener(false)
, mFrozen(aFrozen)
{
MOZ_ASSERT(XRE_IsParentProcess());
LOGP("Creating ParticularProcessPriorityManager.");
}
@@ -690,17 +623,16 @@ ParticularProcessPriorityManager::Static
void
ParticularProcessPriorityManager::Init()
{
RegisterWakeLockObserver(this);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
- os->AddObserver(this, "audio-channel-process-changed", /* ownsWeak */ true);
os->AddObserver(this, "remote-browser-shown", /* ownsWeak */ true);
os->AddObserver(this, "ipc:browser-destroyed", /* ownsWeak */ true);
os->AddObserver(this, "frameloader-visible-changed", /* ownsWeak */ true);
os->AddObserver(this, "activity-opened", /* ownsWeak */ true);
os->AddObserver(this, "activity-closed", /* ownsWeak */ true);
}
// This process may already hold the CPU lock; for example, our parent may
@@ -763,19 +695,17 @@ ParticularProcessPriorityManager::Observ
{
if (!mContentParent) {
// We've been shut down.
return NS_OK;
}
nsDependentCString topic(aTopic);
- if (topic.EqualsLiteral("audio-channel-process-changed")) {
- OnAudioChannelProcessChanged(aSubject);
- } else if (topic.EqualsLiteral("remote-browser-shown")) {
+ if (topic.EqualsLiteral("remote-browser-shown")) {
OnRemoteBrowserFrameShown(aSubject);
} else if (topic.EqualsLiteral("ipc:browser-destroyed")) {
OnTabParentDestroyed(aSubject);
} else if (topic.EqualsLiteral("frameloader-visible-changed")) {
OnFrameloaderVisibleChanged(aSubject);
} else if (topic.EqualsLiteral("activity-opened")) {
OnActivityOpened(aData);
} else if (topic.EqualsLiteral("activity-closed")) {
@@ -818,29 +748,16 @@ ParticularProcessPriorityManager::NameWi
}
mNameWithComma = NS_ConvertUTF16toUTF8(name);
mNameWithComma.AppendLiteral(", ");
return mNameWithComma;
}
void
-ParticularProcessPriorityManager::OnAudioChannelProcessChanged(nsISupports* aSubject)
-{
- nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
- NS_ENSURE_TRUE_VOID(props);
-
- uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
- props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
- if (childID == ChildID()) {
- ResetPriority();
- }
-}
-
-void
ParticularProcessPriorityManager::OnRemoteBrowserFrameShown(nsISupports* aSubject)
{
nsCOMPtr<nsIFrameLoader> fl = do_QueryInterface(aSubject);
NS_ENSURE_TRUE_VOID(fl);
TabParent* tp = TabParent::GetFrom(fl);
NS_ENSURE_TRUE_VOID(tp);
@@ -1043,40 +960,32 @@ ParticularProcessPriorityManager::Comput
return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE;
}
return mIsActivityOpener ? PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE
: PROCESS_PRIORITY_BACKGROUND;
}
void
-ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority,
- uint32_t aLRU)
+ParticularProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority)
{
if (aPriority == PROCESS_PRIORITY_UNKNOWN) {
MOZ_ASSERT(false);
return;
}
if (!ProcessPriorityManagerImpl::PrefsEnabled() ||
!mContentParent ||
mFrozen ||
- ((mPriority == aPriority) && (mLRU == aLRU))) {
+ mPriority == aPriority) {
return;
}
- if ((mPriority == aPriority) && (mLRU != aLRU)) {
- mLRU = aLRU;
- hal::SetProcessPriority(Pid(), mPriority, aLRU);
-
- nsPrintfCString processPriorityWithLRU("%s:%d",
- ProcessPriorityToString(mPriority), aLRU);
-
- FireTestOnlyObserverNotification("process-priority-with-LRU-set",
- processPriorityWithLRU.get());
+ if (mPriority == aPriority) {
+ hal::SetProcessPriority(Pid(), mPriority);
return;
}
LOGP("Changing priority from %s to %s.",
ProcessPriorityToString(mPriority),
ProcessPriorityToString(aPriority));
ProcessPriority oldPriority = mPriority;
@@ -1254,122 +1163,16 @@ ProcessPriorityManagerChild::CurrentProc
bool
ProcessPriorityManagerChild::CurrentProcessIsHighPriority()
{
return mCachedPriority == PROCESS_PRIORITY_UNKNOWN ||
mCachedPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH;
}
-ProcessLRUPool::ProcessLRUPool(ProcessPriority aPriority)
- : mPriority(aPriority)
- , mLRUPoolLevels(1)
-{
- // We set mLRUPoolLevels according to our pref.
- // This value is used to set background process LRU pool
- const char* str = ProcessPriorityToString(aPriority);
- nsPrintfCString pref("dom.ipc.processPriorityManager.%s.LRUPoolLevels", str);
-
- Preferences::GetUint(pref.get(), &mLRUPoolLevels);
-
- // GonkHal defines OOM_ADJUST_MAX is 15 and b2g.js defines
- // PROCESS_PRIORITY_BACKGROUND's oom_score_adj is 667 and oom_adj is 10.
- // This means we can only have at most (15 -10 + 1) = 6 background LRU levels.
- // Similarly we can have at most 4 background perceivable LRU levels. We
- // should really be getting rid of oom_adj and just rely on oom_score_adj
- // only which would lift this constraint.
- MOZ_ASSERT(aPriority != PROCESS_PRIORITY_BACKGROUND || mLRUPoolLevels <= 6);
- MOZ_ASSERT(aPriority != PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE ||
- mLRUPoolLevels <= 4);
-
- // LRU pool size = 2 ^ (number of background LRU pool levels) - 1
- uint32_t LRUPoolSize = (1 << mLRUPoolLevels) - 1;
-
- LOG("Making %s LRU pool with size(%d)", str, LRUPoolSize);
-}
-
-uint32_t
-ProcessLRUPool::CalculateLRULevel(uint32_t aLRU)
-{
- // This is used to compute the LRU adjustment for the specified LRU position.
- // We use power-of-two groups with increasing adjustments that look like the
- // following:
-
- // Priority : LRU0, LRU1
- // Priority+1: LRU2, LRU3
- // Priority+2: LRU4, LRU5, LRU6, LRU7
- // Priority+3: LRU8, LRU9, LRU10, LRU11, LRU12, LRU12, LRU13, LRU14, LRU15
- // ...
- // Priority+L-1: 2^(number of LRU pool levels - 1)
- // (End of buffer)
-
- int exp;
- Unused << frexp(static_cast<double>(aLRU), &exp);
- uint32_t level = std::max(exp - 1, 0);
-
- return std::min(mLRUPoolLevels - 1, level);
-}
-
-void
-ProcessLRUPool::Remove(ParticularProcessPriorityManager* aParticularManager)
-{
- nsTArray<ParticularProcessPriorityManager*>::index_type index =
- mLRUPool.IndexOf(aParticularManager);
-
- if (index == nsTArray<ParticularProcessPriorityManager*>::NoIndex) {
- return;
- }
-
- mLRUPool.RemoveElementAt(index);
- AdjustLRUValues(index, /* removed */ true);
-
- LOG("Remove ChildID(%" PRIu64 ") from %s LRU pool",
- static_cast<uint64_t>(aParticularManager->ChildID()),
- ProcessPriorityToString(mPriority));
-}
-
-/*
- * Adjust the LRU values of all the processes in an LRU pool. When true the
- * `removed` parameter indicates that the processes were shifted left because
- * an element was removed; otherwise it means the elements were shifted right
- * as an element was added.
- */
-void
-ProcessLRUPool::AdjustLRUValues(
- nsTArray<ParticularProcessPriorityManager*>::index_type aStart,
- bool removed)
-{
- uint32_t adj = (removed ? 2 : 1);
-
- for (nsTArray<ParticularProcessPriorityManager*>::index_type i = aStart;
- i < mLRUPool.Length();
- i++) {
- /* Check whether i is a power of two. If so, then it crossed a LRU group
- * boundary and we need to assign its new process priority LRU. Note that
- * depending on the direction and the bias this test will pick different
- * elements. */
- if (((i + adj) & (i + adj - 1)) == 0) {
- mLRUPool[i]->SetPriorityNow(mPriority, CalculateLRULevel(i + 1));
- }
- }
-}
-
-void
-ProcessLRUPool::Add(ParticularProcessPriorityManager* aParticularManager)
-{
- // Shift the list in the pool, so we have room at index 0 for the newly added
- // manager
- mLRUPool.InsertElementAt(0, aParticularManager);
- AdjustLRUValues(1, /* removed */ false);
-
- LOG("Add ChildID(%" PRIu64 ") into %s LRU pool",
- static_cast<uint64_t>(aParticularManager->ChildID()),
- ProcessPriorityToString(mPriority));
-}
-
} // namespace
namespace mozilla {
/* static */ void
ProcessPriorityManager::Init()
{
ProcessPriorityManagerImpl::StaticInit();
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -15,16 +15,17 @@
#include "Layers.h"
#include "ContentChild.h"
#include "TabParent.h"
#include "mozilla/Preferences.h"
#include "mozilla/BrowserElementParent.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/dom/indexedDB/PIndexedDBPermissionRequestChild.h"
+#include "mozilla/dom/PaymentRequestChild.h"
#include "mozilla/dom/TelemetryScrollProbe.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/ipc/DocumentRendererChild.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZCTreeManagerChild.h"
@@ -3203,16 +3204,29 @@ TabChild::CreatePluginWidget(nsIWidget*
if (NS_FAILED(rv)) {
NS_WARNING("Creating native plugin widget on the chrome side failed.");
}
pluginWidget.forget(aOut);
return rv;
}
#endif // XP_WIN
+PPaymentRequestChild*
+TabChild::AllocPPaymentRequestChild()
+{
+ MOZ_CRASH("We should never be manually allocating PPaymentRequestChild actors");
+ return nullptr;
+}
+
+bool
+TabChild::DeallocPPaymentRequestChild(PPaymentRequestChild* actor)
+{
+ return true;
+}
+
ScreenIntSize
TabChild::GetInnerSize()
{
LayoutDeviceIntSize innerSize =
RoundedToInt(mUnscaledInnerSize * mPuppetWidget->GetDefaultScale());
return ViewAs<ScreenPixel>(innerSize, PixelCastJustification::LayoutDeviceIsScreenForTabDims);
};
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -615,16 +615,22 @@ public:
PPluginWidgetChild* AllocPPluginWidgetChild() override;
bool DeallocPPluginWidgetChild(PPluginWidgetChild* aActor) override;
#ifdef XP_WIN
nsresult CreatePluginWidget(nsIWidget* aParent, nsIWidget** aOut);
#endif
+ virtual PPaymentRequestChild*
+ AllocPPaymentRequestChild() override;
+
+ virtual bool
+ DeallocPPaymentRequestChild(PPaymentRequestChild* aActor) override;
+
LayoutDeviceIntPoint GetClientOffset() const { return mClientOffset; }
LayoutDeviceIntPoint GetChromeDisplacement() const { return mChromeDisp; };
bool IPCOpen() const { return mIPCOpen; }
bool ParentIsActive() const
{
return mParentIsActive;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -14,16 +14,17 @@
#endif
#include "mozilla/BrowserElementParent.h"
#include "mozilla/dom/ContentBridgeParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/DataTransfer.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/indexedDB/ActorsParent.h"
#include "mozilla/dom/IPCBlobUtils.h"
+#include "mozilla/dom/PaymentRequestParent.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/Hal.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
@@ -2854,16 +2855,31 @@ TabParent::AllocPPluginWidgetParent()
bool
TabParent::DeallocPPluginWidgetParent(mozilla::plugins::PPluginWidgetParent* aActor)
{
delete aActor;
return true;
}
+PPaymentRequestParent*
+TabParent::AllocPPaymentRequestParent()
+{
+ RefPtr<PaymentRequestParent> actor = new PaymentRequestParent(GetTabId());
+ return actor.forget().take();
+}
+
+bool
+TabParent::DeallocPPaymentRequestParent(PPaymentRequestParent* aActor)
+{
+ RefPtr<PaymentRequestParent> actor =
+ dont_AddRef(static_cast<PaymentRequestParent*>(aActor));
+ return true;
+}
+
nsresult
TabParent::HandleEvent(nsIDOMEvent* aEvent)
{
nsAutoString eventType;
aEvent->GetType(eventType);
if (eventType.EqualsLiteral("MozUpdateWindowPos") && !mIsDestroyed) {
// This event is sent when the widget moved. Therefore we only update
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -548,16 +548,22 @@ public:
/**
* Native widget remoting protocol for use with windowed plugins with e10s.
*/
virtual PPluginWidgetParent* AllocPPluginWidgetParent() override;
virtual bool
DeallocPPluginWidgetParent(PPluginWidgetParent* aActor) override;
+ virtual PPaymentRequestParent*
+ AllocPPaymentRequestParent() override;
+
+ virtual bool
+ DeallocPPaymentRequestParent(PPaymentRequestParent* aActor) override;
+
void SetInitedByParent() { mInitedByParent = true; }
bool IsInitedByParent() const { return mInitedByParent; }
bool SendLoadRemoteScript(const nsString& aURL,
const bool& aRunInGlobalScope);
void LayerTreeUpdate(uint64_t aEpoch, bool aActive);
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -31,16 +31,17 @@ interfaces = [
'storage',
'json',
'offline',
'geolocation',
'notification',
'svg',
'smil',
'push',
+ 'payments',
]
DIRS += ['interfaces/' + i for i in interfaces]
DIRS += [
'animation',
'base',
'bindings',
@@ -100,16 +101,17 @@ DIRS += [
'vr',
'u2f',
'console',
'performance',
'webbrowserpersist',
'xhr',
'worklet',
'script',
+ 'payments',
]
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += ['plugins/ipc/hangui']
if CONFIG['MOZ_SECUREELEMENT']:
DIRS += ['secureelement']
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentActionRequest.cpp
@@ -0,0 +1,110 @@
+/* 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 "nsArrayUtils.h"
+#include "nsIMutableArray.h"
+#include "PaymentActionRequest.h"
+#include "PaymentRequestData.h"
+
+using namespace mozilla::dom::payments;
+
+namespace mozilla {
+namespace dom {
+
+/* PaymentActionRequest */
+
+NS_IMPL_ISUPPORTS(PaymentActionRequest,
+ nsIPaymentActionRequest)
+
+NS_IMETHODIMP
+PaymentActionRequest::Init(const nsAString& aRequestId,
+ const uint32_t aType)
+{
+ mRequestId = aRequestId;
+ mType = aType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentActionRequest::GetRequestId(nsAString& aRequestId)
+{
+ aRequestId = mRequestId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentActionRequest::GetType(uint32_t* aType)
+{
+ *aType = mType;
+ return NS_OK;
+}
+
+/* PaymentCreateActionRequest */
+
+NS_IMPL_ISUPPORTS_INHERITED(PaymentCreateActionRequest,
+ PaymentActionRequest,
+ nsIPaymentCreateActionRequest)
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::InitRequest(const nsAString& aRequestId,
+ const uint64_t aTabId,
+ nsIArray* aMethodData,
+ nsIPaymentDetails* aDetails,
+ nsIPaymentOptions* aOptions)
+{
+ NS_ENSURE_ARG_POINTER(aMethodData);
+ NS_ENSURE_ARG_POINTER(aDetails);
+ NS_ENSURE_ARG_POINTER(aOptions);
+ Init(aRequestId, nsIPaymentActionRequest::CREATE_ACTION);
+ mTabId = aTabId;
+ mMethodData = aMethodData;
+ mDetails = aDetails;
+ mOptions = aOptions;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetTabId(uint64_t* aTabId)
+{
+ NS_ENSURE_ARG_POINTER(aTabId);
+ *aTabId = mTabId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetMethodData(nsIArray** aMethodData)
+{
+ NS_ENSURE_ARG_POINTER(aMethodData);
+ *aMethodData = nullptr;
+ MOZ_ASSERT(mMethodData);
+ nsCOMPtr<nsIArray> methodData = mMethodData;
+ methodData.forget(aMethodData);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetDetails(nsIPaymentDetails** aDetails)
+{
+ NS_ENSURE_ARG_POINTER(aDetails);
+ *aDetails = nullptr;
+ MOZ_ASSERT(mDetails);
+ nsCOMPtr<nsIPaymentDetails> details = mDetails;
+ details.forget(aDetails);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCreateActionRequest::GetOptions(nsIPaymentOptions** aOptions)
+{
+ NS_ENSURE_ARG_POINTER(aOptions);
+ *aOptions = nullptr;
+ MOZ_ASSERT(mOptions);
+ nsCOMPtr<nsIPaymentOptions> options = mOptions;
+ options.forget(aOptions);
+ return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentActionRequest.h
@@ -0,0 +1,56 @@
+/* -*- 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_PaymentActionRequest_h
+#define mozilla_dom_PaymentActionRequest_h
+
+#include "nsIPaymentActionRequest.h"
+#include "nsCOMPtr.h"
+#include "nsCOMArray.h"
+#include "nsIArray.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentActionRequest : public nsIPaymentActionRequest
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTACTIONREQUEST
+
+ PaymentActionRequest() = default;
+
+protected:
+ virtual ~PaymentActionRequest() = default;
+
+ nsString mRequestId;
+ uint32_t mType;
+};
+
+class PaymentCreateActionRequest final : public nsIPaymentCreateActionRequest
+ , public PaymentActionRequest
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_FORWARD_NSIPAYMENTACTIONREQUEST(PaymentActionRequest::)
+ NS_DECL_NSIPAYMENTCREATEACTIONREQUEST
+
+ PaymentCreateActionRequest() = default;
+
+private:
+ ~PaymentCreateActionRequest() = default;
+
+ uint64_t mTabId;
+ nsCOMPtr<nsIArray> mMethodData;
+ nsCOMPtr<nsIPaymentDetails> mDetails;
+ nsCOMPtr<nsIPaymentOptions> mOptions;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequest.cpp
@@ -0,0 +1,281 @@
+/* -*- 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/dom/PaymentRequest.h"
+#include "nsContentUtils.h"
+#include "PaymentRequestManager.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(PaymentRequest)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PaymentRequest,
+ DOMEventTargetHelper)
+ // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
+ // DOMEventTargetHelper does it for us.
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PaymentRequest,
+ DOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PaymentRequest,
+ DOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PaymentRequest)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(PaymentRequest, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(PaymentRequest, DOMEventTargetHelper)
+
+bool
+PaymentRequest::PrefEnabled(JSContext* aCx, JSObject* aObj)
+{
+ return Preferences::GetBool("dom.payments.request.enabled");
+}
+
+bool
+PaymentRequest::IsValidNumber(const nsAString& aItem,
+ const nsAString& aStr,
+ nsAString& aErrorMsg)
+{
+ nsAutoString aValue(aStr);
+ nsresult error = NS_OK;
+ aValue.ToFloat(&error);
+ if (NS_FAILED(error)) {
+ aErrorMsg.AssignLiteral("The amount.value of \"");
+ aErrorMsg.Append(aItem);
+ aErrorMsg.AppendLiteral("\"(");
+ aErrorMsg.Append(aValue);
+ aErrorMsg.AppendLiteral(") must be a valid decimal monetary value.");
+ return false;
+ }
+ return true;
+}
+
+bool
+PaymentRequest::IsPositiveNumber(const nsAString& aItem,
+ const nsAString& aStr,
+ nsAString& aErrorMsg)
+{
+ nsAutoString aValue(aStr);
+ nsresult error = NS_OK;
+ float value = aValue.ToFloat(&error);
+ if (NS_FAILED(error) || value < 0) {
+ aErrorMsg.AssignLiteral("The amount.value of \"");
+ aErrorMsg.Append(aItem);
+ aErrorMsg.AppendLiteral("\"(");
+ aErrorMsg.Append(aValue);
+ aErrorMsg.AppendLiteral(") must be a valid and positive decimal monetary value.");
+ return false;
+ }
+ return true;
+}
+
+bool
+PaymentRequest::IsValidDetailsInit(const PaymentDetailsInit& aDetails, nsAString& aErrorMsg)
+{
+ // Check the amount.value of detail.total
+ if (!IsPositiveNumber(NS_LITERAL_STRING("details.total"),
+ aDetails.mTotal.mAmount.mValue, aErrorMsg)) {
+ return false;
+ }
+
+ return IsValidDetailsBase(aDetails, aErrorMsg);
+}
+
+bool
+PaymentRequest::IsValidDetailsBase(const PaymentDetailsBase& aDetails, nsAString& aErrorMsg)
+{
+ // Check the amount.value of each item in the display items
+ if (aDetails.mDisplayItems.WasPassed()) {
+ const Sequence<PaymentItem>& displayItems = aDetails.mDisplayItems.Value();
+ for (const PaymentItem& displayItem : displayItems) {
+ if (!IsValidNumber(displayItem.mLabel,
+ displayItem.mAmount.mValue, aErrorMsg)) {
+ return false;
+ }
+ }
+ }
+
+ // Check the shipping option
+ if (aDetails.mShippingOptions.WasPassed()) {
+ const Sequence<PaymentShippingOption>& shippingOptions = aDetails.mShippingOptions.Value();
+ for (const PaymentShippingOption& shippingOption : shippingOptions) {
+ if (!IsValidNumber(NS_LITERAL_STRING("details.shippingOptions"),
+ shippingOption.mAmount.mValue, aErrorMsg)) {
+ return false;
+ }
+ }
+ }
+
+ // Check payment details modifiers
+ if (aDetails.mModifiers.WasPassed()) {
+ const Sequence<PaymentDetailsModifier>& modifiers = aDetails.mModifiers.Value();
+ for (const PaymentDetailsModifier& modifier : modifiers) {
+ if (!IsPositiveNumber(NS_LITERAL_STRING("details.modifiers.total"),
+ modifier.mTotal.mAmount.mValue, aErrorMsg)) {
+ return false;
+ }
+ if (modifier.mAdditionalDisplayItems.WasPassed()) {
+ const Sequence<PaymentItem>& displayItems = modifier.mAdditionalDisplayItems.Value();
+ for (const PaymentItem& displayItem : displayItems) {
+ if (!IsValidNumber(displayItem.mLabel,
+ displayItem.mAmount.mValue, aErrorMsg)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+already_AddRefed<PaymentRequest>
+PaymentRequest::Constructor(const GlobalObject& aGlobal,
+ const Sequence<PaymentMethodData>& aMethodData,
+ const PaymentDetailsInit& aDetails,
+ const PaymentOptions& aOptions,
+ ErrorResult& aRv)
+{
+ nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
+ if (!window) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
+ // [TODO] Bug 1318988 - Implement `allowPaymentRequest` on iframe
+
+ // Check payment methods is done by webidl
+
+ // Check payment details
+ nsAutoString message;
+ if (!IsValidDetailsInit(aDetails, message)) {
+ aRv.ThrowTypeError<MSG_ILLEGAL_PR_CONSTRUCTOR>(message);
+ return nullptr;
+ }
+
+ RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
+ if (NS_WARN_IF(!manager)) {
+ return nullptr;
+ }
+
+ // Create PaymentRequest and set its |mId|
+ RefPtr<PaymentRequest> request;
+ nsresult rv = manager->CreatePayment(window, aMethodData, aDetails,
+ aOptions, getter_AddRefs(request));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
+
+ return request.forget();
+}
+
+already_AddRefed<PaymentRequest>
+PaymentRequest::CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv)
+{
+ // Generate a unique id for identification
+ nsID uuid;
+ aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
+ if (NS_WARN_IF(NS_FAILED(aRv))) {
+ return nullptr;
+ }
+ char buffer[NSID_LENGTH];
+ uuid.ToProvidedString(buffer);
+ nsAutoString id;
+ CopyASCIItoUTF16(buffer, id);
+
+ RefPtr<PaymentRequest> request = new PaymentRequest(aWindow, id);
+ return request.forget();
+}
+
+PaymentRequest::PaymentRequest(nsPIDOMWindowInner* aWindow, const nsAString& aInternalId)
+ : DOMEventTargetHelper(aWindow)
+ , mInternalId(aInternalId)
+ , mUpdating(false)
+ , mState(eCreated)
+{
+ MOZ_ASSERT(aWindow);
+}
+
+already_AddRefed<Promise>
+PaymentRequest::Show(ErrorResult& aRv)
+{
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+}
+
+already_AddRefed<Promise>
+PaymentRequest::CanMakePayment(ErrorResult& aRv)
+{
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+}
+
+already_AddRefed<Promise>
+PaymentRequest::Abort(ErrorResult& aRv)
+{
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+}
+
+void
+PaymentRequest::GetId(nsAString& aRetVal) const
+{
+ aRetVal = mId;
+}
+
+void
+PaymentRequest::GetInternalId(nsAString& aRetVal)
+{
+ aRetVal = mInternalId;
+}
+
+void
+PaymentRequest::SetId(const nsAString& aId)
+{
+ mId = aId;
+}
+
+bool
+PaymentRequest::Equals(const nsAString& aInternalId) const
+{
+ return mInternalId.Equals(aInternalId);
+}
+
+void
+PaymentRequest::SetUpdating(bool aUpdating)
+{
+ mUpdating = aUpdating;
+}
+
+void
+PaymentRequest::GetShippingOption(nsAString& aRetVal) const
+{
+ aRetVal = mShippingOption;
+}
+
+Nullable<PaymentShippingType>
+PaymentRequest::GetShippingType() const
+{
+ return nullptr;
+}
+
+PaymentRequest::~PaymentRequest()
+{
+}
+
+JSObject*
+PaymentRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return PaymentRequestBinding::Wrap(aCx, this, aGivenProto);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequest.h
@@ -0,0 +1,110 @@
+/* -*- 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_PaymentRequest_h
+#define mozilla_dom_PaymentRequest_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/dom/PaymentRequestBinding.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/ErrorResult.h"
+#include "nsWrapperCache.h"
+
+namespace mozilla {
+namespace dom {
+
+class EventHandlerNonNull;
+class PaymentResponse;
+
+class PaymentRequest final : public DOMEventTargetHelper
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PaymentRequest, DOMEventTargetHelper)
+
+ virtual JSObject* WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override;
+
+ static already_AddRefed<PaymentRequest>
+ CreatePaymentRequest(nsPIDOMWindowInner* aWindow, nsresult& aRv);
+
+ static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
+
+ static bool
+ IsValidNumber(const nsAString& aItem,
+ const nsAString& aStr,
+ nsAString& aErrorMsg);
+ static bool
+ IsPositiveNumber(const nsAString& aItem,
+ const nsAString& aStr,
+ nsAString& aErrorMsg);
+
+ static bool
+ IsValidDetailsInit(const PaymentDetailsInit& aDetails,
+ nsAString& aErrorMsg);
+ static bool
+ IsValidDetailsBase(const PaymentDetailsBase& aDetails,
+ nsAString& aErrorMsg);
+
+ static already_AddRefed<PaymentRequest>
+ Constructor(const GlobalObject& aGlobal,
+ const Sequence<PaymentMethodData>& aMethodData,
+ const PaymentDetailsInit& aDetails,
+ const PaymentOptions& aOptions,
+ ErrorResult& aRv);
+
+ already_AddRefed<Promise> Show(ErrorResult& aRv);
+ already_AddRefed<Promise> Abort(ErrorResult& aRv);
+ already_AddRefed<Promise> CanMakePayment(ErrorResult& aRv);
+
+ void GetId(nsAString& aRetVal) const;
+ void GetInternalId(nsAString& aRetVal);
+ void SetId(const nsAString& aId);
+
+ bool Equals(const nsAString& aInternalId) const;
+
+ void SetUpdating(bool aUpdating);
+
+ void GetShippingOption(nsAString& aRetVal) const;
+
+ Nullable<PaymentShippingType> GetShippingType() const;
+
+ IMPL_EVENT_HANDLER(shippingaddresschange);
+ IMPL_EVENT_HANDLER(shippingoptionchange);
+
+protected:
+ ~PaymentRequest();
+
+ PaymentRequest(nsPIDOMWindowInner* aWindow, const nsAString& aInternalId);
+
+ // Id for internal identification
+ nsString mInternalId;
+ // Id for communicating with merchant side
+ // mId is initialized to details.id if it exists
+ // otherwise, mId has the same value as mInternalId.
+ nsString mId;
+ // It is populated when the user chooses a shipping option.
+ nsString mShippingOption;
+
+ // "true" when there is a pending updateWith() call to update the payment request
+ // and "false" otherwise.
+ bool mUpdating;
+ // The error is set in AbortUpdate(). The value is NS_OK by default.
+ //nsresult mUpdateError;
+
+ enum {
+ eUnknown,
+ eCreated,
+ eInteractive,
+ eClosed
+ } mState;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PaymentRequest_h
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestData.cpp
@@ -0,0 +1,660 @@
+/* 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 "nsArrayUtils.h"
+#include "nsIMutableArray.h"
+#include "nsISupportsPrimitives.h"
+#include "PaymentRequestData.h"
+#include "PaymentRequestUtils.h"
+
+namespace mozilla {
+namespace dom {
+namespace payments {
+
+/* PaymentMethodData */
+
+NS_IMPL_ISUPPORTS(PaymentMethodData,
+ nsIPaymentMethodData)
+
+PaymentMethodData::PaymentMethodData(nsIArray* aSupportedMethods,
+ const nsAString& aData)
+ : mSupportedMethods(aSupportedMethods)
+ , mData(aData)
+{
+}
+
+nsresult
+PaymentMethodData::Create(const IPCPaymentMethodData& aIPCMethodData,
+ nsIPaymentMethodData** aMethodData)
+{
+ NS_ENSURE_ARG_POINTER(aMethodData);
+ nsCOMPtr<nsIArray> supportedMethods;
+ nsresult rv = ConvertStringstoISupportsStrings(aIPCMethodData.supportedMethods(),
+ getter_AddRefs(supportedMethods));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ nsCOMPtr<nsIPaymentMethodData> methodData =
+ new PaymentMethodData(supportedMethods, aIPCMethodData.data());
+ methodData.forget(aMethodData);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentMethodData::GetSupportedMethods(nsIArray** aSupportedMethods)
+{
+ NS_ENSURE_ARG_POINTER(aSupportedMethods);
+ MOZ_ASSERT(mSupportedMethods);
+ nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
+ supportedMethods.forget(aSupportedMethods);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentMethodData::GetData(nsAString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+/* PaymentCurrencyAmount */
+
+NS_IMPL_ISUPPORTS(PaymentCurrencyAmount,
+ nsIPaymentCurrencyAmount)
+
+PaymentCurrencyAmount::PaymentCurrencyAmount(const nsAString& aCurrency,
+ const nsAString& aValue)
+ : mCurrency(aCurrency)
+ , mValue(aValue)
+{
+}
+
+nsresult
+PaymentCurrencyAmount::Create(const IPCPaymentCurrencyAmount& aIPCAmount,
+ nsIPaymentCurrencyAmount** aAmount)
+{
+ NS_ENSURE_ARG_POINTER(aAmount);
+ nsCOMPtr<nsIPaymentCurrencyAmount> amount =
+ new PaymentCurrencyAmount(aIPCAmount.currency(), aIPCAmount.value());
+ amount.forget(aAmount);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCurrencyAmount::GetCurrency(nsAString& aCurrency)
+{
+ aCurrency = mCurrency;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentCurrencyAmount::GetValue(nsAString& aValue)
+{
+ aValue = mValue;
+ return NS_OK;
+}
+
+/* PaymentItem */
+
+NS_IMPL_ISUPPORTS(PaymentItem,
+ nsIPaymentItem)
+
+PaymentItem::PaymentItem(const nsAString& aLabel,
+ nsIPaymentCurrencyAmount* aAmount,
+ const bool aPending)
+ : mLabel(aLabel)
+ , mAmount(aAmount)
+ , mPending(aPending)
+{
+}
+
+nsresult
+PaymentItem::Create(const IPCPaymentItem& aIPCItem, nsIPaymentItem** aItem)
+{
+ NS_ENSURE_ARG_POINTER(aItem);
+ nsCOMPtr<nsIPaymentCurrencyAmount> amount;
+ nsresult rv = PaymentCurrencyAmount::Create(aIPCItem.amount(),
+ getter_AddRefs(amount));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ nsCOMPtr<nsIPaymentItem> item =
+ new PaymentItem(aIPCItem.label(), amount, aIPCItem.pending());
+ item.forget(aItem);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentItem::GetLabel(nsAString& aLabel)
+{
+ aLabel = mLabel;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentItem::GetAmount(nsIPaymentCurrencyAmount** aAmount)
+{
+ NS_ENSURE_ARG_POINTER(aAmount);
+ MOZ_ASSERT(mAmount);
+ nsCOMPtr<nsIPaymentCurrencyAmount> amount = mAmount;
+ amount.forget(aAmount);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentItem::GetPending(bool* aPending)
+{
+ NS_ENSURE_ARG_POINTER(aPending);
+ *aPending = mPending;
+ return NS_OK;
+}
+
+/* PaymentDetailsModifier */
+
+NS_IMPL_ISUPPORTS(PaymentDetailsModifier,
+ nsIPaymentDetailsModifier)
+
+PaymentDetailsModifier::PaymentDetailsModifier(nsIArray* aSupportedMethods,
+ nsIPaymentItem* aTotal,
+ nsIArray* aAdditionalDisplayItems,
+ const nsAString& aData)
+ : mSupportedMethods(aSupportedMethods)
+ , mTotal(aTotal)
+ , mAdditionalDisplayItems(aAdditionalDisplayItems)
+ , mData(aData)
+{
+}
+
+nsresult
+PaymentDetailsModifier::Create(const IPCPaymentDetailsModifier& aIPCModifier,
+ nsIPaymentDetailsModifier** aModifier)
+{
+ NS_ENSURE_ARG_POINTER(aModifier);
+ nsCOMPtr<nsIPaymentItem> total;
+ nsresult rv = PaymentItem::Create(aIPCModifier.total(), getter_AddRefs(total));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIArray> supportedMethods;
+ rv = ConvertStringstoISupportsStrings(aIPCModifier.supportedMethods(),
+ getter_AddRefs(supportedMethods));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIArray> displayItems;
+ if (aIPCModifier.additionalDisplayItemsPassed()) {
+ nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ MOZ_ASSERT(items);
+ for (const IPCPaymentItem& item : aIPCModifier.additionalDisplayItems()) {
+ nsCOMPtr<nsIPaymentItem> additionalItem;
+ rv = PaymentItem::Create(item, getter_AddRefs(additionalItem));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ rv = items->AppendElement(additionalItem, false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+ displayItems = items.forget();
+ }
+ nsCOMPtr<nsIPaymentDetailsModifier> modifier =
+ new PaymentDetailsModifier(supportedMethods, total, displayItems, aIPCModifier.data());
+ modifier.forget(aModifier);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetSupportedMethods(nsIArray** aSupportedMethods)
+{
+ NS_ENSURE_ARG_POINTER(aSupportedMethods);
+ MOZ_ASSERT(mSupportedMethods);
+ nsCOMPtr<nsIArray> supportedMethods = mSupportedMethods;
+ supportedMethods.forget(aSupportedMethods);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetTotal(nsIPaymentItem** aTotal)
+{
+ NS_ENSURE_ARG_POINTER(aTotal);
+ MOZ_ASSERT(mTotal);
+ nsCOMPtr<nsIPaymentItem> total = mTotal;
+ total.forget(aTotal);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetAdditionalDisplayItems(nsIArray** aAdditionalDisplayItems)
+{
+ NS_ENSURE_ARG_POINTER(aAdditionalDisplayItems);
+ nsCOMPtr<nsIArray> additionalItems = mAdditionalDisplayItems;
+ additionalItems.forget(aAdditionalDisplayItems);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetailsModifier::GetData(nsAString& aData)
+{
+ aData = mData;
+ return NS_OK;
+}
+
+/* PaymentShippingOption */
+
+NS_IMPL_ISUPPORTS(PaymentShippingOption,
+ nsIPaymentShippingOption)
+
+PaymentShippingOption::PaymentShippingOption(const nsAString& aId,
+ const nsAString& aLabel,
+ nsIPaymentCurrencyAmount* aAmount,
+ const bool aSelected)
+ : mId(aId)
+ , mLabel(aLabel)
+ , mAmount(aAmount)
+ , mSelected(aSelected)
+{
+}
+
+nsresult
+PaymentShippingOption::Create(const IPCPaymentShippingOption& aIPCOption,
+ nsIPaymentShippingOption** aOption)
+{
+ NS_ENSURE_ARG_POINTER(aOption);
+ nsCOMPtr<nsIPaymentCurrencyAmount> amount;
+ nsresult rv = PaymentCurrencyAmount::Create(aIPCOption.amount(), getter_AddRefs(amount));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ nsCOMPtr<nsIPaymentShippingOption> option =
+ new PaymentShippingOption(aIPCOption.id(), aIPCOption.label(), amount, aIPCOption.selected());
+ option.forget(aOption);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetId(nsAString& aId)
+{
+ aId = mId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetLabel(nsAString& aLabel)
+{
+ aLabel = mLabel;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetAmount(nsIPaymentCurrencyAmount** aAmount)
+{
+ NS_ENSURE_ARG_POINTER(aAmount);
+ MOZ_ASSERT(mAmount);
+ nsCOMPtr<nsIPaymentCurrencyAmount> amount = mAmount;
+ amount.forget(aAmount);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::GetSelected(bool* aSelected)
+{
+ NS_ENSURE_ARG_POINTER(aSelected);
+ *aSelected = mSelected;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentShippingOption::SetSelected(bool aSelected)
+{
+ mSelected = aSelected;
+ return NS_OK;
+}
+
+/* PaymentDetails */
+
+NS_IMPL_ISUPPORTS(PaymentDetails,
+ nsIPaymentDetails)
+
+PaymentDetails::PaymentDetails(const nsAString& aId,
+ nsIPaymentItem* aTotalItem,
+ nsIArray* aDisplayItems,
+ nsIArray* aShippingOptions,
+ nsIArray* aModifiers,
+ const nsAString& aError)
+ : mId(aId)
+ , mTotalItem(aTotalItem)
+ , mDisplayItems(aDisplayItems)
+ , mShippingOptions(aShippingOptions)
+ , mModifiers(aModifiers)
+ , mError(aError)
+{
+}
+
+nsresult
+PaymentDetails::Create(const IPCPaymentDetails& aIPCDetails,
+ nsIPaymentDetails** aDetails)
+{
+ NS_ENSURE_ARG_POINTER(aDetails);
+
+ nsCOMPtr<nsIPaymentItem> total;
+ nsresult rv = PaymentItem::Create(aIPCDetails.total(), getter_AddRefs(total));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIArray> displayItems;
+ if (aIPCDetails.displayItemsPassed()) {
+ nsCOMPtr<nsIMutableArray> items = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ MOZ_ASSERT(items);
+ for (const IPCPaymentItem& displayItem : aIPCDetails.displayItems()) {
+ nsCOMPtr<nsIPaymentItem> item;
+ rv = PaymentItem::Create(displayItem, getter_AddRefs(item));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ rv = items->AppendElement(item, false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+ displayItems = items.forget();
+ }
+
+ nsCOMPtr<nsIArray> shippingOptions;
+ if (aIPCDetails.shippingOptionsPassed()) {
+ nsCOMPtr<nsIMutableArray> options = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ MOZ_ASSERT(options);
+ for (const IPCPaymentShippingOption& shippingOption : aIPCDetails.shippingOptions()) {
+ nsCOMPtr<nsIPaymentShippingOption> option;
+ rv = PaymentShippingOption::Create(shippingOption, getter_AddRefs(option));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ rv = options->AppendElement(option, false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+ shippingOptions = options.forget();
+ }
+
+ nsCOMPtr<nsIArray> modifiers;
+ if (aIPCDetails.modifiersPassed()) {
+ nsCOMPtr<nsIMutableArray> detailsModifiers = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ MOZ_ASSERT(detailsModifiers);
+ for (const IPCPaymentDetailsModifier& modifier : aIPCDetails.modifiers()) {
+ nsCOMPtr<nsIPaymentDetailsModifier> detailsModifier;
+ rv = PaymentDetailsModifier::Create(modifier, getter_AddRefs(detailsModifier));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ rv = detailsModifiers->AppendElement(detailsModifier, false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+ modifiers = detailsModifiers.forget();
+ }
+
+ nsCOMPtr<nsIPaymentDetails> details =
+ new PaymentDetails(aIPCDetails.id(), total, displayItems, shippingOptions,
+ modifiers, aIPCDetails.error());
+
+ details.forget(aDetails);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetId(nsAString& aId)
+{
+ aId = mId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetTotalItem(nsIPaymentItem** aTotalItem)
+{
+ NS_ENSURE_ARG_POINTER(aTotalItem);
+ MOZ_ASSERT(mTotalItem);
+ nsCOMPtr<nsIPaymentItem> total = mTotalItem;
+ total.forget(aTotalItem);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetDisplayItems(nsIArray** aDisplayItems)
+{
+ NS_ENSURE_ARG_POINTER(aDisplayItems);
+ nsCOMPtr<nsIArray> displayItems = mDisplayItems;
+ displayItems.forget(aDisplayItems);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetShippingOptions(nsIArray** aShippingOptions)
+{
+ NS_ENSURE_ARG_POINTER(aShippingOptions);
+ nsCOMPtr<nsIArray> options = mShippingOptions;
+ options.forget(aShippingOptions);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetModifiers(nsIArray** aModifiers)
+{
+ NS_ENSURE_ARG_POINTER(aModifiers);
+ nsCOMPtr<nsIArray> modifiers = mModifiers;
+ modifiers.forget(aModifiers);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::GetError(nsAString& aError)
+{
+ aError = mError;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentDetails::Update(nsIPaymentDetails* aDetails)
+{
+ MOZ_ASSERT(aDetails);
+ /*
+ * According to the spec [1], update the attributes if they present in new
+ * details (i.e., PaymentDetailsUpdate); otherwise, keep original value.
+ * Note |id| comes only from initial details (i.e., PaymentDetailsInit) and
+ * |error| only from new details.
+ *
+ * [1] https://www.w3.org/TR/payment-request/#updatewith-method
+ */
+
+ nsresult rv = aDetails->GetTotalItem(getter_AddRefs(mTotalItem));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIArray> displayItems;
+ rv = aDetails->GetDisplayItems(getter_AddRefs(displayItems));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ if (displayItems) {
+ mDisplayItems = displayItems;
+ }
+
+ nsCOMPtr<nsIArray> shippingOptions;
+ rv = aDetails->GetShippingOptions(getter_AddRefs(shippingOptions));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ if (shippingOptions) {
+ mShippingOptions = shippingOptions;
+ }
+
+ nsCOMPtr<nsIArray> modifiers;
+ rv = aDetails->GetModifiers(getter_AddRefs(modifiers));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ if (modifiers) {
+ mModifiers = modifiers;
+ }
+
+ rv = aDetails->GetError(mError);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ return NS_OK;
+
+}
+/* PaymentOptions */
+
+NS_IMPL_ISUPPORTS(PaymentOptions,
+ nsIPaymentOptions)
+
+PaymentOptions::PaymentOptions(const bool aRequestPayerName,
+ const bool aRequestPayerEmail,
+ const bool aRequestPayerPhone,
+ const bool aRequestShipping,
+ const nsAString& aShippingType)
+ : mRequestPayerName(aRequestPayerName)
+ , mRequestPayerEmail(aRequestPayerEmail)
+ , mRequestPayerPhone(aRequestPayerPhone)
+ , mRequestShipping(aRequestShipping)
+ , mShippingType(aShippingType)
+{
+}
+
+nsresult
+PaymentOptions::Create(const IPCPaymentOptions& aIPCOptions,
+ nsIPaymentOptions** aOptions)
+{
+ NS_ENSURE_ARG_POINTER(aOptions);
+
+ nsCOMPtr<nsIPaymentOptions> options =
+ new PaymentOptions(aIPCOptions.requestPayerName(),
+ aIPCOptions.requestPayerEmail(),
+ aIPCOptions.requestPayerPhone(),
+ aIPCOptions.requestShipping(),
+ aIPCOptions.shippingType());
+ options.forget(aOptions);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestPayerName(bool* aRequestPayerName)
+{
+ NS_ENSURE_ARG_POINTER(aRequestPayerName);
+ *aRequestPayerName = mRequestPayerName;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestPayerEmail(bool* aRequestPayerEmail)
+{
+ NS_ENSURE_ARG_POINTER(aRequestPayerEmail);
+ *aRequestPayerEmail = mRequestPayerEmail;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestPayerPhone(bool* aRequestPayerPhone)
+{
+ NS_ENSURE_ARG_POINTER(aRequestPayerPhone);
+ *aRequestPayerPhone = mRequestPayerPhone;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetRequestShipping(bool* aRequestShipping)
+{
+ NS_ENSURE_ARG_POINTER(aRequestShipping);
+ *aRequestShipping = mRequestShipping;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentOptions::GetShippingType(nsAString& aShippingType)
+{
+ aShippingType = mShippingType;
+ return NS_OK;
+}
+
+/* PaymentReqeust */
+
+NS_IMPL_ISUPPORTS(PaymentRequest,
+ nsIPaymentRequest)
+
+PaymentRequest::PaymentRequest(const uint64_t aTabId,
+ const nsAString& aRequestId,
+ nsIArray* aPaymentMethods,
+ nsIPaymentDetails* aPaymentDetails,
+ nsIPaymentOptions* aPaymentOptions)
+ : mTabId(aTabId)
+ , mRequestId(aRequestId)
+ , mPaymentMethods(aPaymentMethods)
+ , mPaymentDetails(aPaymentDetails)
+ , mPaymentOptions(aPaymentOptions)
+{
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetTabId(uint64_t* aTabId)
+{
+ NS_ENSURE_ARG_POINTER(aTabId);
+ *aTabId = mTabId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetRequestId(nsAString& aRequestId)
+{
+ aRequestId = mRequestId;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetPaymentMethods(nsIArray** aPaymentMethods)
+{
+ NS_ENSURE_ARG_POINTER(aPaymentMethods);
+ MOZ_ASSERT(mPaymentMethods);
+ nsCOMPtr<nsIArray> methods = mPaymentMethods;
+ methods.forget(aPaymentMethods);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetPaymentDetails(nsIPaymentDetails** aPaymentDetails)
+{
+ NS_ENSURE_ARG_POINTER(aPaymentDetails);
+ MOZ_ASSERT(mPaymentDetails);
+ nsCOMPtr<nsIPaymentDetails> details = mPaymentDetails;
+ details.forget(aPaymentDetails);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::GetPaymentOptions(nsIPaymentOptions** aPaymentOptions)
+{
+ NS_ENSURE_ARG_POINTER(aPaymentOptions);
+ MOZ_ASSERT(mPaymentOptions);
+ nsCOMPtr<nsIPaymentOptions> options = mPaymentOptions;
+ options.forget(aPaymentOptions);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequest::UpdatePaymentDetails(nsIPaymentDetails* aPaymentDetails)
+{
+ MOZ_ASSERT(aPaymentDetails);
+ return mPaymentDetails->Update(aPaymentDetails);
+}
+
+} // end of namespace payment
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestData.h
@@ -0,0 +1,199 @@
+/* -*- 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_PaymentRequestData_h
+#define mozilla_dom_PaymentRequestData_h
+
+#include "nsIPaymentRequest.h"
+#include "nsCOMPtr.h"
+#include "mozilla/dom/PPaymentRequest.h"
+
+namespace mozilla {
+namespace dom {
+namespace payments {
+
+class PaymentMethodData final : public nsIPaymentMethodData
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTMETHODDATA
+
+ static nsresult Create(const IPCPaymentMethodData& aIPCMethodData,
+ nsIPaymentMethodData** aMethodData);
+
+private:
+ PaymentMethodData(nsIArray* aSupportedMethods,
+ const nsAString& aData);
+
+ ~PaymentMethodData() = default;
+
+ nsCOMPtr<nsIArray> mSupportedMethods;
+ nsString mData;
+};
+
+class PaymentCurrencyAmount final : public nsIPaymentCurrencyAmount
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTCURRENCYAMOUNT
+
+ static nsresult Create(const IPCPaymentCurrencyAmount& aIPCAmount,
+ nsIPaymentCurrencyAmount** aAmount);
+
+private:
+ PaymentCurrencyAmount(const nsAString& aCurrency,
+ const nsAString& aValue);
+
+ ~PaymentCurrencyAmount() = default;
+
+ nsString mCurrency;
+ nsString mValue;
+};
+
+class PaymentItem final : public nsIPaymentItem
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTITEM
+
+ static nsresult Create(const IPCPaymentItem& aIPCItem, nsIPaymentItem** aItem);
+
+private:
+ PaymentItem(const nsAString& aLabel,
+ nsIPaymentCurrencyAmount* aAmount,
+ const bool aPending);
+
+ ~PaymentItem() = default;
+
+ nsString mLabel;
+ nsCOMPtr<nsIPaymentCurrencyAmount> mAmount;
+ bool mPending;
+};
+
+class PaymentDetailsModifier final : public nsIPaymentDetailsModifier
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTDETAILSMODIFIER
+
+ static nsresult Create(const IPCPaymentDetailsModifier& aIPCModifier,
+ nsIPaymentDetailsModifier** aModifier);
+
+private:
+ PaymentDetailsModifier(nsIArray* aSupportedMethods,
+ nsIPaymentItem* aTotal,
+ nsIArray* aAdditionalDisplayItems,
+ const nsAString& aData);
+
+ ~PaymentDetailsModifier() = default;
+
+ nsCOMPtr<nsIArray> mSupportedMethods;
+ nsCOMPtr<nsIPaymentItem> mTotal;
+ nsCOMPtr<nsIArray> mAdditionalDisplayItems;
+ nsString mData;
+};
+
+class PaymentShippingOption final : public nsIPaymentShippingOption
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTSHIPPINGOPTION
+
+ static nsresult Create(const IPCPaymentShippingOption& aIPCOption,
+ nsIPaymentShippingOption** aOption);
+
+private:
+ PaymentShippingOption(const nsAString& aId,
+ const nsAString& aLabel,
+ nsIPaymentCurrencyAmount* aAmount,
+ const bool aSelected=false);
+
+ ~PaymentShippingOption() = default;
+
+ nsString mId;
+ nsString mLabel;
+ nsCOMPtr<nsIPaymentCurrencyAmount> mAmount;
+ bool mSelected;
+};
+
+class PaymentDetails final : public nsIPaymentDetails
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTDETAILS
+
+
+ static nsresult Create(const IPCPaymentDetails& aIPCDetails,
+ nsIPaymentDetails** aDetails);
+private:
+ PaymentDetails(const nsAString& aId,
+ nsIPaymentItem* aTotalItem,
+ nsIArray* aDisplayItems,
+ nsIArray* aShippingOptions,
+ nsIArray* aModifiers,
+ const nsAString& aError);
+
+ ~PaymentDetails() = default;
+
+ nsString mId;
+ nsCOMPtr<nsIPaymentItem> mTotalItem;
+ nsCOMPtr<nsIArray> mDisplayItems;
+ nsCOMPtr<nsIArray> mShippingOptions;
+ nsCOMPtr<nsIArray> mModifiers;
+ nsString mError;
+};
+
+class PaymentOptions final : public nsIPaymentOptions
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTOPTIONS
+
+ static nsresult Create(const IPCPaymentOptions& aIPCOptions,
+ nsIPaymentOptions** aOptions);
+
+private:
+ PaymentOptions(const bool aRequestPayerName,
+ const bool aRequestPayerEmail,
+ const bool aRequestPayerPhone,
+ const bool aRequestShipping,
+ const nsAString& aShippintType);
+ ~PaymentOptions() = default;
+
+ bool mRequestPayerName;
+ bool mRequestPayerEmail;
+ bool mRequestPayerPhone;
+ bool mRequestShipping;
+ nsString mShippingType;
+};
+
+class PaymentRequest final : public nsIPaymentRequest
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTREQUEST
+
+ PaymentRequest(const uint64_t aTabId,
+ const nsAString& aRequestId,
+ nsIArray* aPaymentMethods,
+ nsIPaymentDetails* aPaymentDetails,
+ nsIPaymentOptions* aPaymentOptions);
+
+private:
+ ~PaymentRequest() = default;
+
+ uint64_t mTabId;
+ nsString mRequestId;
+ nsCOMPtr<nsIArray> mPaymentMethods;
+ nsCOMPtr<nsIPaymentDetails> mPaymentDetails;
+ nsCOMPtr<nsIPaymentOptions> mPaymentOptions;
+};
+
+} // end of namespace payment
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestManager.cpp
@@ -0,0 +1,394 @@
+/* -*- 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 "PaymentRequestManager.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/PaymentRequestChild.h"
+#include "nsContentUtils.h"
+#include "nsIJSON.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace dom {
+namespace {
+
+/*
+ * Following Convert* functions are used for convert PaymentRequest structs
+ * to transferable structs for IPC.
+ */
+nsresult
+SerializeFromJSObject(JSContext* aCx, JS::HandleObject aObject, nsAString& aSerializedObject){
+ nsCOMPtr<nsIJSON> serializer = do_CreateInstance("@mozilla.org/dom/json;1");
+ if (NS_WARN_IF(!serializer)) {
+ return NS_ERROR_FAILURE;
+ }
+ JS::RootedValue value(aCx, JS::ObjectValue(*aObject));
+ //JS::Value value = JS::ObjectValue(*aObject);
+ return serializer->EncodeFromJSVal(value.address(), aCx, aSerializedObject);
+}
+
+nsresult
+ConvertMethodData(const PaymentMethodData& aMethodData,
+ IPCPaymentMethodData& aIPCMethodData)
+{
+ // Convert Sequence<nsString> to nsTArray<nsString>
+ nsTArray<nsString> supportedMethods;
+ for (const nsString& method : aMethodData.mSupportedMethods) {
+ supportedMethods.AppendElement(method);
+ }
+
+ // Convert JSObject to a serialized string
+ nsAutoString serializedData;
+ if (aMethodData.mData.WasPassed()) {
+ JSContext* cx = nsContentUtils::GetCurrentJSContext();
+ MOZ_ASSERT(cx);
+ JS::RootedObject object(cx, aMethodData.mData.Value());
+ nsresult rv = SerializeFromJSObject(cx, object, serializedData);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+ aIPCMethodData = IPCPaymentMethodData(supportedMethods, serializedData);
+ return NS_OK;
+}
+
+void
+ConvertCurrencyAmount(const PaymentCurrencyAmount& aAmount,
+ IPCPaymentCurrencyAmount& aIPCCurrencyAmount)
+{
+ aIPCCurrencyAmount = IPCPaymentCurrencyAmount(aAmount.mCurrency, aAmount.mValue);
+}
+
+void
+ConvertItem(const PaymentItem& aItem, IPCPaymentItem& aIPCItem)
+{
+ IPCPaymentCurrencyAmount amount;
+ ConvertCurrencyAmount(aItem.mAmount, amount);
+ aIPCItem = IPCPaymentItem(aItem.mLabel, amount, aItem.mPending);
+}
+
+nsresult
+ConvertModifier(const PaymentDetailsModifier& aModifier,
+ IPCPaymentDetailsModifier& aIPCModifier)
+{
+ // Convert Sequence<nsString> to nsTArray<nsString>
+ nsTArray<nsString> supportedMethods;
+ for (const nsString& method : aModifier.mSupportedMethods) {
+ supportedMethods.AppendElement(method);
+ }
+
+ // Convert JSObject to a serialized string
+ nsAutoString serializedData;
+ if (aModifier.mData.WasPassed()) {
+ JSContext* cx = nsContentUtils::GetCurrentJSContext();
+ MOZ_ASSERT(cx);
+ JS::RootedObject object(cx, aModifier.mData.Value());
+ nsresult rv = SerializeFromJSObject(cx, object, serializedData);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+
+ IPCPaymentItem total;
+ ConvertItem(aModifier.mTotal, total);
+
+ nsTArray<IPCPaymentItem> additionalDisplayItems;
+ if (aModifier.mAdditionalDisplayItems.WasPassed()) {
+ for (const PaymentItem& item : aModifier.mAdditionalDisplayItems.Value()) {
+ IPCPaymentItem displayItem;
+ ConvertItem(item, displayItem);
+ additionalDisplayItems.AppendElement(displayItem);
+ }
+ }
+ aIPCModifier = IPCPaymentDetailsModifier(supportedMethods,
+ total,
+ additionalDisplayItems,
+ serializedData,
+ aModifier.mAdditionalDisplayItems.WasPassed());
+ return NS_OK;
+}
+
+void
+ConvertShippingOption(const PaymentShippingOption& aOption,
+ IPCPaymentShippingOption& aIPCOption)
+{
+ IPCPaymentCurrencyAmount amount;
+ ConvertCurrencyAmount(aOption.mAmount, amount);
+ aIPCOption = IPCPaymentShippingOption(aOption.mId, aOption.mLabel, amount, aOption.mSelected);
+}
+
+nsresult
+ConvertDetailsBase(const PaymentDetailsBase& aDetails,
+ nsTArray<IPCPaymentItem>& aDisplayItems,
+ nsTArray<IPCPaymentShippingOption>& aShippingOptions,
+ nsTArray<IPCPaymentDetailsModifier>& aModifiers)
+{
+ if (aDetails.mDisplayItems.WasPassed()) {
+ for (const PaymentItem& item : aDetails.mDisplayItems.Value()) {
+ IPCPaymentItem displayItem;
+ ConvertItem(item, displayItem);
+ aDisplayItems.AppendElement(displayItem);
+ }
+ }
+ if (aDetails.mShippingOptions.WasPassed()) {
+ for (const PaymentShippingOption& option : aDetails.mShippingOptions.Value()) {
+ IPCPaymentShippingOption shippingOption;
+ ConvertShippingOption(option, shippingOption);
+ aShippingOptions.AppendElement(shippingOption);
+ }
+ }
+ if (aDetails.mModifiers.WasPassed()) {
+ for (const PaymentDetailsModifier& modifier : aDetails.mModifiers.Value()) {
+ IPCPaymentDetailsModifier detailsModifier;
+ nsresult rv = ConvertModifier(modifier, detailsModifier);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ aModifiers.AppendElement(detailsModifier);
+ }
+ }
+ return NS_OK;
+}
+
+nsresult
+ConvertDetailsInit(const PaymentDetailsInit& aDetails,
+ IPCPaymentDetails& aIPCDetails)
+{
+ // Convert PaymentDetailsBase members
+ nsTArray<IPCPaymentItem> displayItems;
+ nsTArray<IPCPaymentShippingOption> shippingOptions;
+ nsTArray<IPCPaymentDetailsModifier> modifiers;
+ nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ // Convert |id|
+ nsString id(EmptyString());
+ if (aDetails.mId.WasPassed()) {
+ id = aDetails.mId.Value();
+ }
+
+ // Convert required |total|
+ IPCPaymentItem total;
+ ConvertItem(aDetails.mTotal, total);
+
+ aIPCDetails = IPCPaymentDetails(id,
+ total,
+ displayItems,
+ shippingOptions,
+ modifiers,
+ EmptyString(), // error message
+ aDetails.mDisplayItems.WasPassed(),
+ aDetails.mShippingOptions.WasPassed(),
+ aDetails.mModifiers.WasPassed());
+ return NS_OK;
+}
+
+void
+ConvertOptions(const PaymentOptions& aOptions,
+ IPCPaymentOptions& aIPCOption)
+{
+ uint8_t shippingTypeIndex = static_cast<uint8_t>(aOptions.mShippingType);
+ nsString shippingType(NS_LITERAL_STRING("shipping"));
+ if (shippingTypeIndex < ArrayLength(PaymentShippingTypeValues::strings)) {
+ shippingType.AssignASCII(
+ PaymentShippingTypeValues::strings[shippingTypeIndex].value);
+ }
+ aIPCOption = IPCPaymentOptions(aOptions.mRequestPayerName,
+ aOptions.mRequestPayerEmail,
+ aOptions.mRequestPayerPhone,
+ aOptions.mRequestShipping,
+ shippingType);
+}
+} // end of namespace
+
+/* PaymentRequestManager */
+
+StaticRefPtr<PaymentRequestManager> gPaymentManager;
+
+nsresult
+PaymentRequestManager::GetPaymentChild(PaymentRequest* aRequest,
+ PaymentRequestChild** aChild)
+{
+ NS_ENSURE_ARG_POINTER(aRequest);
+ NS_ENSURE_ARG_POINTER(aChild);
+ *aChild = nullptr;
+
+ RefPtr<PaymentRequestChild> paymentChild;
+ if (mPaymentChildHash.Get(aRequest, getter_AddRefs(paymentChild))) {
+ paymentChild.forget(aChild);
+ return NS_OK;
+ }
+
+ nsPIDOMWindowInner* win = aRequest->GetOwner();
+ NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
+ TabChild* tabChild = TabChild::GetFrom(win->GetDocShell());
+ NS_ENSURE_TRUE(tabChild, NS_ERROR_FAILURE);
+ nsAutoString requestId;
+ aRequest->GetInternalId(requestId);
+
+ // Only one payment request can interact with user at the same time.
+ // Before we create a new PaymentRequestChild, make sure there is no other
+ // payment request are interacting on the same tab.
+ for (auto iter = mPaymentChildHash.ConstIter(); !iter.Done(); iter.Next()) {
+ RefPtr<PaymentRequest> request = iter.Key();
+ if (request->Equals(requestId)) {
+ continue;
+ }
+ nsPIDOMWindowInner* requestOwner = request->GetOwner();
+ NS_ENSURE_TRUE(requestOwner, NS_ERROR_FAILURE);
+ TabChild* tmpChild = TabChild::GetFrom(requestOwner->GetDocShell());
+ NS_ENSURE_TRUE(tmpChild, NS_ERROR_FAILURE);
+ if (tmpChild->GetTabId() == tabChild->GetTabId()) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ paymentChild = new PaymentRequestChild();
+ tabChild->SendPPaymentRequestConstructor(paymentChild);
+ if (!mPaymentChildHash.Put(aRequest, paymentChild, mozilla::fallible) ) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ paymentChild.forget(aChild);
+ return NS_OK;
+}
+
+nsresult
+PaymentRequestManager::ReleasePaymentChild(PaymentRequestChild* aPaymentChild)
+{
+ NS_ENSURE_ARG_POINTER(aPaymentChild);
+ for (auto iter = mPaymentChildHash.Iter(); !iter.Done(); iter.Next()) {
+ RefPtr<PaymentRequestChild> child = iter.Data();
+ if (NS_WARN_IF(!child)) {
+ return NS_ERROR_FAILURE;
+ }
+ if (child == aPaymentChild) {
+ iter.Remove();
+ return NS_OK;
+ }
+ }
+ return NS_OK;
+}
+
+nsresult
+PaymentRequestManager::ReleasePaymentChild(PaymentRequest* aRequest)
+{
+ NS_ENSURE_ARG_POINTER(aRequest);
+
+ RefPtr<PaymentRequestChild> paymentChild;
+ if(!mPaymentChildHash.Remove(aRequest, getter_AddRefs(paymentChild))) {
+ return NS_ERROR_FAILURE;
+ }
+ if (NS_WARN_IF(!paymentChild)) {
+ return NS_ERROR_FAILURE;
+ }
+ paymentChild->MaybeDelete();
+ return NS_OK;
+}
+
+already_AddRefed<PaymentRequestManager>
+PaymentRequestManager::GetSingleton()
+{
+ if (!gPaymentManager) {
+ gPaymentManager = new PaymentRequestManager();
+ ClearOnShutdown(&gPaymentManager);
+ }
+ RefPtr<PaymentRequestManager> manager = gPaymentManager;
+ return manager.forget();
+}
+
+already_AddRefed<PaymentRequest>
+PaymentRequestManager::GetPaymentRequestById(const nsAString& aRequestId)
+{
+ for (const RefPtr<PaymentRequest>& request : mRequestQueue) {
+ if (request->Equals(aRequestId)) {
+ RefPtr<PaymentRequest> paymentRequest = request;
+ return paymentRequest.forget();
+ }
+ }
+ return nullptr;
+}
+
+nsresult
+PaymentRequestManager::CreatePayment(nsPIDOMWindowInner* aWindow,
+ const Sequence<PaymentMethodData>& aMethodData,
+ const PaymentDetailsInit& aDetails,
+ const PaymentOptions& aOptions,
+ PaymentRequest** aRequest)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ NS_ENSURE_ARG_POINTER(aRequest);
+ *aRequest = nullptr;
+
+ nsresult rv;
+ nsTArray<IPCPaymentMethodData> methodData;
+ for (const PaymentMethodData& data : aMethodData) {
+ IPCPaymentMethodData ipcMethodData;
+ rv = ConvertMethodData(data, ipcMethodData);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ methodData.AppendElement(ipcMethodData);
+ }
+
+ IPCPaymentDetails details;
+ rv = ConvertDetailsInit(aDetails, details);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ IPCPaymentOptions options;
+ ConvertOptions(aOptions, options);
+
+ RefPtr<PaymentRequest> paymentRequest = PaymentRequest::CreatePaymentRequest(aWindow, rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ /*
+ * Set request's |mId| to details.id if details.id exists.
+ * Otherwise, set |mId| to internal id.
+ */
+ nsAutoString requestId;
+ if (aDetails.mId.WasPassed() && !aDetails.mId.Value().IsEmpty()) {
+ requestId = aDetails.mId.Value();
+ } else {
+ paymentRequest->GetInternalId(requestId);
+ }
+ paymentRequest->SetId(requestId);
+
+ RefPtr<PaymentRequestChild> requestChild;
+ rv = GetPaymentChild(paymentRequest, getter_AddRefs(requestChild));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsAutoString internalId;
+ paymentRequest->GetInternalId(internalId);
+ IPCPaymentCreateActionRequest request(internalId,
+ methodData,
+ details,
+ options);
+ rv = requestChild->RequestPayment(request);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ rv = ReleasePaymentChild(paymentRequest);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ mRequestQueue.AppendElement(paymentRequest);
+ paymentRequest.forget(aRequest);
+ return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestManager.h
@@ -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_PaymentRequestManager_h
+#define mozilla_dom_PaymentRequestManager_h
+
+#include "nsISupports.h"
+#include "PaymentRequest.h"
+#include "mozilla/dom/PaymentRequestBinding.h"
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentRequestChild;
+
+/*
+ * PaymentRequestManager is a singleton used to manage the created PaymentRequests.
+ * It is also the communication agent to chrome proces.
+ */
+class PaymentRequestManager final
+{
+public:
+ NS_INLINE_DECL_REFCOUNTING(PaymentRequestManager)
+
+ static already_AddRefed<PaymentRequestManager> GetSingleton();
+
+ already_AddRefed<PaymentRequest>
+ GetPaymentRequestById(const nsAString& aRequestId);
+
+ /*
+ * This method is used to create PaymentRequest object and send corresponding
+ * data to chrome process for internal payment creation, such that content
+ * process can ask specific task by sending requestId only.
+ */
+ nsresult
+ CreatePayment(nsPIDOMWindowInner* aWindow,
+ const Sequence<PaymentMethodData>& aMethodData,
+ const PaymentDetailsInit& aDetails,
+ const PaymentOptions& aOptions,
+ PaymentRequest** aRequest);
+
+ nsresult
+ ReleasePaymentChild(PaymentRequestChild* aPaymentChild);
+protected:
+ PaymentRequestManager() = default;
+ ~PaymentRequestManager() = default;
+
+ nsresult GetPaymentChild(PaymentRequest* aRequest,
+ PaymentRequestChild** aPaymentChild);
+ nsresult ReleasePaymentChild(PaymentRequest* aRequest);
+
+ // The container for the created PaymentRequests
+ nsTArray<RefPtr<PaymentRequest>> mRequestQueue;
+ nsRefPtrHashtable<nsRefPtrHashKey<PaymentRequest>, PaymentRequestChild> mPaymentChildHash;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestModule.cpp
@@ -0,0 +1,52 @@
+/* -*- 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/ModuleUtils.h"
+#include "PaymentActionRequest.h"
+#include "PaymentRequestService.h"
+
+using mozilla::dom::PaymentActionRequest;
+using mozilla::dom::PaymentCreateActionRequest;
+using mozilla::dom::PaymentRequestService;
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentActionRequest)
+NS_GENERIC_FACTORY_CONSTRUCTOR(PaymentCreateActionRequest)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(PaymentRequestService,
+ PaymentRequestService::GetSingleton)
+
+NS_DEFINE_NAMED_CID(NS_PAYMENT_ACTION_REQUEST_CID);
+NS_DEFINE_NAMED_CID(NS_PAYMENT_CREATE_ACTION_REQUEST_CID);
+NS_DEFINE_NAMED_CID(NS_PAYMENT_REQUEST_SERVICE_CID);
+
+static const mozilla::Module::CIDEntry kPaymentRequestCIDs[] = {
+ { &kNS_PAYMENT_ACTION_REQUEST_CID, false, nullptr, PaymentActionRequestConstructor},
+ { &kNS_PAYMENT_CREATE_ACTION_REQUEST_CID, false, nullptr, PaymentCreateActionRequestConstructor},
+ { &kNS_PAYMENT_REQUEST_SERVICE_CID, true, nullptr, PaymentRequestServiceConstructor },
+ { nullptr }
+};
+
+static const mozilla::Module::ContractIDEntry kPaymentRequestContracts[] = {
+ { NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID, &kNS_PAYMENT_ACTION_REQUEST_CID },
+ { NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID, &kNS_PAYMENT_CREATE_ACTION_REQUEST_CID },
+ { NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID, &kNS_PAYMENT_REQUEST_SERVICE_CID },
+ { nullptr }
+};
+
+static const mozilla::Module::CategoryEntry kPaymentRequestCategories[] = {
+ { "payment-request", "PaymentActionRequest", NS_PAYMENT_ACTION_REQUEST_CONTRACT_ID },
+ { "payment-request", "PaymentCreateActionRequest", NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID },
+ { "payment-request", "PaymentRequestService", NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID },
+ { nullptr }
+};
+
+static const mozilla::Module kPaymentRequestModule = {
+ mozilla::Module::kVersion,
+ kPaymentRequestCIDs,
+ kPaymentRequestContracts,
+ kPaymentRequestCategories
+};
+
+NSMODULE_DEFN(PaymentRequestModule) = &kPaymentRequestModule;
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestService.cpp
@@ -0,0 +1,201 @@
+/* -*- 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/ClearOnShutdown.h"
+#include "PaymentRequestData.h"
+#include "PaymentRequestService.h"
+
+namespace mozilla {
+namespace dom {
+
+StaticRefPtr<PaymentRequestService> gPaymentService;
+
+namespace {
+
+class PaymentRequestEnumerator final : public nsISimpleEnumerator
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISIMPLEENUMERATOR
+
+ PaymentRequestEnumerator()
+ : mIndex(0)
+ {}
+private:
+ ~PaymentRequestEnumerator() = default;
+ uint32_t mIndex;
+};
+
+NS_IMPL_ISUPPORTS(PaymentRequestEnumerator, nsISimpleEnumerator)
+
+NS_IMETHODIMP
+PaymentRequestEnumerator::HasMoreElements(bool* aReturn)
+{
+ NS_ENSURE_ARG_POINTER(aReturn);
+ *aReturn = false;
+ if (NS_WARN_IF(!gPaymentService)) {
+ return NS_ERROR_FAILURE;
+ }
+ RefPtr<PaymentRequestService> service = gPaymentService;
+ *aReturn = mIndex < service->NumPayments();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestEnumerator::GetNext(nsISupports** aItem)
+{
+ NS_ENSURE_ARG_POINTER(aItem);
+ if (NS_WARN_IF(!gPaymentService)) {
+ return NS_ERROR_FAILURE;
+ }
+ nsCOMPtr<nsIPaymentRequest> request =
+ gPaymentService->GetPaymentRequestByIndex(mIndex);
+ if (NS_WARN_IF(!request)) {
+ return NS_ERROR_FAILURE;
+ }
+ nsCOMPtr<nsISupports> item = do_QueryInterface(request);
+ if (NS_WARN_IF(!item)) {
+ return NS_ERROR_FAILURE;
+ }
+ mIndex++;
+ item.forget(aItem);
+ return NS_OK;
+}
+
+} // end of anonymous namespace
+
+/* PaymentRequestService */
+
+NS_IMPL_ISUPPORTS(PaymentRequestService,
+ nsIPaymentRequestService)
+
+already_AddRefed<PaymentRequestService>
+PaymentRequestService::GetSingleton()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!gPaymentService) {
+ gPaymentService = new PaymentRequestService();
+ ClearOnShutdown(&gPaymentService);
+ }
+ RefPtr<PaymentRequestService> service = gPaymentService;
+ return service.forget();
+}
+
+uint32_t
+PaymentRequestService::NumPayments() const
+{
+ return mRequestQueue.Length();
+}
+
+already_AddRefed<nsIPaymentRequest>
+PaymentRequestService::GetPaymentRequestByIndex(const uint32_t aIndex)
+{
+ if (aIndex >= mRequestQueue.Length()) {
+ return nullptr;
+ }
+ nsCOMPtr<nsIPaymentRequest> request = mRequestQueue[aIndex];
+ MOZ_ASSERT(request);
+ return request.forget();
+}
+
+NS_IMETHODIMP
+PaymentRequestService::GetPaymentRequestById(const nsAString& aRequestId,
+ nsIPaymentRequest** aRequest)
+{
+ NS_ENSURE_ARG_POINTER(aRequest);
+ *aRequest = nullptr;
+ uint32_t numRequests = mRequestQueue.Length();
+ for (uint32_t index = 0; index < numRequests; ++index) {
+ nsCOMPtr<nsIPaymentRequest> request = mRequestQueue[index];
+ MOZ_ASSERT(request);
+ nsAutoString requestId;
+ nsresult rv = request->GetRequestId(requestId);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (requestId == aRequestId) {
+ request.forget(aRequest);
+ break;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestService::Enumerate(nsISimpleEnumerator** aEnumerator)
+{
+ NS_ENSURE_ARG_POINTER(aEnumerator);
+ nsCOMPtr<nsISimpleEnumerator> enumerator = new PaymentRequestEnumerator();
+ enumerator.forget(aEnumerator);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestService::Cleanup()
+{
+ mRequestQueue.Clear();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
+{
+ NS_ENSURE_ARG_POINTER(aRequest);
+ uint32_t type;
+ nsresult rv = aRequest->GetType(&type);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ switch (type) {
+ case nsIPaymentActionRequest::CREATE_ACTION: {
+ nsCOMPtr<nsIPaymentCreateActionRequest> request =
+ do_QueryInterface(aRequest);
+ MOZ_ASSERT(request);
+ uint64_t tabId;
+ rv = request->GetTabId(&tabId);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsString requestId;
+ rv = request->GetRequestId(requestId);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsIArray> methodData;
+ rv = request->GetMethodData(getter_AddRefs(methodData));
+ if (NS_WARN_IF(NS_FAILED(rv) || !methodData)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr<nsIPaymentDetails> details;
+ rv = request->GetDetails(getter_AddRefs(details));
+ if (NS_WARN_IF(NS_FAILED(rv) || !details)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr<nsIPaymentOptions> options;
+ rv = request->GetOptions(getter_AddRefs(options));
+ if (NS_WARN_IF(NS_FAILED(rv) || !options)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr<nsIPaymentRequest> payment =
+ new payments::PaymentRequest(tabId, requestId, methodData, details, options);
+
+ if (!mRequestQueue.AppendElement(payment, mozilla::fallible)) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ break;
+ }
+ default: {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestService.h
@@ -0,0 +1,45 @@
+/* -*- 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_PaymentRequestService_h
+#define mozilla_dom_PaymentRequestService_h
+
+#include "nsIPaymentRequest.h"
+#include "nsIPaymentRequestService.h"
+#include "nsISimpleEnumerator.h"
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace dom {
+
+// The implmentation of nsIPaymentRequestService
+
+class PaymentRequestService final : public nsIPaymentRequestService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPAYMENTREQUESTSERVICE
+
+ PaymentRequestService() = default;
+
+ static already_AddRefed<PaymentRequestService> GetSingleton();
+
+ already_AddRefed<nsIPaymentRequest>
+ GetPaymentRequestByIndex(const uint32_t index);
+
+ uint32_t NumPayments() const;
+
+private:
+ ~PaymentRequestService() = default;
+
+ FallibleTArray<nsCOMPtr<nsIPaymentRequest>> mRequestQueue;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestUtils.cpp
@@ -0,0 +1,90 @@
+/* -*- 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 "nsArrayUtils.h"
+#include "PaymentRequestUtils.h"
+#include "nsIMutableArray.h"
+#include "nsISupportsPrimitives.h"
+
+namespace mozilla {
+namespace dom {
+
+nsresult
+ConvertStringstoISupportsStrings(const nsTArray<nsString>& aStrings,
+ nsIArray** aIStrings)
+{
+ NS_ENSURE_ARG_POINTER(aIStrings);
+ *aIStrings = nullptr;
+ nsCOMPtr<nsIMutableArray> iStrings = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ for (const nsString& string : aStrings) {
+ nsCOMPtr<nsISupportsString> iString =
+ do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
+ if (NS_WARN_IF(!iString)) {
+ return NS_ERROR_FAILURE;
+ }
+ nsresult rv = iString->SetData(string);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ rv = iStrings->AppendElement(iString, false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ }
+ iStrings.forget(aIStrings);
+ return NS_OK;
+}
+
+nsresult
+ConvertISupportsStringstoStrings(nsIArray* aIStrings,
+ nsTArray<nsString>& aStrings)
+{
+ NS_ENSURE_ARG_POINTER(aIStrings);
+ uint32_t length;
+ aStrings.Clear();
+ nsresult rv = aIStrings->GetLength(&length);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ for (uint32_t index = 0; index < length; ++index) {
+ nsCOMPtr<nsISupportsString> iString = do_QueryElementAt(aIStrings, index);
+ if (NS_WARN_IF(!iString)) {
+ return NS_ERROR_FAILURE;
+ }
+ nsString string;
+ rv = iString->GetData(string);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ aStrings.AppendElement(string);
+ }
+ return NS_OK;
+}
+
+nsresult
+CopyISupportsStrings(nsIArray* aSourceStrings, nsIArray** aTargetStrings)
+{
+ NS_ENSURE_ARG_POINTER(aTargetStrings);
+ *aTargetStrings = nullptr;
+ nsCOMPtr<nsIMutableArray> strings = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ uint32_t length;
+ nsresult rv = aSourceStrings->GetLength(&length);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ for (uint32_t index = 0; index < length; ++index) {
+ nsCOMPtr<nsISupportsString> string = do_QueryElementAt(aSourceStrings, index);
+ if (NS_WARN_IF(!string)) {
+ return NS_ERROR_FAILURE;
+ }
+ strings->AppendElement(string, false);
+ }
+ strings.forget(aTargetStrings);
+ return NS_OK;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/PaymentRequestUtils.h
@@ -0,0 +1,30 @@
+/* -*- 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_PaymentRequestUtils_h
+#define mozilla_dom_PaymentRequestUtils_h
+
+#include "nsIArray.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace dom {
+
+nsresult
+ConvertStringstoISupportsStrings(const nsTArray<nsString>& aStrings,
+ nsIArray** aIStrings);
+
+nsresult
+ConvertISupportsStringstoStrings(nsIArray* aIStrings,
+ nsTArray<nsString>& aStrings);
+
+nsresult
+CopyISupportsStrings(nsIArray* aSourceStrings, nsIArray** aTargetStrings);
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PPaymentRequest.ipdl
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
+/* 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 protocol PBrowser;
+
+namespace mozilla {
+namespace dom {
+
+struct IPCPaymentMethodData
+{
+ nsString[] supportedMethods;
+ nsString data;
+};
+
+struct IPCPaymentCurrencyAmount
+{
+ nsString currency;
+ nsString value;
+};
+
+struct IPCPaymentItem
+{
+ nsString label;
+ IPCPaymentCurrencyAmount amount;
+ bool pending;
+};
+
+struct IPCPaymentDetailsModifier
+{
+ nsString[] supportedMethods;
+ IPCPaymentItem total;
+ IPCPaymentItem[] additionalDisplayItems;
+ nsString data;
+ bool additionalDisplayItemsPassed;
+};
+
+struct IPCPaymentShippingOption
+{
+ nsString id;
+ nsString label;
+ IPCPaymentCurrencyAmount amount;
+ bool selected;
+};
+
+struct IPCPaymentDetails
+{
+ nsString id;
+ IPCPaymentItem total;
+ IPCPaymentItem[] displayItems;
+ IPCPaymentShippingOption[] shippingOptions;
+ IPCPaymentDetailsModifier[] modifiers;
+ nsString error;
+ bool displayItemsPassed;
+ bool shippingOptionsPassed;
+ bool modifiersPassed;
+};
+
+struct IPCPaymentOptions
+{
+ bool requestPayerName;
+ bool requestPayerEmail;
+ bool requestPayerPhone;
+ bool requestShipping;
+ nsString shippingType;
+};
+
+struct IPCPaymentCreateActionRequest
+{
+ nsString requestId;
+ IPCPaymentMethodData[] methodData;
+ IPCPaymentDetails details;
+ IPCPaymentOptions options;
+};
+
+union IPCPaymentActionRequest
+{
+ IPCPaymentCreateActionRequest;
+};
+
+sync protocol PPaymentRequest
+{
+ manager PBrowser;
+
+parent:
+ async __delete__();
+
+ async RequestPayment(IPCPaymentActionRequest aAction);
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestChild.cpp
@@ -0,0 +1,53 @@
+/* -*- 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 "PaymentRequestChild.h"
+#include "mozilla/dom/PaymentRequestManager.h"
+
+namespace mozilla {
+namespace dom {
+
+PaymentRequestChild::PaymentRequestChild()
+ : mActorAlive(true)
+{
+}
+
+nsresult
+PaymentRequestChild::RequestPayment(const IPCPaymentActionRequest& aAction)
+{
+ if (!mActorAlive) {
+ return NS_ERROR_FAILURE;
+ }
+ SendRequestPayment(aAction);
+ return NS_OK;
+}
+
+void
+PaymentRequestChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+ mActorAlive = false;
+ RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
+ MOZ_ASSERT(manager);
+ manager->ReleasePaymentChild(this);
+}
+
+void
+PaymentRequestChild::MaybeDelete()
+{
+ if (mActorAlive) {
+ mActorAlive = false;
+ Send__delete__(this);
+ }
+}
+
+bool
+PaymentRequestChild::SendRequestPayment(const IPCPaymentActionRequest& aAction)
+{
+ return PPaymentRequestChild::SendRequestPayment(aAction);
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestChild.h
@@ -0,0 +1,37 @@
+/* -*- 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_PaymentRequestChild_h
+#define mozilla_dom_PaymentRequestChild_h
+
+#include "mozilla/dom/PPaymentRequestChild.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentRequestChild final : public PPaymentRequestChild
+{
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PaymentRequestChild);
+public:
+ PaymentRequestChild();
+
+ void ActorDestroy(ActorDestroyReason aWhy) override;
+
+ void MaybeDelete();
+
+ nsresult RequestPayment(const IPCPaymentActionRequest& aAction);
+private:
+ ~PaymentRequestChild() = default;
+
+ bool SendRequestPayment(const IPCPaymentActionRequest& aAction);
+
+ bool mActorAlive;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestParent.cpp
@@ -0,0 +1,109 @@
+/* -*- 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/ipc/InputStreamUtils.h"
+#include "nsArrayUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIMutableArray.h"
+#include "nsIPaymentActionRequest.h"
+#include "nsIPaymentRequestService.h"
+#include "nsISupportsPrimitives.h"
+#include "nsServiceManagerUtils.h"
+#include "PaymentRequestData.h"
+#include "PaymentRequestParent.h"
+
+namespace mozilla {
+namespace dom {
+
+PaymentRequestParent::PaymentRequestParent(uint64_t aTabId)
+ : mActorAlived(true)
+ , mTabId(aTabId)
+{
+}
+
+mozilla::ipc::IPCResult
+PaymentRequestParent::RecvRequestPayment(const IPCPaymentActionRequest& aRequest)
+{
+ MOZ_ASSERT(mActorAlived);
+ nsCOMPtr<nsIPaymentActionRequest> actionRequest;
+ nsresult rv;
+ switch (aRequest.type()) {
+ case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: {
+ IPCPaymentCreateActionRequest request = aRequest;
+
+ nsCOMPtr<nsIMutableArray> methodData = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ MOZ_ASSERT(methodData);
+ for (IPCPaymentMethodData data : request.methodData()) {
+ nsCOMPtr<nsIPaymentMethodData> method;
+ rv = payments::PaymentMethodData::Create(data, getter_AddRefs(method));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ rv = methodData->AppendElement(method, false);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ }
+
+ nsCOMPtr<nsIPaymentDetails> details;
+ rv = payments::PaymentDetails::Create(request.details(), getter_AddRefs(details));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+
+ nsCOMPtr<nsIPaymentOptions> options;
+ rv = payments::PaymentOptions::Create(request.options(), getter_AddRefs(options));
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+
+ nsCOMPtr<nsIPaymentCreateActionRequest> createRequest =
+ do_CreateInstance(NS_PAYMENT_CREATE_ACTION_REQUEST_CONTRACT_ID);
+ if (NS_WARN_IF(!createRequest)) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ rv = createRequest->InitRequest(request.requestId(),
+ mTabId,
+ methodData,
+ details,
+ options);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+
+ actionRequest = do_QueryInterface(createRequest);
+ MOZ_ASSERT(actionRequest);
+ break;
+ }
+ default: {
+ return IPC_FAIL(this, "Unexpected request type");
+ }
+ }
+ nsCOMPtr<nsIPaymentRequestService> service =
+ do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID);
+ MOZ_ASSERT(service);
+ rv = service->RequestPayment(actionRequest);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return IPC_FAIL_NO_REASON(this);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+PaymentRequestParent::Recv__delete__()
+{
+ mActorAlived = false;
+ return IPC_OK();
+}
+
+void
+PaymentRequestParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+ mActorAlived = false;
+}
+
+} // end of namespace dom
+} // end of namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/PaymentRequestParent.h
@@ -0,0 +1,40 @@
+/* -*- 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_PaymentRequestParent_h
+#define mozilla_dom_PaymentRequestParent_h
+
+#include "mozilla/dom/PPaymentRequestParent.h"
+#include "nsISupports.h"
+
+namespace mozilla {
+namespace dom {
+
+class PaymentRequestParent final : public PPaymentRequestParent
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PaymentRequestParent)
+
+ explicit PaymentRequestParent(uint64_t aTabId);
+
+protected:
+ mozilla::ipc::IPCResult
+ RecvRequestPayment(const IPCPaymentActionRequest& aRequest) override;
+
+ mozilla::ipc::IPCResult Recv__delete__() override;
+
+ void ActorDestroy(ActorDestroyReason aWhy) override;
+private:
+ ~PaymentRequestParent() = default;
+
+ bool mActorAlived;
+ uint64_t mTabId;
+};
+
+} // end of namespace dom
+} // end of namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/payments/ipc/moz.build
@@ -0,0 +1,23 @@
+# -*- Mode: python; 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/.
+
+EXPORTS.mozilla.dom += [
+ 'PaymentRequestChild.h',
+ 'PaymentRequestParent.h',
+]
+
+UNIFIED_SOURCES += [
+ 'PaymentRequestChild.cpp',
+ 'PaymentRequestParent.cpp',
+]
+
+IPDL_SOURCES += [
+ 'PPaymentRequest.ipdl',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/dom/payments/moz.build
@@ -0,0 +1,35 @@
+# -*- Mode: python; 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/.
+
+DIRS += [
+ 'ipc',
+]
+
+EXPORTS += [
+ 'PaymentRequestData.h',
+ 'PaymentRequestService.h',
+]
+
+EXPORTS.mozilla.dom += [
+ 'PaymentRequest.h',
+ 'PaymentRequestManager.h',
+]
+
+UNIFIED_SOURCES += [
+ 'PaymentActionRequest.cpp',
+ 'PaymentRequest.cpp',
+ 'PaymentRequestData.cpp',
+ 'PaymentRequestManager.cpp',
+ 'PaymentRequestModule.cpp',
+ 'PaymentRequestService.cpp',
+ 'PaymentRequestUtils.cpp',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
+
+BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser.ini
@@ -0,0 +1,11 @@
+[DEFAULT]
+# skip-if !e10s will be removed once non-e10s is supported
+skip-if = !e10s
+support-files =
+ head.js
+ simple_payment_request.html
+ multiple_payment_request.html
+
+[browser_payment_construction.js]
+[browser_multiple_construction.js]
+[browser_payment_in_different_tabs.js]
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser_multiple_construction.js
@@ -0,0 +1,32 @@
+"use strict";
+
+// kTestRoot is from head.js
+const kTestPage = kTestRoot + "multiple_payment_request.html";
+
+registerCleanupFunction(cleanup);
+
+add_task(function*() {
+ Services.prefs.setBoolPref("dom.payments.request.enabled", true);
+ yield BrowserTestUtils.withNewTab(kTestPage,
+ function*(browser) {
+
+ const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+ ok(paymentSrv, "Fail to get PaymentRequestService.");
+
+ const paymentEnum = paymentSrv.enumerate();
+ ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
+ while (paymentEnum.hasMoreElements()) {
+ let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ ok(payment, "Fail to get existing payment request.");
+ if (payment.paymentDetails.id == "complex details") {
+ checkComplexPayment(payment);
+ } else if (payment.paymentDetails.id == "simple details") {
+ checkSimplePayment(payment);
+ } else {
+ ok(false, "Unknown payment.");
+ }
+ }
+ Services.prefs.setBoolPref("dom.payments.request.enabled", false);
+ }
+ );
+});
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser_payment_construction.js
@@ -0,0 +1,26 @@
+"use strict";
+
+// kTestRoot is from head.js
+const kTestPage = kTestRoot + "simple_payment_request.html";
+
+registerCleanupFunction(cleanup);
+
+add_task(function*() {
+ Services.prefs.setBoolPref("dom.payments.request.enabled", true);
+ yield BrowserTestUtils.withNewTab(kTestPage,
+ function*(browser) {
+
+ const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+ ok(paymentSrv, "Fail to get PaymentRequestService.");
+
+ const paymentEnum = paymentSrv.enumerate();
+ ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
+ while (paymentEnum.hasMoreElements()) {
+ let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ ok(payment, "Fail to get existing payment request.");
+ checkSimplePayment(payment);
+ }
+ Services.prefs.setBoolPref("dom.payments.request.enabled", false);
+ }
+ );
+});
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/browser_payment_in_different_tabs.js
@@ -0,0 +1,33 @@
+"use strict";
+
+// kTestRoot is from head.js
+const kTestPage = kTestRoot + "simple_payment_request.html";
+
+registerCleanupFunction(cleanup);
+
+add_task(function*() {
+ Services.prefs.setBoolPref("dom.payments.request.enabled", true);
+ yield BrowserTestUtils.withNewTab(kTestPage,
+ function*(browser) {
+ yield BrowserTestUtils.withNewTab(kTestPage,
+ function*(browser) {
+ const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+ ok(paymentSrv, "Fail to get PaymentRequestService.");
+
+ const paymentEnum = paymentSrv.enumerate();
+ ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request.");
+ let tabIds = [];
+ while (paymentEnum.hasMoreElements()) {
+ let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest);
+ ok(payment, "Fail to get existing payment request.");
+ checkSimplePayment(payment);
+ tabIds.push(payment.tabId);
+ }
+ is(tabIds.length, 2, "TabId array length should be 2.");
+ ok(tabIds[0] != tabIds[1], "TabIds should be different.");
+ Services.prefs.setBoolPref("dom.payments.request.enabled", false);
+ }
+ );
+ }
+ );
+});
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/head.js
@@ -0,0 +1,120 @@
+const kTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content",
+ "https://example.com");
+
+function checkSimplePayment(aSimplePayment) {
+ // checking the passed PaymentMethods parameter
+ is(aSimplePayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
+
+ const methodData = aSimplePayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
+ ok(methodData, "Fail to get payment methodData.");
+ is(methodData.supportedMethods.length, 2, "supportedMethods' length should be 2.");
+ let supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
+ is(supportedMethod, "MyPay", "1st supported method should be 'MyPay'.");
+ supportedMethod = methodData.supportedMethods.queryElementAt(1, Ci.nsISupportsString);
+ is(supportedMethod, "TestPay", "2nd supported method should be 'TestPay'.");
+ is(methodData.data, "", "method data should be empty");
+
+ // checking the passed PaymentDetails parameter
+ const details = aSimplePayment.paymentDetails;
+ is(details.id, "simple details", "details.id should be 'simple details'.");
+ is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
+ is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
+ is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
+
+ ok(!details.displayItems, "details.displayItems should be undefined.");
+ ok(!details.modifiers, "details.modifiers should be undefined.");
+ ok(!details.shippingOptions, "details.shippingOptions should be undefined.");
+
+ // checking the default generated PaymentOptions parameter
+ const paymentOptions = aSimplePayment.paymentOptions;
+ ok(!paymentOptions.requestPayerName, "payerName option should be false");
+ ok(!paymentOptions.requestPayerEmail, "payerEmail option should be false");
+ ok(!paymentOptions.requestPayerPhone, "payerPhone option should be false");
+ ok(!paymentOptions.requestShipping, "requestShipping option should be false");
+ is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
+}
+
+function checkComplexPayment(aPayment) {
+ // checking the passed PaymentMethods parameter
+ is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1.");
+
+ const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData);
+ ok(methodData, "Fail to get payment methodData.");
+ is(methodData.supportedMethods.length, 2, "supportedMethods' length should be 2.");
+ let supportedMethod = methodData.supportedMethods.queryElementAt(0, Ci.nsISupportsString);
+ is(supportedMethod, "MyPay", "1st supported method should be 'MyPay'.");
+ supportedMethod = methodData.supportedMethods.queryElementAt(1, Ci.nsISupportsString);
+ is(supportedMethod, "TestPay", "2nd supported method should be 'TestPay'.");
+ is(methodData.data, "", "method data should be empty");
+
+ // checking the passed PaymentDetails parameter
+ const details = aPayment.paymentDetails;
+ is(details.id, "complex details", "details.id should be 'complex details'.");
+ is(details.totalItem.label, "Donation", "total item's label should be 'Donation'.");
+ is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'.");
+ is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'.");
+
+ const displayItems = details.displayItems;
+ is(displayItems.length, 2, "displayItems' length should be 2.");
+ let item = displayItems.queryElementAt(0, Ci.nsIPaymentItem);
+ is(item.label, "Original donation amount", "1st display item's label should be 'Original donation amount'.");
+ is(item.amount.currency, "USD", "1st display item's currency should be 'USD'.");
+ is(item.amount.value, "-65.00", "1st display item's value should be '-65.00'.");
+ item = displayItems.queryElementAt(1, Ci.nsIPaymentItem);
+ is(item.label, "Friends and family discount", "2nd display item's label should be 'Friends and family discount'.");
+ is(item.amount.currency, "USD", "2nd display item's currency should be 'USD'.");
+ is(item.amount.value, "10.00", "2nd display item's value should be '10.00'.");
+
+ const modifiers = details.modifiers;
+ is(modifiers.length, 1, "modifiers' length should be 1.");
+
+ const modifier = modifiers.queryElementAt(0, Ci.nsIPaymentDetailsModifier);
+ const modifierSupportedMethods = modifier.supportedMethods;
+ is(modifierSupportedMethods.length, 1, "modifier's supported methods length should be 1.");
+ supportedMethod = modifierSupportedMethods.queryElementAt(0, Ci.nsISupportsString);
+ is(supportedMethod, "MyPay", "modifier's supported method name should be 'MyPay'.");
+ is(modifier.total.label, "Discounted donation", "modifier's total label should be 'Discounted donation'.");
+ is(modifier.total.amount.currency, "USD", "modifier's total currency should be 'USD'.");
+ is(modifier.total.amount.value, "45.00", "modifier's total value should be '45.00'.");
+
+ const additionalItems = modifier.additionalDisplayItems;
+ is(additionalItems.length, "1", "additionalDisplayItems' length should be 1.");
+ const additionalItem = additionalItems.queryElementAt(0, Ci.nsIPaymentItem);
+ is(additionalItem.label, "MyPay discount", "additional item's label should be 'MyPay discount'.");
+ is(additionalItem.amount.currency, "USD", "additional item's currency should be 'USD'.");
+ is(additionalItem.amount.value, "-10.00", "additional item's value should be '-10.00'.");
+ is(modifier.data, "{\"discountProgramParticipantId\":\"86328764873265\"}",
+ "modifier's data should be '{\"discountProgramParticipantId\":\"86328764873265\"}'.");
+
+ const shippingOptions = details.shippingOptions;
+ is(shippingOptions.length, 2, "shippingOptions' length should be 2.");
+
+ let shippingOption = shippingOptions.queryElementAt(0, Ci.nsIPaymentShippingOption);
+ is(shippingOption.id, "NormalShipping", "1st shippingOption's id should be 'NoramlShpping'.");
+ is(shippingOption.label, "NormalShipping", "1st shippingOption's lable should be 'NormalShipping'.");
+ is(shippingOption.amount.currency, "USD", "1st shippingOption's amount currency should be 'USD'.");
+ is(shippingOption.amount.value, "10.00", "1st shippingOption's amount value should be '10.00'.");
+ ok(shippingOption.selected, "1st shippingOption should be selected.");
+
+ shippingOption = shippingOptions.queryElementAt(1, Ci.nsIPaymentShippingOption);
+ is(shippingOption.id, "FastShipping", "2nd shippingOption's id should be 'FastShpping'.");
+ is(shippingOption.label, "FastShipping", "2nd shippingOption's lable should be 'FastShipping'.");
+ is(shippingOption.amount.currency, "USD", "2nd shippingOption's amount currency should be 'USD'.");
+ is(shippingOption.amount.value, "30.00", "2nd shippingOption's amount value should be '30.00'.");
+ ok(!shippingOption.selected, "2nd shippingOption should not be selected.");
+
+ // checking the passed PaymentOptions parameter
+ const paymentOptions = aPayment.paymentOptions;
+ ok(paymentOptions.requestPayerName, "payerName option should be true");
+ ok(paymentOptions.requestPayerEmail, "payerEmail option should be true");
+ ok(paymentOptions.requestPayerPhone, "payerPhone option should be true");
+ ok(paymentOptions.requestShipping, "requestShipping option should be true");
+ is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'");
+}
+
+function cleanup() {
+ const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
+ if (paymentSrv) {
+ paymentSrv.cleanup();
+ }
+}
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/multiple_payment_request.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Payment Request Testing</title>
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+ <meta content="utf-8" http-equiv="encoding">
+ </head>
+ <body>
+ <script type="text/javascript">
+ const supportedInstruments = [{
+ supportedMethods: [ "MyPay", "TestPay" ]
+ }];
+ const complexDetails = {
+ id: "complex details",
+ total: {
+ label: "Donation",
+ amount: { currency: "USD", value: "55.00" }
+ },
+ displayItems: [
+ {
+ label: "Original donation amount",
+ amount: { currency: "USD", value: "-65.00", }
+ },
+ {
+ label: "Friends and family discount",
+ amount: { currency: "USD", value: "10.00", }
+ }
+ ],
+ modifiers: [
+ {
+ supportedMethods: ["MyPay"],
+ total: {
+ label: "Discounted donation",
+ amount: { currency: "USD", value: "45.00", }
+ },
+ additionalDisplayItems: [
+ {
+ label: "MyPay discount",
+ amount: { currency: "USD", value: "-10.00", }
+ }
+ ],
+ data: { discountProgramParticipantId: "86328764873265", }
+ },
+ ],
+ shippingOptions: [
+ {
+ id: "NormalShipping",
+ label: "NormalShipping",
+ amount: { currency: "USD", value: "10.00", },
+ selected: true,
+ },
+ {
+ id: "FastShipping",
+ label: "FastShipping",
+ amount: { currency: "USD", value: "30.00", },
+ selected: false,
+ },
+ ],
+ };
+
+ const simpleDetails = {
+ id: "simple details",
+ total: {
+ label: "Donation",
+ amount: { currency: "USD", value: "55.00" }
+ },
+ };
+
+ const options = {
+ requestPayerName: true,
+ requestPayerEmail: true,
+ requestPayerPhone: true,
+ requestShipping: true,
+ shippingType: "shipping",
+ };
+
+ const paymentRequest1 = new PaymentRequest(supportedInstruments,
+ complexDetails,
+ options);
+ const paymentRequest2 = new PaymentRequest(supportedInstruments,
+ simpleDetails);
+ </script>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/payments/test/simple_payment_request.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Payment Request Testing</title>
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+ <meta content="utf-8" http-equiv="encoding">
+ </head>
+ <body>
+ <script type="text/javascript">
+ const supportedInstruments = [{
+ supportedMethods: [ "MyPay", "TestPay" ]
+ }];
+ const details = {
+ id: "simple details",
+ total: {
+ label: "Donation",
+ amount: { currency: "USD", value: "55.00" }
+ },
+ };
+ const payRequest = new PaymentRequest(supportedInstruments, details);
+ </script>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/webidl/PaymentRequest.webidl
@@ -0,0 +1,89 @@
+/* -*- 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/.
+ *
+ * The origin of this WebIDL file is
+ * https://www.w3.org/TR/payment-request/#paymentrequest-interface
+ */
+
+dictionary PaymentMethodData {
+ required sequence<DOMString> supportedMethods;
+ object data;
+};
+
+dictionary PaymentCurrencyAmount {
+ required DOMString currency;
+ required DOMString value;
+ DOMString currencySystem = "urn:iso:std:iso:4217";
+};
+
+dictionary PaymentItem {
+ required DOMString label;
+ required PaymentCurrencyAmount amount;
+ boolean pending = false;
+};
+
+dictionary PaymentShippingOption {
+ required DOMString id;
+ required DOMString label;
+ required PaymentCurrencyAmount amount;
+ boolean selected = false;
+};
+
+dictionary PaymentDetailsModifier {
+ required sequence<DOMString> supportedMethods;
+ PaymentItem total;
+ sequence<PaymentItem> additionalDisplayItems;
+ object data;
+};
+
+dictionary PaymentDetailsBase {
+ sequence<PaymentItem> displayItems;
+ sequence<PaymentShippingOption> shippingOptions;
+ sequence<PaymentDetailsModifier> modifiers;
+};
+
+dictionary PaymentDetailsInit : PaymentDetailsBase {
+ DOMString id;
+ required PaymentItem total;
+};
+
+enum PaymentShippingType {
+ "shipping",
+ "delivery",
+ "pickup"
+};
+
+dictionary PaymentOptions {
+ boolean requestPayerName = false;
+ boolean requestPayerEmail = false;
+ boolean requestPayerPhone = false;
+ boolean requestShipping = false;
+ PaymentShippingType shippingType = "shipping";
+};
+
+[Constructor(sequence<PaymentMethodData> methodData, PaymentDetailsInit details,
+ optional PaymentOptions options),
+ SecureContext,
+ Func="mozilla::dom::PaymentRequest::PrefEnabled"]
+interface PaymentRequest : EventTarget {
+ /* TODO : Add show() support in Bug 1345366
+ [NewObject]
+ Promise<PaymentResponse> show();
+ */
+ [NewObject]
+ Promise<void> abort();
+ [NewObject]
+ Promise<boolean> canMakePayment();
+
+ readonly attribute DOMString id;
+ /* TODO : Add PaymentAddress support in Bug 1345369
+ readonly attribute PaymentAddress? shippingAddress;
+ */
+ readonly attribute DOMString? shippingOption;
+ readonly attribute PaymentShippingType? shippingType;
+
+ attribute EventHandler onshippingaddresschange;
+ attribute EventHandler onshippingoptionchange;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -716,16 +716,17 @@ WEBIDL_FILES = [
'OfflineResourceList.webidl',
'OffscreenCanvas.webidl',
'OscillatorNode.webidl',
'PaintRequest.webidl',
'PaintRequestList.webidl',
'PaintWorkletGlobalScope.webidl',
'PannerNode.webidl',
'ParentNode.webidl',
+ 'PaymentRequest.webidl',
'Performance.webidl',
'PerformanceEntry.webidl',
'PerformanceMark.webidl',
'PerformanceMeasure.webidl',
'PerformanceNavigation.webidl',
'PerformanceObserver.webidl',
'PerformanceObserverEntryList.webidl',
'PerformanceResourceTiming.webidl',
new file mode 100644
--- /dev/null
+++ b/dom/xslt/crashtests/1361892.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <script id=o_xml type="text/plain"><?xml version="1.0" encoding="UTF-8"?>
+<tag_name/>
+ </script>
+ <script id=o_xslt type="text/plain"><?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="42">
+ <xsl:template match="*">
+ <xsl:value-of xmlns:regexp="http://exslt.org/regular-expressions" select="regexp:match('foo','bar','-2')"/>
+ </xsl:template>
+</xsl:stylesheet>
+ </script>
+ <script>
+window.onload = function(){
+ let doc = new DOMParser(), proc = new XSLTProcessor();
+ proc.importStylesheet(doc.parseFromString(document.getElementById('o_xslt').textContent, "text/xml"));
+ proc.transformToDocument(doc.parseFromString(document.getElementById('o_xml').textContent, "text/xml"));
+};
+ </script>
+ </head>
+</html>
--- a/dom/xslt/crashtests/crashtests.list
+++ b/dom/xslt/crashtests/crashtests.list
@@ -14,8 +14,9 @@ load 545927.html
load 601543.html
load 602115.html
load 603844.html
load 667315.xml
load 1089049.html
load 1205163.xml
load 1243337.xml
load 1338277.html
+load 1361892.html
--- a/dom/xslt/xpath/txXPCOMExtensionFunction.cpp
+++ b/dom/xslt/xpath/txXPCOMExtensionFunction.cpp
@@ -340,17 +340,19 @@ txParamArrayHolder::~txParamArrayHolder(
if (variant.DoesValNeedCleanup()) {
if (variant.type.TagPart() == nsXPTType::T_DOMSTRING)
delete (nsAString*)variant.val.p;
else {
MOZ_ASSERT(variant.type.TagPart() == nsXPTType::T_INTERFACE ||
variant.type.TagPart() == nsXPTType::T_INTERFACE_IS,
"We only support cleanup of strings and interfaces "
"here, and this looks like neither!");
- static_cast<nsISupports*>(variant.val.p)->Release();
+ if (variant.val.p != nullptr) {
+ static_cast<nsISupports*>(variant.val.p)->Release();
+ }
}
}
}
}
bool
txParamArrayHolder::Init(uint8_t aCount)
{
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -846,21 +846,21 @@ NotifySwitchChange(const SwitchEvent& aE
if (!sSwitchObserverLists)
return;
SwitchObserverList& observer = GetSwitchObserverList(aEvent.device());
observer.Broadcast(aEvent);
}
void
-SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
+SetProcessPriority(int aPid, ProcessPriority aPriority)
{
// n.b. The sandboxed implementation crashes; SetProcessPriority works only
// from the main process.
- PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority, aLRU));
+ PROXY_IF_SANDBOXED(SetProcessPriority(aPid, aPriority));
}
void
SetCurrentThreadPriority(hal::ThreadPriority aThreadPriority)
{
PROXY_IF_SANDBOXED(SetCurrentThreadPriority(aThreadPriority));
}
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -432,19 +432,17 @@ void NotifySwitchStateFromInputDevice(ha
/**
* Set the priority of the given process.
*
* Exactly what this does will vary between platforms. On *nix we might give
* background processes higher nice values. On other platforms, we might
* ignore this call entirely.
*/
-void SetProcessPriority(int aPid,
- hal::ProcessPriority aPriority,
- uint32_t aLRU = 0);
+void SetProcessPriority(int aPid, hal::ProcessPriority aPriority);
/**
* Set the current thread's priority to appropriate platform-specific value for
* given functionality. Instead of providing arbitrary priority numbers you
* must specify a type of function like THREAD_PRIORITY_COMPOSITOR.
*/
void SetCurrentThreadPriority(hal::ThreadPriority aThreadPriority);
--- a/hal/fallback/FallbackProcessPriority.cpp
+++ b/hal/fallback/FallbackProcessPriority.cpp
@@ -6,16 +6,16 @@
#include "HalLog.h"
using namespace mozilla::hal;
namespace mozilla {
namespace hal_impl {
void
-SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
+SetProcessPriority(int aPid, ProcessPriority aPriority)
{
- HAL_LOG("FallbackProcessPriority - SetProcessPriority(%d, %s, %u)\n",
- aPid, ProcessPriorityToString(aPriority), aLRU);
+ HAL_LOG("FallbackProcessPriority - SetProcessPriority(%d, %s)\n",
+ aPid, ProcessPriorityToString(aPriority));
}
} // namespace hal_impl
} // namespace mozilla
deleted file mode 100644
--- a/hal/gonk/nsIRecoveryService.idl
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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 "nsISupports.idl"
-
-[scriptable, uuid(bc24fb33-a0c1-49ca-aa43-05f167e02fb6)]
-interface nsIRecoveryService : nsISupports
-{
- /**
- * Possible values of fotaStatus.result. These should stay in sync with
- * librecovery/librecovery.h
- */
- const long FOTA_UPDATE_UNKNOWN = 0;
- const long FOTA_UPDATE_FAIL = 1;
- const long FOTA_UPDATE_SUCCESS = 2;
-
- /**
- * Uses recovery to wipe the data and cache partitions. If this call is
- * successful, the device should reboot before the function call ever returns.
- *
- * @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason.
- */
- void factoryReset(in string reason);
-
- /**
- * Use recovery to install an OTA update.zip. If this call is
- * successful, the device should reboot before the function call ever returns.
- *
- * @throws NS_ERROR_FAILURE when rebooting into recovery fails for some reason.
- */
- void installFotaUpdate(in string updatePath);
-
- /**
- * @return The status of the last FOTA update. One of FOTA_UPDATE_UNKNOWN,
- * FOTA_UPDATE_FAIL, FOTA_UPDATE_SUCCESS.
- */
- long getFotaUpdateStatus();
-};
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -2,22 +2,16 @@
# 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/.
with Files('**'):
BUG_COMPONENT = ('Core', 'Hardware Abstraction Layer (HAL)')
-XPIDL_SOURCES += [
- 'gonk/nsIRecoveryService.idl',
-]
-
-XPIDL_MODULE = 'hal'
-
EXPORTS.mozilla += [
'Hal.h',
'HalImpl.h',
'HalSandbox.h',
'HalScreenConfiguration.h',
'HalSensor.h',
'HalTypes.h',
'HalWakeLock.h',
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -344,17 +344,17 @@ DisableAlarm()
bool
SetAlarm(int32_t aSeconds, int32_t aNanoseconds)
{
NS_RUNTIMEABORT("Alarms can't be programmed from sandboxed contexts. Yet.");
return false;
}
void
-SetProcessPriority(int aPid, ProcessPriority aPriority, uint32_t aLRU)
+SetProcessPriority(int aPid, ProcessPriority aPriority)
{
NS_RUNTIMEABORT("Only the main process may set processes' priorities.");
}
void
SetCurrentThreadPriority(ThreadPriority aThreadPriority)
{
NS_RUNTIMEABORT("Setting current thread priority cannot be called from sandboxed contexts.");
--- a/ipc/glue/BackgroundUtils.cpp
+++ b/ipc/glue/BackgroundUtils.cpp
@@ -5,27 +5,29 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BackgroundUtils.h"
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
+#include "mozilla/ipc/URIUtils.h"
#include "mozilla/net/NeckoChannelParams.h"
#include "ExpandedPrincipal.h"
#include "nsIScriptSecurityManager.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "mozilla/LoadInfo.h"
#include "ContentPrincipal.h"
#include "NullPrincipal.h"
#include "nsContentUtils.h"
#include "nsString.h"
#include "nsTArray.h"
+#include "mozilla/nsRedirectHistoryEntry.h"
namespace mozilla {
namespace net {
class OptionalLoadInfoArgs;
}
using mozilla::BasePrincipal;
using namespace mozilla::net;
@@ -253,16 +255,56 @@ IsPincipalInfoPrivate(const PrincipalInf
if (aPrincipalInfo.type() != ipc::PrincipalInfo::TContentPrincipalInfo) {
return false;
}
const ContentPrincipalInfo& info = aPrincipalInfo.get_ContentPrincipalInfo();
return !!info.attrs().mPrivateBrowsingId;
}
+already_AddRefed<nsIRedirectHistoryEntry>
+RHEntryInfoToRHEntry(const RedirectHistoryEntryInfo& aRHEntryInfo)
+{
+ nsresult rv;
+ nsCOMPtr<nsIPrincipal> principal =
+ PrincipalInfoToPrincipal(aRHEntryInfo.principalInfo(), &rv);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return nullptr;
+ }
+
+ nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aRHEntryInfo.referrerUri());
+
+ nsCOMPtr<nsIRedirectHistoryEntry> entry =
+ new nsRedirectHistoryEntry(principal, referrerUri, aRHEntryInfo.remoteAddress());
+
+ return entry.forget();
+}
+
+nsresult
+RHEntryToRHEntryInfo(nsIRedirectHistoryEntry* aRHEntry,
+ RedirectHistoryEntryInfo* aRHEntryInfo)
+{
+ MOZ_ASSERT(aRHEntry);
+ MOZ_ASSERT(aRHEntryInfo);
+
+ nsresult rv;
+ aRHEntry->GetRemoteAddress(aRHEntryInfo->remoteAddress());
+
+ nsCOMPtr<nsIURI> referrerUri;
+ rv = aRHEntry->GetReferrerURI(getter_AddRefs(referrerUri));
+ NS_ENSURE_SUCCESS(rv, rv);
+ SerializeURI(referrerUri, aRHEntryInfo->referrerUri());
+
+ nsCOMPtr<nsIPrincipal> principal;
+ rv = aRHEntry->GetPrincipal(getter_AddRefs(principal));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return PrincipalToPrincipalInfo(principal, &aRHEntryInfo->principalInfo());
+}
+
nsresult
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
OptionalLoadInfoArgs* aOptionalLoadInfoArgs)
{
if (!aLoadInfo) {
// if there is no loadInfo, then there is nothing to serialize
*aOptionalLoadInfoArgs = void_t();
return NS_OK;
@@ -299,25 +341,29 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoa
getter_AddRefs(sandboxedLoadingPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
rv = PrincipalToPrincipalInfo(sandboxedLoadingPrincipal,
&sandboxedLoadingPrincipalInfoTemp);
NS_ENSURE_SUCCESS(rv, rv);
sandboxedLoadingPrincipalInfo = sandboxedLoadingPrincipalInfoTemp;
}
- nsTArray<PrincipalInfo> redirectChainIncludingInternalRedirects;
- for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChainIncludingInternalRedirects()) {
- rv = PrincipalToPrincipalInfo(principal, redirectChainIncludingInternalRedirects.AppendElement());
+ nsTArray<RedirectHistoryEntryInfo> redirectChainIncludingInternalRedirects;
+ for (const nsCOMPtr<nsIRedirectHistoryEntry>& redirectEntry :
+ aLoadInfo->RedirectChainIncludingInternalRedirects()) {
+ RedirectHistoryEntryInfo* entry = redirectChainIncludingInternalRedirects.AppendElement();
+ rv = RHEntryToRHEntryInfo(redirectEntry, entry);
NS_ENSURE_SUCCESS(rv, rv);
}
- nsTArray<PrincipalInfo> redirectChain;
- for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChain()) {
- rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement());
+ nsTArray<RedirectHistoryEntryInfo> redirectChain;
+ for (const nsCOMPtr<nsIRedirectHistoryEntry>& redirectEntry :
+ aLoadInfo->RedirectChain()) {
+ RedirectHistoryEntryInfo* entry = redirectChain.AppendElement();
+ rv = RHEntryToRHEntryInfo(redirectEntry, entry);
NS_ENSURE_SUCCESS(rv, rv);
}
*aOptionalLoadInfoArgs =
LoadInfoArgs(
loadingPrincipalInfo,
triggeringPrincipalInfo,
principalToInheritInfo,
@@ -380,30 +426,31 @@ LoadInfoArgsToLoadInfo(const OptionalLoa
nsCOMPtr<nsIPrincipal> sandboxedLoadingPrincipal;
if (loadInfoArgs.sandboxedLoadingPrincipalInfo().type() != OptionalPrincipalInfo::Tvoid_t) {
sandboxedLoadingPrincipal =
PrincipalInfoToPrincipal(loadInfoArgs.sandboxedLoadingPrincipalInfo(), &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
- nsTArray<nsCOMPtr<nsIPrincipal>> redirectChainIncludingInternalRedirects;
- for (const PrincipalInfo& principalInfo : loadInfoArgs.redirectChainIncludingInternalRedirects()) {
- nsCOMPtr<nsIPrincipal> redirectedPrincipal =
- PrincipalInfoToPrincipal(principalInfo, &rv);
+ RedirectHistoryArray redirectChainIncludingInternalRedirects;
+ for (const RedirectHistoryEntryInfo& entryInfo :
+ loadInfoArgs.redirectChainIncludingInternalRedirects()) {
+ nsCOMPtr<nsIRedirectHistoryEntry> redirectHistoryEntry =
+ RHEntryInfoToRHEntry(entryInfo);
NS_ENSURE_SUCCESS(rv, rv);
- redirectChainIncludingInternalRedirects.AppendElement(redirectedPrincipal.forget());
+ redirectChainIncludingInternalRedirects.AppendElement(redirectHistoryEntry.forget());
}
- nsTArray<nsCOMPtr<nsIPrincipal>> redirectChain;
- for (const PrincipalInfo& principalInfo : loadInfoArgs.redirectChain()) {
- nsCOMPtr<nsIPrincipal> redirectedPrincipal =
- PrincipalInfoToPrincipal(principalInfo, &rv);
+ RedirectHistoryArray redirectChain;
+ for (const RedirectHistoryEntryInfo& entryInfo : loadInfoArgs.redirectChain()) {
+ nsCOMPtr<nsIRedirectHistoryEntry> redirectHistoryEntry =
+ RHEntryInfoToRHEntry(entryInfo);
NS_ENSURE_SUCCESS(rv, rv);
- redirectChain.AppendElement(redirectedPrincipal.forget());
+ redirectChain.AppendElement(redirectHistoryEntry.forget());
}
nsCOMPtr<nsILoadInfo> loadInfo =
new mozilla::LoadInfo(loadingPrincipal,
triggeringPrincipal,
principalToInherit,
sandboxedLoadingPrincipal,
loadInfoArgs.securityFlags(),
--- a/ipc/glue/BackgroundUtils.h
+++ b/ipc/glue/BackgroundUtils.h
@@ -10,16 +10,17 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/BasePrincipal.h"
#include "nsCOMPtr.h"
#include "nscore.h"
class nsILoadInfo;
class nsIPrincipal;
+class nsIRedirectHistoryEntry;
namespace IPC {
namespace detail {
template<class ParamType>
struct OriginAttributesParamTraits
{
typedef ParamType paramType;
@@ -44,16 +45,17 @@ template<>
struct ParamTraits<mozilla::OriginAttributes>
: public detail::OriginAttributesParamTraits<mozilla::OriginAttributes> {};
} // namespace IPC
namespace mozilla {
namespace net {
class OptionalLoadInfoArgs;
+class RedirectHistoryEntryInfo;
} // namespace net
using namespace mozilla::net;
namespace ipc {
class PrincipalInfo;
@@ -78,16 +80,31 @@ PrincipalToPrincipalInfo(nsIPrincipal* a
/**
* Return true if this PrincipalInfo is a content principal and it has
* a privateBrowsing id in its OriginAttributes
*/
bool
IsPincipalInfoPrivate(const PrincipalInfo& aPrincipalInfo);
/**
+ * Convert an RedirectHistoryEntryInfo to a nsIRedirectHistoryEntry.
+ */
+
+already_AddRefed<nsIRedirectHistoryEntry>
+RHEntryInfoToRHEntry(const RedirectHistoryEntryInfo& aRHEntryInfo);
+
+/**
+ * Convert an nsIRedirectHistoryEntry to a RedirectHistoryEntryInfo.
+ */
+
+nsresult
+RHEntryToRHEntryInfo(nsIRedirectHistoryEntry* aRHEntry,
+ RedirectHistoryEntryInfo* aRHEntryInfo);
+
+/**
* Convert a LoadInfo to LoadInfoArgs struct.
*/
nsresult
LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
OptionalLoadInfoArgs* outOptionalLoadInfoArgs);
/**
* Convert LoadInfoArgs to a LoadInfo.
--- a/js/src/builtin/String.js
+++ b/js/src/builtin/String.js
@@ -554,22 +554,25 @@ function StringIteratorNext() {
return result;
}
var charCount = 1;
var first = callFunction(std_String_charCodeAt, S, index);
if (first >= 0xD800 && first <= 0xDBFF && index + 1 < size) {
var second = callFunction(std_String_charCodeAt, S, index + 1);
if (second >= 0xDC00 && second <= 0xDFFF) {
+ first = (first - 0xD800) * 0x400 + (second - 0xDC00) + 0x10000;
charCount = 2;
}
}
UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
- result.value = callFunction(String_substring, S, index, index + charCount);
+
+ // Communicate |first|'s possible range to the compiler.
+ result.value = callFunction(std_String_fromCodePoint, null, first & 0x1fffff);
return result;
}
/**
* Compare this String against that String, using the locale and collation
* options provided.
*
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -777,16 +777,17 @@ CheckSelfTime(Phase parent,
if (selfTimes[parent] < childTime) {
fprintf(stderr,
"Parent %s time = %.3fms with %.3fms remaining, child %s time %.3fms\n",
phases[parent].name,
times[parent].ToMilliseconds(),
selfTimes[parent].ToMilliseconds(),
phases[child].name,
childTime.ToMilliseconds());
+ fflush(stderr);
MOZ_CRASH();
}
}
static PhaseKind
LongestPhaseSelfTime(const Statistics::PhaseTimeTable& times)
{
// Start with total times per expanded phase, including children's times.
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/recover-newstringiterator.js
@@ -0,0 +1,63 @@
+var max = 40;
+setJitCompilerOption("ion.warmup.trigger", max - 10);
+
+function selfhosted() {
+ if (typeof getSelfHostedValue === "undefined")
+ return;
+
+ var NewStringIterator = getSelfHostedValue("NewStringIterator");
+ var iter = NewStringIterator();
+ bailout();
+ // assertRecoveredOnBailout(iter, true);
+}
+
+function iterator(i) {
+ var string = String.fromCharCode(0x41, i);
+ var iter = string[Symbol.iterator]();
+ assertEq(iter.next().value, 'A');
+ bailout();
+ // This sometimes fails
+ // assertRecoveredOnBailout(iter, true);
+ var result = iter.next();
+ assertEq(result.value, String.fromCharCode(i));
+ assertEq(result.done, false);
+ assertEq(iter.next().done, true);
+}
+
+function forof(i) {
+ var string = String.fromCharCode(0x41, i);
+ var first = true;
+
+ for (var x of string) {
+ if (first) {
+ assertEq(x, 'A');
+ bailout();
+ first = false;
+ } else {
+ assertEq(x, String.fromCharCode(i));
+ }
+ }
+}
+
+var data = {
+ a: 'foo',
+ b: {c: 'd'},
+ str: 'ABC'
+};
+
+function fn() {
+ var {a, b:{c:b}, str:[, c]} = data;
+ return c;
+}
+
+function destructuring() {
+ for (var i = 0; i < max; i++)
+ assertEq(fn(), 'B');
+}
+
+for (var i = 0; i < max; i++) {
+ selfhosted();
+ iterator(i);
+ forof(i);
+ destructuring();
+}
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -778,31 +778,33 @@ static bool
DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_, HandleValue lhs,
HandleValue rhs, MutableHandleValue res)
{
// This fallback stub may trigger debug mode toggling.
DebugModeOSRVolatileStub<ICGetElem_Fallback*> stub(frame, stub_);
RootedScript script(cx, frame->script());
jsbytecode* pc = stub->icEntry()->pc(frame->script());
+ StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
+
JSOp op = JSOp(*pc);
FallbackICSpew(cx, stub, "GetElem(%s)", CodeName[op]);
MOZ_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
// Don't pass lhs directly, we need it when generating stubs.
RootedValue lhsCopy(cx, lhs);
bool isOptimizedArgs = false;
if (lhs.isMagic(JS_OPTIMIZED_ARGUMENTS)) {
// Handle optimized arguments[i] access.
if (!GetElemOptimizedArguments(cx, frame, &lhsCopy, rhs, res, &isOptimizedArgs))
return false;
if (isOptimizedArgs)
- TypeScript::Monitor(cx, frame->script(), pc, res);
+ TypeScript::Monitor(cx, script, pc, types, res);
}
bool attached = false;
bool isTemporarilyUnoptimizable = false;
if (stub->state().maybeTransition())
stub->discardStubs(cx);
@@ -823,25 +825,25 @@ DoGetElemFallback(JSContext* cx, Baselin
}
if (!attached && !isTemporarilyUnoptimizable)
stub->state().trackNotAttached();
}
if (!isOptimizedArgs) {
if (!GetElementOperation(cx, op, lhsCopy, rhs, res))
return false;
- TypeScript::Monitor(cx, frame->script(), pc, res);
+ TypeScript::Monitor(cx, script, pc, types, res);
}
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
// Add a type monitor stub for the resulting value.
- if (!stub->addMonitorStubForValue(cx, frame, res))
+ if (!stub->addMonitorStubForValue(cx, frame, types, res))
return false;
if (attached)
return true;
// GetElem operations which could access negative indexes generally can't
// be optimized without the potential for bailouts, as we can't statically
// determine that an object has no properties on such indexes.
@@ -1367,24 +1369,25 @@ DoGetNameFallback(JSContext* cx, Baselin
if (JSOp(pc[JSOP_GETGNAME_LENGTH]) == JSOP_TYPEOF) {
if (!GetEnvironmentName<GetNameMode::TypeOf>(cx, envChain, name, res))
return false;
} else {
if (!GetEnvironmentName<GetNameMode::Normal>(cx, envChain, name, res))
return false;
}
- TypeScript::Monitor(cx, script, pc, res);
+ StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
+ TypeScript::Monitor(cx, script, pc, types, res);
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
// Add a type monitor stub for the resulting value.
- if (!stub->addMonitorStubForValue(cx, frame, res))
+ if (!stub->addMonitorStubForValue(cx, frame, types, res))
return false;
if (!attached)
stub->noteUnoptimizableAccess();
return true;
}
typedef bool (*DoGetNameFallbackFn)(JSContext*, BaselineFrame*, ICGetName_Fallback*,
@@ -2010,16 +2013,21 @@ GetTemplateObjectForNative(JSContext* cx
return !!res;
}
if (native == js::intrinsic_NewArrayIterator) {
res.set(NewArrayIteratorObject(cx, TenuredObject));
return !!res;
}
+ if (native == js::intrinsic_NewStringIterator) {
+ res.set(NewStringIteratorObject(cx, TenuredObject));
+ return !!res;
+ }
+
if (JitSupportsSimd() && GetTemplateObjectForSimd(cx, target, res))
return !!res;
return true;
}
static bool
GetTemplateObjectForClassHook(JSContext* cx, JSNative hook, CallArgs& args,
@@ -2445,24 +2453,25 @@ DoCallFallback(JSContext* cx, BaselineFr
}
if (!CallFromStack(cx, callArgs))
return false;
res.set(callArgs.rval());
}
- TypeScript::Monitor(cx, script, pc, res);
+ StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
+ TypeScript::Monitor(cx, script, pc, types, res);
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
// Add a type monitor stub for the resulting value.
- if (!stub->addMonitorStubForValue(cx, frame, res))
+ if (!stub->addMonitorStubForValue(cx, frame, types, res))
return false;
// If 'callee' is a potential Call_StringSplit, try to attach an
// optimized StringSplit stub. Note that vp[0] now holds the return value
// instead of the callee, so we pass the callee as well.
if (!TryAttachStringSplit(cx, stub, script, argc, callee, vp, pc, res, &handled))
return false;
@@ -2504,17 +2513,18 @@ DoSpreadCallFallback(JSContext* cx, Base
if (!SpreadCallOperation(cx, script, pc, thisv, callee, arr, newTarget, res))
return false;
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
// Add a type monitor stub for the resulting value.
- if (!stub->addMonitorStubForValue(cx, frame, res))
+ StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
+ if (!stub->addMonitorStubForValue(cx, frame, types, res))
return false;
if (!handled)
stub->noteUnoptimizableCall();
return true;
}
void
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5648,26 +5648,42 @@ CodeGenerator::visitNewArrayDynamicLengt
masm.bind(ool->rejoin());
}
typedef ArrayIteratorObject* (*NewArrayIteratorObjectFn)(JSContext*, NewObjectKind);
static const VMFunction NewArrayIteratorObjectInfo =
FunctionInfo<NewArrayIteratorObjectFn>(NewArrayIteratorObject, "NewArrayIteratorObject");
-void
-CodeGenerator::visitNewArrayIterator(LNewArrayIterator* lir)
+typedef StringIteratorObject* (*NewStringIteratorObjectFn)(JSContext*, NewObjectKind);
+static const VMFunction NewStringIteratorObjectInfo =
+ FunctionInfo<NewStringIteratorObjectFn>(NewStringIteratorObject, "NewStringIteratorObject");
+
+void
+CodeGenerator::visitNewIterator(LNewIterator* lir)
{
Register objReg = ToRegister(lir->output());
Register tempReg = ToRegister(lir->temp());
JSObject* templateObject = lir->mir()->templateObject();
- OutOfLineCode* ool = oolCallVM(NewArrayIteratorObjectInfo, lir,
- ArgList(Imm32(GenericObject)),
- StoreRegisterTo(objReg));
+ OutOfLineCode* ool;
+ switch (lir->mir()->type()) {
+ case MNewIterator::ArrayIterator:
+ ool = oolCallVM(NewArrayIteratorObjectInfo, lir,
+ ArgList(Imm32(GenericObject)),
+ StoreRegisterTo(objReg));
+ break;
+ case MNewIterator::StringIterator:
+ ool = oolCallVM(NewStringIteratorObjectInfo, lir,
+ ArgList(Imm32(GenericObject)),
+ StoreRegisterTo(objReg));
+ break;
+ default:
+ MOZ_CRASH("unexpected iterator type");
+ }
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, ool->entry());
masm.bind(ool->rejoin());
}
typedef TypedArrayObject* (*TypedArrayConstructorOneArgFn)(JSContext*, HandleObject, int32_t length);
static const VMFunction TypedArrayConstructorOneArgInfo =
@@ -8038,34 +8054,100 @@ typedef JSString* (*StringFromCodePointF
static const VMFunction StringFromCodePointInfo =
FunctionInfo<StringFromCodePointFn>(jit::StringFromCodePoint, "StringFromCodePoint");
void
CodeGenerator::visitFromCodePoint(LFromCodePoint* lir)
{
Register codePoint = ToRegister(lir->codePoint());
Register output = ToRegister(lir->output());
+ Register temp1 = ToRegister(lir->temp1());
+ Register temp2 = ToRegister(lir->temp2());
LSnapshot* snapshot = lir->snapshot();
+ // The OOL path is only taken when we can't allocate the inline string.
OutOfLineCode* ool = oolCallVM(StringFromCodePointInfo, lir, ArgList(codePoint),
StoreRegisterTo(output));
- // Use a bailout if the input is not a valid code point, because
- // MFromCodePoint is movable and it'd be observable when a moved
- // fromCodePoint throws an exception before its actual call site.
- bailoutCmp32(Assembler::Above, codePoint, Imm32(unicode::NonBMPMax), snapshot);
-
- // OOL path if code point >= UNIT_STATIC_LIMIT.
+ Label isTwoByte;
+ Label* done = ool->rejoin();
+
+ static_assert(StaticStrings::UNIT_STATIC_LIMIT -1 == JSString::MAX_LATIN1_CHAR,
+ "Latin-1 strings can be loaded from static strings");
masm.branch32(Assembler::AboveOrEqual, codePoint, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
- ool->entry());
-
- masm.movePtr(ImmPtr(&GetJitContext()->runtime->staticStrings().unitStaticTable), output);
- masm.loadPtr(BaseIndex(output, codePoint, ScalePointer), output);
-
- masm.bind(ool->rejoin());
+ &isTwoByte);
+ {
+ masm.movePtr(ImmPtr(&GetJitContext()->runtime->staticStrings().unitStaticTable), output);
+ masm.loadPtr(BaseIndex(output, codePoint, ScalePointer), output);
+ masm.jump(done);
+ }
+ masm.bind(&isTwoByte);
+ {
+ // Use a bailout if the input is not a valid code point, because
+ // MFromCodePoint is movable and it'd be observable when a moved
+ // fromCodePoint throws an exception before its actual call site.
+ bailoutCmp32(Assembler::Above, codePoint, Imm32(unicode::NonBMPMax), snapshot);
+
+ // Allocate a JSThinInlineString.
+ {
+ static_assert(JSThinInlineString::MAX_LENGTH_TWO_BYTE >= 2,
+ "JSThinInlineString can hold a supplementary code point");
+
+ uint32_t flags = JSString::INIT_THIN_INLINE_FLAGS;
+ masm.newGCString(output, temp1, ool->entry());
+ masm.store32(Imm32(flags), Address(output, JSString::offsetOfFlags()));
+ }
+
+ Label isSupplementary;
+ masm.branch32(Assembler::AboveOrEqual, codePoint, Imm32(unicode::NonBMPMin),
+ &isSupplementary);
+ {
+ // Store length.
+ masm.store32(Imm32(1), Address(output, JSString::offsetOfLength()));
+
+ // Load chars pointer in temp1.
+ masm.computeEffectiveAddress(Address(output, JSInlineString::offsetOfInlineStorage()),
+ temp1);
+
+ masm.store16(codePoint, Address(temp1, 0));
+
+ // Null-terminate.
+ masm.store16(Imm32(0), Address(temp1, sizeof(char16_t)));
+
+ masm.jump(done);
+ }
+ masm.bind(&isSupplementary);
+ {
+ // Store length.
+ masm.store32(Imm32(2), Address(output, JSString::offsetOfLength()));
+
+ // Load chars pointer in temp1.
+ masm.computeEffectiveAddress(Address(output, JSInlineString::offsetOfInlineStorage()),
+ temp1);
+
+ // Inlined unicode::LeadSurrogate(uint32_t).
+ masm.move32(codePoint, temp2);
+ masm.rshift32(Imm32(10), temp2);
+ masm.add32(Imm32(unicode::LeadSurrogateMin - (unicode::NonBMPMin >> 10)), temp2);
+
+ masm.store16(temp2, Address(temp1, 0));
+
+ // Inlined unicode::TrailSurrogate(uint32_t).
+ masm.move32(codePoint, temp2);
+ masm.and32(Imm32(0x3FF), temp2);
+ masm.or32(Imm32(unicode::TrailSurrogateMin), temp2);
+
+ masm.store16(temp2, Address(temp1, sizeof(char16_t)));
+
+ // Null-terminate.
+ masm.store16(Imm32(0), Address(temp1, 2 * sizeof(char16_t)));
+ }
+ }
+
+ masm.bind(done);
}
void
CodeGenerator::visitSinCos(LSinCos *lir)
{
Register temp = ToRegister(lir->temp());
Register params = ToRegister(lir->temp2());
FloatRegister input = ToFloatRegister(lir->input());
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -193,17 +193,17 @@ class CodeGenerator final : public CodeG
void visitCallDirectEval(LCallDirectEval* lir);
void visitDoubleToInt32(LDoubleToInt32* lir);
void visitFloat32ToInt32(LFloat32ToInt32* lir);
void visitNewArrayCallVM(LNewArray* lir);
void visitNewArray(LNewArray* lir);
void visitOutOfLineNewArray(OutOfLineNewArray* ool);
void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir);
void visitNewArrayDynamicLength(LNewArrayDynamicLength* lir);
- void visitNewArrayIterator(LNewArrayIterator* lir);
+ void visitNewIterator(LNewIterator* lir);
void visitNewTypedArray(LNewTypedArray* lir);
void visitNewTypedArrayDynamicLength(LNewTypedArrayDynamicLength* lir);
void visitNewObjectVMCall(LNewObject* lir);
void visitNewObject(LNewObject* lir);
void visitOutOfLineNewObject(OutOfLineNewObject* ool);
void visitNewTypedObject(LNewTypedObject* lir);
void visitSimdBox(LSimdBox* lir);
void visitSimdUnbox(LSimdUnbox* lir);
--- a/js/src/jit/InlinableNatives.h
+++ b/js/src/jit/InlinableNatives.h
@@ -125,16 +125,17 @@
_(IntrinsicIsSetIterator) \
_(IntrinsicIsStringIterator) \
\
_(IntrinsicGetNextMapEntryForIterator) \
\
_(IntrinsicGetNextSetEntryForIterator) \
\
_(IntrinsicNewArrayIterator) \
+ _(IntrinsicNewStringIterator) \
\
_(IntrinsicArrayBufferByteLength) \
_(IntrinsicPossiblyWrappedArrayBufferByteLength) \
\
_(TypedArrayConstructor) \
_(IntrinsicIsTypedArray) \
_(IntrinsicIsPossiblyWrappedTypedArray) \
_(IntrinsicTypedArrayLength) \
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -628,18 +628,18 @@ class IonBuilder
// Array natives.
InliningResult inlineArray(CallInfo& callInfo);
InliningResult inlineArrayIsArray(CallInfo& callInfo);
InliningResult inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode);
InliningResult inlineArrayPush(CallInfo& callInfo);
InliningResult inlineArraySlice(CallInfo& callInfo);
InliningResult inlineArrayJoin(CallInfo& callInfo);
- // Array intrinsics.
- InliningResult inlineNewArrayIterator(CallInfo& callInfo);
+ // Iterator intrinsics.
+ InliningResult inlineNewIterator(CallInfo& callInfo, MNewIterator::Type type);
// Math natives.
InliningResult inlineMathAbs(CallInfo& callInfo);
InliningResult inlineMathFloor(CallInfo& callInfo);
InliningResult inlineMathCeil(CallInfo& callInfo);
InliningResult inlineMathClz32(CallInfo& callInfo);
InliningResult inlineMathRound(CallInfo& callInfo);
InliningResult inlineMathSqrt(CallInfo& callInfo);
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -239,19 +239,19 @@ LIRGenerator::visitNewArrayDynamicLength
MOZ_ASSERT(length->type() == MIRType::Int32);
LNewArrayDynamicLength* lir = new(alloc()) LNewArrayDynamicLength(useRegister(length), temp());
define(lir, ins);
assignSafepoint(lir, ins);
}
void
-LIRGenerator::visitNewArrayIterator(MNewArrayIterator* ins)
-{
- LNewArrayIterator* lir = new(alloc()) LNewArrayIterator(temp());
+LIRGenerator::visitNewIterator(MNewIterator* ins)
+{
+ LNewIterator* lir = new(alloc()) LNewIterator(temp());
define(lir, ins);
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitNewTypedArray(MNewTypedArray* ins)
{
LNewTypedArray* lir = new(alloc()) LNewTypedArray(temp(), temp());
@@ -2000,17 +2000,17 @@ LIRGenerator::visitFromCharCode(MFromCha
void
LIRGenerator::visitFromCodePoint(MFromCodePoint* ins)
{
MDefinition* codePoint = ins->getOperand(0);
MOZ_ASSERT(codePoint->type() == MIRType::Int32);
- LFromCodePoint* lir = new(alloc()) LFromCodePoint(useRegister(codePoint));
+ LFromCodePoint* lir = new(alloc()) LFromCodePoint(useRegister(codePoint), temp(), temp());
assignSnapshot(lir, Bailout_BoundsCheck);
define(lir, ins);
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitStart(MStart* start)
{
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -73,17 +73,17 @@ class LIRGenerator : public LIRGenerator
void visitParameter(MParameter* param);
void visitCallee(MCallee* callee);
void visitIsConstructing(MIsConstructing* ins);
void visitGoto(MGoto* ins);
void visitTableSwitch(MTableSwitch* tableswitch);
void visitNewArray(MNewArray* ins);
void visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite* ins);
void visitNewArrayDynamicLength(MNewArrayDynamicLength* ins);
- void visitNewArrayIterator(MNewArrayIterator* ins);
+ void visitNewIterator(MNewIterator* ins);
void visitNewTypedArray(MNewTypedArray* ins);
void visitNewTypedArrayDynamicLength(MNewTypedArrayDynamicLength* ins);
void visitNewObject(MNewObject* ins);
void visitNewTypedObject(MNewTypedObject* ins);
void visitNewNamedLambdaObject(MNewNamedLambdaObject* ins);
void visitNewCallObject(MNewCallObject* ins);
void visitNewSingletonCallObject(MNewSingletonCallObject* ins);
void visitNewStringObject(MNewStringObject* ins);
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -85,17 +85,17 @@ IonBuilder::inlineNativeCall(CallInfo& c
return inlineArrayPopShift(callInfo, MArrayPopShift::Shift);
case InlinableNative::ArrayPush:
return inlineArrayPush(callInfo);
case InlinableNative::ArraySlice:
return inlineArraySlice(callInfo);
// Array intrinsics.
case InlinableNative::IntrinsicNewArrayIterator:
- return inlineNewArrayIterator(callInfo);
+ return inlineNewIterator(callInfo, MNewIterator::ArrayIterator);
// Atomic natives.
case InlinableNative::AtomicsCompareExchange:
return inlineAtomicsCompareExchange(callInfo);
case InlinableNative::AtomicsExchange:
return inlineAtomicsExchange(callInfo);
case InlinableNative::AtomicsLoad:
return inlineAtomicsLoad(callInfo);
@@ -220,16 +220,18 @@ IonBuilder::inlineNativeCall(CallInfo& c
case InlinableNative::StringCharAt:
return inlineStrCharAt(callInfo);
// String intrinsics.
case InlinableNative::IntrinsicStringReplaceString:
return inlineStringReplaceString(callInfo);
case InlinableNative::IntrinsicStringSplitString:
return inlineStringSplitString(callInfo);
+ case InlinableNative::IntrinsicNewStringIterator:
+ return inlineNewIterator(callInfo, MNewIterator::StringIterator);
// Object natives.
case InlinableNative::ObjectCreate:
return inlineObjectCreate(callInfo);
// SIMD natives.
case InlinableNative::SimdInt32x4:
return inlineSimd(callInfo, target, SimdType::Int32x4);
@@ -892,34 +894,44 @@ IonBuilder::inlineArraySlice(CallInfo& c
current->push(ins);
MOZ_TRY(resumeAfter(ins));
MOZ_TRY(pushTypeBarrier(ins, getInlineReturnTypeSet(), BarrierKind::TypeSet));
return InliningStatus_Inlined;
}
IonBuilder::InliningResult
-IonBuilder::inlineNewArrayIterator(CallInfo& callInfo)
+IonBuilder::inlineNewIterator(CallInfo& callInfo, MNewIterator::Type type)
{
if (callInfo.argc() != 0 || callInfo.constructing()) {
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
return InliningStatus_NotInlined;
}
- JSObject* templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewArrayIterator);
+ JSObject* templateObject = nullptr;
+ switch (type) {
+ case MNewIterator::ArrayIterator:
+ templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewArrayIterator);
+ MOZ_ASSERT_IF(templateObject, templateObject->is<ArrayIteratorObject>());
+ break;
+ case MNewIterator::StringIterator:
+ templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewStringIterator);
+ MOZ_ASSERT_IF(templateObject, templateObject->is<StringIteratorObject>());
+ break;
+ }
+
if (!templateObject)
return InliningStatus_NotInlined;
- MOZ_ASSERT(templateObject->is<ArrayIteratorObject>());
callInfo.setImplicitlyUsedUnchecked();
MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
current->add(templateConst);
- MNewArrayIterator* ins = MNewArrayIterator::New(alloc(), constraints(), templateConst);
+ MNewIterator* ins = MNewIterator::New(alloc(), constraints(), templateConst, type);
current->add(ins);
current->push(ins);
MOZ_TRY(resumeAfter(ins));
return InliningStatus_Inlined;
}
IonBuilder::InliningResult
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -4956,18 +4956,18 @@ JSObject*
MObjectState::templateObjectOf(MDefinition* obj)
{
if (obj->isNewObject())
return obj->toNewObject()->templateObject();
else if (obj->isCreateThisWithTemplate())
return obj->toCreateThisWithTemplate()->templateObject();
else if (obj->isNewCallObject())
return obj->toNewCallObject()->templateObject();
- else if (obj->isNewArrayIterator())
- return obj->toNewArrayIterator()->templateObject();
+ else if (obj->isNewIterator())
+ return obj->toNewIterator()->templateObject();
MOZ_CRASH("unreachable");
}
bool
MObjectState::init(TempAllocator& alloc, MDefinition* obj)
{
if (!MVariadicInstruction::init(alloc, numSlots() + 1))
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3531,31 +3531,45 @@ class MNewObject
bool canRecoverOnBailout() const override {
// The template object can safely be used in the recover instruction
// because it can never be mutated by any other function execution.
return templateObject() != nullptr;
}
};
-class MNewArrayIterator
+class MNewIterator
: public MUnaryInstruction,
public NoTypePolicy::Data
{
- explicit MNewArrayIterator(CompilerConstraintList* constraints, MConstant* templateConst)
- : MUnaryInstruction(templateConst)
+ public:
+ enum Type {
+ ArrayIterator,
+ StringIterator,
+ };
+
+private:
+ Type type_;
+
+ MNewIterator(CompilerConstraintList* constraints, MConstant* templateConst, Type type)
+ : MUnaryInstruction(templateConst),
+ type_(type)
{
setResultType(MIRType::Object);
setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject()));
templateConst->setEmittedAtUses();
}
public:
- INSTRUCTION_HEADER(NewArrayIterator)
- TRIVIAL_NEW_WRAPPERS
+ INSTRUCTION_HEADER(NewIterator)
+ TRIVIAL_NEW_WRAPPERS
+
+ Type type() const {
+ return type_;
+ }
JSObject* templateObject() {
return getOperand(0)->toConstant()->toObjectOrNull();
}
AliasSet getAliasSet() const override {
return AliasSet::None();
}
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -128,17 +128,17 @@ namespace jit {
_(WrapInt64ToInt32) \
_(ExtendInt32ToInt64) \
_(Int64ToFloatingPoint) \
_(ToString) \
_(ToObjectOrNull) \
_(NewArray) \
_(NewArrayCopyOnWrite) \
_(NewArrayDynamicLength) \
- _(NewArrayIterator) \
+ _(NewIterator) \
_(NewTypedArray) \
_(NewTypedArrayDynamicLength) \
_(NewObject) \
_(NewTypedObject) \
_(NewNamedLambdaObject) \
_(NewCallObject) \
_(NewSingletonCallObject) \
_(NewStringObject) \
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1362,35 +1362,45 @@ RNewArray::recover(JSContext* cx, Snapsh
return false;
result.setObject(*resultObject);
iter.storeInstructionResult(result);
return true;
}
bool
-MNewArrayIterator::writeRecoverData(CompactBufferWriter& writer) const
+MNewIterator::writeRecoverData(CompactBufferWriter& writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
- writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArrayIterator));
+ writer.writeUnsigned(uint32_t(RInstruction::Recover_NewIterator));
+ writer.writeByte(type_);
return true;
}
-RNewArrayIterator::RNewArrayIterator(CompactBufferReader& reader)
+RNewIterator::RNewIterator(CompactBufferReader& reader)
{
+ type_ = reader.readByte();
}
bool
-RNewArrayIterator::recover(JSContext* cx, SnapshotIterator& iter) const
+RNewIterator::recover(JSContext* cx, SnapshotIterator& iter) const
{
RootedObject templateObject(cx, &iter.read().toObject());
RootedValue result(cx);
+ JSObject* resultObject = nullptr;
+ switch (MNewIterator::Type(type_)) {
+ case MNewIterator::ArrayIterator:
+ resultObject = NewArrayIteratorObject(cx);
+ break;
+ case MNewIterator::StringIterator:
+ resultObject = NewStringIteratorObject(cx);
+ break;
+ }
- JSObject* resultObject = NewArrayIteratorObject(cx);
if (!resultObject)
return false;
result.setObject(*resultObject);
iter.storeInstructionResult(result);
return true;
}
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -97,17 +97,17 @@ namespace jit {
_(StringReplace) \
_(TypeOf) \
_(ToDouble) \
_(ToFloat32) \
_(TruncateToInt32) \
_(NewObject) \
_(NewTypedArray) \
_(NewArray) \
- _(NewArrayIterator) \
+ _(NewIterator) \
_(NewDerivedTypedObject) \
_(CreateThisWithTemplate) \
_(Lambda) \
_(LambdaArrow) \
_(SimdBox) \
_(ObjectState) \
_(ArrayState) \
_(AtomicIsLockFree) \
@@ -590,20 +590,23 @@ class RNewArray final : public RInstruct
uint32_t count_;
public:
RINSTRUCTION_HEADER_NUM_OP_(NewArray, 1)
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
};
-class RNewArrayIterator final : public RInstruction
+class RNewIterator final : public RInstruction
{
+ private:
+ uint8_t type_;
+
public:
- RINSTRUCTION_HEADER_NUM_OP_(NewArrayIterator, 1)
+ RINSTRUCTION_HEADER_NUM_OP_(NewIterator, 1)
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const override;
};
class RNewDerivedTypedObject final : public RInstruction
{
public:
RINSTRUCTION_HEADER_NUM_OP_(NewDerivedTypedObject, 3)
--- a/js/src/jit/ScalarReplacement.cpp
+++ b/js/src/jit/ScalarReplacement.cpp
@@ -134,17 +134,17 @@ IsLambdaEscaped(MInstruction* lambda, JS
JitSpew(JitSpew_Escape, "Lambda is not escaped");
return false;
}
static inline bool
IsOptimizableObjectInstruction(MInstruction* ins)
{
return ins->isNewObject() || ins->isCreateThisWithTemplate() || ins->isNewCallObject() ||
- ins->isNewArrayIterator();
+ ins->isNewIterator();
}
// Returns False if the object is not escaped and if it is optimizable by
// ScalarReplacementOfObject.
//
// For the moment, this code is dumb as it only supports objects which are not
// changing shape, and which are known by TI at the object creation.
static bool
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -451,19 +451,19 @@ ICMonitoredFallbackStub::initMonitoringC
if (!stub)
return false;
fallbackMonitorStub_ = stub;
return true;
}
bool
ICMonitoredFallbackStub::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
- HandleValue val)
+ StackTypeSet* types, HandleValue val)
{
- return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, val);
+ return fallbackMonitorStub_->addMonitorStubForValue(cx, frame, types, val);
}
bool
ICUpdatedStub::initUpdatingChain(JSContext* cx, ICStubSpace* space)
{
MOZ_ASSERT(firstUpdateStub_ == nullptr);
ICTypeUpdate_Fallback::Compiler compiler(cx);
@@ -2054,24 +2054,25 @@ DoGetPropFallback(JSContext* cx, Baselin
}
if (!attached && !isTemporarilyUnoptimizable)
stub->state().trackNotAttached();
}
if (!ComputeGetPropResult(cx, frame, op, name, val, res))
return false;
- TypeScript::Monitor(cx, script, pc, res);
+ StackTypeSet* types = TypeScript::BytecodeTypes(script, pc);
+ TypeScript::Monitor(cx, script, pc, types, res);
// Check if debug mode toggling made the stub invalid.
if (stub.invalid())
return true;
// Add a type monitor stub for the resulting value.
- if (!stub->addMonitorStubForValue(cx, frame, res))
+ if (!stub->addMonitorStubForValue(cx, frame, types, res))
return false;
if (attached)
return true;
MOZ_ASSERT(!attached);
if (!isTemporarilyUnoptimizable)
stub->noteUnoptimizableAccess();
@@ -2168,18 +2169,21 @@ BaselineScript::noteAccessedGetter(uint3
if (stub->isGetProp_Fallback())
stub->toGetProp_Fallback()->noteAccessedGetter();
}
// TypeMonitor_Fallback
//
bool
-ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val)
+ICTypeMonitor_Fallback::addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
+ StackTypeSet* types, HandleValue val)
{
+ MOZ_ASSERT(types);
+
bool wasDetachedMonitorChain = lastMonitorStubPtrAddr_ == nullptr;
MOZ_ASSERT_IF(wasDetachedMonitorChain, numOptimizedMonitorStubs_ == 0);
if (numOptimizedMonitorStubs_ >= MAX_OPTIMIZED_STUBS) {
// TODO: if the TypeSet becomes unknown or has the AnyObject type,
// replace stubs with a single stub to handle these.
return true;
}
@@ -2293,61 +2297,69 @@ ICTypeMonitor_Fallback::addMonitorStubFo
static bool
DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallback* stub,
HandleValue value, MutableHandleValue res)
{
JSScript* script = frame->script();
jsbytecode* pc = stub->icEntry()->pc(script);
TypeFallbackICSpew(cx, stub, "TypeMonitor");
- if (value.isMagic()) {
+ // Copy input value to res.
+ res.set(value);
+
+ if (MOZ_UNLIKELY(value.isMagic())) {
// It's possible that we arrived here from bailing out of Ion, and that
// Ion proved that the value is dead and optimized out. In such cases,
// do nothing. However, it's also possible that we have an uninitialized
// this, in which case we should not look for other magic values.
if (value.whyMagic() == JS_OPTIMIZED_OUT) {
MOZ_ASSERT(!stub->monitorsThis());
- res.set(value);
return true;
}
// In derived class constructors (including nested arrows/eval), the
// |this| argument or GETALIASEDVAR can return the magic TDZ value.
MOZ_ASSERT(value.isMagic(JS_UNINITIALIZED_LEXICAL));
MOZ_ASSERT(frame->isFunctionFrame() || frame->isEvalFrame());
MOZ_ASSERT(stub->monitorsThis() ||
*GetNextPc(pc) == JSOP_CHECKTHIS ||
*GetNextPc(pc) == JSOP_CHECKRETURN);
- }
-
- uint32_t argument;
- if (stub->monitorsThis()) {
- MOZ_ASSERT(pc == script->code());
- if (value.isMagic(JS_UNINITIALIZED_LEXICAL))
+ if (stub->monitorsThis())
TypeScript::SetThis(cx, script, TypeSet::UnknownType());
else
- TypeScript::SetThis(cx, script, value);
- } else if (stub->monitorsArgument(&argument)) {
+ TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType());
+ return true;
+ }
+
+ // Note: ideally we would merge this if-else statement with the one below,
+ // but that triggers an MSVC 2015 compiler bug. See bug 1363054.
+ StackTypeSet* types;
+ uint32_t argument;
+ if (stub->monitorsArgument(&argument))
+ types = TypeScript::ArgTypes(script, argument);
+ else if (stub->monitorsThis())
+ types = TypeScript::ThisTypes(script);
+ else
+ types = TypeScript::BytecodeTypes(script, pc);
+
+ if (stub->monitorsArgument(&argument)) {
MOZ_ASSERT(pc == script->code());
- MOZ_ASSERT(!value.isMagic(JS_UNINITIALIZED_LEXICAL));
TypeScript::SetArgument(cx, script, argument, value);
+ } else if (stub->monitorsThis()) {
+ MOZ_ASSERT(pc == script->code());
+ TypeScript::SetThis(cx, script, value);
} else {
- if (value.isMagic(JS_UNINITIALIZED_LEXICAL))
- TypeScript::Monitor(cx, script, pc, TypeSet::UnknownType());
- else
- TypeScript::Monitor(cx, script, pc, value);
+ TypeScript::Monitor(cx, script, pc, types, value);
}
- if (!stub->invalid() && !stub->addMonitorStubForValue(cx, frame, value))
- return false;
-
- // Copy input value to res.
- res.set(value);
- return true;
+ if (MOZ_UNLIKELY(stub->invalid()))
+ return true;
+
+ return stub->addMonitorStubForValue(cx, frame, types, value);
}
typedef bool (*DoTypeMonitorFallbackFn)(JSContext*, BaselineFrame*, ICTypeMonitor_Fallback*,
HandleValue, MutableHandleValue);
static const VMFunction DoTypeMonitorFallbackInfo =
FunctionInfo<DoTypeMonitorFallbackFn>(DoTypeMonitorFallback, "DoTypeMonitorFallback",
TailCall);
--- a/js/src/jit/SharedIC.h
+++ b/js/src/jit/SharedIC.h
@@ -1203,17 +1203,18 @@ class ICMonitoredFallbackStub : public I
ICTypeMonitor_Fallback* fallbackMonitorStub_;
ICMonitoredFallbackStub(Kind kind, JitCode* stubCode)
: ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
fallbackMonitorStub_(nullptr) {}
public:
MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, ICStubSpace* space);
- MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val);
+ MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
+ StackTypeSet* types, HandleValue val);
inline ICTypeMonitor_Fallback* fallbackMonitorStub() const {
return fallbackMonitorStub_;
}
static inline size_t offsetOfFallbackMonitorStub() {
return offsetof(ICMonitoredFallbackStub, fallbackMonitorStub_);
}
@@ -1463,17 +1464,18 @@ class ICTypeMonitor_Fallback : public IC
MOZ_ASSERT(icEntry_ == nullptr);
MOZ_ASSERT(lastMonitorStubPtrAddr_ == nullptr);
icEntry_ = icEntry;
lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
}
// Create a new monitor stub for the type of the given value, and
// add it to this chain.
- MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame, HandleValue val);
+ MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
+ StackTypeSet* types, HandleValue val);
void resetMonitorStubChain(Zone* zone);
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
ICMonitoredFallbackStub* mainFallbackStub_;
uint32_t argumentIndex_;
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -278,16 +278,17 @@ template <> struct TypeToDataType<JSObje
template <> struct TypeToDataType<NativeObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<PlainObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<InlineTypedObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<NamedLambdaObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<LexicalEnvironmentObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<ArrayIteratorObject*> { static const DataType result = Type_Object; };
+template <> struct TypeToDataType<StringIteratorObject*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<JSFlatString*> { static const DataType result = Type_Object; };
template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; };
template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; };
template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; };
template <> struct TypeToDataType<Handle<NativeObject*> > { static const DataType result = Type_Handle; };
template <> struct TypeToDataType<Handle<InlineTypedObject*> > { static const DataType result = Type_Handle; };
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -1057,31 +1057,31 @@ class LNewArrayDynamicLength : public LI
return getTemp(0);
}
MNewArrayDynamicLength* mir() const {
return mir_->toNewArrayDynamicLength();
}
};
-class LNewArrayIterator : public LInstructionHelper<1, 0, 1>
-{
- public:
- LIR_HEADER(NewArrayIterator)
-
- explicit LNewArrayIterator(const LDefinition& temp) {
+class LNewIterator : public LInstructionHelper<1, 0, 1>
+{
+ public:
+ LIR_HEADER(NewIterator)
+
+ explicit LNewIterator(const LDefinition& temp) {
setTemp(0, temp);
}
const LDefinition* temp() {
return getTemp(0);
}
- MNewArrayIterator* mir() const {
- return mir_->toNewArrayIterator();
+ MNewIterator* mir() const {
+ return mir_->toNewIterator();
}
};
class LNewTypedArray : public LInstructionHelper<1, 0, 2>
{
public:
LIR_HEADER(NewTypedArray)
@@ -4105,28 +4105,40 @@ class LFromCharCode : public LInstructio
}
const LAllocation* code() {
return this->getOperand(0);
}
};
// Convert uint32 code point to a string.
-class LFromCodePoint : public LInstructionHelper<1, 1, 0>
+class LFromCodePoint : public LInstructionHelper<1, 1, 2>
{
public:
LIR_HEADER(FromCodePoint)
- explicit LFromCodePoint(const LAllocation& codePoint) {
+ explicit LFromCodePoint(const LAllocation& codePoint, const LDefinition& temp1,
+ const LDefinition& temp2)
+ {
setOperand(0, codePoint);
+ setTemp(0, temp1);
+ setTemp(1, temp2);
}
const LAllocation* codePoint() {
return this->getOperand(0);
}
+
+ const LDefinition* temp1() {
+ return this->getTemp(0);
+ }
+
+ const LDefinition* temp2() {
+ return this->getTemp(1);
+ }
};
// Calculates sincos(x) and returns two values (sin/cos).
class LSinCos : public LCallInstructionHelper<2, 1, 2>
{
public:
LIR_HEADER(SinCos)
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -62,17 +62,17 @@
_(Callee) \
_(IsConstructing) \
_(TableSwitch) \
_(TableSwitchV) \
_(Goto) \
_(NewArray) \
_(NewArrayCopyOnWrite) \
_(NewArrayDynamicLength) \
- _(NewArrayIterator) \
+ _(NewIterator) \
_(NewTypedArray) \
_(NewTypedArrayDynamicLength) \
_(NewObject) \
_(NewTypedObject) \
_(NewNamedLambdaObject) \
_(NewCallObject) \
_(NewSingletonCallObject) \
_(NewStringObject) \
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1170,16 +1170,26 @@ const Class StringIteratorObject::class_
JSCLASS_HAS_RESERVED_SLOTS(StringIteratorSlotCount)
};
static const JSFunctionSpec string_iterator_methods[] = {
JS_SELF_HOSTED_FN("next", "StringIteratorNext", 0, 0),
JS_FS_END
};
+StringIteratorObject*
+js::NewStringIteratorObject(JSContext* cx, NewObjectKind newKind)
+{
+ RootedObject proto(cx, GlobalObject::getOrCreateStringIteratorPrototype(cx, cx->global()));
+ if (!proto)
+ return nullptr;
+
+ return NewObjectWithGivenProto<StringIteratorObject>(cx, proto, newKind);
+}
+
JSObject*
js::ValueToIterator(JSContext* cx, unsigned flags, HandleValue vp)
{
/* JSITER_KEYVALUE must always come with JSITER_FOREACH */
MOZ_ASSERT_IF(flags & JSITER_KEYVALUE, flags & JSITER_FOREACH);
RootedObject obj(cx);
if (vp.isObject()) {
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -149,16 +149,19 @@ ArrayIteratorObject*
NewArrayIteratorObject(JSContext* cx, NewObjectKind newKind = GenericObject);
class StringIteratorObject : public JSObject
{
public:
static const Class class_;
};
+StringIteratorObject*
+NewStringIteratorObject(JSContext* cx, NewObjectKind newKind = GenericObject);
+
bool
GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleObject objp);
JSObject*
GetIteratorObject(JSContext* cx, HandleObject obj, unsigned flags);
/*
* Creates either a key or value iterator, depending on flags. For a value
--- a/js/src/shell/OSObject.cpp
+++ b/js/src/shell/OSObject.cpp
@@ -118,17 +118,17 @@ ResolvePath(JSContext* cx, HandleString
if (!scriptFilename.get())
return nullptr;
if (strcmp(scriptFilename.get(), "-e") == 0 || strcmp(scriptFilename.get(), "typein") == 0)
resolveMode = RootRelative;
}
- static char buffer[PATH_MAX+1];
+ char buffer[PATH_MAX+1];
if (resolveMode == ScriptRelative) {
#ifdef XP_WIN
// The docs say it can return EINVAL, but the compiler says it's void
_splitpath(scriptFilename.get(), nullptr, buffer, nullptr, nullptr);
#else
strncpy(buffer, scriptFilename.get(), PATH_MAX+1);
if (buffer[PATH_MAX] != '\0')
return nullptr;
@@ -227,17 +227,17 @@ FileAsTypedArray(JSContext* cx, JS::Hand
}
/**
* Return the current working directory or |null| on failure.
*/
UniqueChars
GetCWD()
{
- static char buffer[PATH_MAX + 1];
+ char buffer[PATH_MAX + 1];
const char* cwd = getcwd(buffer, PATH_MAX);
if (!cwd)
return UniqueChars();
return js::DuplicateString(buffer);
}
static bool
ReadFile(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative)
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -768,27 +768,23 @@ intrinsic_CreateSetIterationResult(JSCon
JSObject* result = SetIteratorObject::createResult(cx);
if (!result)
return false;
args.rval().setObject(*result);
return true;
}
-static bool
-intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp)
+bool
+js::intrinsic_NewStringIterator(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 0);
- RootedObject proto(cx, GlobalObject::getOrCreateStringIteratorPrototype(cx, cx->global()));
- if (!proto)
- return false;
-
- JSObject* obj = NewObjectWithGivenProto(cx, &StringIteratorObject::class_, proto);
+ JSObject* obj = NewStringIteratorObject(cx);
if (!obj)
return false;
args.rval().setObject(*obj);
return true;
}
static bool
@@ -2272,16 +2268,17 @@ static const JSFunctionSpec intrinsic_fu
JS_FN("std_Reflect_getPrototypeOf", Reflect_getPrototypeOf, 1,0),
JS_FN("std_Reflect_isExtensible", Reflect_isExtensible, 1,0),
JS_FN("std_Set_has", SetObject::has, 1,0),
JS_FN("std_Set_iterator", SetObject::values, 0,0),
JS_INLINABLE_FN("std_String_fromCharCode", str_fromCharCode, 1,0, StringFromCharCode),
+ JS_INLINABLE_FN("std_String_fromCodePoint", str_fromCodePoint, 1,0, StringFromCodePoint),
JS_INLINABLE_FN("std_String_charCodeAt", str_charCodeAt, 1,0, StringCharCodeAt),
JS_FN("std_String_includes", str_includes, 1,0),
JS_FN("std_String_indexOf", str_indexOf, 1,0),
JS_FN("std_String_lastIndexOf", str_lastIndexOf, 1,0),
JS_FN("std_String_startsWith", str_startsWith, 1,0),
JS_FN("std_String_toLowerCase", str_toLowerCase, 0,0),
JS_FN("std_String_toUpperCase", str_toUpperCase, 0,0),
@@ -2403,17 +2400,18 @@ static const JSFunctionSpec intrinsic_fu
JS_FN("_CreateSetIterationResult", intrinsic_CreateSetIterationResult, 0, 0),
JS_INLINABLE_FN("_GetNextSetEntryForIterator", intrinsic_GetNextSetEntryForIterator, 2,0,
IntrinsicGetNextSetEntryForIterator),
JS_FN("CallSetIteratorMethodIfWrapped",
CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>, 2,0),
- JS_FN("NewStringIterator", intrinsic_NewStringIterator, 0,0),
+ JS_INLINABLE_FN("NewStringIterator", intrinsic_NewStringIterator, 0,0,
+ IntrinsicNewStringIterator),
JS_FN("CallStringIteratorMethodIfWrapped",
CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>, 2,0),
JS_FN("IsStarGeneratorObject",
intrinsic_IsInstanceOfBuiltin<StarGeneratorObject>, 1,0),
JS_FN("StarGeneratorObjectIsClosed", intrinsic_StarGeneratorObjectIsClosed, 1,0),
JS_FN("IsSuspendedStarGenerator",intrinsic_IsSuspendedStarGenerator,1,0),
--- a/js/src/vm/SelfHosting.h
+++ b/js/src/vm/SelfHosting.h
@@ -45,11 +45,14 @@ CallSelfHostedFunction(JSContext* cx, Ha
const AnyInvokeArgs& args, MutableHandleValue rval);
bool
intrinsic_StringSplitString(JSContext* cx, unsigned argc, JS::Value* vp);
bool
intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, JS::Value* vp);
+bool
+intrinsic_NewStringIterator(JSContext* cx, unsigned argc, JS::Value* vp);
+
} /* namespace js */
#endif /* vm_SelfHosting_h_ */
--- a/js/src/vm/TypeInference-inl.h
+++ b/js/src/vm/TypeInference-inl.h
@@ -484,16 +484,18 @@ inline void
MarkObjectStateChange(JSContext* cx, JSObject* obj)
{
if (!obj->hasLazyGroup() && !obj->group()->unknownProperties())
obj->group()->markStateChange(cx);
}
/* Interface helpers for JSScript*. */
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, TypeSet::Type type);
+extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
+ TypeSet::Type type);
extern void TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const Value& rval);
/////////////////////////////////////////////////////////////////////
// Script interface functions
/////////////////////////////////////////////////////////////////////
/* static */ inline unsigned
TypeScript::NumTypeSets(JSScript* script)
@@ -585,16 +587,25 @@ TypeScript::Monitor(JSContext* cx, JSScr
TypeScript::Monitor(JSContext* cx, const js::Value& rval)
{
jsbytecode* pc;
RootedScript script(cx, cx->currentScript(&pc));
Monitor(cx, script, pc, rval);
}
/* static */ inline void
+TypeScript::Monitor(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
+ const js::Value& rval)
+{
+ TypeSet::Type type = TypeSet::GetValueType(rval);
+ if (!types->hasType(type))
+ TypeMonitorResult(cx, script, pc, types, type);
+}
+
+/* static */ inline void
TypeScript::MonitorAssign(JSContext* cx, HandleObject obj, jsid id)
{
if (!obj->isSingleton()) {
/*
* Mark as unknown any object which has had dynamic assignments to
* non-integer properties at SETELEM opcodes. This avoids making large
* numbers of type properties for hashmap-style objects. We don't need
* to do this for objects with singleton type, because type properties
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -3337,16 +3337,32 @@ js::TypeMonitorResult(JSContext* cx, JSS
return;
InferSpew(ISpewOps, "bytecodeType: %p %05" PRIuSIZE ": %s",
script, script->pcToOffset(pc), TypeSet::TypeString(type));
types->addType(cx, type);
}
void
+js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackTypeSet* types,
+ TypeSet::Type type)
+{
+ assertSameCompartment(cx, script, type);
+
+ AutoEnterAnalysis enter(cx);
+
+ MOZ_ASSERT(types == TypeScript::BytecodeTypes(script, pc));
+ MOZ_ASSERT(!types->hasType(type));
+
+ InferSpew(ISpewOps, "bytecodeType: %p %05" PRIuSIZE ": %s",
+ script, script->pcToOffset(pc), TypeSet::TypeString(type));
+ types->addType(cx, type);
+}
+
+void
js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, const js::Value& rval)
{
/* Allow the non-TYPESET scenario to simplify stubs used in compound opcodes. */
if (!(CodeSpec[*pc].format & JOF_TYPESET))
return;
if (!script->hasBaselineScript())
return;
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -1240,16 +1240,19 @@ class TypeScript
* and only look at barriers when generating JIT code for the script.
*/
static inline void Monitor(JSContext* cx, JSScript* script, jsbytecode* pc,
const js::Value& val);
static inline void Monitor(JSContext* cx, JSScript* script, jsbytecode* pc,
TypeSet::Type type);
static inline void Monitor(JSContext* cx, const js::Value& rval);
+ static inline void Monitor(JSContext* cx, JSScript* script, jsbytecode* pc,
+ StackTypeSet* types, const js::Value& val);
+
/* Monitor an assignment at a SETELEM on a non-integer identifier. */
static inline void MonitorAssign(JSContext* cx, HandleObject obj, jsid id);
/* Add a type for a variable in a script. */
static inline void SetThis(JSContext* cx, JSScript* script, TypeSet::Type type);
static inline void SetThis(JSContext* cx, JSScript* script, const js::Value& value);
static inline void SetArgument(JSContext* cx, JSScript* script, unsigned arg,
TypeSet::Type type);
--- a/layout/base/nsArenaMemoryStats.h
+++ b/layout/base/nsArenaMemoryStats.h
@@ -45,51 +45,59 @@ struct nsArenaMemoryStats {
macro(Style, mStyleStructs) \
macro(Other, mOther)
nsArenaMemoryStats()
:
#define ZERO_SIZE(kind, mSize) mSize(0),
FOR_EACH_SIZE(ZERO_SIZE)
#undef ZERO_SIZE
- #define FRAME_ID(classname) FRAME_ID_STAT_FIELD(classname)(),
+ #define FRAME_ID(classname, ...) FRAME_ID_STAT_FIELD(classname)(),
+ #define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
+ #undef ABSTRACT_FRAME_ID
dummy()
{}
void addToTabSizes(nsTabSizes *sizes) const
{
#define ADD_TO_TAB_SIZES(kind, mSize) sizes->add(nsTabSizes::kind, mSize);
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
#undef ADD_TO_TAB_SIZES
- #define FRAME_ID(classname) \
+ #define FRAME_ID(classname, ...) \
sizes->add(nsTabSizes::Other, FRAME_ID_STAT_FIELD(classname));
+ #define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
+ #undef ABSTRACT_FRAME_ID
}
size_t getTotalSize() const
{
size_t total = 0;
#define ADD_TO_TOTAL_SIZE(kind, mSize) total += mSize;
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
#undef ADD_TO_TOTAL_SIZE
- #define FRAME_ID(classname) \
- total += FRAME_ID_STAT_FIELD(classname);
+ #define FRAME_ID(classname, ...) \
+ total += FRAME_ID_STAT_FIELD(classname);
+ #define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
+ #undef ABSTRACT_FRAME_ID
return total;
}
#define DECL_SIZE(kind, mSize) size_t mSize;
FOR_EACH_SIZE(DECL_SIZE)
#undef DECL_SIZE
- #define FRAME_ID(classname) size_t FRAME_ID_STAT_FIELD(classname);
+ #define FRAME_ID(classname, ...) size_t FRAME_ID_STAT_FIELD(classname);
+ #define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
+ #undef ABSTRACT_FRAME_ID
int dummy; // present just to absorb the trailing comma from FRAME_ID in the
// constructor
#undef FOR_EACH_SIZE
};
#endif // nsArenaMemoryStats_h
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -189,22 +189,24 @@ nsPresArena::AddSizeOfExcludingThis(mozi
// list here. The free list knows how many objects we've allocated
// ever (which includes any objects that may be on the FreeList's
// |mEntries| at this point) and we're using that to determine the
// total size of objects allocated with a given ID.
size_t totalSize = entry->mEntrySize * entry->mEntriesEverAllocated;
size_t* p;
switch (entry - mFreeLists) {
-#define FRAME_ID(classname) \
+#define FRAME_ID(classname, ...) \
case nsQueryFrame::classname##_id: \
p = &aArenaStats->FRAME_ID_STAT_FIELD(classname); \
break;
+#define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
case eArenaObjectID_nsLineBox:
p = &aArenaStats->mLineBoxes;
break;
case eArenaObjectID_nsRuleNode:
p = &aArenaStats->mRuleNodes;
break;
case eArenaObjectID_nsStyleContext:
p = &aArenaStats->mStyleContexts;
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -230,36 +230,37 @@ public:
virtual TimeDuration GetTimerRate() = 0;
bool LastTickSkippedAnyPaints() const
{
return mLastFireSkipped;
}
- Maybe<TimeStamp> GetIdleDeadlineHint()
+ TimeStamp GetIdleDeadlineHint(TimeStamp aDefault)
{
MOZ_ASSERT(NS_IsMainThread());
if (LastTickSkippedAnyPaints()) {
- return Some(TimeStamp());
+ return TimeStamp::Now();
}
TimeStamp mostRecentRefresh = MostRecentRefresh();
TimeDuration refreshRate = GetTimerRate();
TimeStamp idleEnd = mostRecentRefresh + refreshRate;
if (idleEnd +
refreshRate * nsLayoutUtils::QuiescentFramesBeforeIdlePeriod() <
TimeStamp::Now()) {
- return Nothing();
+ return aDefault;
}
- return Some(idleEnd - TimeDuration::FromMilliseconds(
- nsLayoutUtils::IdlePeriodDeadlineLimit()));
+ idleEnd = idleEnd - TimeDuration::FromMilliseconds(
+ nsLayoutUtils::IdlePeriodDeadlineLimit());
+ return idleEnd < aDefault ? idleEnd : aDefault;
}
protected:
virtual void StartTimer() = 0;
virtual void StopTimer() = 0;
virtual void ScheduleNextTick(TimeStamp aNowTime) = 0;
bool IsRootRefreshDriver(nsRefreshDriver* aDriver)
@@ -2310,32 +2311,33 @@ nsRefreshDriver::CancelPendingEvents(nsI
{
for (auto i : Reversed(IntegerRange(mPendingEvents.Length()))) {
if (mPendingEvents[i].mTarget->OwnerDoc() == aDocument) {
mPendingEvents.RemoveElementAt(i);
}
}
}
-/* static */ Maybe<TimeStamp>
-nsRefreshDriver::GetIdleDeadlineHint()
+/* static */ TimeStamp
+nsRefreshDriver::GetIdleDeadlineHint(TimeStamp aDefault)
{
MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!aDefault.IsNull());
if (!sRegularRateTimer) {
- return Nothing();
+ return aDefault;
}
// For computing idleness of refresh drivers we only care about
// sRegularRateTimer, since we consider refresh drivers attached to
// sThrottledRateTimer to be inactive. This implies that tasks
// resulting from a tick on the sRegularRateTimer counts as being
// busy but tasks resulting from a tick on sThrottledRateTimer
// counts as being idle.
- return sRegularRateTimer->GetIdleDeadlineHint();
+ return sRegularRateTimer->GetIdleDeadlineHint(aDefault);
}
void
nsRefreshDriver::Disconnect()
{
MOZ_ASSERT(NS_IsMainThread());
StopTimer();
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -319,47 +319,24 @@ public:
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override { return TransactionIdAllocator::AddRef(); }
NS_IMETHOD_(MozExternalRefCountType) Release(void) override { return TransactionIdAllocator::Release(); }
virtual void WillRefresh(mozilla::TimeStamp aTime) override;
/**
* Compute the time when the currently active refresh driver timer
* will start its next tick.
*
- * Returns 'Nothing' if the refresh driver timer hasn't been
- * initialized or if we can't tell when the next tick will happen.
- *
- * Returns Some(TimeStamp()), i.e. the null time, if the next tick is late.
- *
- * Otherwise returns Some(TimeStamp(t)), where t is the time of the next tick.
- *
- * Using these three types of return values it is possible to
- * estimate three different things about the idleness of the
- * currently active group of refresh drivers. This information is
- * used by nsThread to schedule lower priority "idle tasks".
+ * Expects a non-null default value that is the upper bound of the
+ * expected deadline. If the next expected deadline is later than
+ * the default value, the default value is returned.
*
- * The 'Nothing' return value indicates to nsThread that the
- * currently active refresh drivers will be idle for a time
- * significantly longer than the current refresh rate and that it is
- * free to schedule longer periods for executing idle tasks. This is the
- * expected result when we aren't animating.
-
- * Returning the null time indicates to nsThread that we are very
- * busy and that it should definitely not schedule idle tasks at
- * all. This is the expected result when we are animating, but
- * aren't able to keep up with the animation and hence need to skip
- * paints. Since catching up to missed paints will happen as soon as
- * possible, this is the expected result if any of the refresh
- * drivers attached to the current refresh driver misses a paint.
- *
- * Returning Some(TimeStamp(t)) indicates to nsThread that we will
- * be idle until. This is usually the case when we're animating
- * without skipping paints.
+ * If we're animating and we have skipped paints a time in the past
+ * is returned.
*/
- static mozilla::Maybe<mozilla::TimeStamp> GetIdleDeadlineHint();
+ static mozilla::TimeStamp GetIdleDeadlineHint(mozilla::TimeStamp aDefault);
bool SkippedPaints() const
{
return mSkippedPaints;
}
private:
typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
--- a/layout/forms/nsColorControlFrame.cpp
+++ b/layout/forms/nsColorControlFrame.cpp
@@ -18,17 +18,17 @@
#include "mozilla/dom/HTMLInputElement.h"
#include "nsIDocument.h"
using mozilla::dom::Element;
using mozilla::dom::HTMLInputElement;
using mozilla::dom::CallerType;
nsColorControlFrame::nsColorControlFrame(nsStyleContext* aContext)
- : nsHTMLButtonControlFrame(aContext, LayoutFrameType::ColorControl)
+ : nsHTMLButtonControlFrame(aContext, kClassID)
{
}
nsIFrame*
NS_NewColorControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsColorControlFrame(aContext);
}
--- a/layout/forms/nsColorControlFrame.h
+++ b/layout/forms/nsColorControlFrame.h
@@ -23,34 +23,32 @@ class nsColorControlFrame final : public
typedef mozilla::dom::Element Element;
public:
friend nsIFrame* NS_NewColorControlFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
- NS_DECL_QUERYFRAME_TARGET(nsColorControlFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsColorControlFrame)
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
// nsIFrame
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
- virtual bool IsLeaf() const override { return true; }
virtual nsContainerFrame* GetContentInsertionFrame() override;
virtual Element* GetPseudoElement(CSSPseudoElementType aType) override;
// Refresh the color swatch, using associated input's value
nsresult UpdateColor();
private:
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -218,17 +218,17 @@ static int32_t gReflowInx = -1;
#define PX(__v) __v
#endif
//------------------------------------------------------
//-- Done with macros
//------------------------------------------------------
nsComboboxControlFrame::nsComboboxControlFrame(nsStyleContext* aContext)
- : nsBlockFrame(aContext, LayoutFrameType::ComboboxControl)
+ : nsBlockFrame(aContext, kClassID)
, mDisplayFrame(nullptr)
, mButtonFrame(nullptr)
, mDropdownFrame(nullptr)
, mListControlFrame(nullptr)
, mDisplayISize(0)
, mRecentSelectedIndex(NS_SKIP_NOTIFY_INDEX)
, mDisplayedIndex(-1)
, mLastDropDownBeforeScreenBCoord(nscoord_MIN)
@@ -1277,21 +1277,21 @@ nsComboboxControlFrame::AppendAnonymousC
aElements.AppendElement(mButtonContent);
}
}
// XXXbz this is a for-now hack. Now that display:inline-block works,
// need to revisit this.
class nsComboboxDisplayFrame : public nsBlockFrame {
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsComboboxDisplayFrame)
nsComboboxDisplayFrame(nsStyleContext* aContext,
nsComboboxControlFrame* aComboBox)
- : nsBlockFrame(aContext, LayoutFrameType::ComboboxDisplay)
+ : nsBlockFrame(aContext, kClassID)
, mComboBox(aComboBox)
{}
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override
{
return MakeFrameName(NS_LITERAL_STRING("ComboboxDisplay"), aResult);
}
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -49,27 +49,26 @@ class nsComboboxControlFrame final : pub
public nsIAnonymousContentCreator,
public nsISelectControlFrame,
public nsIRollupListener,
public nsIStatefulFrame
{
typedef mozilla::gfx::DrawTarget DrawTarget;
public:
- NS_DECL_QUERYFRAME_TARGET(nsComboboxControlFrame)
friend nsComboboxControlFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext,
nsFrameState aFlags);
friend class nsComboboxDisplayFrame;
explicit nsComboboxControlFrame(nsStyleContext* aContext);
~nsComboboxControlFrame();
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsComboboxControlFrame)
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
nsIContent* GetDisplayNode() { return mDisplayContent; }
nsIFrame* CreateFrameForDisplayNode();
--- a/layout/forms/nsDateTimeControlFrame.cpp
+++ b/layout/forms/nsDateTimeControlFrame.cpp
@@ -38,17 +38,17 @@ NS_NewDateTimeControlFrame(nsIPresShell*
NS_IMPL_FRAMEARENA_HELPERS(nsDateTimeControlFrame)
NS_QUERYFRAME_HEAD(nsDateTimeControlFrame)
NS_QUERYFRAME_ENTRY(nsDateTimeControlFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsDateTimeControlFrame::nsDateTimeControlFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::DateTimeControl)
+ : nsContainerFrame(aContext, kClassID)
{
}
void
nsDateTimeControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
nsContentUtils::DestroyAnonymousContent(&mInputAreaContent);
nsContainerFrame::DestroyFrom(aDestructRoot);
--- a/layout/forms/nsDateTimeControlFrame.h
+++ b/layout/forms/nsDateTimeControlFrame.h
@@ -35,19 +35,18 @@ class nsDateTimeControlFrame final : pub
public:
friend nsIFrame* NS_NewDateTimeControlFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
void ContentStatesChanged(mozilla::EventStates aStates) override;
void DestroyFrom(nsIFrame* aDestructRoot) override;
- NS_DECL_QUERYFRAME_TARGET(nsDateTimeControlFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsDateTimeControlFrame)
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("DateTimeControl"), aResult);
}
#endif
bool IsFrameOfType(uint32_t aFlags) const override
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -27,17 +27,17 @@ nsContainerFrame*
NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsFieldSetFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsFieldSetFrame)
nsFieldSetFrame::nsFieldSetFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::FieldSet)
+ : nsContainerFrame(aContext, kClassID)
, mLegendRect(GetWritingMode())
{
mLegendSpace = 0;
}
nsRect
nsFieldSetFrame::VisualBorderRectRelativeToSelf() const
{
--- a/layout/forms/nsFieldSetFrame.h
+++ b/layout/forms/nsFieldSetFrame.h
@@ -10,17 +10,17 @@
#include "DrawResult.h"
#include "nsContainerFrame.h"
class nsFieldSetFrame final : public nsContainerFrame
{
typedef mozilla::image::DrawResult DrawResult;
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsFieldSetFrame)
explicit nsFieldSetFrame(nsStyleContext* aContext);
nscoord
GetIntrinsicISize(nsRenderingContext* aRenderingContext,
nsLayoutUtils::IntrinsicISizeType);
virtual nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -34,17 +34,17 @@ nsIFrame*
NS_NewFileControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsFileControlFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsFileControlFrame)
nsFileControlFrame::nsFileControlFrame(nsStyleContext* aContext)
- : nsBlockFrame(aContext)
+ : nsBlockFrame(aContext, kClassID)
{
AddStateBits(NS_BLOCK_FLOAT_MGR);
}
void
nsFileControlFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -32,17 +32,17 @@ public:
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsFileControlFrame)
// nsIFormControlFrame
virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) override;
virtual void SetFocus(bool aOn, bool aRepaint) override;
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
@@ -50,20 +50,16 @@ public:
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
virtual void ContentStatesChanged(mozilla::EventStates aStates) override;
- virtual bool IsLeaf() const override
- {
- return true;
- }
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
--- a/layout/forms/nsFormControlFrame.cpp
+++ b/layout/forms/nsFormControlFrame.cpp
@@ -12,18 +12,19 @@
#include "mozilla/LookAndFeel.h"
#include "nsDeviceContext.h"
#include "nsIContent.h"
using namespace mozilla;
//#define FCF_NOISY
-nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext)
- : nsAtomicContainerFrame(aContext, LayoutFrameType::FormControl)
+nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext,
+ nsIFrame::ClassID aID)
+ : nsAtomicContainerFrame(aContext, aID)
{
}
nsFormControlFrame::~nsFormControlFrame()
{
}
void
--- a/layout/forms/nsFormControlFrame.h
+++ b/layout/forms/nsFormControlFrame.h
@@ -20,17 +20,17 @@ class nsFormControlFrame : public nsAtom
public nsIFormControlFrame
{
public:
/**
* Main constructor
* @param aContent the content representing this frame
* @param aParentFrame the parent frame
*/
- explicit nsFormControlFrame(nsStyleContext*);
+ nsFormControlFrame(nsStyleContext*, nsIFrame::ClassID);
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
return nsAtomicContainerFrame::IsFrameOfType(aFlags &
~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
NS_DECL_QUERYFRAME
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -14,17 +14,17 @@
#include "nsContentList.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsTextNode.h"
using namespace mozilla;
nsGfxButtonControlFrame::nsGfxButtonControlFrame(nsStyleContext* aContext)
- : nsHTMLButtonControlFrame(aContext, LayoutFrameType::GfxButtonControl)
+ : nsHTMLButtonControlFrame(aContext, kClassID)
{
}
nsContainerFrame*
NS_NewGfxButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsGfxButtonControlFrame(aContext);
}
@@ -171,22 +171,16 @@ nsGfxButtonControlFrame::AttributeChange
// defer to HTMLButtonControlFrame
} else {
rv = nsHTMLButtonControlFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
}
return rv;
}
-bool
-nsGfxButtonControlFrame::IsLeaf() const
-{
- return true;
-}
-
nsContainerFrame*
nsGfxButtonControlFrame::GetContentInsertionFrame()
{
return this;
}
nsresult
nsGfxButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
--- a/layout/forms/nsGfxButtonControlFrame.h
+++ b/layout/forms/nsGfxButtonControlFrame.h
@@ -16,17 +16,17 @@
// The label for button is specified through generated content
// in the ua.css file.
class nsGfxButtonControlFrame final
: public nsHTMLButtonControlFrame
, public nsIAnonymousContentCreator
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsGfxButtonControlFrame)
explicit nsGfxButtonControlFrame(nsStyleContext* aContext);
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
@@ -41,18 +41,16 @@ public:
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
- virtual bool IsLeaf() const override;
-
virtual nsContainerFrame* GetContentInsertionFrame() override;
protected:
nsresult GetDefaultLabel(nsXPIDLString& aLabel) const;
nsresult GetLabel(nsXPIDLString& aLabel);
virtual bool IsInput() override { return true; }
--- a/layout/forms/nsGfxCheckboxControlFrame.cpp
+++ b/layout/forms/nsGfxCheckboxControlFrame.cpp
@@ -87,17 +87,17 @@ NS_NewGfxCheckboxControlFrame(nsIPresShe
}
NS_IMPL_FRAMEARENA_HELPERS(nsGfxCheckboxControlFrame)
//------------------------------------------------------------
// Initialize GFX-rendered state
nsGfxCheckboxControlFrame::nsGfxCheckboxControlFrame(nsStyleContext* aContext)
-: nsFormControlFrame(aContext)
+: nsFormControlFrame(aContext, kClassID)
{
}
nsGfxCheckboxControlFrame::~nsGfxCheckboxControlFrame()
{
}
#ifdef ACCESSIBILITY
--- a/layout/forms/nsGfxCheckboxControlFrame.h
+++ b/layout/forms/nsGfxCheckboxControlFrame.h
@@ -6,17 +6,17 @@
#define nsGfxCheckboxControlFrame_h___
#include "mozilla/Attributes.h"
#include "nsFormControlFrame.h"
class nsGfxCheckboxControlFrame : public nsFormControlFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsGfxCheckboxControlFrame)
explicit nsGfxCheckboxControlFrame(nsStyleContext* aContext);
virtual ~nsGfxCheckboxControlFrame();
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult);
}
--- a/layout/forms/nsGfxRadioControlFrame.cpp
+++ b/layout/forms/nsGfxRadioControlFrame.cpp
@@ -20,17 +20,17 @@ nsIFrame*
NS_NewGfxRadioControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsGfxRadioControlFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsGfxRadioControlFrame)
nsGfxRadioControlFrame::nsGfxRadioControlFrame(nsStyleContext* aContext):
- nsFormControlFrame(aContext)
+ nsFormControlFrame(aContext, kClassID)
{
}
nsGfxRadioControlFrame::~nsGfxRadioControlFrame()
{
}
#ifdef ACCESSIBILITY
--- a/layout/forms/nsGfxRadioControlFrame.h
+++ b/layout/forms/nsGfxRadioControlFrame.h
@@ -13,17 +13,17 @@
// nsGfxRadioControlFrame
class nsGfxRadioControlFrame : public nsFormControlFrame
{
public:
explicit nsGfxRadioControlFrame(nsStyleContext* aContext);
~nsGfxRadioControlFrame();
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsGfxRadioControlFrame)
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
#ifdef MOZ_WIDGET_ANDROID
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -22,18 +22,18 @@ nsContainerFrame*
NS_NewHTMLButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsHTMLButtonControlFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsHTMLButtonControlFrame)
nsHTMLButtonControlFrame::nsHTMLButtonControlFrame(nsStyleContext* aContext,
- LayoutFrameType aType)
- : nsContainerFrame(aContext, aType)
+ nsIFrame::ClassID aID)
+ : nsContainerFrame(aContext, aID)
{
}
nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame()
{
}
void
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -14,26 +14,25 @@
class nsRenderingContext;
class nsPresContext;
class nsHTMLButtonControlFrame : public nsContainerFrame,
public nsIFormControlFrame
{
public:
explicit nsHTMLButtonControlFrame(nsStyleContext* aContext)
- : nsHTMLButtonControlFrame(aContext,
- mozilla::LayoutFrameType::HTMLButtonControl)
+ : nsHTMLButtonControlFrame(aContext, kClassID)
{}
~nsHTMLButtonControlFrame();
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsHTMLButtonControlFrame)
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
@@ -101,18 +100,17 @@ public:
/**
* Update the style of our ::-moz-button-content anonymous box.
*/
void DoUpdateStyleOfOwnedAnonBoxes(mozilla::ServoStyleSet& aStyleSet,
nsStyleChangeList& aChangeList,
nsChangeHint aHintForThisFrame) override;
protected:
- nsHTMLButtonControlFrame(nsStyleContext* aContext,
- mozilla::LayoutFrameType aType);
+ nsHTMLButtonControlFrame(nsStyleContext* aContext, nsIFrame::ClassID aID);
virtual bool IsInput() { return false; }
// Indicates whether we should clip our children's painting to our
// border-box (either because of "overflow" or because of legacy reasons
// about how <input>-flavored buttons work).
bool ShouldClipPaintingToBorderBox();
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -23,17 +23,17 @@ public:
~nsImageControlFrame();
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsImageControlFrame)
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual nsresult HandleEvent(nsPresContext* aPresContext,
WidgetGUIEvent* aEvent,
@@ -53,17 +53,17 @@ public:
nsIFrame::Cursor& aCursor) override;
// nsIFormContromFrame
virtual void SetFocus(bool aOn, bool aRepaint) override;
virtual nsresult SetFormProperty(nsIAtom* aName,
const nsAString& aValue) override;
};
nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext)
- : nsImageFrame(aContext, LayoutFrameType::ImageControl)
+ : nsImageFrame(aContext, kClassID)
{
}
nsImageControlFrame::~nsImageControlFrame()
{
}
void
--- a/layout/forms/nsLegendFrame.h
+++ b/layout/forms/nsLegendFrame.h
@@ -7,22 +7,21 @@
#define nsLegendFrame_h___
#include "mozilla/Attributes.h"
#include "nsBlockFrame.h"
class nsLegendFrame final : public nsBlockFrame
{
public:
- NS_DECL_QUERYFRAME_TARGET(nsLegendFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsLegendFrame)
explicit nsLegendFrame(nsStyleContext* aContext)
- : nsBlockFrame(aContext, mozilla::LayoutFrameType::Legend)
+ : nsBlockFrame(aContext, kClassID)
{}
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -87,17 +87,17 @@ NS_NewListControlFrame(nsIPresShell* aPr
return it;
}
NS_IMPL_FRAMEARENA_HELPERS(nsListControlFrame)
//---------------------------------------------------------
nsListControlFrame::nsListControlFrame(nsStyleContext* aContext)
- : nsHTMLScrollFrame(aContext, LayoutFrameType::ListControl, false)
+ : nsHTMLScrollFrame(aContext, kClassID, false)
, mView(nullptr)
, mMightNeedSecondPass(false)
, mHasPendingInterruptAtStartOfReflow(false)
, mDropdownCanGrow(false)
, mForceSelection(false)
, mLastDropdownComputedBSize(NS_UNCONSTRAINEDSIZE)
{
mComboboxFrame = nullptr;
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -50,17 +50,17 @@ class nsListControlFrame final : public
{
public:
typedef mozilla::dom::HTMLOptionElement HTMLOptionElement;
friend nsContainerFrame* NS_NewListControlFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsListControlFrame)
// nsIFrame
virtual nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
virtual void SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList) override;
--- a/layout/forms/nsMeterFrame.cpp
+++ b/layout/forms/nsMeterFrame.cpp
@@ -34,17 +34,17 @@ nsIFrame*
NS_NewMeterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsMeterFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsMeterFrame)
nsMeterFrame::nsMeterFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::Meter)
+ : nsContainerFrame(aContext, kClassID)
, mBarDiv(nullptr)
{
}
nsMeterFrame::~nsMeterFrame()
{
}
--- a/layout/forms/nsMeterFrame.h
+++ b/layout/forms/nsMeterFrame.h
@@ -14,19 +14,18 @@
class nsMeterFrame : public nsContainerFrame,
public nsIAnonymousContentCreator
{
typedef mozilla::dom::Element Element;
public:
- NS_DECL_QUERYFRAME_TARGET(nsMeterFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsMeterFrame)
explicit nsMeterFrame(nsStyleContext* aContext);
virtual ~nsMeterFrame();
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual void Reflow(nsPresContext* aCX,
ReflowOutput& aDesiredSize,
@@ -34,18 +33,16 @@ public:
nsReflowStatus& aStatus) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("Meter"), aResult);
}
#endif
- virtual bool IsLeaf() const override { return true; }
-
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
--- a/layout/forms/nsNumberControlFrame.cpp
+++ b/layout/forms/nsNumberControlFrame.cpp
@@ -45,17 +45,17 @@ NS_IMPL_FRAMEARENA_HELPERS(nsNumberContr
NS_QUERYFRAME_HEAD(nsNumberControlFrame)
NS_QUERYFRAME_ENTRY(nsNumberControlFrame)
NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsNumberControlFrame::nsNumberControlFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::NumberControl)
+ : nsContainerFrame(aContext, kClassID)
, mHandlingInputEvent(false)
{
}
void
nsNumberControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
{
NS_ASSERTION(!GetPrevContinuation() && !GetNextContinuation(),
--- a/layout/forms/nsNumberControlFrame.h
+++ b/layout/forms/nsNumberControlFrame.h
@@ -38,23 +38,21 @@ class nsNumberControlFrame final : publi
typedef mozilla::dom::Element Element;
typedef mozilla::dom::HTMLInputElement HTMLInputElement;
typedef mozilla::WidgetEvent WidgetEvent;
typedef mozilla::WidgetGUIEvent WidgetGUIEvent;
explicit nsNumberControlFrame(nsStyleContext* aContext);
public:
- NS_DECL_QUERYFRAME_TARGET(nsNumberControlFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsNumberControlFrame)
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual void ContentStatesChanged(mozilla::EventStates aStates) override;
- virtual bool IsLeaf() const override { return true; }
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
virtual nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext) override;
--- a/layout/forms/nsProgressFrame.cpp
+++ b/layout/forms/nsProgressFrame.cpp
@@ -33,17 +33,17 @@ nsIFrame*
NS_NewProgressFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsProgressFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsProgressFrame)
nsProgressFrame::nsProgressFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::Progress)
+ : nsContainerFrame(aContext, kClassID)
, mBarDiv(nullptr)
{
}
nsProgressFrame::~nsProgressFrame()
{
}
--- a/layout/forms/nsProgressFrame.h
+++ b/layout/forms/nsProgressFrame.h
@@ -18,19 +18,18 @@ enum class CSSPseudoElementType : uint8_
class nsProgressFrame final
: public nsContainerFrame
, public nsIAnonymousContentCreator
{
typedef mozilla::CSSPseudoElementType CSSPseudoElementType;
typedef mozilla::dom::Element Element;
public:
- NS_DECL_QUERYFRAME_TARGET(nsProgressFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsProgressFrame)
explicit nsProgressFrame(nsStyleContext* aContext);
virtual ~nsProgressFrame();
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
@@ -42,18 +41,16 @@ public:
nsReflowStatus& aStatus) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("Progress"), aResult);
}
#endif
- virtual bool IsLeaf() const override { return true; }
-
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -42,17 +42,17 @@ NS_IMPL_ISUPPORTS(nsRangeFrame::DummyTou
nsIFrame*
NS_NewRangeFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsRangeFrame(aContext);
}
nsRangeFrame::nsRangeFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::Range)
+ : nsContainerFrame(aContext, kClassID)
{
}
nsRangeFrame::~nsRangeFrame()
{
#ifdef DEBUG
if (mOuterFocusStyle) {
mOuterFocusStyle->FrameRelease();
--- a/layout/forms/nsRangeFrame.h
+++ b/layout/forms/nsRangeFrame.h
@@ -26,19 +26,18 @@ class nsRangeFrame final : public nsCont
explicit nsRangeFrame(nsStyleContext* aContext);
virtual ~nsRangeFrame();
typedef mozilla::CSSPseudoElementType CSSPseudoElementType;
typedef mozilla::dom::Element Element;
public:
- NS_DECL_QUERYFRAME_TARGET(nsRangeFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsRangeFrame)
// nsIFrame overrides
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
@@ -52,18 +51,16 @@ public:
nsReflowStatus& aStatus) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(NS_LITERAL_STRING("Range"), aResult);
}
#endif
- virtual bool IsLeaf() const override { return true; }
-
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
// nsIAnonymousContentCreator
virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) override;
--- a/layout/forms/nsSelectsAreaFrame.h
+++ b/layout/forms/nsSelectsAreaFrame.h
@@ -6,17 +6,17 @@
#define nsSelectsAreaFrame_h___
#include "mozilla/Attributes.h"
#include "nsBlockFrame.h"
class nsSelectsAreaFrame : public nsBlockFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsSelectsAreaFrame)
friend nsContainerFrame* NS_NewSelectsAreaFrame(nsIPresShell* aShell,
nsStyleContext* aContext,
nsFrameState aFlags);
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
@@ -29,17 +29,17 @@ public:
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
nscoord BSizeOfARow() const { return mBSizeOfARow; }
protected:
explicit nsSelectsAreaFrame(nsStyleContext* aContext) :
- nsBlockFrame(aContext),
+ nsBlockFrame(aContext, kClassID),
mBSizeOfARow(0)
{}
// We cache the block size of a single row so that changes to the
// "size" attribute, padding, etc. can all be handled with only one
// reflow. We'll have to reflow twice if someone changes our font
// size or something like that, so that the block size of our options
// will change.
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -98,17 +98,17 @@ public:
bool EnteredMoreThanOnce() const { return !mFirstEntry; }
private:
nsTextControlFrame &mFrame;
bool mFirstEntry;
};
#endif
nsTextControlFrame::nsTextControlFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::TextInput)
+ : nsContainerFrame(aContext, kClassID)
, mFirstBaseline(NS_INTRINSIC_WIDTH_UNKNOWN)
, mEditorHasBeenInitialized(false)
, mIsProcessing(false)
, mUsePlaceholder(false)
, mUsePreview(false)
#ifdef DEBUG
, mInEditorInitialization(false)
#endif
@@ -609,22 +609,16 @@ nsTextControlFrame::GetXULMinSize(nsBoxL
bool
nsTextControlFrame::IsXULCollapsed()
{
// We're never collapsed in the box sense.
return false;
}
-bool
-nsTextControlFrame::IsLeaf() const
-{
- return true;
-}
-
NS_IMETHODIMP
nsTextControlFrame::ScrollOnFocusEvent::Run()
{
if (mFrame) {
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(mFrame->GetContent());
NS_ASSERTION(txtCtrl, "Content not a text control element");
nsISelectionController* selCon = txtCtrl->GetSelectionController();
if (selCon) {
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -26,17 +26,17 @@ class Element;
} // namespace mozilla
class nsTextControlFrame final : public nsContainerFrame,
public nsIAnonymousContentCreator,
public nsITextControlFrame,
public nsIStatefulFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsTextControlFrame)
NS_DECLARE_FRAME_PROPERTY_DELETABLE(ContentScrollPos, nsPoint)
explicit nsTextControlFrame(nsStyleContext* aContext);
virtual ~nsTextControlFrame();
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
@@ -82,18 +82,16 @@ public:
} else {
*aBaseline = BSize(aWM) - mFirstBaseline;
}
return true;
}
virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override;
virtual bool IsXULCollapsed() override;
-
- virtual bool IsLeaf() const override;
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override
{
--- a/layout/generic/BRFrame.cpp
+++ b/layout/generic/BRFrame.cpp
@@ -22,17 +22,17 @@
using namespace mozilla;
namespace mozilla {
class BRFrame final : public nsFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(BRFrame)
friend nsIFrame* ::NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) override;
virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) override;
virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
bool aRespectClusters = true) override;
@@ -59,17 +59,17 @@ public:
}
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
protected:
explicit BRFrame(nsStyleContext* aContext)
- : nsFrame(aContext, LayoutFrameType::Br)
+ : nsFrame(aContext, kClassID)
, mAscent(NS_INTRINSIC_WIDTH_UNKNOWN)
{}
virtual ~BRFrame();
nscoord mAscent;
};
--- a/layout/generic/DetailsFrame.cpp
+++ b/layout/generic/DetailsFrame.cpp
@@ -26,17 +26,17 @@ nsBlockFrame*
NS_NewDetailsFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) DetailsFrame(aContext);
}
namespace mozilla {
DetailsFrame::DetailsFrame(nsStyleContext* aContext)
- : nsBlockFrame(aContext, LayoutFrameType::Details)
+ : nsBlockFrame(aContext, kClassID)
{
}
DetailsFrame::~DetailsFrame()
{
}
void
--- a/layout/generic/DetailsFrame.h
+++ b/layout/generic/DetailsFrame.h
@@ -18,18 +18,17 @@ namespace mozilla {
// DetailsFrame is generated by HTMLDetailsElement. See
// nsCSSFrameConstructor::ConstructDetailsFrame for the structure of a
// DetailsFrame.
//
class DetailsFrame final : public nsBlockFrame
, public nsIAnonymousContentCreator
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(DetailsFrame)
+ NS_DECL_FRAMEARENA_HELPERS(DetailsFrame)
NS_DECL_QUERYFRAME
explicit DetailsFrame(nsStyleContext* aContext);
virtual ~DetailsFrame();
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override
--- a/layout/generic/ViewportFrame.h
+++ b/layout/generic/ViewportFrame.h
@@ -20,22 +20,21 @@ namespace mozilla {
/**
* ViewportFrame is the parent of a single child - the doc root frame or a scroll frame
* containing the doc root frame. ViewportFrame stores this child in its primary child
* list.
*/
class ViewportFrame : public nsContainerFrame {
public:
- NS_DECL_QUERYFRAME_TARGET(ViewportFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(ViewportFrame)
explicit ViewportFrame(nsStyleContext* aContext)
- : ViewportFrame(aContext, mozilla::LayoutFrameType::Viewport)
+ : ViewportFrame(aContext, kClassID)
{}
virtual ~ViewportFrame() { } // useful for debugging
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
@@ -73,18 +72,18 @@ public:
*/
nsRect AdjustReflowInputAsContainingBlock(ReflowInput* aReflowInput) const;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
protected:
- ViewportFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType)
- : nsContainerFrame(aContext, aType)
+ ViewportFrame(nsStyleContext* aContext, ClassID aID)
+ : nsContainerFrame(aContext, aID)
, mView(nullptr)
{}
/**
* Calculate how much room is available for fixed frames. That means
* determining if the viewport is scrollable and whether the vertical and/or
* horizontal scrollbars are visible. Adjust the computed width/height and
* available width for aReflowInput accordingly.
--- a/layout/generic/nsAtomicContainerFrame.h
+++ b/layout/generic/nsAtomicContainerFrame.h
@@ -19,31 +19,29 @@
*/
class nsAtomicContainerFrame : public nsContainerFrame
{
public:
NS_DECL_ABSTRACT_FRAME(nsAtomicContainerFrame)
// Bypass the nsContainerFrame/nsSplittableFrame impl of the following
// methods so we behave like a leaf frame.
- bool IsLeaf() const override { return true; }
FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) override
{
return nsFrame::PeekOffsetNoAmount(aForward, aOffset);
}
FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
bool aRespectClusters = true) override
{
return nsFrame::PeekOffsetCharacter(aForward, aOffset, aRespectClusters);
}
nsSplittableType GetSplittableType() const override
{
return nsFrame::GetSplittableType();
}
protected:
- nsAtomicContainerFrame(nsStyleContext* aContext,
- mozilla::LayoutFrameType aType)
- : nsContainerFrame(aContext, aType)
+ nsAtomicContainerFrame(nsStyleContext* aContext, ClassID aID)
+ : nsContainerFrame(aContext, aID)
{}
};
#endif // nsAtomicContainerFrame_h___
--- a/layout/generic/nsBackdropFrame.h
+++ b/layout/generic/nsBackdropFrame.h
@@ -9,20 +9,20 @@
#ifndef nsBackdropFrame_h___
#define nsBackdropFrame_h___
#include "nsFrame.h"
class nsBackdropFrame final : public nsFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsBackdropFrame)
explicit nsBackdropFrame(nsStyleContext* aContext)
- : nsFrame(aContext, mozilla::LayoutFrameType::Backdrop)
+ : nsFrame(aContext, kClassID)
{}
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
virtual nsStyleContext*
GetParentStyleContext(nsIFrame** aProviderFrame) const override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -75,18 +75,17 @@ class BlockReflowInput;
* The block frame has an additional child list, kAbsoluteList, which
* contains the absolutely positioned frames.
*/
class nsBlockFrame : public nsContainerFrame
{
using BlockReflowInput = mozilla::BlockReflowInput;
public:
- NS_DECL_QUERYFRAME_TARGET(nsBlockFrame)
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsBlockFrame)
typedef nsLineList::iterator LineIterator;
typedef nsLineList::const_iterator ConstLineIterator;
typedef nsLineList::reverse_iterator ReverseLineIterator;
typedef nsLineList::const_reverse_iterator ConstReverseLineIterator;
LineIterator LinesBegin() { return mLines.begin(); }
LineIterator LinesEnd() { return mLines.end(); }
@@ -392,30 +391,26 @@ public:
static nsBlockFrame* GetNearestAncestorBlock(nsIFrame* aCandidate);
struct FrameLines {
nsLineList mLines;
nsFrameList mFrames;
};
protected:
- nsBlockFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType)
- : nsContainerFrame(aContext, aType)
+ explicit nsBlockFrame(nsStyleContext* aContext, ClassID aID = kClassID)
+ : nsContainerFrame(aContext, aID)
, mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
, mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
{
#ifdef DEBUG
InitDebugFlags();
#endif
}
- explicit nsBlockFrame(nsStyleContext* aContext)
- : nsBlockFrame(aContext, mozilla::LayoutFrameType::Block)
- {}
-
virtual ~nsBlockFrame();
#ifdef DEBUG
already_AddRefed<nsStyleContext> GetFirstLetterStyle(nsPresContext* aPresContext);
#endif
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(LineCursorProperty, nsLineBox)
bool HasLineCursor() { return GetStateBits() & NS_BLOCK_HAS_LINE_CURSOR; }
--- a/layout/generic/nsBulletFrame.h
+++ b/layout/generic/nsBulletFrame.h
@@ -42,24 +42,23 @@ private:
/**
* A simple class that manages the layout and rendering of html bullets.
* This class also supports the CSS list-style properties.
*/
class nsBulletFrame final : public nsFrame {
typedef mozilla::image::DrawResult DrawResult;
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsBulletFrame)
#ifdef DEBUG
- NS_DECL_QUERYFRAME_TARGET(nsBulletFrame)
NS_DECL_QUERYFRAME
#endif
explicit nsBulletFrame(nsStyleContext* aContext)
- : nsFrame(aContext, mozilla::LayoutFrameType::Bullet)
+ : nsFrame(aContext, kClassID)
, mPadding(GetWritingMode())
, mIntrinsicSize(GetWritingMode())
, mOrdinal(0)
, mRequestRegistered(false)
, mBlockingOnload(false)
{}
virtual ~nsBulletFrame();
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -29,24 +29,23 @@ class nsRenderingContext;
* frame in the main child list.
*/
class nsCanvasFrame final : public nsContainerFrame,
public nsIScrollPositionListener,
public nsIAnonymousContentCreator
{
public:
explicit nsCanvasFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, mozilla::LayoutFrameType::Canvas)
+ : nsContainerFrame(aContext, kClassID)
, mDoPaintFocus(false)
, mAddedScrollPositionListener(false)
{}
- NS_DECL_QUERYFRAME_TARGET(nsCanvasFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsCanvasFrame)
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual void SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList) override;
virtual void AppendFrames(ChildListID aListID,
nsFrameList& aFrameList) override;
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -124,17 +124,17 @@ NS_NewColumnSetFrame(nsIPresShell* aPres
nsColumnSetFrame* it = new (aPresShell) nsColumnSetFrame(aContext);
it->AddStateBits(aStateFlags | NS_BLOCK_MARGIN_ROOT);
return it;
}
NS_IMPL_FRAMEARENA_HELPERS(nsColumnSetFrame)
nsColumnSetFrame::nsColumnSetFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::ColumnSet)
+ : nsContainerFrame(aContext, kClassID)
, mLastBalanceBSize(NS_INTRINSICSIZE)
{
}
void
nsColumnSetFrame::ForEachColumn(const std::function<void(const nsRect& lineRect)>& aSetLineRect,
const nsPoint& aPt)
{
--- a/layout/generic/nsColumnSetFrame.h
+++ b/layout/generic/nsColumnSetFrame.h
@@ -15,17 +15,17 @@
/**
* nsColumnSetFrame implements CSS multi-column layout.
* @note nsColumnSetFrame keeps true overflow containers in the normal flow
* child lists (i.e. the principal and overflow lists).
*/
class nsColumnSetFrame final : public nsContainerFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsColumnSetFrame)
explicit nsColumnSetFrame(nsStyleContext* aContext);
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -346,22 +346,16 @@ nsContainerFrame::BuildDisplayListForNon
/* virtual */ void
nsContainerFrame::ChildIsDirty(nsIFrame* aChild)
{
NS_ASSERTION(NS_SUBTREE_DIRTY(aChild), "child isn't actually dirty");
AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
}
-bool
-nsContainerFrame::IsLeaf() const
-{
- return false;
-}
-
nsIFrame::FrameSearchResult
nsContainerFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
{
NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
// Don't allow the caret to stay in an empty (leaf) container frame.
return CONTINUE_EMPTY;
}
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -60,17 +60,16 @@ public:
return this;
}
virtual const nsFrameList& GetChildList(ChildListID aList) const override;
virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual void ChildIsDirty(nsIFrame* aChild) override;
- virtual bool IsLeaf() const override;
virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) override;
virtual FrameSearchResult PeekOffsetCharacter(bool aForward, int32_t* aOffset,
bool aRespectClusters = true) override;
virtual nsresult AttributeChanged(int32_t aNameSpaceID,
nsIAtom* aAttribute,
int32_t aModType) override;
@@ -529,18 +528,18 @@ public:
// Use this to suppress the CRAZY_SIZE assertions.
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(DebugReflowingWithInfiniteISize, bool)
bool IsCrazySizeAssertSuppressed() const {
return Properties().Get(DebugReflowingWithInfiniteISize());
}
#endif
protected:
- nsContainerFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType)
- : nsSplittableFrame(aContext, aType)
+ nsContainerFrame(nsStyleContext* aContext, ClassID aID)
+ : nsSplittableFrame(aContext, aID)
{}
~nsContainerFrame();
/**
* Helper for DestroyFrom. DestroyAbsoluteFrames is called before
* destroying frames on lists that can contain placeholders.
* Derived classes must do that too, if they destroy such frame lists.
--- a/layout/generic/nsFirstLetterFrame.h
+++ b/layout/generic/nsFirstLetterFrame.h
@@ -8,22 +8,21 @@
/* rendering object for CSS :first-letter pseudo-element */
#include "mozilla/Attributes.h"
#include "nsContainerFrame.h"
class nsFirstLetterFrame final : public nsContainerFrame {
public:
- NS_DECL_QUERYFRAME_TARGET(nsFirstLetterFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsFirstLetterFrame)
explicit nsFirstLetterFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, mozilla::LayoutFrameType::Letter)
+ : nsContainerFrame(aContext, kClassID)
{}
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -39,18 +39,17 @@ nsContainerFrame* NS_NewFlexContainerFra
* "-webkit" versions, since we're mostly expecting to encounter them in that
* form. (Technically, the "-moz" versions of these properties *can* influence
* layout here as well (since that's what the -webkit versions are aliased to)
* -- but only inside of a "display:-webkit-{inline-}box" container.)
*/
class nsFlexContainerFrame final : public nsContainerFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(nsFlexContainerFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsFlexContainerFrame)
NS_DECL_QUERYFRAME
// Factory method:
friend nsContainerFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
// Forward-decls of helper classes
class FlexItem;
@@ -128,17 +127,17 @@ public:
uint8_t aAlignVal,
nscoord* aFirstSubjectOffset,
uint32_t* aNumPackingSpacesRemaining,
nscoord* aPackingSpaceRemaining);
protected:
// Protected constructor & destructor
explicit nsFlexContainerFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, mozilla::LayoutFrameType::FlexContainer)
+ : nsContainerFrame(aContext, kClassID)
, mBaselineFromLastReflow(NS_INTRINSIC_WIDTH_UNKNOWN)
, mLastBaselineFromLastReflow(NS_INTRINSIC_WIDTH_UNKNOWN)
{}
virtual ~nsFlexContainerFrame();
/*
* This method does the bulk of the flex layout, implementing the algorithm
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -111,16 +111,50 @@
using namespace mozilla;
using namespace mozilla::css;
using namespace mozilla::dom;
using namespace mozilla::gfx;
using namespace mozilla::layers;
using namespace mozilla::layout;
typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
+const mozilla::LayoutFrameType nsIFrame::sLayoutFrameTypes[
+#define FRAME_ID(...) 1 +
+#define ABSTRACT_FRAME_ID(...)
+#include "nsFrameIdList.h"
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+ 0] = {
+#define FRAME_ID(class_, type_, ...) mozilla::LayoutFrameType:: type_,
+#define ABSTRACT_FRAME_ID(...)
+#include "nsFrameIdList.h"
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+};
+
+const nsIFrame::FrameClassBits nsIFrame::sFrameClassBits[
+#define FRAME_ID(...) 1 +
+#define ABSTRACT_FRAME_ID(...)
+#include "nsFrameIdList.h"
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+ 0] = {
+#define Leaf eFrameClassBitsLeaf
+#define NotLeaf eFrameClassBitsNone
+#define DynamicLeaf eFrameClassBitsDynamicLeaf
+#define FRAME_ID(class_, type_, leaf_, ...) leaf_,
+#define ABSTRACT_FRAME_ID(...)
+#include "nsFrameIdList.h"
+#undef Leaf
+#undef NotLeaf
+#undef DynamicLeaf
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+};
+
// Struct containing cached metrics for box-wrapped frames.
struct nsBoxLayoutMetrics
{
nsSize mPrefSize;
nsSize mMinSize;
nsSize mMaxSize;
nsSize mBlockMinSize;
@@ -443,21 +477,21 @@ WeakFrame::Init(nsIFrame* aFrame)
mFrame = nullptr;
}
}
}
nsIFrame*
NS_NewEmptyFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
- return new (aPresShell) nsFrame(aContext, LayoutFrameType::None);
-}
-
-nsFrame::nsFrame(nsStyleContext* aContext, LayoutFrameType aType)
- : nsBox(aType)
+ return new (aPresShell) nsFrame(aContext);
+}
+
+nsFrame::nsFrame(nsStyleContext* aContext, ClassID aID)
+ : nsBox(aID)
{
MOZ_COUNT_CTOR(nsFrame);
mStyleContext = aContext;
mWritingMode = WritingMode(mStyleContext);
mStyleContext->AddRef();
#ifdef DEBUG
mStyleContext->FrameAddRef();
@@ -565,16 +599,17 @@ IsFontSizeInflationContainer(nsIFrame* a
return !isInline;
}
void
nsFrame::Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow)
{
+ MOZ_ASSERT(nsQueryFrame::FrameIID(mClass) == GetFrameId());
NS_PRECONDITION(!mContent, "Double-initing a frame?");
NS_ASSERTION(IsFrameOfType(eDEBUGAllFrames) &&
!IsFrameOfType(eDEBUGNoFrames),
"IsFrameOfType implementation that doesn't call base class");
mContent = aContent;
mParent = aParent;
@@ -6257,22 +6292,16 @@ nsIFrame::GetNearestWidget(nsPoint& aOff
nsPoint offsetToView;
nsPoint offsetToWidget;
nsIWidget* widget =
GetClosestView(&offsetToView)->GetNearestWidget(&offsetToWidget);
aOffset = offsetToView + offsetToWidget;
return widget;
}
-bool
-nsIFrame::IsLeaf() const
-{
- return true;
-}
-
Matrix4x4
nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
nsIFrame** aOutAncestor)
{
NS_PRECONDITION(aOutAncestor, "Need a place to put the ancestor!");
/* If we're transformed, we want to hand back the combination
* transform/translate matrix that will apply our current transform, then
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -85,25 +85,27 @@
// either use NS_{DECL,IMPL}_FRAMEARENA_HELPERS pair for allocating
// memory correctly, or use NS_DECL_ABSTRACT_FRAME to declare a frame
// class abstract and stop it from being instantiated. If a frame class
// without its own operator new and GetFrameId gets instantiated, the
// per-frame recycler lists in nsPresArena will not work correctly,
// with potentially catastrophic consequences (not enough memory is
// allocated for a frame object).
-#define NS_DECL_FRAMEARENA_HELPERS \
- void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE; \
- nsQueryFrame::FrameIID GetFrameId() override MOZ_MUST_OVERRIDE;
+#define NS_DECL_FRAMEARENA_HELPERS(class) \
+ NS_DECL_QUERYFRAME_TARGET(class) \
+ static constexpr nsIFrame::ClassID kClassID = nsIFrame::ClassID::class##_id; \
+ void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE; \
+ nsQueryFrame::FrameIID GetFrameId() override MOZ_MUST_OVERRIDE { \
+ return nsQueryFrame::class##_id; \
+ }
#define NS_IMPL_FRAMEARENA_HELPERS(class) \
void* class::operator new(size_t sz, nsIPresShell* aShell) \
{ return aShell->AllocateFrame(nsQueryFrame::class##_id, sz); } \
- nsQueryFrame::FrameIID class::GetFrameId() \
- { return nsQueryFrame::class##_id; }
#define NS_DECL_ABSTRACT_FRAME(class) \
void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE = delete; \
virtual nsQueryFrame::FrameIID GetFrameId() override MOZ_MUST_OVERRIDE = 0;
//----------------------------------------------------------------------
struct nsBoxLayoutMetrics;
@@ -142,18 +144,21 @@ protected:
// from the "deleting destructors" that they emit in case of
// delete-expressions, so it can't even be undefined.
void operator delete(void* aPtr, size_t sz);
public:
// nsQueryFrame
NS_DECL_QUERYFRAME
+ NS_DECL_QUERYFRAME_TARGET(nsFrame)
+ virtual nsQueryFrame::FrameIID GetFrameId() MOZ_MUST_OVERRIDE {
+ return kFrameIID;
+ }
void* operator new(size_t, nsIPresShell*) MOZ_MUST_OVERRIDE;
- virtual nsQueryFrame::FrameIID GetFrameId() MOZ_MUST_OVERRIDE;
// nsIFrame
void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
void DestroyFrom(nsIFrame* aDestructRoot) override;
nsStyleContext* GetAdditionalStyleContext(int32_t aIndex) const override;
void SetAdditionalStyleContext(int32_t aIndex,
@@ -574,17 +579,19 @@ public:
* Must not be null.
* @param aChildPseudo the child's pseudo type, if any.
*/
static nsIFrame*
CorrectStyleParentFrame(nsIFrame* aProspectiveParent, nsIAtom* aChildPseudo);
protected:
// Protected constructor and destructor
- explicit nsFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType);
+ nsFrame(nsStyleContext* aContext, ClassID aID);
+ explicit nsFrame(nsStyleContext* aContext)
+ : nsFrame(aContext, ClassID::nsFrame_id) {}
virtual ~nsFrame();
/**
* To be called by |BuildDisplayLists| of this class or derived classes to add
* a translucent overlay if this frame's content is selected.
* @param aContentType an nsISelectionDisplay DISPLAY_ constant identifying
* which kind of content this is for
*/
--- a/layout/generic/nsFrameIdList.h
+++ b/layout/generic/nsFrameIdList.h
@@ -1,180 +1,181 @@
/* 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/. */
-FRAME_ID(BRFrame)
-FRAME_ID(DetailsFrame)
-FRAME_ID(nsAutoRepeatBoxFrame)
-FRAME_ID(nsBCTableCellFrame)
-FRAME_ID(nsBackdropFrame)
-FRAME_ID(nsBlockFrame)
-FRAME_ID(nsBox)
-FRAME_ID(nsBoxFrame)
-FRAME_ID(nsBulletFrame)
-FRAME_ID(nsButtonBoxFrame)
-FRAME_ID(nsCanvasFrame)
-FRAME_ID(nsColorControlFrame)
-FRAME_ID(nsColumnSetFrame)
-FRAME_ID(nsComboboxControlFrame)
-FRAME_ID(nsComboboxDisplayFrame)
-FRAME_ID(nsContainerFrame)
-FRAME_ID(nsContinuingTextFrame)
-FRAME_ID(nsDateTimeControlFrame)
-FRAME_ID(nsDeckFrame)
-FRAME_ID(nsDocElementBoxFrame)
-FRAME_ID(nsFieldSetFrame)
-FRAME_ID(nsFileControlFrame)
-FRAME_ID(nsFirstLetterFrame)
-FRAME_ID(nsFirstLineFrame)
-FRAME_ID(nsFlexContainerFrame)
-FRAME_ID(nsFormControlFrame)
-FRAME_ID(nsFrame)
-FRAME_ID(nsGfxButtonControlFrame)
-FRAME_ID(nsGfxCheckboxControlFrame)
-FRAME_ID(nsGfxRadioControlFrame)
-FRAME_ID(nsGridContainerFrame)
-FRAME_ID(nsGridRowGroupFrame)
-FRAME_ID(nsGridRowLeafFrame)
-FRAME_ID(nsGroupBoxFrame)
-FRAME_ID(nsHTMLButtonControlFrame)
-FRAME_ID(nsHTMLCanvasFrame)
-FRAME_ID(nsHTMLFramesetBlankFrame)
-FRAME_ID(nsHTMLFramesetBorderFrame)
-FRAME_ID(nsHTMLFramesetFrame)
-FRAME_ID(nsHTMLScrollFrame)
-FRAME_ID(nsIAnonymousContentCreator)
-FRAME_ID(nsIComboboxControlFrame)
-FRAME_ID(nsIFormControlFrame)
-FRAME_ID(nsIFrame)
-FRAME_ID(nsIFrameFrame)
-FRAME_ID(nsIListControlFrame)
-FRAME_ID(nsIMathMLFrame)
-FRAME_ID(nsIMenuFrame)
-FRAME_ID(nsIObjectFrame)
-FRAME_ID(nsIPageSequenceFrame)
-FRAME_ID(nsIPercentBSizeObserver)
-FRAME_ID(nsIRootBox)
-FRAME_ID(nsSVGDisplayableFrame)
-FRAME_ID(nsISVGSVGFrame)
-FRAME_ID(nsIScrollableFrame)
-FRAME_ID(nsIScrollbarMediator)
-FRAME_ID(nsISelectControlFrame)
-FRAME_ID(nsIStatefulFrame)
-FRAME_ID(nsITableCellLayout)
-FRAME_ID(nsITableLayout)
-FRAME_ID(nsITextControlFrame)
-FRAME_ID(nsITreeBoxObject)
-FRAME_ID(nsImageBoxFrame)
-FRAME_ID(nsImageControlFrame)
-FRAME_ID(nsImageFrame)
-FRAME_ID(nsInlineFrame)
-FRAME_ID(nsLeafBoxFrame)
-FRAME_ID(nsLeafFrame)
-FRAME_ID(nsLegendFrame)
-FRAME_ID(nsListBoxBodyFrame)
-FRAME_ID(nsListControlFrame)
-FRAME_ID(nsListItemFrame)
-FRAME_ID(nsMathMLContainerFrame)
-FRAME_ID(nsMathMLFrame)
-FRAME_ID(nsMathMLmactionFrame)
-FRAME_ID(nsMathMLmathBlockFrame)
-FRAME_ID(nsMathMLmathInlineFrame)
-FRAME_ID(nsMathMLmencloseFrame)
-FRAME_ID(nsMathMLmfencedFrame)
-FRAME_ID(nsMathMLmfracFrame)
-FRAME_ID(nsMathMLmmultiscriptsFrame)
-FRAME_ID(nsMathMLmoFrame)
-FRAME_ID(nsMathMLmoverFrame)
-FRAME_ID(nsMathMLmpaddedFrame)
-FRAME_ID(nsMathMLmrootFrame)
-FRAME_ID(nsMathMLmrowFrame)
-FRAME_ID(nsMathMLmspaceFrame)
-FRAME_ID(nsMathMLmsqrtFrame)
-FRAME_ID(nsMathMLmstyleFrame)
-FRAME_ID(nsMathMLmtableFrame)
-FRAME_ID(nsMathMLmtableWrapperFrame)
-FRAME_ID(nsMathMLmtdFrame)
-FRAME_ID(nsMathMLmtdInnerFrame)
-FRAME_ID(nsMathMLmtrFrame)
-FRAME_ID(nsMathMLmunderFrame)
-FRAME_ID(nsMathMLmunderoverFrame)
-FRAME_ID(nsMathMLsemanticsFrame)
-FRAME_ID(nsMathMLTokenFrame)
-FRAME_ID(nsMenuBarFrame)
-FRAME_ID(nsMenuFrame)
-FRAME_ID(nsMenuPopupFrame)
-FRAME_ID(nsMeterFrame)
-FRAME_ID(nsNumberControlFrame)
-FRAME_ID(nsPluginFrame)
-FRAME_ID(nsPageBreakFrame)
-FRAME_ID(nsPageContentFrame)
-FRAME_ID(nsPageFrame)
-FRAME_ID(nsPlaceholderFrame)
-FRAME_ID(nsPopupSetFrame)
-FRAME_ID(nsProgressFrame)
-FRAME_ID(nsProgressMeterFrame)
-FRAME_ID(nsRangeFrame)
-FRAME_ID(nsResizerFrame)
-FRAME_ID(nsRootBoxFrame)
-FRAME_ID(nsRubyBaseContainerFrame)
-FRAME_ID(nsRubyBaseFrame)
-FRAME_ID(nsRubyContentFrame)
-FRAME_ID(nsRubyFrame)
-FRAME_ID(nsRubyTextContainerFrame)
-FRAME_ID(nsRubyTextFrame)
-FRAME_ID(nsScrollbarButtonFrame)
-FRAME_ID(nsScrollbarFrame)
-FRAME_ID(nsSelectsAreaFrame)
-FRAME_ID(nsSimplePageSequenceFrame)
-FRAME_ID(nsSliderFrame)
-FRAME_ID(nsSplittableFrame)
-FRAME_ID(nsSplitterFrame)
-FRAME_ID(nsStackFrame)
-FRAME_ID(nsSubDocumentFrame)
-FRAME_ID(nsSVGAFrame)
-FRAME_ID(nsSVGClipPathFrame)
-FRAME_ID(nsSVGContainerFrame)
-FRAME_ID(nsSVGDisplayContainerFrame)
-FRAME_ID(SVGFEContainerFrame)
-FRAME_ID(SVGFEImageFrame)
-FRAME_ID(SVGFELeafFrame)
-FRAME_ID(SVGFEUnstyledLeafFrame)
-FRAME_ID(nsSVGFilterFrame)
-FRAME_ID(nsSVGForeignObjectFrame)
-FRAME_ID(nsSVGGenericContainerFrame)
-FRAME_ID(nsSVGGFrame)
-FRAME_ID(nsSVGGradientFrame)
-FRAME_ID(nsSVGImageFrame)
-FRAME_ID(nsSVGInnerSVGFrame)
-FRAME_ID(nsSVGLinearGradientFrame)
-FRAME_ID(nsSVGMarkerFrame)
-FRAME_ID(nsSVGMarkerAnonChildFrame)
-FRAME_ID(nsSVGMaskFrame)
-FRAME_ID(nsSVGOuterSVGFrame)
-FRAME_ID(nsSVGOuterSVGAnonChildFrame)
-FRAME_ID(nsSVGPaintServerFrame)
-FRAME_ID(SVGGeometryFrame)
-FRAME_ID(nsSVGPatternFrame)
-FRAME_ID(nsSVGRadialGradientFrame)
-FRAME_ID(nsSVGStopFrame)
-FRAME_ID(nsSVGSwitchFrame)
-FRAME_ID(SVGTextFrame)
-FRAME_ID(nsSVGUseFrame)
-FRAME_ID(SVGViewFrame)
-FRAME_ID(nsTableCellFrame)
-FRAME_ID(nsTableColFrame)
-FRAME_ID(nsTableColGroupFrame)
-FRAME_ID(nsTableFrame)
-FRAME_ID(nsTableWrapperFrame)
-FRAME_ID(nsTableRowFrame)
-FRAME_ID(nsTableRowGroupFrame)
-FRAME_ID(nsTextBoxFrame)
-FRAME_ID(nsTextControlFrame)
-FRAME_ID(nsTextFrame)
-FRAME_ID(nsTitleBarFrame)
-FRAME_ID(nsTreeBodyFrame)
-FRAME_ID(nsTreeColFrame)
-FRAME_ID(nsVideoFrame)
-FRAME_ID(nsXULLabelFrame)
-FRAME_ID(nsXULScrollFrame)
-FRAME_ID(ViewportFrame)
+FRAME_ID(BRFrame, Br, Leaf)
+FRAME_ID(DetailsFrame, Details, NotLeaf)
+FRAME_ID(nsAutoRepeatBoxFrame, Box, NotLeaf)
+FRAME_ID(nsBCTableCellFrame, BCTableCell, NotLeaf)
+FRAME_ID(nsBackdropFrame, Backdrop, Leaf)
+FRAME_ID(nsBlockFrame, Block, NotLeaf)
+FRAME_ID(nsBox, None, NotLeaf)
+FRAME_ID(nsBoxFrame, Box, NotLeaf)
+FRAME_ID(nsBulletFrame, Bullet, Leaf)
+FRAME_ID(nsButtonBoxFrame, Box, NotLeaf)
+FRAME_ID(nsCanvasFrame, Canvas, NotLeaf)
+FRAME_ID(nsColorControlFrame, ColorControl, Leaf)
+FRAME_ID(nsColumnSetFrame, ColumnSet, NotLeaf)
+FRAME_ID(nsComboboxControlFrame, ComboboxControl, NotLeaf)
+FRAME_ID(nsComboboxDisplayFrame, ComboboxDisplay, NotLeaf)
+FRAME_ID(nsContinuingTextFrame, Text, Leaf)
+FRAME_ID(nsDateTimeControlFrame, DateTimeControl, NotLeaf)
+FRAME_ID(nsDeckFrame, Deck, NotLeaf)
+FRAME_ID(nsDocElementBoxFrame, Box, NotLeaf)
+FRAME_ID(nsFieldSetFrame, FieldSet, NotLeaf)
+FRAME_ID(nsFileControlFrame, Block, Leaf)
+FRAME_ID(nsFirstLetterFrame, Letter, NotLeaf)
+FRAME_ID(nsFirstLineFrame, Line, NotLeaf)
+FRAME_ID(nsFlexContainerFrame, FlexContainer, NotLeaf)
+FRAME_ID(nsFrame, None, NotLeaf)
+FRAME_ID(nsGfxButtonControlFrame, GfxButtonControl, Leaf)
+FRAME_ID(nsGfxCheckboxControlFrame, FormControl, Leaf)
+FRAME_ID(nsGfxRadioControlFrame, FormControl, Leaf)
+FRAME_ID(nsGridContainerFrame, GridContainer, NotLeaf)
+FRAME_ID(nsGridRowGroupFrame, Box, NotLeaf)
+FRAME_ID(nsGridRowLeafFrame, Box, NotLeaf)
+FRAME_ID(nsGroupBoxFrame, Box, NotLeaf)
+FRAME_ID(nsHTMLButtonControlFrame, HTMLButtonControl, NotLeaf)
+FRAME_ID(nsHTMLCanvasFrame, HTMLCanvas, NotLeaf)
+FRAME_ID(nsHTMLFramesetBlankFrame, None, Leaf)
+FRAME_ID(nsHTMLFramesetBorderFrame, None, Leaf)
+FRAME_ID(nsHTMLFramesetFrame, FrameSet, Leaf)
+FRAME_ID(nsHTMLScrollFrame, Scroll, NotLeaf)
+FRAME_ID(nsImageBoxFrame, ImageBox, Leaf)
+FRAME_ID(nsImageControlFrame, ImageControl, Leaf)
+FRAME_ID(nsImageFrame, Image, Leaf)
+FRAME_ID(nsInlineFrame, Inline, NotLeaf)
+FRAME_ID(nsLeafBoxFrame, LeafBox, Leaf)
+FRAME_ID(nsLegendFrame, Legend, NotLeaf)
+FRAME_ID(nsListBoxBodyFrame, Box, NotLeaf)
+FRAME_ID(nsListControlFrame, ListControl, NotLeaf)
+FRAME_ID(nsListItemFrame, Box, NotLeaf)
+FRAME_ID(nsMathMLFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmactionFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmathBlockFrame, Block, NotLeaf)
+FRAME_ID(nsMathMLmathInlineFrame, Inline, NotLeaf)
+FRAME_ID(nsMathMLmencloseFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmfencedFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmfracFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmmultiscriptsFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmoFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmpaddedFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmrootFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmrowFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmspaceFrame, None, Leaf)
+FRAME_ID(nsMathMLmsqrtFrame, None, NotLeaf)
+FRAME_ID(nsMathMLmtableFrame, Table, NotLeaf)
+FRAME_ID(nsMathMLmtableWrapperFrame, TableWrapper, NotLeaf)
+FRAME_ID(nsMathMLmtdFrame, TableCell, NotLeaf)
+FRAME_ID(nsMathMLmtdInnerFrame, Block, NotLeaf)
+FRAME_ID(nsMathMLmtrFrame, TableRow, NotLeaf)
+FRAME_ID(nsMathMLmunderoverFrame, None, NotLeaf)
+FRAME_ID(nsMathMLsemanticsFrame, None, NotLeaf)
+FRAME_ID(nsMathMLTokenFrame, None, NotLeaf)
+FRAME_ID(nsMenuBarFrame, Box, NotLeaf)
+FRAME_ID(nsMenuFrame, Menu, NotLeaf)
+FRAME_ID(nsMenuPopupFrame, MenuPopup, DynamicLeaf)
+FRAME_ID(nsMeterFrame, Meter, Leaf)
+FRAME_ID(nsNumberControlFrame, NumberControl, Leaf)
+FRAME_ID(nsPluginFrame, Object, Leaf)
+FRAME_ID(nsPageBreakFrame, PageBreak, Leaf)
+FRAME_ID(nsPageContentFrame, PageContent, NotLeaf)
+FRAME_ID(nsPageFrame, Page, NotLeaf)
+FRAME_ID(nsPlaceholderFrame, Placeholder, Leaf)
+FRAME_ID(nsPopupSetFrame, PopupSet, NotLeaf)
+FRAME_ID(nsProgressFrame, Progress, Leaf)
+FRAME_ID(nsProgressMeterFrame, Box, NotLeaf)
+FRAME_ID(nsRangeFrame, Range, Leaf)
+FRAME_ID(nsResizerFrame, Box, NotLeaf)
+FRAME_ID(nsRootBoxFrame, Root, NotLeaf)
+FRAME_ID(nsRubyBaseContainerFrame, RubyBaseContainer, NotLeaf)
+FRAME_ID(nsRubyBaseFrame, RubyBase, NotLeaf)
+FRAME_ID(nsRubyFrame, Ruby, NotLeaf)
+FRAME_ID(nsRubyTextContainerFrame, RubyTextContainer, NotLeaf)
+FRAME_ID(nsRubyTextFrame, RubyText, NotLeaf)
+FRAME_ID(nsScrollbarButtonFrame, Box, NotLeaf)
+FRAME_ID(nsScrollbarFrame, Scrollbar, NotLeaf)
+FRAME_ID(nsSelectsAreaFrame, Block, NotLeaf)
+FRAME_ID(nsSimplePageSequenceFrame, Sequence, NotLeaf)
+FRAME_ID(nsSliderFrame, Slider, NotLeaf)
+FRAME_ID(nsSplitterFrame, Box, NotLeaf)
+FRAME_ID(nsStackFrame, Box, NotLeaf)
+FRAME_ID(nsSubDocumentFrame, SubDocument, Leaf)
+FRAME_ID(nsSVGAFrame, SVGA, NotLeaf)
+FRAME_ID(nsSVGClipPathFrame, SVGClipPath, NotLeaf)
+FRAME_ID(nsSVGContainerFrame, None, NotLeaf)
+FRAME_ID(SVGFEContainerFrame, SVGFEContainer, NotLeaf)
+FRAME_ID(SVGFEImageFrame, SVGFEImage, Leaf)
+FRAME_ID(SVGFELeafFrame, SVGFELeaf, Leaf)
+FRAME_ID(SVGFEUnstyledLeafFrame, SVGFEUnstyledLeaf, Leaf)
+FRAME_ID(nsSVGFilterFrame, SVGFilter, NotLeaf)
+FRAME_ID(nsSVGForeignObjectFrame, SVGForeignObject, NotLeaf)
+FRAME_ID(nsSVGGenericContainerFrame, SVGGenericContainer, NotLeaf)
+FRAME_ID(nsSVGGFrame, SVGG, NotLeaf)
+FRAME_ID(nsSVGImageFrame, SVGImage, Leaf)
+FRAME_ID(nsSVGInnerSVGFrame, SVGInnerSVG, NotLeaf)
+FRAME_ID(nsSVGLinearGradientFrame, SVGLinearGradient, NotLeaf)
+FRAME_ID(nsSVGMarkerFrame, SVGMarker, NotLeaf)
+FRAME_ID(nsSVGMarkerAnonChildFrame, SVGMarkerAnonChild, NotLeaf)
+FRAME_ID(nsSVGMaskFrame, SVGMask, NotLeaf)
+FRAME_ID(nsSVGOuterSVGFrame, SVGOuterSVG, NotLeaf)
+FRAME_ID(nsSVGOuterSVGAnonChildFrame, SVGOuterSVGAnonChild, NotLeaf)
+FRAME_ID(SVGGeometryFrame, SVGGeometry, Leaf)
+FRAME_ID(nsSVGPatternFrame, SVGPattern, NotLeaf)
+FRAME_ID(nsSVGRadialGradientFrame, SVGRadialGradient, NotLeaf)
+FRAME_ID(nsSVGStopFrame, SVGStop, Leaf)
+FRAME_ID(nsSVGSwitchFrame, SVGSwitch, NotLeaf)
+FRAME_ID(SVGTextFrame, SVGText, NotLeaf)
+FRAME_ID(nsSVGUseFrame, SVGUse, Leaf)
+FRAME_ID(SVGViewFrame, SVGView, Leaf)
+FRAME_ID(nsTableCellFrame, TableCell, NotLeaf)
+FRAME_ID(nsTableColFrame, TableCol, Leaf)
+FRAME_ID(nsTableColGroupFrame, TableColGroup, NotLeaf)
+FRAME_ID(nsTableFrame, Table, NotLeaf)
+FRAME_ID(nsTableWrapperFrame, TableWrapper, NotLeaf)
+FRAME_ID(nsTableRowFrame, TableRow, NotLeaf)
+FRAME_ID(nsTableRowGroupFrame, TableRowGroup, NotLeaf)
+FRAME_ID(nsTextBoxFrame, LeafBox, Leaf)
+FRAME_ID(nsTextControlFrame, TextInput, Leaf)
+FRAME_ID(nsTextFrame, Text, Leaf)
+FRAME_ID(nsTitleBarFrame, Box, NotLeaf)
+FRAME_ID(nsTreeBodyFrame, LeafBox, Leaf)
+FRAME_ID(nsTreeColFrame, Box, NotLeaf)
+FRAME_ID(nsVideoFrame, HTMLVideo, Leaf)
+FRAME_ID(nsXULLabelFrame, XULLabel, NotLeaf)
+FRAME_ID(nsXULScrollFrame, Scroll, NotLeaf)
+FRAME_ID(ViewportFrame, Viewport, NotLeaf)
+
+// Non-concrete classes (for FrameIID use)
+ABSTRACT_FRAME_ID(nsContainerFrame)
+ABSTRACT_FRAME_ID(nsFormControlFrame)
+ABSTRACT_FRAME_ID(nsIFrame)
+ABSTRACT_FRAME_ID(nsLeafFrame)
+ABSTRACT_FRAME_ID(nsMathMLContainerFrame)
+ABSTRACT_FRAME_ID(nsRubyContentFrame)
+ABSTRACT_FRAME_ID(nsSplittableFrame)
+ABSTRACT_FRAME_ID(nsSVGDisplayContainerFrame)
+ABSTRACT_FRAME_ID(nsSVGGradientFrame)
+ABSTRACT_FRAME_ID(nsSVGPaintServerFrame)
+
+// Interfaces (for FrameIID use)
+ABSTRACT_FRAME_ID(nsIAnonymousContentCreator)
+ABSTRACT_FRAME_ID(nsIComboboxControlFrame)
+ABSTRACT_FRAME_ID(nsIFormControlFrame)
+ABSTRACT_FRAME_ID(nsIFrameFrame)
+ABSTRACT_FRAME_ID(nsIListControlFrame)
+ABSTRACT_FRAME_ID(nsIMathMLFrame)
+ABSTRACT_FRAME_ID(nsIMenuFrame)
+ABSTRACT_FRAME_ID(nsIObjectFrame)
+ABSTRACT_FRAME_ID(nsIPageSequenceFrame)
+ABSTRACT_FRAME_ID(nsIPercentBSizeObserver)
+ABSTRACT_FRAME_ID(nsIRootBox)
+ABSTRACT_FRAME_ID(nsIScrollableFrame)
+ABSTRACT_FRAME_ID(nsIScrollbarMediator)
+ABSTRACT_FRAME_ID(nsISelectControlFrame)
+ABSTRACT_FRAME_ID(nsISVGSVGFrame)
+ABSTRACT_FRAME_ID(nsIStatefulFrame)
+ABSTRACT_FRAME_ID(nsITableCellLayout)
+ABSTRACT_FRAME_ID(nsITableLayout)
+ABSTRACT_FRAME_ID(nsITextControlFrame)
+ABSTRACT_FRAME_ID(nsITreeBoxObject)
+ABSTRACT_FRAME_ID(nsSVGDisplayableFrame)
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -81,17 +81,17 @@ void nsFramesetDrag::UnSet()
}
/*******************************************************************************
* nsHTMLFramesetBorderFrame
******************************************************************************/
class nsHTMLFramesetBorderFrame final : public nsLeafFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsHTMLFramesetBorderFrame)
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
virtual nsresult HandleEvent(nsPresContext* aPresContext,
WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) override;
@@ -132,19 +132,18 @@ protected:
friend class nsHTMLFramesetFrame;
};
/*******************************************************************************
* nsHTMLFramesetBlankFrame
******************************************************************************/
class nsHTMLFramesetBlankFrame final : public nsLeafFrame
{
public:
- NS_DECL_QUERYFRAME_TARGET(nsHTMLFramesetBlankFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsHTMLFramesetBlankFrame)
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override
{
return MakeFrameName(NS_LITERAL_STRING("FramesetBlank"), aResult);
}
#endif
@@ -154,17 +153,17 @@ public:
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
protected:
explicit nsHTMLFramesetBlankFrame(nsStyleContext* aContext)
- : nsLeafFrame(aContext, LayoutFrameType::None)
+ : nsLeafFrame(aContext, kClassID)
{}
virtual ~nsHTMLFramesetBlankFrame();
virtual nscoord GetIntrinsicISize() override;
virtual nscoord GetIntrinsicBSize() override;
friend class nsHTMLFramesetFrame;
friend class nsHTMLFrameset;
@@ -172,17 +171,17 @@ protected:
/*******************************************************************************
* nsHTMLFramesetFrame
******************************************************************************/
bool nsHTMLFramesetFrame::gDragInProgress = false;
#define DEFAULT_BORDER_WIDTH_PX 6
nsHTMLFramesetFrame::nsHTMLFramesetFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::FrameSet)
+ : nsContainerFrame(aContext, kClassID)
{
mNumRows = 0;
mNumCols = 0;
mEdgeVisibility = 0;
mParentFrameborder = eFrameborder_Yes; // default
mParentBorderWidth = -1; // default not set
mParentBorderColor = NO_COLOR; // default not set
mFirstDragPoint.x = mFirstDragPoint.y = 0;
@@ -1098,23 +1097,16 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
nsresult
nsHTMLFramesetFrame::GetFrameName(nsAString& aResult) const
{
return MakeFrameName(NS_LITERAL_STRING("Frameset"), aResult);
}
#endif
bool
-nsHTMLFramesetFrame::IsLeaf() const
-{
- // We handle constructing our kids manually
- return true;
-}
-
-bool
nsHTMLFramesetFrame::CanResize(bool aVertical,
bool aLeft)
{
int32_t childX;
int32_t startX;
if (aVertical) {
startX = (aLeft) ? 0 : mNumCols-1;
for (childX = startX; childX < mNonBorderChildCount; childX += mNumCols) {
@@ -1332,17 +1324,17 @@ NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramese
/*******************************************************************************
* nsHTMLFramesetBorderFrame
******************************************************************************/
nsHTMLFramesetBorderFrame::nsHTMLFramesetBorderFrame(nsStyleContext* aContext,
int32_t aWidth,
bool aVertical,
bool aVisibility)
- : nsLeafFrame(aContext, LayoutFrameType::None)
+ : nsLeafFrame(aContext, kClassID)
, mWidth(aWidth)
, mVertical(aVertical)
, mVisibility(aVisibility)
{
mCanResize = true;
mColor = NO_COLOR;
mPrevNeighbor = 0;
mNextNeighbor = 0;
--- a/layout/generic/nsFrameSetFrame.h
+++ b/layout/generic/nsFrameSetFrame.h
@@ -59,19 +59,18 @@ struct nsFramesetDrag {
};
/*******************************************************************************
* nsHTMLFramesetFrame
******************************************************************************/
class nsHTMLFramesetFrame : public nsContainerFrame
{
public:
- NS_DECL_QUERYFRAME_TARGET(nsHTMLFramesetFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsHTMLFramesetFrame)
explicit nsHTMLFramesetFrame(nsStyleContext* aContext);
virtual ~nsHTMLFramesetFrame();
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
@@ -104,18 +103,16 @@ public:
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
- virtual bool IsLeaf() const override;
-
void StartMouseDrag(nsPresContext* aPresContext,
nsHTMLFramesetBorderFrame* aBorder,
mozilla::WidgetGUIEvent* aEvent);
void MouseDrag(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent);
void EndMouseDrag(nsPresContext* aPresContext);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -105,19 +105,19 @@ nsHTMLScrollFrame*
NS_NewHTMLScrollFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, bool aIsRoot)
{
return new (aPresShell) nsHTMLScrollFrame(aContext, aIsRoot);
}
NS_IMPL_FRAMEARENA_HELPERS(nsHTMLScrollFrame)
nsHTMLScrollFrame::nsHTMLScrollFrame(nsStyleContext* aContext,
- LayoutFrameType aType,
+ nsIFrame::ClassID aID,
bool aIsRoot)
- : nsContainerFrame(aContext, aType)
+ : nsContainerFrame(aContext, aID)
, mHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this), aIsRoot)
{
}
void
nsHTMLScrollFrame::ScrollbarActivityStarted() const
{
if (mHelper.mScrollbarActivity) {
@@ -1156,17 +1156,17 @@ NS_NewXULScrollFrame(nsIPresShell* aPres
aClipAllDescendants);
}
NS_IMPL_FRAMEARENA_HELPERS(nsXULScrollFrame)
nsXULScrollFrame::nsXULScrollFrame(nsStyleContext* aContext,
bool aIsRoot,
bool aClipAllDescendants)
- : nsBoxFrame(aContext, LayoutFrameType::Scroll, aIsRoot)
+ : nsBoxFrame(aContext, kClassID, aIsRoot)
, mHelper(ALLOW_THIS_IN_INITIALIZER_LIST(this), aIsRoot)
{
SetXULLayoutManager(nullptr);
mHelper.mClipAllDescendants = aClipAllDescendants;
}
void
nsXULScrollFrame::ScrollbarActivityStarted() const
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -677,17 +677,17 @@ public:
typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
typedef mozilla::CSSIntPoint CSSIntPoint;
typedef mozilla::ScrollReflowInput ScrollReflowInput;
friend nsHTMLScrollFrame* NS_NewHTMLScrollFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext,
bool aIsRoot);
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsHTMLScrollFrame)
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override {
mHelper.BuildDisplayList(aBuilder, aDirtyRect, aLists);
}
bool TryLayout(ScrollReflowInput* aState,
@@ -1055,21 +1055,21 @@ public:
#endif
#ifdef ACCESSIBILITY
virtual mozilla::a11y::AccType AccessibleType() override;
#endif
protected:
nsHTMLScrollFrame(nsStyleContext* aContext, bool aIsRoot)
- : nsHTMLScrollFrame(aContext, mozilla::LayoutFrameType::Scroll, aIsRoot)
+ : nsHTMLScrollFrame(aContext, kClassID, aIsRoot)
{}
nsHTMLScrollFrame(nsStyleContext* aContext,
- mozilla::LayoutFrameType aType,
+ nsIFrame::ClassID aID,
bool aIsRoot);
void SetSuppressScrollbarUpdate(bool aSuppress) {
mHelper.mSupppressScrollbarUpdate = aSuppress;
}
bool GuessHScrollbarNeeded(const ScrollReflowInput& aState);
bool GuessVScrollbarNeeded(const ScrollReflowInput& aState);
bool IsScrollbarUpdateSuppressed() const {
@@ -1106,17 +1106,17 @@ class nsXULScrollFrame final : public ns
public nsIAnonymousContentCreator,
public nsIStatefulFrame
{
public:
typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
typedef mozilla::CSSIntPoint CSSIntPoint;
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsXULScrollFrame)
friend nsXULScrollFrame* NS_NewXULScrollFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext,
bool aIsRoot,
bool aClipAllDescendants);
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
--- a/layout/generic/nsGridContainerFrame.h
+++ b/layout/generic/nsGridContainerFrame.h
@@ -79,18 +79,17 @@ struct ComputedGridLineInfo
nsTArray<nsString> mNamesBefore;
nsTArray<nsString> mNamesAfter;
};
} // namespace mozilla
class nsGridContainerFrame final : public nsContainerFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(nsGridContainerFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsGridContainerFrame)
NS_DECL_QUERYFRAME
typedef mozilla::ComputedGridTrackInfo ComputedGridTrackInfo;
typedef mozilla::ComputedGridLineInfo ComputedGridLineInfo;
// nsIFrame overrides
void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
@@ -253,17 +252,17 @@ protected:
struct LineRange;
struct SharedGridData;
struct TrackSizingFunctions;
struct Tracks;
struct TranslatedLineRange;
friend nsContainerFrame* NS_NewGridContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsGridContainerFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, mozilla::LayoutFrameType::GridContainer)
+ : nsContainerFrame(aContext, kClassID)
, mCachedMinISize(NS_INTRINSIC_WIDTH_UNKNOWN)
, mCachedPrefISize(NS_INTRINSIC_WIDTH_UNKNOWN)
{
mBaseline[0][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
mBaseline[0][1] = NS_INTRINSIC_WIDTH_UNKNOWN;
mBaseline[1][0] = NS_INTRINSIC_WIDTH_UNKNOWN;
mBaseline[1][1] = NS_INTRINSIC_WIDTH_UNKNOWN;
}
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -27,22 +27,21 @@ nsIFrame* NS_NewHTMLCanvasFrame (nsIPres
class nsHTMLCanvasFrame final : public nsContainerFrame
{
public:
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
- NS_DECL_QUERYFRAME_TARGET(nsHTMLCanvasFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsHTMLCanvasFrame)
explicit nsHTMLCanvasFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, mozilla::LayoutFrameType::HTMLCanvas)
+ : nsContainerFrame(aContext, kClassID)
, mBorderPadding(GetWritingMode())
{}
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -598,28 +598,29 @@ public:
typedef mozilla::layout::FrameChildListIterator ChildListIterator;
typedef mozilla::layout::FrameChildListArrayIterator ChildListArrayIterator;
typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Matrix Matrix;
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
typedef mozilla::Sides Sides;
typedef mozilla::LogicalSides LogicalSides;
typedef mozilla::SmallPointerArray<mozilla::DisplayItemData> DisplayItemArray;
+ typedef nsQueryFrame::ClassID ClassID;
NS_DECL_QUERYFRAME_TARGET(nsIFrame)
- explicit nsIFrame(mozilla::LayoutFrameType aType)
+ explicit nsIFrame(ClassID aID)
: mRect()
, mContent(nullptr)
, mStyleContext(nullptr)
, mParent(nullptr)
, mNextSibling(nullptr)
, mPrevSibling(nullptr)
, mState(NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY)
- , mType(aType)
+ , mClass(aID)
{
mozilla::PodZero(&mOverflow);
}
nsPresContext* PresContext() const {
return StyleContext()->PresContext();
}
@@ -2697,22 +2698,25 @@ public:
*/
nsIWidget* GetNearestWidget(nsPoint& aOffset) const;
/**
* Get the "type" of the frame.
*
* @see mozilla::LayoutFrameType
*/
- mozilla::LayoutFrameType Type() const { return mType; }
+ mozilla::LayoutFrameType Type() const {
+ MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sLayoutFrameTypes));
+ return sLayoutFrameTypes[uint8_t(mClass)];
+ }
#define FRAME_TYPE(name_) \
bool Is##name_##Frame() const \
{ \
- return mType == mozilla::LayoutFrameType::name_; \
+ return Type() == mozilla::LayoutFrameType::name_; \
}
#include "mozilla/FrameTypeList.h"
#undef FRAME_TYPE
/**
* Returns a transformation matrix that converts points in this frame's
* coordinate space to points in some ancestor frame's coordinate space.
* The frame decides which ancestor it will use as a reference point.
@@ -2829,17 +2833,25 @@ public:
* Is this a leaf frame? Frames that want the frame constructor to be able
* to construct kids for them should return false, all others should return
* true. Note that returning true here does not mean that the frame _can't_
* have kids. It could still have kids created via
* nsIAnonymousContentCreator. Returning true indicates that "normal"
* (non-anonymous, XBL-bound, CSS generated content, etc) children should not
* be constructed.
*/
- virtual bool IsLeaf() const;
+ bool IsLeaf() const
+ {
+ MOZ_ASSERT(uint8_t(mClass) < mozilla::ArrayLength(sFrameClassBits));
+ FrameClassBits bits = sFrameClassBits[uint8_t(mClass)];
+ if (MOZ_UNLIKELY(bits & eFrameClassBitsDynamicLeaf)) {
+ return IsLeafDynamic();
+ }
+ return bits & eFrameClassBitsLeaf;
+ }
/**
* Marks all display items created by this frame as needing a repaint,
* and calls SchedulePaint() if requested and one is not already pending.
*
* This includes all display items created by this frame, including
* container types.
*
@@ -3811,16 +3823,23 @@ protected:
/**
* Reparent this frame's view if it has one.
*/
void ReparentFrameViewTo(nsViewManager* aViewManager,
nsView* aNewParentView,
nsView* aOldParentView);
+ /**
+ * To be overridden by frame classes that have a varying IsLeaf() state and
+ * is indicating that with DynamicLeaf in nsFrameIdList.h.
+ * @see IsLeaf()
+ */
+ virtual bool IsLeafDynamic() const { return false; }
+
// Members
nsRect mRect;
nsIContent* mContent;
nsStyleContext* mStyleContext;
private:
nsContainerFrame* mParent;
nsIFrame* mNextSibling; // doubly-linked list of frames
nsIFrame* mPrevSibling; // Do not touch outside SetNextSibling!
@@ -3894,18 +3913,18 @@ protected:
union {
uint32_t mType;
VisualDeltas mVisualDeltas;
} mOverflow;
/** @see GetWritingMode() */
mozilla::WritingMode mWritingMode;
- /** The type of the frame. */
- mozilla::LayoutFrameType mType;
+ /** The ClassID of the concrete class of this instance. */
+ ClassID mClass; // 1 byte
// Helpers
/**
* Can we stop inside this frame when we're skipping non-rendered whitespace?
* @param aForward [in] Are we moving forward (or backward) in content order.
* @param aOffset [in/out] At what offset into the frame to start looking.
* on output - what offset was reached (whether or not we found a place to stop).
* @return STOP: An appropriate offset was found within this frame,
@@ -4020,16 +4039,39 @@ private:
static nsIFrame* SortedMerge(nsIFrame *aLeft, nsIFrame *aRight);
template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
static nsIFrame* MergeSort(nsIFrame *aSource);
bool HasOpacityInternal(float aThreshold,
mozilla::EffectSet* aEffectSet = nullptr) const;
+ // Maps mClass to LayoutFrameType.
+ static const mozilla::LayoutFrameType sLayoutFrameTypes[
+#define FRAME_ID(...) 1 +
+#define ABSTRACT_FRAME_ID(...)
+#include "nsFrameIdList.h"
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+ 0];
+
+ enum FrameClassBits {
+ eFrameClassBitsNone = 0x0,
+ eFrameClassBitsLeaf = 0x1,
+ eFrameClassBitsDynamicLeaf = 0x2,
+ };
+ // Maps mClass to IsLeaf() flags.
+ static const FrameClassBits sFrameClassBits[
+#define FRAME_ID(...) 1 +
+#define ABSTRACT_FRAME_ID(...)
+#include "nsFrameIdList.h"
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+ 0];
+
#ifdef DEBUG_FRAME_DUMP
public:
static void IndentBy(FILE* out, int32_t aIndent) {
while (--aIndent >= 0) fputs(" ", out);
}
void ListTag(FILE* out) const {
ListTag(out, this);
}
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -130,18 +130,18 @@ inline bool HaveFixedSize(const ReflowIn
nsIFrame*
NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsImageFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsImageFrame)
-nsImageFrame::nsImageFrame(nsStyleContext* aContext, LayoutFrameType aType)
- : nsAtomicContainerFrame(aContext, aType)
+nsImageFrame::nsImageFrame(nsStyleContext* aContext, ClassID aID)
+ : nsAtomicContainerFrame(aContext, aID)
, mComputedSize(0, 0)
, mIntrinsicRatio(0, 0)
, mDisplayingIcon(false)
, mFirstFrameComplete(false)
, mReflowCallbackPosted(false)
, mForceSyncDecoding(false)
{
EnableVisibilityTracking();
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -64,23 +64,17 @@ public:
using Nothing = mozilla::Nothing;
using Visibility = mozilla::Visibility;
typedef mozilla::image::DrawResult DrawResult;
typedef mozilla::layers::ImageContainer ImageContainer;
typedef mozilla::layers::ImageLayer ImageLayer;
typedef mozilla::layers::LayerManager LayerManager;
- NS_DECL_FRAMEARENA_HELPERS
-
- explicit nsImageFrame(nsStyleContext* aContext)
- : nsImageFrame(aContext, mozilla::LayoutFrameType::Image)
- {}
-
- NS_DECL_QUERYFRAME_TARGET(nsImageFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsImageFrame)
NS_DECL_QUERYFRAME
virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) override;
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
@@ -177,19 +171,23 @@ public:
InlineMinISizeData *aData) override;
void DisconnectMap();
// nsIReflowCallback
virtual bool ReflowFinished() override;
virtual void ReflowCallbackCanceled() override;
+private:
+ friend nsIFrame* NS_NewImageFrame(nsIPresShell*, nsStyleContext*);
+ explicit nsImageFrame(nsStyleContext* aContext)
+ : nsImageFrame(aContext, kClassID) {}
+
protected:
- nsImageFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType);
-
+ nsImageFrame(nsStyleContext* aContext, ClassID aID);
virtual ~nsImageFrame();
void EnsureIntrinsicSizeAndRatio();
virtual mozilla::LogicalSize
ComputeSize(nsRenderingContext *aRenderingContext,
mozilla::WritingMode aWritingMode,
const mozilla::LogicalSize& aCBSize,
--- a/layout/generic/nsInlineFrame.h
+++ b/layout/generic/nsInlineFrame.h
@@ -17,19 +17,18 @@ class nsLineLayout;
* Inline frame class.
*
* This class manages a list of child frames that are inline frames. Working with
* nsLineLayout, the class will reflow and place inline frames on a line.
*/
class nsInlineFrame : public nsContainerFrame
{
public:
- NS_DECL_QUERYFRAME_TARGET(nsInlineFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsInlineFrame)
friend nsInlineFrame* NS_NewInlineFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
// nsIFrame overrides
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
@@ -136,25 +135,21 @@ protected:
mPrevFrame = nullptr;
mNextInFlow = nullptr;
mLineContainer = nullptr;
mLineLayout = nullptr;
mSetParentPointer = false;
}
};
- nsInlineFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType)
- : nsContainerFrame(aContext, aType)
+ nsInlineFrame(nsStyleContext* aContext, ClassID aID)
+ : nsContainerFrame(aContext, aID)
, mBaseline(NS_INTRINSIC_WIDTH_UNKNOWN)
{}
- explicit nsInlineFrame(nsStyleContext* aContext)
- : nsInlineFrame(aContext, mozilla::LayoutFrameType::Inline)
- {}
-
virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override;
void ReflowFrames(nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
InlineReflowInput& rs,
ReflowOutput& aMetrics,
nsReflowStatus& aStatus);
@@ -178,16 +173,20 @@ protected:
bool* aIsComplete);
virtual void PushFrames(nsPresContext* aPresContext,
nsIFrame* aFromChild,
nsIFrame* aPrevSibling,
InlineReflowInput& aState);
private:
+ explicit nsInlineFrame(nsStyleContext* aContext)
+ : nsInlineFrame(aContext, kClassID)
+ {}
+
// Helper method for DrainSelfOverflowList() to deal with lazy parenting
// (which we only do for nsInlineFrame, not nsFirstLineFrame).
enum DrainFlags {
eDontReparentFrames = 1, // skip reparenting the overflow list frames
eInFirstLine = 2, // the request is for an inline descendant of a nsFirstLineFrame
eForDestroy = 4, // the request is from DestroyFrom; in this case we do the
// minimal work required since the frame is about to be
// destroyed (just fixup parent pointers)
@@ -207,17 +206,17 @@ protected:
//----------------------------------------------------------------------
/**
* Variation on inline-frame used to manage lines for line layout in
* special situations (:first-line style in particular).
*/
class nsFirstLineFrame final : public nsInlineFrame {
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsFirstLineFrame)
friend nsFirstLineFrame* NS_NewFirstLineFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
virtual void Reflow(nsPresContext* aPresContext,
@@ -228,17 +227,17 @@ public:
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
virtual void PullOverflowsFromPrevInFlow() override;
virtual bool DrainSelfOverflowList() override;
protected:
explicit nsFirstLineFrame(nsStyleContext* aContext)
- : nsInlineFrame(aContext, mozilla::LayoutFrameType::Line)
+ : nsInlineFrame(aContext, kClassID)
{}
virtual nsIFrame* PullOneFrame(nsPresContext* aPresContext,
InlineReflowInput& rs,
bool* aIsComplete) override;
};
#endif /* nsInlineFrame_h___ */
--- a/layout/generic/nsLeafFrame.h
+++ b/layout/generic/nsLeafFrame.h
@@ -72,18 +72,18 @@ public:
virtual bool IsFrameOfType(uint32_t aFlags) const override
{
// We don't actually contain a block, but we do always want a
// computed width, so tell a little white lie here.
return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplacedContainsBlock));
}
protected:
- nsLeafFrame(nsStyleContext* aContext, mozilla::LayoutFrameType aType)
- : nsFrame(aContext, aType)
+ nsLeafFrame(nsStyleContext* aContext, ClassID aID)
+ : nsFrame(aContext, aID)
{}
virtual ~nsLeafFrame();
/**
* Return the intrinsic isize of the frame's content area. Note that this
* should not include borders or padding and should not depend on the applied
* styles.
--- a/layout/generic/nsPageContentFrame.h
+++ b/layout/generic/nsPageContentFrame.h
@@ -10,17 +10,17 @@
class nsPageFrame;
class nsSharedPageData;
// Page frame class used by the simple page sequence frame
class nsPageContentFrame final : public mozilla::ViewportFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsPageContentFrame)
friend nsPageContentFrame* NS_NewPageContentFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
friend class nsPageFrame;
// nsIFrame
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
@@ -39,16 +39,16 @@ public:
#ifdef DEBUG_FRAME_DUMP
// Debugging
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
protected:
explicit nsPageContentFrame(nsStyleContext* aContext)
- : ViewportFrame(aContext, mozilla::LayoutFrameType::PageContent)
+ : ViewportFrame(aContext, kClassID)
{}
nsSharedPageData* mPD;
};
#endif /* nsPageContentFrame_h___ */
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -36,17 +36,17 @@ NS_NewPageFrame(nsIPresShell* aPresShell
NS_IMPL_FRAMEARENA_HELPERS(nsPageFrame)
NS_QUERYFRAME_HEAD(nsPageFrame)
NS_QUERYFRAME_ENTRY(nsPageFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
nsPageFrame::nsPageFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, LayoutFrameType::Page)
+ : nsContainerFrame(aContext, kClassID)
{
}
nsPageFrame::~nsPageFrame()
{
}
void
@@ -677,17 +677,17 @@ NS_NewPageBreakFrame(nsIPresShell* aPres
NS_ASSERTION(aPresShell->GetPresContext()->IsPaginated(), "created a page break frame while not printing");
return new (aPresShell) nsPageBreakFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsPageBreakFrame)
nsPageBreakFrame::nsPageBreakFrame(nsStyleContext* aContext)
- : nsLeafFrame(aContext, LayoutFrameType::PageBreak)
+ : nsLeafFrame(aContext, kClassID)
, mHaveReflowed(false)
{
}
nsPageBreakFrame::~nsPageBreakFrame()
{
}
--- a/layout/generic/nsPageFrame.h
+++ b/layout/generic/nsPageFrame.h
@@ -11,19 +11,18 @@
class nsFontMetrics;
class nsSharedPageData;
// Page frame class used by the simple page sequence frame
class nsPageFrame final : public nsContainerFrame {
public:
- NS_DECL_QUERYFRAME_TARGET(nsPageFrame)
NS_DECL_QUERYFRAME
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsPageFrame)
friend nsPageFrame* NS_NewPageFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aMaxSize,
nsReflowStatus& aStatus) override;
@@ -94,17 +93,17 @@ protected:
nsSharedPageData* mPD;
nsMargin mPageContentMargin;
};
class nsPageBreakFrame : public nsLeafFrame
{
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsPageBreakFrame)
explicit nsPageBreakFrame(nsStyleContext* aContext);
~nsPageBreakFrame();
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
--- a/layout/generic/nsPlaceholderFrame.h
+++ b/layout/generic/nsPlaceholderFrame.h
@@ -49,31 +49,30 @@ nsIFrame* NS_NewPlaceholderFrame(nsIPres
PLACEHOLDER_FOR_TOPLAYER)
/**
* Implementation of a frame that's used as a placeholder for a frame that
* has been moved out of the flow.
*/
class nsPlaceholderFrame final : public nsFrame {
public:
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsPlaceholderFrame)
#ifdef DEBUG
- NS_DECL_QUERYFRAME_TARGET(nsPlaceholderFrame)
NS_DECL_QUERYFRAME
#endif
/**
* Create a new placeholder frame. aTypeBit must be one of the
* PLACEHOLDER_FOR_* constants above.
*/
friend nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext,
nsFrameState aTypeBit);
nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBit)
- : nsFrame(aContext, mozilla::LayoutFrameType::Placeholder)
+ : nsFrame(aContext, kClassID)
, mOutOfFlowFrame(nullptr)
{
NS_PRECONDITION(aTypeBit == PLACEHOLDER_FOR_FLOAT ||
aTypeBit == PLACEHOLDER_FOR_ABSPOS ||
aTypeBit == PLACEHOLDER_FOR_FIXEDPOS ||
aTypeBit == PLACEHOLDER_FOR_POPUP ||
aTypeBit == PLACEHOLDER_FOR_TOPLAYER,
"Unexpected type bit");
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -140,17 +140,17 @@ protected:
return false;
}
uint64_t mLastSequenceNumber;
nsPluginFrame* mFrame;
};
nsPluginFrame::nsPluginFrame(nsStyleContext* aContext)
- : nsFrame(aContext, LayoutFrameType::Object)
+ : nsFrame(aContext, kClassID)
, mInstanceOwner(nullptr)
, mOuterView(nullptr)
, mInnerView(nullptr)
, mBackgroundSink(nullptr)
, mReflowCallbackPosted(false)
{
MOZ_LOG(sPluginFrameLog, LogLevel::Debug,
("Created new nsPluginFrame %p\n", this));
--- a/layout/generic/nsPluginFrame.h
+++ b/layout/generic/nsPluginFrame.h
@@ -57,23 +57,21 @@ public:
typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint;
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layers::ImageContainer ImageContainer;
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
- NS_DECL_FRAMEARENA_HELPERS
+ NS_DECL_FRAMEARENA_HELPERS(nsPluginFrame)
+ NS_DECL_QUERYFRAME
friend nsIFrame* NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
- NS_DECL_QUERYFRAME
- NS_DECL_QUERYFRAME_TARGET(nsPluginFrame)
-
virtual void Init(nsIContent* aContent,
nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
--- a/layout/generic/nsQueryFrame.h
+++ b/layout/generic/nsQueryFrame.h
@@ -53,26 +53,37 @@
"NS_QUERYFRAME_ENTRY() line with its own type name"); \
return nullptr; \
}
class nsQueryFrame
{
public:
enum FrameIID {
-#define FRAME_ID(classname) classname##_id,
+#define FRAME_ID(classname, ...) classname##_id,
+#define ABSTRACT_FRAME_ID(classname) classname##_id,
#include "nsFrameIdList.h"
#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
// This marker allows mozilla::ArenaObjectID to "extend" this enum
// with additional sequential values for use in nsPresArena and
// nsIPresShell::{Allocate,Free}ByObjectId
NON_FRAME_MARKER
};
+ // A strict subset of FrameIID above for frame classes that we instantiate.
+ enum class ClassID : uint8_t {
+#define FRAME_ID(classname, ...) classname##_id,
+#define ABSTRACT_FRAME_ID(classname)
+#include "nsFrameIdList.h"
+#undef FRAME_ID
+#undef ABSTRACT_FRAME_ID
+ };
+
virtual void* QueryFrame(FrameIID id) = 0;
};
class do_QueryFrame
{
public:
explicit do_QueryFrame(nsQueryFrame *s) : mRawPtr(s) { }
--- a/layout/generic/nsRubyBaseContainerFrame.h
+++ b/layout/generic/nsRubyBaseContainerFrame.h
@@ -17,18 +17,17 @@
* @return a newly allocated nsRubyBaseContainerFrame (infallible)
*/
nsContainerFrame* NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyBaseContainerFrame final : public nsContainerFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(nsRubyBaseContainerFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsRubyBaseContainerFrame)
NS_DECL_QUERYFRAME
// nsIFrame overrides
virtual bool IsFrameOfType(uint32_t aFlags) const override;
virtual bool CanContinueTextRun() const override;
virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,
InlineMinISizeData *aData) override;
virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
@@ -62,17 +61,17 @@ public:
}
protected:
friend nsContainerFrame*
NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyBaseContainerFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, mozilla::LayoutFrameType::RubyBaseContainer)
+ : nsContainerFrame(aContext, kClassID)
{}
struct RubyReflowInput;
nscoord ReflowColumns(const RubyReflowInput& aReflowInput,
nsReflowStatus& aStatus);
nscoord ReflowOneColumn(const RubyReflowInput& aReflowInput,
uint32_t aColumnIndex,
const mozilla::RubyColumn& aColumn,
--- a/layout/generic/nsRubyBaseFrame.h
+++ b/layout/generic/nsRubyBaseFrame.h
@@ -16,25 +16,24 @@
* @return a newly allocated nsRubyBaseFrame (infallible)
*/
nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyBaseFrame final : public nsRubyContentFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(nsRubyBaseFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsRubyBaseFrame)
NS_DECL_QUERYFRAME
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
protected:
friend nsContainerFrame* NS_NewRubyBaseFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyBaseFrame(nsStyleContext* aContext)
- : nsRubyContentFrame(aContext, mozilla::LayoutFrameType::RubyBase)
+ : nsRubyContentFrame(aContext, kClassID)
{}
};
#endif /* nsRubyBaseFrame_h___ */
--- a/layout/generic/nsRubyContentFrame.h
+++ b/layout/generic/nsRubyContentFrame.h
@@ -22,15 +22,14 @@ public:
// Indicates whether this is an "intra-level whitespace" frame, i.e.
// an anonymous frame that was created to contain non-droppable
// whitespaces directly inside a ruby level container. This impacts
// ruby pairing behavior.
// See http://dev.w3.org/csswg/css-ruby/#anon-gen-interpret-space
bool IsIntraLevelWhitespace() const;
protected:
- explicit nsRubyContentFrame(nsStyleContext* aContext,
- mozilla::LayoutFrameType aType)
- : nsInlineFrame(aContext, aType)
+ nsRubyContentFrame(nsStyleContext* aContext, ClassID aID)
+ : nsInlineFrame(aContext, aID)
{}
};
#endif /* nsRubyContentFrame_h___ */
--- a/layout/generic/nsRubyFrame.h
+++ b/layout/generic/nsRubyFrame.h
@@ -17,18 +17,17 @@
* @return a newly allocated nsRubyFrame (infallible)
*/
nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyFrame final : public nsInlineFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(nsRubyFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsRubyFrame)
NS_DECL_QUERYFRAME
// nsIFrame overrides
virtual bool IsFrameOfType(uint32_t aFlags) const override;
virtual void AddInlineMinISize(nsRenderingContext *aRenderingContext,
InlineMinISizeData *aData) override;
virtual void AddInlinePrefISize(nsRenderingContext *aRenderingContext,
InlinePrefISizeData *aData) override;
@@ -44,17 +43,17 @@ public:
mozilla::RubyBlockLeadings GetBlockLeadings() const {
return mLeadings;
}
protected:
friend nsContainerFrame* NS_NewRubyFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyFrame(nsStyleContext* aContext)
- : nsInlineFrame(aContext, mozilla::LayoutFrameType::Ruby)
+ : nsInlineFrame(aContext, kClassID)
{}
void ReflowSegment(nsPresContext* aPresContext,
const ReflowInput& aReflowInput,
nsRubyBaseContainerFrame* aBaseContainer,
nsReflowStatus& aStatus);
nsRubyBaseContainerFrame* PullOneSegment(const nsLineLayout* aLineLayout,
--- a/layout/generic/nsRubyTextContainerFrame.h
+++ b/layout/generic/nsRubyTextContainerFrame.h
@@ -16,18 +16,17 @@
* @return a newly allocated nsRubyTextContainerFrame (infallible)
*/
nsContainerFrame* NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyTextContainerFrame final : public nsContainerFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(nsRubyTextContainerFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsRubyTextContainerFrame)
NS_DECL_QUERYFRAME
// nsIFrame overrides
virtual bool IsFrameOfType(uint32_t aFlags) const override;
virtual void Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
@@ -52,17 +51,17 @@ public:
}
protected:
friend nsContainerFrame*
NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyTextContainerFrame(nsStyleContext* aContext)
- : nsContainerFrame(aContext, mozilla::LayoutFrameType::RubyTextContainer)
+ : nsContainerFrame(aContext, kClassID)
, mISize(0)
{}
void UpdateSpanFlag();
friend class nsRubyBaseContainerFrame;
void SetISize(nscoord aISize) { mISize = aISize; }
--- a/layout/generic/nsRubyTextFrame.h
+++ b/layout/generic/nsRubyTextFrame.h
@@ -16,18 +16,17 @@
* @return a newly allocated nsRubyTextFrame (infallible)
*/
nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
class nsRubyTextFrame final : public nsRubyContentFrame
{
public:
- NS_DECL_FRAMEARENA_HELPERS
- NS_DECL_QUERYFRAME_TARGET(nsRubyTextFrame)
+ NS_DECL_FRAMEARENA_HELPERS(nsRubyTextFrame)
NS_DECL_QUERYFRAME
// nsIFrame overrides
virtual bool CanContinueTextRun() const override;
#ifdef DEBUG_FRAME_DUMP
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
@@ -45,13 +44,13 @@ public:
{
return GetStateBits() & NS_RUBY_TEXT_FRAME_AUTOHIDE;
}
protected:
friend nsContainerFrame* NS_NewRubyTextFrame(nsIPresShell* aPresShell,
nsStyleContext* aContext);
explicit nsRubyTextFrame(nsStyleContext* aContext)
- : nsRubyContentFrame(aContext, mozilla::LayoutFrameType::RubyText)
+ : nsRubyContentFrame(aContext, kClassID)
{}
};
#endif /* nsRubyTextFrame_h___ */
--- a/layout/generic/nsSimplePageSequenceFrame.cpp
+++ b/layout/generic/nsSimplePageSequenceFrame.cpp
@@ -40,17 +40,17 @@ nsSimplePageSequenceFrame*
NS_NewSimplePageSequenceFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsSimplePageSequenceFrame(aContext);
}