зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
e9a067a401
|
@ -261,9 +261,6 @@ function getClipboardHelper() {
|
|||
}
|
||||
const gClipboardHelper = getClipboardHelper();
|
||||
|
||||
// Interface for image loading content
|
||||
const nsIImageLoadingContent = Components.interfaces.nsIImageLoadingContent;
|
||||
|
||||
// namespaces, don't need all of these yet...
|
||||
const XLinkNS = "http://www.w3.org/1999/xlink";
|
||||
const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
|
|
@ -18,7 +18,6 @@ add_task(async function testSources() {
|
|||
|
||||
let tabs = await browser.tabs.query({active: true, currentWindow: true});
|
||||
await browser.pageAction.show(tabs[0].id);
|
||||
browser.test.sendMessage("page-action-shown");
|
||||
|
||||
browser.pageAction.onClicked.addListener(request);
|
||||
browser.browserAction.onClicked.addListener(request);
|
||||
|
@ -29,6 +28,8 @@ add_task(async function testSources() {
|
|||
contexts: ["page"],
|
||||
});
|
||||
browser.contextMenus.onClicked.addListener(request);
|
||||
|
||||
browser.test.sendMessage("actions-ready");
|
||||
},
|
||||
|
||||
manifest: {
|
||||
|
@ -49,8 +50,8 @@ add_task(async function testSources() {
|
|||
CustomizableUI.removeWidgetFromArea("sidebar-button");
|
||||
|
||||
await extension.startup();
|
||||
await extension.awaitMessage("actions-ready");
|
||||
|
||||
await extension.awaitMessage("page-action-shown");
|
||||
clickPageAction(extension);
|
||||
await check("page action click");
|
||||
|
||||
|
|
|
@ -454,8 +454,7 @@ class ContextMenu {
|
|||
return true;
|
||||
}
|
||||
|
||||
let request = aTarget.QueryInterface(Ci.nsIImageLoadingContent)
|
||||
.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
let request = aTarget.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
|
||||
if (!request) {
|
||||
return true;
|
||||
|
|
|
@ -9,32 +9,34 @@
|
|||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
Task.spawn(function* () {
|
||||
let doc = aPanel.panelWin.document;
|
||||
let panel = doc.getElementById("instruments-pane");
|
||||
let button = doc.getElementById("instruments-pane-toggle");
|
||||
ok(panel.classList.contains("pane-collapsed"),
|
||||
"The instruments panel is initially in collapsed state");
|
||||
async function test() {
|
||||
let [aTab,, aPanel] = await initDebugger(TAB_URL);
|
||||
|
||||
yield togglePane(button, "Press on the toggle button to expand", panel, "VK_RETURN");
|
||||
ok(!panel.classList.contains("pane-collapsed"),
|
||||
"The instruments panel is in the expanded state");
|
||||
let doc = aPanel.panelWin.document;
|
||||
let panel = doc.getElementById("instruments-pane");
|
||||
let button = doc.getElementById("instruments-pane-toggle");
|
||||
ok(panel.classList.contains("pane-collapsed"),
|
||||
"The instruments panel is initially in collapsed state");
|
||||
|
||||
yield togglePane(button, "Press on the toggle button to collapse", panel, "VK_SPACE");
|
||||
ok(panel.classList.contains("pane-collapsed"),
|
||||
"The instruments panel is in the collapsed state");
|
||||
await togglePane(button, "Press on the toggle button to expand", panel, "VK_RETURN");
|
||||
ok(!panel.classList.contains("pane-collapsed"),
|
||||
"The instruments panel is in the expanded state");
|
||||
|
||||
closeDebuggerAndFinish(aPanel);
|
||||
});
|
||||
});
|
||||
await togglePane(button, "Press on the toggle button to collapse", panel, "VK_SPACE");
|
||||
ok(panel.classList.contains("pane-collapsed"),
|
||||
"The instruments panel is in the collapsed state");
|
||||
|
||||
closeDebuggerAndFinish(aPanel);
|
||||
}
|
||||
|
||||
function* togglePane(button, message, pane, keycode) {
|
||||
async function togglePane(button, message, pane, keycode) {
|
||||
let onTransitionEnd = once(pane, "transitionend");
|
||||
info(message);
|
||||
button.focus();
|
||||
EventUtils.synthesizeKey(keycode, {});
|
||||
yield onTransitionEnd;
|
||||
await onTransitionEnd;
|
||||
|
||||
// Wait for the next event tick to make sure all transitionend event
|
||||
// handlers finish.
|
||||
await waitForTick();
|
||||
}
|
||||
|
|
|
@ -11,16 +11,16 @@ const TEST_URI = "data:text/html;charset=utf-8,<head>" +
|
|||
"ets.css'></head><body><div></div><span></span></body>";
|
||||
const {TreeWidget} = require("devtools/client/shared/widgets/TreeWidget");
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("about:blank");
|
||||
let [host, win, doc] = yield createHost("bottom", TEST_URI);
|
||||
add_task(async function () {
|
||||
await addTab("about:blank");
|
||||
let [host, win, doc] = await createHost("bottom", TEST_URI);
|
||||
|
||||
let tree = new TreeWidget(doc.querySelector("div"), {
|
||||
defaultType: "store"
|
||||
});
|
||||
|
||||
populateTree(tree, doc);
|
||||
yield testKeyboardInteraction(tree, win);
|
||||
await testKeyboardInteraction(tree, win);
|
||||
|
||||
tree.destroy();
|
||||
host.destroy();
|
||||
|
@ -83,7 +83,7 @@ function click(node) {
|
|||
/**
|
||||
* Tests if pressing navigation keys on the tree items does the expected behavior
|
||||
*/
|
||||
function* testKeyboardInteraction(tree, win) {
|
||||
async function testKeyboardInteraction(tree, win) {
|
||||
info("Testing keyboard interaction with the tree");
|
||||
let event;
|
||||
let pass = (e, d, a) => event.resolve([e, d, a]);
|
||||
|
@ -91,9 +91,12 @@ function* testKeyboardInteraction(tree, win) {
|
|||
info("clicking on first top level item");
|
||||
let node = tree.root.children.firstChild.firstChild;
|
||||
event = defer();
|
||||
// The select event handler will be called before the click event hasn't
|
||||
// fully finished, so wait for both of them.
|
||||
let clicked = once(node, "click");
|
||||
tree.once("select", pass);
|
||||
click(node);
|
||||
yield event.promise;
|
||||
await Promise.all([event.promise, clicked]);
|
||||
node = tree.root.children.firstChild.nextSibling.firstChild;
|
||||
// node should not have selected class
|
||||
ok(!node.classList.contains("theme-selected"), "Node should not have selected class");
|
||||
|
@ -103,7 +106,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
event = defer();
|
||||
tree.once("select", pass);
|
||||
EventUtils.sendKey("DOWN", win);
|
||||
let [name, data, attachment] = yield event.promise;
|
||||
let [name, data, attachment] = await event.promise;
|
||||
is(name, "select", "Select event was fired after pressing down");
|
||||
is(data[0], "level1", "Correct item was selected after pressing down");
|
||||
ok(!attachment, "null attachment was emitted");
|
||||
|
@ -114,7 +117,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
event = defer();
|
||||
tree.once("select", pass);
|
||||
EventUtils.sendKey("DOWN", win);
|
||||
[name, data, attachment] = yield event.promise;
|
||||
[name, data, attachment] = await event.promise;
|
||||
is(data.length, 2, "Correct level item was selected after second down keypress");
|
||||
is(data[0], "level1", "Correct parent level");
|
||||
is(data[1], "level2", "Correct second level");
|
||||
|
@ -123,7 +126,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
event = defer();
|
||||
tree.once("select", pass);
|
||||
EventUtils.sendKey("DOWN", win);
|
||||
[name, data, attachment] = yield event.promise;
|
||||
[name, data, attachment] = await event.promise;
|
||||
is(data.length, 3, "Correct level item was selected after third down keypress");
|
||||
is(data[0], "level1", "Correct parent level");
|
||||
is(data[1], "level2", "Correct second level");
|
||||
|
@ -133,7 +136,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
event = defer();
|
||||
tree.once("select", pass);
|
||||
EventUtils.sendKey("DOWN", win);
|
||||
[name, data, attachment] = yield event.promise;
|
||||
[name, data, attachment] = await event.promise;
|
||||
is(data.length, 2, "Correct level item was selected after fourth down keypress");
|
||||
is(data[0], "level1", "Correct parent level");
|
||||
is(data[1], "level2-1", "Correct second level");
|
||||
|
@ -149,7 +152,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
node = tree._selectedLabel;
|
||||
ok(node.hasAttribute("expanded"), "Item is expanded before left keypress");
|
||||
EventUtils.sendKey("LEFT", win);
|
||||
yield event.promise;
|
||||
await event.promise;
|
||||
|
||||
ok(!node.hasAttribute("expanded"), "Item is not expanded after left keypress");
|
||||
|
||||
|
@ -162,7 +165,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
node = tree.root.children.firstChild.nextSibling.firstChild;
|
||||
ok(node.hasAttribute("expanded"), "Parent is expanded");
|
||||
EventUtils.sendKey("LEFT", win);
|
||||
[name, data] = yield event.promise;
|
||||
[name, data] = await event.promise;
|
||||
is(data.length, 3, "Correct level item was selected after second left keypress");
|
||||
is(data[0], "level1", "Correct parent level");
|
||||
is(data[1], "level2", "Correct second level");
|
||||
|
@ -175,7 +178,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
event = defer();
|
||||
tree.once("select", pass);
|
||||
EventUtils.sendKey("DOWN", win);
|
||||
[name, data, attachment] = yield event.promise;
|
||||
[name, data, attachment] = await event.promise;
|
||||
is(data.length, 2, "Correct level item was selected after fifth down keypress");
|
||||
is(data[0], "level1", "Correct parent level");
|
||||
is(data[1], "level2-1", "Correct second level");
|
||||
|
@ -190,7 +193,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
node = tree._selectedLabel;
|
||||
ok(node.hasAttribute("expanded"), "Item is expanded before left keypress");
|
||||
EventUtils.sendKey("LEFT", win);
|
||||
yield event.promise;
|
||||
await event.promise;
|
||||
ok(!node.hasAttribute("expanded"), "Item is collapsed after left keypress");
|
||||
|
||||
// pressing right should expand this now.
|
||||
|
@ -203,7 +206,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
node = tree._selectedLabel;
|
||||
ok(!node.hasAttribute("expanded"), "Item is collapsed before right keypress");
|
||||
EventUtils.sendKey("RIGHT", win);
|
||||
yield event.promise;
|
||||
await event.promise;
|
||||
ok(node.hasAttribute("expanded"), "Item is expanded after right keypress");
|
||||
|
||||
// selecting last item node to test edge navigation case
|
||||
|
@ -217,7 +220,7 @@ function* testKeyboardInteraction(tree, win) {
|
|||
}, {once: true});
|
||||
info("Pressing down key on last item of the tree");
|
||||
EventUtils.sendKey("DOWN", win);
|
||||
yield event.promise;
|
||||
await event.promise;
|
||||
|
||||
ok(tree.isSelected(["level1.1", "level2", "level3"]),
|
||||
"Last item is still selected after pressing down on last item of the tree");
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
add_task(async function () {
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"test/test-console.html";
|
||||
|
||||
yield loadTab(TEST_URI);
|
||||
await loadTab(TEST_URI);
|
||||
|
||||
let hud = yield openConsole();
|
||||
let hud = await openConsole();
|
||||
ok(hud, "Web Console opened");
|
||||
|
||||
info("dump some spew into the console for scrolling");
|
||||
|
@ -21,7 +21,7 @@ add_task(function* () {
|
|||
"console.log('foobarz' + i);" +
|
||||
"}})();");
|
||||
|
||||
yield waitForMessages({
|
||||
await waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "foobarz99",
|
||||
|
@ -61,7 +61,11 @@ add_task(function* () {
|
|||
}
|
||||
synthesizeKeyShortcut(clearShortcut);
|
||||
});
|
||||
yield hud.jsterm.once("messages-cleared");
|
||||
await hud.jsterm.once("messages-cleared");
|
||||
|
||||
// Wait for the next event tick to make sure keyup for the shortcut above
|
||||
// finishes. Otherwise the 2 shortcuts are mixed.
|
||||
await new Promise(executeSoon);
|
||||
|
||||
is(hud.outputNode.textContent.indexOf("foobarz1"), -1, "output cleared");
|
||||
is(hud.jsterm.inputNode.getAttribute("focused"), "true",
|
||||
|
|
|
@ -8,16 +8,16 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
add_task(function* () {
|
||||
add_task(async function () {
|
||||
const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
|
||||
"test/test-console-clear.html";
|
||||
|
||||
yield loadTab(TEST_URI);
|
||||
let hud = yield openConsole();
|
||||
await loadTab(TEST_URI);
|
||||
let hud = await openConsole();
|
||||
ok(hud, "Web Console opened");
|
||||
|
||||
info("Check the console.clear() done on page load has been processed.");
|
||||
yield waitForLog("Console was cleared", hud);
|
||||
await waitForLog("Console was cleared", hud);
|
||||
ok(hud.outputNode.textContent.includes("Console was cleared"),
|
||||
"console.clear() message is displayed");
|
||||
ok(!hud.outputNode.textContent.includes("log1"), "log1 not displayed");
|
||||
|
@ -29,8 +29,8 @@ add_task(function* () {
|
|||
content.wrappedJSObject.console.log("log4");
|
||||
});
|
||||
|
||||
yield waitForLog("log3", hud);
|
||||
yield waitForLog("log4", hud);
|
||||
await waitForLog("log3", hud);
|
||||
await waitForLog("log4", hud);
|
||||
|
||||
ok(hud.outputNode.textContent.includes("Console was cleared"),
|
||||
"console.clear() message is still displayed");
|
||||
|
@ -38,7 +38,7 @@ add_task(function* () {
|
|||
ok(hud.outputNode.textContent.includes("log4"), "log4 is displayed");
|
||||
|
||||
info("Open the variables view sidebar for 'objFromPage'");
|
||||
yield openSidebar("objFromPage", { a: 1 }, hud);
|
||||
await openSidebar("objFromPage", { a: 1 }, hud);
|
||||
let sidebarClosed = hud.jsterm.once("sidebar-closed");
|
||||
|
||||
info("Call console.clear from the page");
|
||||
|
@ -47,9 +47,13 @@ add_task(function* () {
|
|||
});
|
||||
|
||||
// Cannot wait for "Console was cleared" here because such a message is
|
||||
// already present and would yield immediately.
|
||||
// already present and would resolve immediately.
|
||||
info("Wait for variables view sidebar to be closed after console.clear()");
|
||||
yield sidebarClosed;
|
||||
await sidebarClosed;
|
||||
|
||||
// Wait for the next event tick to make sure the remaining part of the
|
||||
// test is not executed before the message is actually flushed.
|
||||
await new Promise(executeSoon);
|
||||
|
||||
ok(!hud.outputNode.textContent.includes("log3"), "log3 not displayed");
|
||||
ok(!hud.outputNode.textContent.includes("log4"), "log4 not displayed");
|
||||
|
@ -62,12 +66,12 @@ add_task(function* () {
|
|||
ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
|
||||
content.wrappedJSObject.console.log("log5");
|
||||
});
|
||||
yield waitForLog("log5", hud);
|
||||
await waitForLog("log5", hud);
|
||||
|
||||
info("Close and reopen the webconsole.");
|
||||
yield closeConsole(gBrowser.selectedTab);
|
||||
hud = yield openConsole();
|
||||
yield waitForLog("Console was cleared", hud);
|
||||
await closeConsole(gBrowser.selectedTab);
|
||||
hud = await openConsole();
|
||||
await waitForLog("Console was cleared", hud);
|
||||
|
||||
ok(hud.outputNode.textContent.includes("Console was cleared"),
|
||||
"console.clear() message is still displayed");
|
||||
|
@ -87,8 +91,8 @@ add_task(function* () {
|
|||
* @param {WebConsole} webconsole
|
||||
* WebConsole instance in which the message should be logged.
|
||||
*/
|
||||
function* waitForLog(message, webconsole, options) {
|
||||
yield waitForMessages({
|
||||
function waitForLog(message, webconsole, options) {
|
||||
return waitForMessages({
|
||||
webconsole: webconsole,
|
||||
messages: [{
|
||||
text: message,
|
||||
|
@ -110,8 +114,8 @@ function* waitForLog(message, webconsole, options) {
|
|||
* WebConsole instance in which the message should be logged.
|
||||
*
|
||||
*/
|
||||
function* openSidebar(objName, expectedObj, webconsole) {
|
||||
let msg = yield webconsole.jsterm.execute(objName);
|
||||
async function openSidebar(objName, expectedObj, webconsole) {
|
||||
let msg = await webconsole.jsterm.execute(objName);
|
||||
ok(msg, "output message found");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
|
@ -119,13 +123,13 @@ function* openSidebar(objName, expectedObj, webconsole) {
|
|||
ok(anchor, "object anchor");
|
||||
ok(body, "message body");
|
||||
|
||||
yield EventUtils.synthesizeMouse(anchor, 2, 2, {}, webconsole.iframeWindow);
|
||||
await EventUtils.synthesizeMouse(anchor, 2, 2, {}, webconsole.iframeWindow);
|
||||
|
||||
let vviewVar = yield webconsole.jsterm.once("variablesview-fetched");
|
||||
let vviewVar = await webconsole.jsterm.once("variablesview-fetched");
|
||||
let vview = vviewVar._variablesView;
|
||||
ok(vview, "variables view object exists");
|
||||
|
||||
yield findVariableViewProperties(vviewVar, [
|
||||
await findVariableViewProperties(vviewVar, [
|
||||
expectedObj,
|
||||
], { webconsole: webconsole });
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ const {
|
|||
const {
|
||||
CanvasFrameAnonymousContentHelper,
|
||||
createNode,
|
||||
getComputedStyle,
|
||||
} = require("./utils/markup");
|
||||
const {
|
||||
getAdjustedQuads,
|
||||
|
@ -26,18 +27,17 @@ const {
|
|||
|
||||
const FLEXBOX_LINES_PROPERTIES = {
|
||||
"edge": {
|
||||
lineDash: [0, 0],
|
||||
alpha: 1,
|
||||
lineDash: [2, 2]
|
||||
},
|
||||
"item": {
|
||||
lineDash: [2, 2],
|
||||
alpha: 1,
|
||||
},
|
||||
lineDash: [0, 0]
|
||||
}
|
||||
};
|
||||
|
||||
const FLEXBOX_CONTAINER_PATTERN_WIDTH = 14; // px
|
||||
const FLEXBOX_CONTAINER_PATTERN_HEIGHT = 14; // px
|
||||
const FLEXBOX_CONTAINER_PATTERN_LINE_DISH = [5, 3]; // px
|
||||
const BASIS_FILL_COLOR = "rgb(109, 184, 255, 0.4)";
|
||||
|
||||
/**
|
||||
* Cached used by `FlexboxHighlighter.getFlexContainerPattern`.
|
||||
|
@ -257,7 +257,31 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
|
|||
}
|
||||
}
|
||||
|
||||
renderFlexContainer() {
|
||||
renderFlexContainerBorder() {
|
||||
if (!this.currentQuads.content || !this.currentQuads.content[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { devicePixelRatio } = this.win;
|
||||
let lineWidth = getDisplayPixelRatio(this.win) * 2;
|
||||
let offset = (lineWidth / 2) % 1;
|
||||
let canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
|
||||
let canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.translate(offset - canvasX, offset - canvasY);
|
||||
this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
|
||||
this.ctx.lineWidth = lineWidth;
|
||||
this.ctx.strokeStyle = DEFAULT_COLOR;
|
||||
|
||||
let { bounds } = this.currentQuads.content[0];
|
||||
drawRect(this.ctx, 0, 0, bounds.width, bounds.height, this.currentMatrix);
|
||||
|
||||
this.ctx.stroke();
|
||||
this.ctx.restore();
|
||||
}
|
||||
|
||||
renderFlexContainerFill() {
|
||||
if (!this.currentQuads.content || !this.currentQuads.content[0]) {
|
||||
return;
|
||||
}
|
||||
|
@ -265,15 +289,13 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
|
|||
let { devicePixelRatio } = this.win;
|
||||
let lineWidth = getDisplayPixelRatio(this.win);
|
||||
let offset = (lineWidth / 2) % 1;
|
||||
|
||||
let canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
|
||||
let canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.translate(offset - canvasX, offset - canvasY);
|
||||
this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.edge.lineDash);
|
||||
this.ctx.globalAlpha = FLEXBOX_LINES_PROPERTIES.edge.alpha;
|
||||
this.ctx.lineWidth = lineWidth;
|
||||
this.ctx.lineWidth = 0;
|
||||
this.ctx.strokeStyle = DEFAULT_COLOR;
|
||||
this.ctx.fillStyle = this.getFlexContainerPattern(devicePixelRatio);
|
||||
|
||||
|
@ -285,6 +307,25 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
|
|||
this.ctx.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the flex basis for a given flex item.
|
||||
*/
|
||||
renderFlexItemBasis(flexItem, left, top, right, bottom, boundsWidth) {
|
||||
let computedStyle = getComputedStyle(flexItem);
|
||||
let basis = computedStyle.getPropertyValue("flex-basis");
|
||||
|
||||
if (basis.endsWith("px")) {
|
||||
right = left + parseFloat(basis);
|
||||
} else if (basis.endsWith("%")) {
|
||||
basis = parseFloat(basis) / 100 * boundsWidth;
|
||||
right = left + basis;
|
||||
}
|
||||
|
||||
this.ctx.fillStyle = BASIS_FILL_COLOR;
|
||||
drawRect(this.ctx, left, top, right, bottom, this.currentMatrix);
|
||||
this.ctx.fill();
|
||||
}
|
||||
|
||||
renderFlexItems() {
|
||||
if (!this.currentQuads.content || !this.currentQuads.content[0]) {
|
||||
return;
|
||||
|
@ -293,14 +334,12 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
|
|||
let { devicePixelRatio } = this.win;
|
||||
let lineWidth = getDisplayPixelRatio(this.win);
|
||||
let offset = (lineWidth / 2) % 1;
|
||||
|
||||
let canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
|
||||
let canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.translate(offset - canvasX, offset - canvasY);
|
||||
this.ctx.setLineDash(FLEXBOX_LINES_PROPERTIES.item.lineDash);
|
||||
this.ctx.globalAlpha = FLEXBOX_LINES_PROPERTIES.item.alpha;
|
||||
this.ctx.lineWidth = lineWidth;
|
||||
this.ctx.strokeStyle = DEFAULT_COLOR;
|
||||
|
||||
|
@ -325,6 +364,54 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
|
|||
clearRect(this.ctx, left, top, right, bottom, this.currentMatrix);
|
||||
drawRect(this.ctx, left, top, right, bottom, this.currentMatrix);
|
||||
this.ctx.stroke();
|
||||
|
||||
this.renderFlexItemBasis(flexItem, left, top, right, bottom, bounds.width);
|
||||
}
|
||||
|
||||
this.ctx.restore();
|
||||
}
|
||||
|
||||
renderFlexLines() {
|
||||
if (!this.currentQuads.content || !this.currentQuads.content[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { devicePixelRatio } = this.win;
|
||||
let lineWidth = getDisplayPixelRatio(this.win);
|
||||
let offset = (lineWidth / 2) % 1;
|
||||
let canvasX = Math.round(this._canvasPosition.x * devicePixelRatio);
|
||||
let canvasY = Math.round(this._canvasPosition.y * devicePixelRatio);
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.translate(offset - canvasX, offset - canvasY);
|
||||
this.ctx.lineWidth = lineWidth;
|
||||
this.ctx.strokeStyle = DEFAULT_COLOR;
|
||||
|
||||
let { bounds } = this.currentQuads.content[0];
|
||||
let computedStyle = getComputedStyle(this.currentNode);
|
||||
let flexLines = this.currentNode.getAsFlexContainer().getLines();
|
||||
|
||||
for (let flexLine of flexLines) {
|
||||
let { crossStart, crossSize } = flexLine;
|
||||
|
||||
if (computedStyle.getPropertyValue("flex-direction") === "column" ||
|
||||
computedStyle.getPropertyValue("flex-direction") === "column-reverse") {
|
||||
clearRect(this.ctx, crossStart, 0, crossStart + crossSize, bounds.height,
|
||||
this.currentMatrix);
|
||||
drawRect(this.ctx, crossStart, 0, crossStart, bounds.height, this.currentMatrix);
|
||||
this.ctx.stroke();
|
||||
drawRect(this.ctx, crossStart + crossSize, 0, crossStart + crossSize,
|
||||
bounds.height, this.currentMatrix);
|
||||
this.ctx.stroke();
|
||||
} else {
|
||||
clearRect(this.ctx, 0, crossStart, bounds.width, crossStart + crossSize,
|
||||
this.currentMatrix);
|
||||
drawRect(this.ctx, 0, crossStart, bounds.width, crossStart, this.currentMatrix);
|
||||
this.ctx.stroke();
|
||||
drawRect(this.ctx, 0, crossStart + crossSize, bounds.width,
|
||||
crossStart + crossSize, this.currentMatrix);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
this.ctx.restore();
|
||||
|
@ -352,8 +439,10 @@ class FlexboxHighlighter extends AutoRefreshHighlighter {
|
|||
this.currentMatrix = currentMatrix;
|
||||
this.hasNodeTransformations = hasNodeTransformations;
|
||||
|
||||
this.renderFlexContainer();
|
||||
this.renderFlexContainerFill();
|
||||
this.renderFlexLines();
|
||||
this.renderFlexItems();
|
||||
this.renderFlexContainerBorder();
|
||||
|
||||
this._showFlexbox();
|
||||
|
||||
|
|
|
@ -81,6 +81,11 @@ add_task(async function () {
|
|||
content.location = url2;
|
||||
await loaded;
|
||||
|
||||
// Wait for the next event tick to make sure the remaining part of the
|
||||
// test is not executed in the microtask checkpoint for load event
|
||||
// itself. Otherwise the synthesizeMouseDown doesn't work.
|
||||
await new Promise(r => setTimeout(r, 0));
|
||||
|
||||
// Update to the new document we just loaded
|
||||
doc = content.document;
|
||||
|
||||
|
|
|
@ -40,6 +40,9 @@ native Visibility(mozilla::Visibility);
|
|||
* interface to mirror this interface when changing it.
|
||||
*/
|
||||
|
||||
// We can't make this interface noscript yet, because there is JS code doing
|
||||
// "instanceof Ci.nsIImageLoadingContent" and using the nsIImageLoadingContent
|
||||
// constants.
|
||||
[scriptable, builtinclass, uuid(0357123d-9224-4d12-a47e-868c32689777)]
|
||||
interface nsIImageLoadingContent : imgINotificationObserver
|
||||
{
|
||||
|
@ -56,11 +59,11 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
const long PENDING_REQUEST = 1;
|
||||
|
||||
/**
|
||||
* loadingEnabled is used to enable and disable loading in
|
||||
* setLoadingEnabled is used to enable and disable loading in
|
||||
* situations where loading images is unwanted. Note that enabling
|
||||
* loading will *not* automatically trigger an image load.
|
||||
*/
|
||||
attribute boolean loadingEnabled;
|
||||
[notxpcom, nostdcall] void setLoadingEnabled(in boolean aEnabled);
|
||||
|
||||
/**
|
||||
* Returns the image blocking status (@see nsIContentPolicy). This
|
||||
|
@ -68,7 +71,7 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
* the image was blocked. This status always refers to the
|
||||
* CURRENT_REQUEST load.
|
||||
*/
|
||||
readonly attribute short imageBlockingStatus;
|
||||
[noscript] readonly attribute short imageBlockingStatus;
|
||||
|
||||
/**
|
||||
* Used to register an image decoder observer. Typically, this will
|
||||
|
@ -78,30 +81,16 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
* current and pending, will be passed through.
|
||||
*
|
||||
* @param aObserver the observer to register
|
||||
*
|
||||
* @throws NS_ERROR_OUT_OF_MEMORY
|
||||
*/
|
||||
[notxpcom] nsresult addNativeObserver(in imgINotificationObserver aObserver);
|
||||
[notxpcom, nostdcall] void addNativeObserver(in imgINotificationObserver aObserver);
|
||||
|
||||
/**
|
||||
* Used to unregister an image decoder observer.
|
||||
*
|
||||
* @param aObserver the observer to unregister
|
||||
*/
|
||||
[notxpcom] nsresult removeNativeObserver(in imgINotificationObserver aObserver);
|
||||
[notxpcom, nostdcall] void removeNativeObserver(in imgINotificationObserver aObserver);
|
||||
|
||||
/**
|
||||
* Same as addNativeObserver but intended for scripted observers or observers
|
||||
* from another or without a document.
|
||||
*/
|
||||
void addObserver(in imgINotificationObserver aObserver);
|
||||
|
||||
/**
|
||||
* Same as removeNativeObserver but intended for scripted observers or
|
||||
* observers from another or without a document.
|
||||
*/
|
||||
void removeObserver(in imgINotificationObserver aObserver);
|
||||
|
||||
/**
|
||||
* Accessor to get the image requests
|
||||
*
|
||||
|
@ -113,7 +102,7 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
* @throws NS_ERROR_UNEXPECTED if the request type requested is not
|
||||
* known
|
||||
*/
|
||||
imgIRequest getRequest(in long aRequestType);
|
||||
[noscript] imgIRequest getRequest(in long aRequestType);
|
||||
|
||||
/**
|
||||
* Call this function when the request was blocked by any of the
|
||||
|
@ -122,7 +111,7 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
* @param aContentDecision the decision returned from nsIContentPolicy
|
||||
* (any of the types REJECT_*)
|
||||
*/
|
||||
void setBlockedRequest(in int16_t aContentDecision);
|
||||
[notxpcom, nostdcall] void setBlockedRequest(in int16_t aContentDecision);
|
||||
|
||||
/**
|
||||
* @return true if the current request's size is available.
|
||||
|
@ -152,14 +141,14 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
*
|
||||
* @throws NS_ERROR_UNEXPECTED if aRequest is not known
|
||||
*/
|
||||
long getRequestType(in imgIRequest aRequest);
|
||||
[noscript] long getRequestType(in imgIRequest aRequest);
|
||||
|
||||
/**
|
||||
* Gets the URI of the current request, if available.
|
||||
* Otherwise, returns the last URI that this content tried to load, or
|
||||
* null if there haven't been any such attempts.
|
||||
*/
|
||||
readonly attribute nsIURI currentURI;
|
||||
[noscript] readonly attribute nsIURI currentURI;
|
||||
|
||||
/**
|
||||
* loadImageWithChannel allows data from an existing channel to be
|
||||
|
@ -173,29 +162,21 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
|||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if aChannel is null
|
||||
*/
|
||||
nsIStreamListener loadImageWithChannel(in nsIChannel aChannel);
|
||||
[noscript] nsIStreamListener loadImageWithChannel(in nsIChannel aChannel);
|
||||
|
||||
/**
|
||||
* forceReload forces reloading of the image pointed to by currentURI
|
||||
*
|
||||
* @param aNotify [optional] request should notify, defaults to true
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if there is no current URI to reload
|
||||
*/
|
||||
[optional_argc] void forceReload([optional] in boolean aNotify /* = true */);
|
||||
|
||||
/**
|
||||
* Enables/disables image state forcing. When |aForce| is PR_TRUE, we force
|
||||
* Enables/disables image state forcing. When |aForce| is true, we force
|
||||
* nsImageLoadingContent::ImageState() to return |aState|. Call again with |aForce|
|
||||
* as PR_FALSE to revert ImageState() to its original behaviour.
|
||||
* as false to revert ImageState() to its original behaviour.
|
||||
*/
|
||||
void forceImageState(in boolean aForce, in unsigned long long aState);
|
||||
[notxpcom, nostdcall] void forceImageState(in boolean aForce, in unsigned long long aState);
|
||||
|
||||
/**
|
||||
* The intrinsic size and width of this content. May differ from actual image
|
||||
* size due to things like responsive image density.
|
||||
*/
|
||||
readonly attribute unsigned long naturalWidth;
|
||||
readonly attribute unsigned long naturalHeight;
|
||||
[noscript] readonly attribute unsigned long naturalWidth;
|
||||
[noscript] readonly attribute unsigned long naturalHeight;
|
||||
|
||||
/**
|
||||
* Called by layout to announce when the frame associated with this content
|
||||
|
|
|
@ -331,20 +331,12 @@ nsImageLoadingContent::OnImageIsAnimated(imgIRequest *aRequest)
|
|||
* nsIImageLoadingContent impl
|
||||
*/
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::GetLoadingEnabled(bool *aLoadingEnabled)
|
||||
{
|
||||
*aLoadingEnabled = mLoadingEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsImageLoadingContent::SetLoadingEnabled(bool aLoadingEnabled)
|
||||
{
|
||||
if (nsContentUtils::GetImgLoaderForChannel(nullptr, nullptr)) {
|
||||
mLoadingEnabled = aLoadingEnabled;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -388,10 +380,12 @@ ReplayImageStatus(imgIRequest* aRequest, imgINotificationObserver* aObserver)
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsImageLoadingContent::AddNativeObserver(imgINotificationObserver* aObserver)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aObserver);
|
||||
if (NS_WARN_IF(!aObserver)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mObserverList.mObserver) {
|
||||
// Don't touch the linking of the list!
|
||||
|
@ -400,7 +394,7 @@ nsImageLoadingContent::AddNativeObserver(imgINotificationObserver* aObserver)
|
|||
ReplayImageStatus(mCurrentRequest, aObserver);
|
||||
ReplayImageStatus(mPendingRequest, aObserver);
|
||||
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise we have to create a new entry
|
||||
|
@ -413,19 +407,19 @@ nsImageLoadingContent::AddNativeObserver(imgINotificationObserver* aObserver)
|
|||
observer->mNext = new ImageObserver(aObserver);
|
||||
ReplayImageStatus(mCurrentRequest, aObserver);
|
||||
ReplayImageStatus(mPendingRequest, aObserver);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsImageLoadingContent::RemoveNativeObserver(imgINotificationObserver* aObserver)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aObserver);
|
||||
if (NS_WARN_IF(!aObserver)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mObserverList.mObserver == aObserver) {
|
||||
mObserverList.mObserver = nullptr;
|
||||
// Don't touch the linking of the list!
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise have to find it and splice it out
|
||||
|
@ -448,13 +442,14 @@ nsImageLoadingContent::RemoveNativeObserver(imgINotificationObserver* aObserver)
|
|||
NS_WARNING("Asked to remove nonexistent observer");
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsImageLoadingContent::AddObserver(imgINotificationObserver* aObserver)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aObserver);
|
||||
if (NS_WARN_IF(!aObserver)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
RefPtr<imgRequestProxy> currentReq;
|
||||
|
@ -464,7 +459,7 @@ nsImageLoadingContent::AddObserver(imgINotificationObserver* aObserver)
|
|||
// to dispatch notifications from the correct scheduler group.
|
||||
rv = mCurrentRequest->Clone(aObserver, nullptr, getter_AddRefs(currentReq));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,22 +469,23 @@ nsImageLoadingContent::AddObserver(imgINotificationObserver* aObserver)
|
|||
rv = mPendingRequest->Clone(aObserver, nullptr, getter_AddRefs(pendingReq));
|
||||
if (NS_FAILED(rv)) {
|
||||
mCurrentRequest->CancelAndForgetObserver(NS_BINDING_ABORTED);
|
||||
return rv;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mScriptedObservers.AppendElement(
|
||||
new ScriptedImageObserver(aObserver, Move(currentReq), Move(pendingReq)));
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
nsImageLoadingContent::RemoveObserver(imgINotificationObserver* aObserver)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aObserver);
|
||||
if (NS_WARN_IF(!aObserver)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(mScriptedObservers.IsEmpty())) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ScriptedImageObserver> observer;
|
||||
|
@ -504,13 +500,12 @@ nsImageLoadingContent::RemoveObserver(imgINotificationObserver* aObserver)
|
|||
} while(i > 0);
|
||||
|
||||
if (NS_WARN_IF(!observer)) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the cancel causes a mutation, it will be harmless, because we have
|
||||
// already removed the observer from the list.
|
||||
observer->CancelRequests();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -815,8 +810,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
|
|||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::ForceReload(const mozilla::dom::Optional<bool>& aNotify,
|
||||
mozilla::ErrorResult& aError)
|
||||
nsImageLoadingContent::ForceReload(bool aNotify, ErrorResult& aError)
|
||||
{
|
||||
nsCOMPtr<nsIURI> currentURI;
|
||||
GetCurrentURI(getter_AddRefs(currentURI));
|
||||
|
@ -825,35 +819,18 @@ nsImageLoadingContent::ForceReload(const mozilla::dom::Optional<bool>& aNotify,
|
|||
return;
|
||||
}
|
||||
|
||||
// defaults to true
|
||||
bool notify = !aNotify.WasPassed() || aNotify.Value();
|
||||
|
||||
// We keep this flag around along with the old URI even for failed requests
|
||||
// without a live request object
|
||||
ImageLoadType loadType = \
|
||||
(mCurrentRequestFlags & REQUEST_IS_IMAGESET) ? eImageLoadType_Imageset
|
||||
: eImageLoadType_Normal;
|
||||
nsresult rv = LoadImage(currentURI, true, notify, loadType, true, nullptr,
|
||||
nsresult rv = LoadImage(currentURI, true, aNotify, loadType, true, nullptr,
|
||||
nsIRequest::VALIDATE_ALWAYS);
|
||||
if (NS_FAILED(rv)) {
|
||||
aError.Throw(rv);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::ForceReload(bool aNotify /* = true */,
|
||||
uint8_t aArgc)
|
||||
{
|
||||
mozilla::dom::Optional<bool> notify;
|
||||
if (aArgc >= 1) {
|
||||
notify.Construct() = aNotify;
|
||||
}
|
||||
|
||||
ErrorResult result;
|
||||
ForceReload(notify, result);
|
||||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-interface methods
|
||||
*/
|
||||
|
@ -1080,13 +1057,12 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsImageLoadingContent::ForceImageState(bool aForce,
|
||||
EventStates::InternalType aState)
|
||||
{
|
||||
mIsImageStateForced = aForce;
|
||||
mForcedImageState = EventStates(aState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1356,13 +1332,13 @@ nsImageLoadingContent::PrepareNextRequest(ImageLoadType aImageLoadType)
|
|||
PrepareCurrentRequest(aImageLoadType);
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
nsImageLoadingContent::SetBlockedRequest(int16_t aContentDecision)
|
||||
{
|
||||
// If this is not calling from LoadImage, for example, from ServiceWorker,
|
||||
// bail out.
|
||||
if (!mIsStartingImageLoad) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity
|
||||
|
@ -1378,8 +1354,6 @@ nsImageLoadingContent::SetBlockedRequest(int16_t aContentDecision)
|
|||
} else {
|
||||
mImageBlockingStatus = aContentDecision;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<imgRequestProxy>&
|
||||
|
|
|
@ -56,28 +56,24 @@ public:
|
|||
NS_DECL_NSIIMAGELOADINGCONTENT
|
||||
|
||||
// Web IDL binding methods.
|
||||
// Note that the XPCOM SetLoadingEnabled, AddObserver, RemoveObserver,
|
||||
// ForceImageState methods are OK for Web IDL bindings to use as well,
|
||||
// since none of them throw when called via the Web IDL bindings.
|
||||
// Note that the XPCOM SetLoadingEnabled, ForceImageState methods are OK for
|
||||
// Web IDL bindings to use as well, since none of them throw when called via
|
||||
// the Web IDL bindings.
|
||||
|
||||
bool LoadingEnabled() const { return mLoadingEnabled; }
|
||||
int16_t ImageBlockingStatus() const
|
||||
{
|
||||
return mImageBlockingStatus;
|
||||
}
|
||||
void AddObserver(imgINotificationObserver* aObserver);
|
||||
void RemoveObserver(imgINotificationObserver* aObserver);
|
||||
already_AddRefed<imgIRequest>
|
||||
GetRequest(int32_t aRequestType, mozilla::ErrorResult& aError);
|
||||
int32_t
|
||||
GetRequestType(imgIRequest* aRequest, mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIURI> GetCurrentURI(mozilla::ErrorResult& aError);
|
||||
already_AddRefed<nsIURI> GetCurrentRequestFinalURI();
|
||||
void ForceReload(const mozilla::dom::Optional<bool>& aNotify,
|
||||
mozilla::ErrorResult& aError);
|
||||
|
||||
// XPCOM [optional] syntax helper
|
||||
nsresult ForceReload(bool aNotify = true) {
|
||||
return ForceReload(aNotify, 1);
|
||||
}
|
||||
void ForceReload(bool aNotify, mozilla::ErrorResult& aError);
|
||||
|
||||
protected:
|
||||
enum ImageLoadType {
|
||||
|
|
|
@ -495,7 +495,8 @@ HTMLImageElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName,
|
|||
// Bug 1076583 - We still use the older synchronous algorithm in
|
||||
// non-responsive mode. Force a new load of the image with the
|
||||
// new cross origin policy
|
||||
ForceReload(aNotify);
|
||||
IgnoredErrorResult error;
|
||||
ForceReload(aNotify, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,8 +92,16 @@ interface MozImageLoadingContent {
|
|||
attribute boolean loadingEnabled;
|
||||
[ChromeOnly]
|
||||
readonly attribute short imageBlockingStatus;
|
||||
/**
|
||||
* Same as addNativeObserver but intended for scripted observers or observers
|
||||
* from another or without a document.
|
||||
*/
|
||||
[ChromeOnly]
|
||||
void addObserver(imgINotificationObserver aObserver);
|
||||
/**
|
||||
* Same as removeNativeObserver but intended for scripted observers or
|
||||
* observers from another or without a document.
|
||||
*/
|
||||
[ChromeOnly]
|
||||
void removeObserver(imgINotificationObserver aObserver);
|
||||
[ChromeOnly,Throws]
|
||||
|
@ -106,8 +114,14 @@ interface MozImageLoadingContent {
|
|||
// Otherwise, returns null.
|
||||
[ChromeOnly]
|
||||
readonly attribute URI? currentRequestFinalURI;
|
||||
/**
|
||||
* forceReload forces reloading of the image pointed to by currentURI
|
||||
*
|
||||
* @param aNotify request should notify
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if there is no current URI to reload
|
||||
*/
|
||||
[ChromeOnly,Throws]
|
||||
void forceReload(optional boolean aNotify);
|
||||
void forceReload(optional boolean aNotify = true);
|
||||
[ChromeOnly]
|
||||
void forceImageState(boolean aForce, unsigned long long aState);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* New DirectWrite interfaces based on Win10 Fall Creators Update versions
|
||||
* of dwrite_3.h and dcommon.h (from SDK 10.0.17061.0). This particular
|
||||
* subset of declarations is intended to be just sufficient to compile the
|
||||
* Gecko DirectWrite font code; it omits many other new interfaces, etc.
|
||||
*/
|
||||
|
||||
#ifndef DWRITE_EXTRA_H
|
||||
#define DWRITE_EXTRA_H
|
||||
|
||||
#pragma once
|
||||
|
||||
interface IDWriteFontResource;
|
||||
interface IDWriteFontFaceReference1;
|
||||
|
||||
enum DWRITE_GLYPH_IMAGE_FORMATS {
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_NONE = 0x00000000,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE = 0x00000001,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_CFF = 0x00000002,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_COLR = 0x00000004,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_SVG = 0x00000008,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_PNG = 0x00000010,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_JPEG = 0x00000020,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_TIFF = 0x00000040,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8 = 0x00000080,
|
||||
};
|
||||
|
||||
#ifdef DEFINE_ENUM_FLAG_OPERATORS
|
||||
DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS);
|
||||
#endif
|
||||
|
||||
#define DWRITE_MAKE_FONT_AXIS_TAG(a,b,c,d) \
|
||||
(static_cast<DWRITE_FONT_AXIS_TAG>(DWRITE_MAKE_OPENTYPE_TAG(a,b,c,d)))
|
||||
|
||||
enum DWRITE_FONT_AXIS_TAG : UINT32 {
|
||||
DWRITE_FONT_AXIS_TAG_WEIGHT = DWRITE_MAKE_FONT_AXIS_TAG('w', 'g', 'h', 't'),
|
||||
DWRITE_FONT_AXIS_TAG_WIDTH = DWRITE_MAKE_FONT_AXIS_TAG('w', 'd', 't', 'h'),
|
||||
DWRITE_FONT_AXIS_TAG_SLANT = DWRITE_MAKE_FONT_AXIS_TAG('s', 'l', 'n', 't'),
|
||||
DWRITE_FONT_AXIS_TAG_OPTICAL_SIZE = DWRITE_MAKE_FONT_AXIS_TAG('o', 'p', 's', 'z'),
|
||||
DWRITE_FONT_AXIS_TAG_ITALIC = DWRITE_MAKE_FONT_AXIS_TAG('i', 't', 'a', 'l'),
|
||||
};
|
||||
|
||||
enum DWRITE_FONT_AXIS_ATTRIBUTES {
|
||||
DWRITE_FONT_AXIS_ATTRIBUTES_NONE = 0x0000,
|
||||
DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE = 0x0001,
|
||||
DWRITE_FONT_AXIS_ATTRIBUTES_HIDDEN = 0x0002,
|
||||
};
|
||||
|
||||
struct DWRITE_FONT_AXIS_VALUE {
|
||||
DWRITE_FONT_AXIS_TAG axisTag;
|
||||
FLOAT value;
|
||||
};
|
||||
|
||||
struct DWRITE_FONT_AXIS_RANGE {
|
||||
DWRITE_FONT_AXIS_TAG axisTag;
|
||||
FLOAT minValue;
|
||||
FLOAT maxValue;
|
||||
};
|
||||
|
||||
struct DWRITE_GLYPH_IMAGE_DATA;
|
||||
|
||||
interface DWRITE_DECLARE_INTERFACE("27F2A904-4EB8-441D-9678-0563F53E3E2F") IDWriteFontFace4
|
||||
: public IDWriteFontFace3
|
||||
{
|
||||
STDMETHOD_(DWRITE_GLYPH_IMAGE_FORMATS, GetGlyphImageFormats)() PURE;
|
||||
STDMETHOD(GetGlyphImageFormats)(
|
||||
UINT16 glyphId,
|
||||
UINT32 pixelsPerEmFirst,
|
||||
UINT32 pixelsPerEmLast,
|
||||
_Out_ DWRITE_GLYPH_IMAGE_FORMATS* glyphImageFormats
|
||||
) PURE;
|
||||
STDMETHOD(GetGlyphImageData)(
|
||||
_In_ UINT16 glyphId,
|
||||
UINT32 pixelsPerEm,
|
||||
DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat,
|
||||
_Out_ DWRITE_GLYPH_IMAGE_DATA* glyphData,
|
||||
_Outptr_result_maybenull_ void** glyphDataContext
|
||||
) PURE;
|
||||
STDMETHOD_(void, ReleaseGlyphImageData)(
|
||||
void* glyphDataContext
|
||||
) PURE;
|
||||
};
|
||||
|
||||
interface DWRITE_DECLARE_INTERFACE("98EFF3A5-B667-479A-B145-E2FA5B9FDC29") IDWriteFontFace5
|
||||
: public IDWriteFontFace4
|
||||
{
|
||||
STDMETHOD_(UINT32, GetFontAxisValueCount)() PURE;
|
||||
STDMETHOD(GetFontAxisValues)(
|
||||
_Out_writes_(fontAxisValueCount) DWRITE_FONT_AXIS_VALUE* fontAxisValues,
|
||||
UINT32 fontAxisValueCount
|
||||
) PURE;
|
||||
STDMETHOD_(BOOL, HasVariations)() PURE;
|
||||
STDMETHOD(GetFontResource)(
|
||||
_COM_Outptr_ IDWriteFontResource** fontResource
|
||||
) PURE;
|
||||
STDMETHOD_(BOOL, Equals)(IDWriteFontFace* fontFace) PURE;
|
||||
};
|
||||
|
||||
interface DWRITE_DECLARE_INTERFACE("1F803A76-6871-48E8-987F-B975551C50F2") IDWriteFontResource
|
||||
: public IUnknown
|
||||
{
|
||||
STDMETHOD(GetFontFile)(
|
||||
_COM_Outptr_ IDWriteFontFile** fontFile
|
||||
) PURE;
|
||||
STDMETHOD_(UINT32, GetFontFaceIndex)() PURE;
|
||||
STDMETHOD_(UINT32, GetFontAxisCount)() PURE;
|
||||
STDMETHOD(GetDefaultFontAxisValues)(
|
||||
_Out_writes_(fontAxisValueCount) DWRITE_FONT_AXIS_VALUE* fontAxisValues,
|
||||
UINT32 fontAxisValueCount
|
||||
) PURE;
|
||||
STDMETHOD(GetFontAxisRanges)(
|
||||
_Out_writes_(fontAxisRangeCount) DWRITE_FONT_AXIS_RANGE* fontAxisRanges,
|
||||
UINT32 fontAxisRangeCount
|
||||
) PURE;
|
||||
STDMETHOD_(DWRITE_FONT_AXIS_ATTRIBUTES, GetFontAxisAttributes)(
|
||||
UINT32 axisIndex
|
||||
) PURE;
|
||||
STDMETHOD(GetAxisNames)(
|
||||
UINT32 axisIndex,
|
||||
_COM_Outptr_ IDWriteLocalizedStrings** names
|
||||
) PURE;
|
||||
STDMETHOD_(UINT32, GetAxisValueNameCount)(
|
||||
UINT32 axisIndex
|
||||
) PURE;
|
||||
STDMETHOD(GetAxisValueNames)(
|
||||
UINT32 axisIndex,
|
||||
UINT32 axisValueIndex,
|
||||
_Out_ DWRITE_FONT_AXIS_RANGE* fontAxisRange,
|
||||
_COM_Outptr_ IDWriteLocalizedStrings** names
|
||||
) PURE;
|
||||
STDMETHOD_(BOOL, HasVariations)() PURE;
|
||||
STDMETHOD(CreateFontFace)(
|
||||
DWRITE_FONT_SIMULATIONS fontSimulations,
|
||||
_In_reads_(fontAxisValueCount) DWRITE_FONT_AXIS_VALUE const* fontAxisValues,
|
||||
UINT32 fontAxisValueCount,
|
||||
_COM_Outptr_ IDWriteFontFace5** fontFace
|
||||
) PURE;
|
||||
STDMETHOD(CreateFontFaceReference)(
|
||||
DWRITE_FONT_SIMULATIONS fontSimulations,
|
||||
_In_reads_(fontAxisValueCount) DWRITE_FONT_AXIS_VALUE const* fontAxisValues,
|
||||
UINT32 fontAxisValueCount,
|
||||
_COM_Outptr_ IDWriteFontFaceReference1** fontFaceReference
|
||||
) PURE;
|
||||
};
|
||||
|
||||
#endif /* DWRITE_EXTRA_H */
|
|
@ -587,33 +587,69 @@ gfxDWriteFontEntry::ReadCMAP(FontInfoData *aFontInfoData)
|
|||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxDWriteFontEntry::HasVariations()
|
||||
{
|
||||
if (mHasVariationsInitialized) {
|
||||
return mHasVariations;
|
||||
}
|
||||
mHasVariationsInitialized = true;
|
||||
if (!mFontFace) {
|
||||
// CreateFontFace will initialize the mFontFace field, and also
|
||||
// mFontFace5 if available on the current DWrite version.
|
||||
RefPtr<IDWriteFontFace> fontFace;
|
||||
if (NS_FAILED(CreateFontFace(getter_AddRefs(fontFace)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (mFontFace5) {
|
||||
mHasVariations = mFontFace5->HasVariations();
|
||||
}
|
||||
return mHasVariations;
|
||||
}
|
||||
|
||||
gfxFont *
|
||||
gfxDWriteFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle,
|
||||
bool aNeedsBold)
|
||||
{
|
||||
DWRITE_FONT_SIMULATIONS sims =
|
||||
aNeedsBold ? DWRITE_FONT_SIMULATIONS_BOLD : DWRITE_FONT_SIMULATIONS_NONE;
|
||||
if (HasVariations() && !aFontStyle->variationSettings.IsEmpty()) {
|
||||
// If we need to apply variations, we can't use the cached mUnscaledFont
|
||||
// or mUnscaledFontBold here.
|
||||
// XXX todo: consider caching a small number of variation instances?
|
||||
RefPtr<IDWriteFontFace> fontFace;
|
||||
nsresult rv = CreateFontFace(getter_AddRefs(fontFace),
|
||||
&aFontStyle->variationSettings,
|
||||
sims);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<UnscaledFontDWrite> unscaledFont =
|
||||
new UnscaledFontDWrite(fontFace, mIsSystemFont ? mFont : nullptr, sims);
|
||||
return new gfxDWriteFont(unscaledFont, this, aFontStyle, aNeedsBold);
|
||||
}
|
||||
|
||||
ThreadSafeWeakPtr<UnscaledFontDWrite>& unscaledFontPtr =
|
||||
aNeedsBold ? mUnscaledFontBold : mUnscaledFont;
|
||||
RefPtr<UnscaledFontDWrite> unscaledFont(unscaledFontPtr);
|
||||
if (!unscaledFont) {
|
||||
DWRITE_FONT_SIMULATIONS sims = DWRITE_FONT_SIMULATIONS_NONE;
|
||||
if (aNeedsBold) {
|
||||
sims |= DWRITE_FONT_SIMULATIONS_BOLD;
|
||||
}
|
||||
RefPtr<IDWriteFontFace> fontFace;
|
||||
nsresult rv = CreateFontFace(getter_AddRefs(fontFace), sims);
|
||||
nsresult rv = CreateFontFace(getter_AddRefs(fontFace), nullptr, sims);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unscaledFont = new UnscaledFontDWrite(fontFace, mIsSystemFont ? mFont : nullptr, sims);
|
||||
unscaledFont =
|
||||
new UnscaledFontDWrite(fontFace,
|
||||
mIsSystemFont ? mFont : nullptr, sims);
|
||||
unscaledFontPtr = unscaledFont;
|
||||
}
|
||||
|
||||
return new gfxDWriteFont(unscaledFont, this, aFontStyle, aNeedsBold);
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxDWriteFontEntry::CreateFontFace(IDWriteFontFace **aFontFace,
|
||||
const nsTArray<gfxFontVariation>* aVariations,
|
||||
DWRITE_FONT_SIMULATIONS aSimulations)
|
||||
{
|
||||
// initialize mFontFace if this hasn't been done before
|
||||
|
@ -637,13 +673,55 @@ gfxDWriteFontEntry::CreateFontFace(IDWriteFontFace **aFontFace,
|
|||
if (FAILED(hr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Also get the IDWriteFontFace5 interface if we're running on a
|
||||
// sufficiently new DWrite version where it is available.
|
||||
if (mFontFace) {
|
||||
mFontFace->QueryInterface(__uuidof(IDWriteFontFace5),
|
||||
(void**)getter_AddRefs(mFontFace5));
|
||||
}
|
||||
}
|
||||
|
||||
// check whether we need to add a DWrite simulated style
|
||||
if ((aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) &&
|
||||
!(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD)) {
|
||||
// Do we need to modify DWrite simulations from what mFontFace has?
|
||||
bool needSimulations =
|
||||
(aSimulations & DWRITE_FONT_SIMULATIONS_BOLD) &&
|
||||
!(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD);
|
||||
|
||||
// If the IDWriteFontFace5 interface is available, we can go via
|
||||
// IDWriteFontResource to create a new modified face.
|
||||
if (mFontFace5 && (aVariations && !aVariations->IsEmpty() ||
|
||||
needSimulations)) {
|
||||
RefPtr<IDWriteFontResource> resource;
|
||||
HRESULT hr = mFontFace5->GetFontResource(getter_AddRefs(resource));
|
||||
MOZ_ASSERT(SUCCEEDED(hr));
|
||||
AutoTArray<DWRITE_FONT_AXIS_VALUE, 4> fontAxisValues;
|
||||
if (aVariations) {
|
||||
for (const auto& v : *aVariations) {
|
||||
DWRITE_FONT_AXIS_VALUE axisValue = {
|
||||
// let dwrite put the tag bytes in the order it wants
|
||||
DWRITE_MAKE_FONT_AXIS_TAG((v.mTag >> 24) & 0xff,
|
||||
(v.mTag >> 16) & 0xff,
|
||||
(v.mTag >> 8) & 0xff,
|
||||
v.mTag & 0xff),
|
||||
v.mValue
|
||||
};
|
||||
fontAxisValues.AppendElement(axisValue);
|
||||
}
|
||||
}
|
||||
IDWriteFontFace5* ff5;
|
||||
resource->CreateFontFace(aSimulations,
|
||||
fontAxisValues.Elements(),
|
||||
fontAxisValues.Length(),
|
||||
&ff5);
|
||||
if (ff5) {
|
||||
*aFontFace = ff5;
|
||||
}
|
||||
return FAILED(hr) ? NS_ERROR_FAILURE : NS_OK;
|
||||
}
|
||||
|
||||
// Do we need to add DWrite simulations to the face?
|
||||
if (needSimulations) {
|
||||
// if so, we need to return not mFontFace itself but a version that
|
||||
// has the Bold simulation - unfortunately, DWrite doesn't provide
|
||||
// has the Bold simulation - unfortunately, old DWrite doesn't provide
|
||||
// a simple API for this
|
||||
UINT32 numberOfFiles = 0;
|
||||
if (FAILED(mFontFace->GetFiles(&numberOfFiles, nullptr))) {
|
||||
|
|
|
@ -8,6 +8,19 @@
|
|||
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "gfxDWriteCommon.h"
|
||||
#include "dwrite_3.h"
|
||||
|
||||
// Currently, we build with WINVER=0x601 (Win7), which means newer
|
||||
// declarations in dwrite_3.h will not be visible. Also, we don't
|
||||
// yet have the Fall Creators Update SDK available on build machines,
|
||||
// so even with updated WINVER, some of the interfaces we need would
|
||||
// not be present.
|
||||
// To work around this, until the build environment is updated,
|
||||
// we #include an extra header that contains copies of the relevant
|
||||
// classes/interfaces we need.
|
||||
#if WINVER < 0x0A00
|
||||
#include "dw-extra.h"
|
||||
#endif
|
||||
|
||||
#include "gfxFont.h"
|
||||
#include "gfxUserFontSet.h"
|
||||
|
@ -93,7 +106,8 @@ public:
|
|||
IDWriteFont *aFont,
|
||||
bool aIsSystemFont = false)
|
||||
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr),
|
||||
mIsSystemFont(aIsSystemFont), mForceGDIClassic(false)
|
||||
mIsSystemFont(aIsSystemFont), mForceGDIClassic(false),
|
||||
mHasVariations(false), mHasVariationsInitialized(false)
|
||||
{
|
||||
DWRITE_FONT_STYLE dwriteStyle = aFont->GetStyle();
|
||||
mStyle = (dwriteStyle == DWRITE_FONT_STYLE_ITALIC ?
|
||||
|
@ -127,7 +141,8 @@ public:
|
|||
int16_t aStretch,
|
||||
uint8_t aStyle)
|
||||
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nullptr),
|
||||
mIsSystemFont(false), mForceGDIClassic(false)
|
||||
mIsSystemFont(false), mForceGDIClassic(false),
|
||||
mHasVariations(false), mHasVariationsInitialized(false)
|
||||
{
|
||||
mWeight = aWeight;
|
||||
mStretch = aStretch;
|
||||
|
@ -154,7 +169,8 @@ public:
|
|||
uint8_t aStyle)
|
||||
: gfxFontEntry(aFaceName), mFont(nullptr),
|
||||
mFontFile(aFontFile), mFontFileStream(aFontFileStream),
|
||||
mIsSystemFont(false), mForceGDIClassic(false)
|
||||
mIsSystemFont(false), mForceGDIClassic(false),
|
||||
mHasVariations(false), mHasVariationsInitialized(false)
|
||||
{
|
||||
mWeight = aWeight;
|
||||
mStretch = aStretch;
|
||||
|
@ -173,6 +189,8 @@ public:
|
|||
|
||||
bool IsCJKFont();
|
||||
|
||||
bool HasVariations();
|
||||
|
||||
void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
|
||||
bool GetForceGDIClassic() { return mForceGDIClassic; }
|
||||
|
||||
|
@ -193,6 +211,7 @@ protected:
|
|||
|
||||
nsresult CreateFontFace(
|
||||
IDWriteFontFace **aFontFace,
|
||||
const nsTArray<gfxFontVariation>* aVariations = nullptr,
|
||||
DWRITE_FONT_SIMULATIONS aSimulations = DWRITE_FONT_SIMULATIONS_NONE);
|
||||
|
||||
static bool InitLogFont(IDWriteFont *aFont, LOGFONTW *aLogFont);
|
||||
|
@ -211,12 +230,16 @@ protected:
|
|||
// font face corresponding to the mFont/mFontFile *without* any DWrite
|
||||
// style simulations applied
|
||||
RefPtr<IDWriteFontFace> mFontFace;
|
||||
// Extended fontface interface if supported, else null
|
||||
RefPtr<IDWriteFontFace5> mFontFace5;
|
||||
|
||||
DWRITE_FONT_FACE_TYPE mFaceType;
|
||||
|
||||
int8_t mIsCJK;
|
||||
bool mIsSystemFont;
|
||||
bool mForceGDIClassic;
|
||||
bool mHasVariations;
|
||||
bool mHasVariationsInitialized;
|
||||
|
||||
mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite> mUnscaledFont;
|
||||
mozilla::ThreadSafeWeakPtr<mozilla::gfx::UnscaledFontDWrite> mUnscaledFontBold;
|
||||
|
|
|
@ -564,7 +564,9 @@ bool
|
|||
gfxDWriteFont::ProvidesGlyphWidths() const
|
||||
{
|
||||
return !mUseSubpixelPositions ||
|
||||
(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD);
|
||||
(mFontFace->GetSimulations() & DWRITE_FONT_SIMULATIONS_BOLD) ||
|
||||
(((gfxDWriteFontEntry*)(GetFontEntry()))->HasVariations() &&
|
||||
!mStyle.variationSettings.IsEmpty());
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
|
|
@ -1521,6 +1521,40 @@ gfxFont::SupportsSubSuperscript(uint32_t aSubSuperscript,
|
|||
return origSize == intersectionSize;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFont::FeatureWillHandleChar(Script aRunScript, uint32_t aFeature,
|
||||
uint32_t aUnicode)
|
||||
{
|
||||
if (!SupportsFeature(aRunScript, aFeature)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// xxx - for graphite, don't really know how to sniff lookups so bail
|
||||
if (mGraphiteShaper && gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mHarfBuzzShaper) {
|
||||
mHarfBuzzShaper = MakeUnique<gfxHarfBuzzShaper>(this);
|
||||
}
|
||||
gfxHarfBuzzShaper* shaper =
|
||||
static_cast<gfxHarfBuzzShaper*>(mHarfBuzzShaper.get());
|
||||
if (!shaper->Initialize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the hbset containing input glyphs for the feature
|
||||
const hb_set_t *inputGlyphs =
|
||||
mFontEntry->InputsForOpenTypeFeature(aRunScript, aFeature);
|
||||
|
||||
if (aUnicode == 0xa0) {
|
||||
aUnicode = ' ';
|
||||
}
|
||||
|
||||
hb_codepoint_t gid = shaper->GetNominalGlyph(aUnicode);
|
||||
return hb_set_has(inputGlyphs, gid);
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFont::HasFeatureSet(uint32_t aFeature, bool& aFeatureOn)
|
||||
{
|
||||
|
|
|
@ -1593,6 +1593,10 @@ public:
|
|||
uint32_t aLength,
|
||||
Script aRunScript);
|
||||
|
||||
// whether the specified feature will apply to the given character
|
||||
bool FeatureWillHandleChar(Script aRunScript, uint32_t aFeature,
|
||||
uint32_t aUnicode);
|
||||
|
||||
// Subclasses may choose to look up glyph ids for characters.
|
||||
// If they do not override this, gfxHarfBuzzShaper will fetch the cmap
|
||||
// table and use that.
|
||||
|
|
|
@ -848,7 +848,8 @@ gfxFontEntry::InputsForOpenTypeFeature(Script aScript, uint32_t aFeatureTag)
|
|||
}
|
||||
|
||||
NS_ASSERTION(aFeatureTag == HB_TAG('s','u','p','s') ||
|
||||
aFeatureTag == HB_TAG('s','u','b','s'),
|
||||
aFeatureTag == HB_TAG('s','u','b','s') ||
|
||||
aFeatureTag == HB_TAG('v','e','r','t'),
|
||||
"use of unknown feature tag");
|
||||
|
||||
uint32_t scriptFeature = SCRIPT_FEATURE(aScript, aFeatureTag);
|
||||
|
|
|
@ -209,8 +209,8 @@ VertFormsGlyphCompare(const void* aKey, const void* aElem)
|
|||
|
||||
// Return a vertical presentation-form codepoint corresponding to the
|
||||
// given Unicode value, or 0 if no such form is available.
|
||||
static hb_codepoint_t
|
||||
GetVerticalPresentationForm(hb_codepoint_t unicode)
|
||||
hb_codepoint_t
|
||||
gfxHarfBuzzShaper::GetVerticalPresentationForm(hb_codepoint_t aUnicode)
|
||||
{
|
||||
static const uint16_t sVerticalForms[][2] = {
|
||||
{ 0x2013, 0xfe32 }, // EN DASH
|
||||
|
@ -248,7 +248,7 @@ GetVerticalPresentationForm(hb_codepoint_t unicode)
|
|||
{ 0xff5d, 0xfe38 } // FULLWIDTH RIGHT CURLY BRACKET
|
||||
};
|
||||
const uint16_t* charPair =
|
||||
static_cast<const uint16_t*>(bsearch(&unicode,
|
||||
static_cast<const uint16_t*>(bsearch(&aUnicode,
|
||||
sVerticalForms,
|
||||
ArrayLength(sVerticalForms),
|
||||
sizeof(sVerticalForms[0]),
|
||||
|
@ -266,7 +266,8 @@ HBGetNominalGlyph(hb_font_t *font, void *font_data,
|
|||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
|
||||
if (fcd->mShaper->UseVerticalPresentationForms()) {
|
||||
hb_codepoint_t verticalForm = GetVerticalPresentationForm(unicode);
|
||||
hb_codepoint_t verticalForm =
|
||||
gfxHarfBuzzShaper::GetVerticalPresentationForm(unicode);
|
||||
if (verticalForm) {
|
||||
*glyph = fcd->mShaper->GetNominalGlyph(verticalForm);
|
||||
if (*glyph != 0) {
|
||||
|
@ -290,7 +291,8 @@ HBGetVariationGlyph(hb_font_t *font, void *font_data,
|
|||
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
|
||||
|
||||
if (fcd->mShaper->UseVerticalPresentationForms()) {
|
||||
hb_codepoint_t verticalForm = GetVerticalPresentationForm(unicode);
|
||||
hb_codepoint_t verticalForm =
|
||||
gfxHarfBuzzShaper::GetVerticalPresentationForm(unicode);
|
||||
if (verticalForm) {
|
||||
*glyph = fcd->mShaper->GetVariationGlyph(verticalForm,
|
||||
variation_selector);
|
||||
|
|
|
@ -97,6 +97,9 @@ public:
|
|||
return hbScript;
|
||||
}
|
||||
|
||||
static hb_codepoint_t
|
||||
GetVerticalPresentationForm(hb_codepoint_t aUnicode);
|
||||
|
||||
protected:
|
||||
nsresult SetGlyphsFromRun(gfxShapedText *aShapedText,
|
||||
uint32_t aOffset,
|
||||
|
|
|
@ -3180,10 +3180,25 @@ void gfxFontGroup::ComputeRanges(nsTArray<gfxTextRange>& aRanges,
|
|||
// on a per-character basis using the UTR50 orientation property.
|
||||
switch (GetVerticalOrientation(ch)) {
|
||||
case VERTICAL_ORIENTATION_U:
|
||||
case VERTICAL_ORIENTATION_Tr:
|
||||
case VERTICAL_ORIENTATION_Tu:
|
||||
orient = ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT;
|
||||
break;
|
||||
case VERTICAL_ORIENTATION_Tr: {
|
||||
// We check for a vertical presentation form first as that's
|
||||
// likely to be cheaper than inspecting lookups to see if the
|
||||
// 'vert' feature is going to handle this character, and if the
|
||||
// presentation form is available then it will be used as
|
||||
// fallback if needed, so it's OK if the feature is missing.
|
||||
uint32_t v = gfxHarfBuzzShaper::GetVerticalPresentationForm(ch);
|
||||
orient = (!font ||
|
||||
(v && font->HasCharacter(v)) ||
|
||||
font->FeatureWillHandleChar(aRunScript,
|
||||
HB_TAG('v','e','r','t'),
|
||||
ch))
|
||||
? ShapedTextFlags::TEXT_ORIENT_VERTICAL_UPRIGHT
|
||||
: ShapedTextFlags::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
|
||||
break;
|
||||
}
|
||||
case VERTICAL_ORIENTATION_R:
|
||||
orient = ShapedTextFlags::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT;
|
||||
break;
|
||||
|
|
|
@ -198,6 +198,7 @@ public:
|
|||
aTag == TRUETYPE_TAG('g', 'v', 'a', 'r') ||
|
||||
aTag == TRUETYPE_TAG('H', 'V', 'A', 'R') ||
|
||||
aTag == TRUETYPE_TAG('M', 'V', 'A', 'R') ||
|
||||
aTag == TRUETYPE_TAG('S', 'T', 'A', 'T') ||
|
||||
aTag == TRUETYPE_TAG('V', 'V', 'A', 'R'))) ||
|
||||
aTag == TRUETYPE_TAG('S', 'V', 'G', ' ') ||
|
||||
aTag == TRUETYPE_TAG('C', 'O', 'L', 'R') ||
|
||||
|
|
|
@ -35,7 +35,6 @@ function ImageObserver(decodeCallback, discardCallback) {
|
|||
function currentRequest() {
|
||||
let img = gBrowser.getBrowserForTab(newTab).contentWindow
|
||||
.document.getElementById('testImg');
|
||||
img.QueryInterface(Ci.nsIImageLoadingContent);
|
||||
return img.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@ var chrome_root = getRootDirectory(gTestPath);
|
|||
const CHROMEROOT = chrome_root;
|
||||
|
||||
function getImageLoading(doc, id) {
|
||||
var htmlImg = doc.getElementById(id);
|
||||
return htmlImg.QueryInterface(Ci.nsIImageLoadingContent);
|
||||
return doc.getElementById(id);
|
||||
}
|
||||
|
||||
// Tries to get the Moz debug image, imgIContainerDebug. Only works
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
observer = SpecialPowers.wrapCallbackObject(observer);
|
||||
var gObserver = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
.createScriptedObserver(observer);
|
||||
var imgLoadingContent =
|
||||
SpecialPowers.wrap(img).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
var imgLoadingContent = SpecialPowers.wrap(img);
|
||||
imgLoadingContent.addObserver(gObserver);
|
||||
function initCF() {
|
||||
setTimeout(function() { document.adoptNode(tCF0); }, 0);
|
||||
|
|
|
@ -45,9 +45,6 @@ function getImageStatus(id)
|
|||
// Get the image
|
||||
var img = SpecialPowers.wrap(document.getElementById(id));
|
||||
|
||||
// QI the image to nsImageLoadingContent
|
||||
img.QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent);
|
||||
|
||||
// Get the request
|
||||
var request = img.getRequest(SpecialPowers.Ci
|
||||
.nsIImageLoadingContent
|
||||
|
|
|
@ -86,7 +86,7 @@ function cleanUpAndFinish() {
|
|||
if (gIsTestFinished) {
|
||||
return;
|
||||
}
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.removeObserver(gMyDecoderObserver);
|
||||
SimpleTest.finish();
|
||||
gIsTestFinished = true;
|
||||
|
@ -101,7 +101,7 @@ function main() {
|
|||
gMyDecoderObserver =
|
||||
Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
.createScriptedObserver(SpecialPowers.wrapCallbackObject(observer));
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.addObserver(gMyDecoderObserver);
|
||||
|
||||
// We want to test the cold loading behavior, so clear cache in case an
|
||||
|
|
|
@ -27,8 +27,7 @@ window.onload = function() {
|
|||
return SpecialPowers.wrap(f.contentDocument.getElementsByTagName("img")[0]);
|
||||
});
|
||||
var containers = imgs.map(function (img) {
|
||||
return img.QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent)
|
||||
.getRequest(SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST)
|
||||
return img.getRequest(SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST)
|
||||
.image;
|
||||
});
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ function runTest() {
|
|||
|
||||
if (triggerDiscardingManually) {
|
||||
var request = SpecialPowers.wrap(image)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent)
|
||||
.getRequest(SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
setTimeout(() => request.requestDiscard(), 1000);
|
||||
}
|
||||
|
@ -82,9 +81,7 @@ function addCallbacks(anImage, loadCompleteCallback, discardCallback) {
|
|||
.getService(SpecialPowers.Ci.imgITools)
|
||||
.createScriptedObserver(observer);
|
||||
|
||||
var imgLoadingContent =
|
||||
SpecialPowers.wrap(anImage)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent);
|
||||
var imgLoadingContent = SpecialPowers.wrap(anImage);
|
||||
imgLoadingContent.addObserver(scriptedObserver);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ SimpleTest.waitForExplicitFinish();
|
|||
window.onload = function() {
|
||||
var img = SpecialPowers.wrap(document.getElementsByTagName("img")[0]);
|
||||
var container = img
|
||||
.QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent)
|
||||
.getRequest(SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST)
|
||||
.image;
|
||||
|
||||
|
|
|
@ -179,15 +179,12 @@ function addCallbacks(anImage, arrayIndex) {
|
|||
.getService(SpecialPowers.Ci.imgITools)
|
||||
.createScriptedObserver(observer);
|
||||
|
||||
var imgLoadingContent =
|
||||
SpecialPowers.wrap(anImage)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent);
|
||||
var imgLoadingContent = SpecialPowers.wrap(anImage);
|
||||
imgLoadingContent.addObserver(scriptedObserver);
|
||||
}
|
||||
|
||||
function requestDiscard(anImage) {
|
||||
var request = SpecialPowers.wrap(anImage)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent)
|
||||
.getRequest(SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
setTimeout(() => request.requestDiscard(), 0);
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ function cleanUpAndFinish() {
|
|||
return;
|
||||
}
|
||||
gIsTestFinished = true;
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.removeObserver(gMyDecoderObserver);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ function main() {
|
|||
gMyDecoderObserver =
|
||||
Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
.createScriptedObserver(SpecialPowers.wrapCallbackObject(observer));
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.addObserver(gMyDecoderObserver);
|
||||
|
||||
// We want to test the cold loading behavior, so clear cache in case an
|
||||
|
|
|
@ -114,7 +114,7 @@ function cleanUpAndFinish() {
|
|||
if (gIsTestFinished) {
|
||||
return;
|
||||
}
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.removeObserver(gMyDecoderObserver);
|
||||
// TODO - this isn't the case until post-bug 716140's refactorings
|
||||
// ok(gNotifications == gLoads, "Should be notified the same number of times as loads");
|
||||
|
@ -136,7 +136,7 @@ function main() {
|
|||
gMyDecoderObserver =
|
||||
Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
.createScriptedObserver(SpecialPowers.wrapCallbackObject(observer));
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.addObserver(gMyDecoderObserver);
|
||||
|
||||
// We want to test the cold loading behavior, so clear cache in case an
|
||||
|
|
|
@ -97,7 +97,7 @@ function cleanUpAndFinish() {
|
|||
if (gIsTestFinished) {
|
||||
return;
|
||||
}
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.removeObserver(gMyDecoderObserver);
|
||||
// TODO: this isn't the case until post-bug 716140's refactorings
|
||||
// ok(gNotifications == gLoads, "Should be notified the same number of times as loads");
|
||||
|
@ -119,7 +119,7 @@ function main() {
|
|||
gMyDecoderObserver =
|
||||
Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
.createScriptedObserver(SpecialPowers.wrapCallbackObject(observer));
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
let imgLoadingContent = SpecialPowers.wrap(gImg);
|
||||
imgLoadingContent.addObserver(gMyDecoderObserver);
|
||||
|
||||
// We want to test the cold loading behavior, so clear cache in case an
|
||||
|
|
|
@ -23,7 +23,7 @@ SimpleTest.waitForExplicitFinish();
|
|||
|
||||
window.onload = function() {
|
||||
var img = document.getElementById("animated");
|
||||
var content = SpecialPowers.wrap(img).QueryInterface(SpecialPowers.Ci.nsIImageLoadingContent);
|
||||
var content = SpecialPowers.wrap(img);
|
||||
|
||||
var request = content.getRequest(SpecialPowers.Ci.nsIImageLoadingContent.CURRENT_REQUEST);
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@ function cleanUpAndFinish() {
|
|||
if (gFinished) {
|
||||
return;
|
||||
}
|
||||
var imgLoadingContent = SpecialPowers.wrap(gImg1).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
var imgLoadingContent = SpecialPowers.wrap(gImg1);
|
||||
imgLoadingContent.removeObserver(gOuter);
|
||||
|
||||
imgLoadingContent = SpecialPowers.wrap(gImg2).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
imgLoadingContent = SpecialPowers.wrap(gImg2);
|
||||
imgLoadingContent.removeObserver(gOuter);
|
||||
|
||||
SimpleTest.finish();
|
||||
|
@ -79,7 +79,7 @@ function waitForLoadAndTest(image) {
|
|||
context.drawImage(image, 0, 0);
|
||||
|
||||
// Attach the observer.
|
||||
var imgLoadingContent = SpecialPowers.wrap(image).QueryInterface(Ci.nsIImageLoadingContent);
|
||||
var imgLoadingContent = SpecialPowers.wrap(image);
|
||||
imgLoadingContent.addObserver(gOuter);
|
||||
|
||||
// If the other image already loaded, add both images to the document, which
|
||||
|
|
|
@ -1052,9 +1052,9 @@ JS_GetDataViewByteLength(JSObject* obj)
|
|||
JS_FRIEND_API(JSObject*)
|
||||
JS_NewDataView(JSContext* cx, HandleObject buffer, uint32_t byteOffset, int32_t byteLength)
|
||||
{
|
||||
RootedObject constructor(cx);
|
||||
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(&DataViewObject::class_);
|
||||
if (!GetBuiltinConstructor(cx, key, &constructor))
|
||||
RootedObject constructor(cx, GlobalObject::getOrCreateConstructor(cx, key));
|
||||
if (!constructor)
|
||||
return nullptr;
|
||||
|
||||
FixedConstructArgs<3> cargs(cx);
|
||||
|
|
|
@ -1569,8 +1569,9 @@ PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
newTarget = unwrappedNewTarget;
|
||||
{
|
||||
AutoCompartment ac(cx, newTarget);
|
||||
RootedObject promiseCtor(cx);
|
||||
if (!GetBuiltinConstructor(cx, JSProto_Promise, &promiseCtor))
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
RootedObject promiseCtor(cx, GlobalObject::getOrCreatePromiseConstructor(cx, global));
|
||||
if (!promiseCtor)
|
||||
return false;
|
||||
|
||||
// Promise subclasses don't get the special Xray treatment, so
|
||||
|
@ -1578,7 +1579,8 @@ PromiseConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
// described above for instances of Promise itself.
|
||||
if (newTarget == promiseCtor) {
|
||||
needsWrapping = true;
|
||||
if (!GetBuiltinPrototype(cx, JSProto_Promise, &proto))
|
||||
proto = GlobalObject::getOrCreatePromisePrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3169,8 +3171,9 @@ BlockOnPromise(JSContext* cx, HandleValue promiseVal, HandleObject blockedPromis
|
|||
// |promise| is an unwrapped Promise, and |then| is the original
|
||||
// |Promise.prototype.then|, inline it here.
|
||||
// 25.4.5.3., step 3.
|
||||
RootedObject PromiseCtor(cx);
|
||||
if (!GetBuiltinConstructor(cx, JSProto_Promise, &PromiseCtor))
|
||||
RootedObject PromiseCtor(cx,
|
||||
GlobalObject::getOrCreatePromiseConstructor(cx, cx->global()));
|
||||
if (!PromiseCtor)
|
||||
return false;
|
||||
|
||||
RootedObject C(cx, SpeciesConstructor(cx, promiseObj, JSProto_Promise, IsPromiseSpecies));
|
||||
|
|
|
@ -3931,7 +3931,8 @@ ReadableByteStreamControllerConvertPullIntoDescriptor(JSContext* cx,
|
|||
// bytesFilled / elementSize).
|
||||
RootedObject ctor(cx, pullIntoDescriptor->ctor());
|
||||
if (!ctor) {
|
||||
if (!GetBuiltinConstructor(cx, JSProto_Uint8Array, &ctor))
|
||||
ctor = GlobalObject::getOrCreateConstructor(cx, JSProto_Uint8Array);
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
}
|
||||
RootedObject buffer(cx, pullIntoDescriptor->buffer());
|
||||
|
@ -4430,12 +4431,14 @@ ReadableByteStreamControllerPullInto(JSContext* cx,
|
|||
JSProtoKey protoKey = StandardProtoKeyOrNull(view);
|
||||
MOZ_ASSERT(protoKey);
|
||||
|
||||
if (!GetBuiltinConstructor(cx, protoKey, &ctor))
|
||||
ctor = GlobalObject::getOrCreateConstructor(cx, protoKey);
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
elementSize = 1 << TypedArrayShift(view->as<TypedArrayObject>().type());
|
||||
} else {
|
||||
// Step 3: Let ctor be %DataView% (reordered).
|
||||
if (!GetBuiltinConstructor(cx, JSProto_DataView, &ctor))
|
||||
ctor = GlobalObject::getOrCreateConstructor(cx, JSProto_DataView);
|
||||
if (!ctor)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -5009,10 +5009,10 @@ bool
|
|||
BaselineCompiler::emit_JSOP_BUILTINPROTO()
|
||||
{
|
||||
// The builtin prototype is a constant for a given global.
|
||||
RootedObject builtin(cx);
|
||||
JSProtoKey key = static_cast<JSProtoKey>(GET_UINT8(pc));
|
||||
MOZ_ASSERT(key < JSProto_LIMIT);
|
||||
if (!GetBuiltinPrototype(cx, key, &builtin))
|
||||
JSObject* builtin = GlobalObject::getOrCreatePrototype(cx, key);
|
||||
if (!builtin)
|
||||
return false;
|
||||
frame.push(ObjectValue(*builtin));
|
||||
return true;
|
||||
|
|
|
@ -1546,16 +1546,16 @@ GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId, HandleId id)
|
|||
return false;
|
||||
}
|
||||
primitiveType = JSVAL_TYPE_STRING;
|
||||
proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_String));
|
||||
proto = MaybeNativeObject(cx_->global()->maybeGetPrototype(JSProto_String));
|
||||
} else if (val_.isNumber()) {
|
||||
primitiveType = JSVAL_TYPE_DOUBLE;
|
||||
proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_Number));
|
||||
proto = MaybeNativeObject(cx_->global()->maybeGetPrototype(JSProto_Number));
|
||||
} else if (val_.isBoolean()) {
|
||||
primitiveType = JSVAL_TYPE_BOOLEAN;
|
||||
proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_Boolean));
|
||||
proto = MaybeNativeObject(cx_->global()->maybeGetPrototype(JSProto_Boolean));
|
||||
} else if (val_.isSymbol()) {
|
||||
primitiveType = JSVAL_TYPE_SYMBOL;
|
||||
proto = MaybeNativeObject(GetBuiltinPrototypePure(cx_->global(), JSProto_Symbol));
|
||||
proto = MaybeNativeObject(cx_->global()->maybeGetPrototype(JSProto_Symbol));
|
||||
} else {
|
||||
MOZ_ASSERT(val_.isNullOrUndefined() || val_.isMagic());
|
||||
return false;
|
||||
|
|
|
@ -7093,8 +7093,7 @@ IonBuilder::testSingletonPropertyTypes(MDefinition* obj, jsid id)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject* proto = GetBuiltinPrototypePure(&script()->global(), key);
|
||||
if (proto)
|
||||
if (JSObject* proto = script()->global().maybeGetPrototype(key))
|
||||
return testSingletonProperty(proto, id);
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -1224,7 +1224,11 @@ JS_GetClassObject(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
|
|||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
return GetBuiltinConstructor(cx, key, objp);
|
||||
JSObject* obj = GlobalObject::getOrCreateConstructor(cx, key);
|
||||
if (!obj)
|
||||
return false;
|
||||
objp.set(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -1232,7 +1236,11 @@ JS_GetClassPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
|
|||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_REQUEST(cx);
|
||||
return GetBuiltinPrototype(cx, key, objp);
|
||||
JSObject* proto = GlobalObject::getOrCreatePrototype(cx, key);
|
||||
if (!proto)
|
||||
return false;
|
||||
objp.set(proto);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace JS {
|
||||
|
|
|
@ -3793,8 +3793,11 @@ NewArray(JSContext* cx, uint32_t length,
|
|||
allocKind = GetBackgroundAllocKind(allocKind);
|
||||
|
||||
RootedObject proto(cx, protoArg);
|
||||
if (!proto && !GetBuiltinPrototype(cx, JSProto_Array, &proto))
|
||||
return nullptr;
|
||||
if (!proto) {
|
||||
proto = GlobalObject::getOrCreateArrayPrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
|
||||
bool isCachable = NewObjectWithTaggedProtoIsCachable(cx, taggedProto, newKind, &ArrayObject::class_);
|
||||
|
|
|
@ -842,11 +842,11 @@ js::NewObjectWithClassProtoCommon(JSContext* cx, const Class* clasp, HandleObjec
|
|||
if (protoKey == JSProto_Null)
|
||||
protoKey = JSProto_Object;
|
||||
|
||||
RootedObject proto(cx);
|
||||
if (!GetBuiltinPrototype(cx, protoKey, &proto))
|
||||
JSObject* proto = GlobalObject::getOrCreatePrototype(cx, protoKey);
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, clasp, AsTaggedProto(proto)));
|
||||
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, clasp, TaggedProto(proto)));
|
||||
if (!group)
|
||||
return nullptr;
|
||||
|
||||
|
@ -858,8 +858,7 @@ js::NewObjectWithClassProtoCommon(JSContext* cx, const Class* clasp, HandleObjec
|
|||
NewObjectCache& cache = cx->caches().newObjectCache;
|
||||
NewObjectCache::EntryIndex entry = -1;
|
||||
cache.lookupGlobal(clasp, global, allocKind, &entry);
|
||||
cache.fillGlobal(entry, clasp, global, allocKind,
|
||||
&obj->as<NativeObject>());
|
||||
cache.fillGlobal(entry, clasp, global, allocKind, &obj->as<NativeObject>());
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
@ -1960,11 +1959,10 @@ js::InitClass(JSContext* cx, HandleObject obj, HandleObject protoProto_,
|
|||
* js::InitClass depend on this nicety.
|
||||
*/
|
||||
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
|
||||
if (key != JSProto_Null &&
|
||||
!protoProto &&
|
||||
!GetBuiltinPrototype(cx, JSProto_Object, &protoProto))
|
||||
{
|
||||
return nullptr;
|
||||
if (key != JSProto_Null && !protoProto) {
|
||||
protoProto = GlobalObject::getOrCreatePrototype(cx, JSProto_Object);
|
||||
if (!protoProto)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
|
||||
|
@ -2103,49 +2101,6 @@ JSObject::changeToSingleton(JSContext* cx, HandleObject obj)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
MaybeResolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
|
||||
{
|
||||
if (global->isStandardClassResolved(key))
|
||||
return true;
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
|
||||
return GlobalObject::resolveConstructor(cx, global, key);
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetBuiltinConstructor(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
|
||||
{
|
||||
MOZ_ASSERT(key != JSProto_Null);
|
||||
Rooted<GlobalObject*> global(cx, cx->global());
|
||||
if (!MaybeResolveConstructor(cx, global, key))
|
||||
return false;
|
||||
|
||||
objp.set(&global->getConstructor(key).toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetBuiltinPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject protop)
|
||||
{
|
||||
MOZ_ASSERT(key != JSProto_Null);
|
||||
Rooted<GlobalObject*> global(cx, cx->global());
|
||||
if (!MaybeResolveConstructor(cx, global, key))
|
||||
return false;
|
||||
|
||||
protop.set(&global->getPrototype(key).toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::IsStandardPrototype(JSObject* obj, JSProtoKey key)
|
||||
{
|
||||
GlobalObject& global = obj->global();
|
||||
Value v = global.getPrototype(key);
|
||||
return v.isObject() && obj == &v.toObject();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the original Object.prototype from the embedding-provided incumbent
|
||||
* global.
|
||||
|
@ -2187,6 +2142,13 @@ js::GetObjectFromIncumbentGlobal(JSContext* cx, MutableHandleObject obj)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsStandardPrototype(JSObject* obj, JSProtoKey key)
|
||||
{
|
||||
Value v = obj->global().getPrototype(key);
|
||||
return v.isObject() && obj == &v.toObject();
|
||||
}
|
||||
|
||||
JSProtoKey
|
||||
JS::IdentifyStandardInstance(JSObject* obj)
|
||||
{
|
||||
|
@ -3226,21 +3188,6 @@ js::IsDelegateOfObject(JSContext* cx, HandleObject protoObj, JSObject* obj, bool
|
|||
}
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey)
|
||||
{
|
||||
MOZ_ASSERT(JSProto_Null <= protoKey);
|
||||
MOZ_ASSERT(protoKey < JSProto_LIMIT);
|
||||
|
||||
if (protoKey != JSProto_Null) {
|
||||
const Value& v = global->getPrototype(protoKey);
|
||||
if (v.isObject())
|
||||
return &v.toObject();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::PrimitiveToObject(JSContext* cx, const Value& v)
|
||||
{
|
||||
|
|
|
@ -1031,19 +1031,6 @@ GetThisValueOfWith(JSObject* env);
|
|||
|
||||
typedef JSObject* (*ClassInitializerOp)(JSContext* cx, JS::HandleObject obj);
|
||||
|
||||
/* Fast access to builtin constructors and prototypes. */
|
||||
bool
|
||||
GetBuiltinConstructor(JSContext* cx, JSProtoKey key, MutableHandleObject objp);
|
||||
|
||||
bool
|
||||
GetBuiltinPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject objp);
|
||||
|
||||
JSObject*
|
||||
GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
|
||||
|
||||
extern bool
|
||||
IsStandardPrototype(JSObject* obj, JSProtoKey key);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
namespace js {
|
||||
|
|
|
@ -119,18 +119,11 @@ GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key)
|
|||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
GlobalObject::ensureConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
|
||||
{
|
||||
if (global->isStandardClassResolved(key))
|
||||
return true;
|
||||
return resolveConstructor(cx, global, key);
|
||||
}
|
||||
|
||||
/* static*/ bool
|
||||
GlobalObject::resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key)
|
||||
{
|
||||
MOZ_ASSERT(!global->isStandardClassResolved(key));
|
||||
MOZ_ASSERT(!cx->helperThread());
|
||||
|
||||
// Prohibit collection of allocation metadata. Metadata builders shouldn't
|
||||
// need to observe lazily-constructed prototype objects coming into
|
||||
|
|
|
@ -134,11 +134,42 @@ class GlobalObject : public NativeObject
|
|||
return getSlot(APPLICATION_SLOTS + key);
|
||||
}
|
||||
static bool skipDeselectedConstructor(JSContext* cx, JSProtoKey key);
|
||||
static bool ensureConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key);
|
||||
static bool resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key);
|
||||
static bool initBuiltinConstructor(JSContext* cx, Handle<GlobalObject*> global,
|
||||
JSProtoKey key, HandleObject ctor, HandleObject proto);
|
||||
|
||||
private:
|
||||
static bool resolveConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key);
|
||||
|
||||
public:
|
||||
static bool ensureConstructor(JSContext* cx, Handle<GlobalObject*> global, JSProtoKey key) {
|
||||
if (global->isStandardClassResolved(key))
|
||||
return true;
|
||||
return resolveConstructor(cx, global, key);
|
||||
}
|
||||
|
||||
static JSObject* getOrCreateConstructor(JSContext* cx, JSProtoKey key) {
|
||||
MOZ_ASSERT(key != JSProto_Null);
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
if (!GlobalObject::ensureConstructor(cx, global, key))
|
||||
return nullptr;
|
||||
return &global->getConstructor(key).toObject();
|
||||
}
|
||||
|
||||
static JSObject* getOrCreatePrototype(JSContext* cx, JSProtoKey key) {
|
||||
MOZ_ASSERT(key != JSProto_Null);
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
if (!GlobalObject::ensureConstructor(cx, global, key))
|
||||
return nullptr;
|
||||
return &global->getPrototype(key).toObject();
|
||||
}
|
||||
|
||||
JSObject* maybeGetPrototype(JSProtoKey protoKey) const {
|
||||
MOZ_ASSERT(JSProto_Null < protoKey);
|
||||
MOZ_ASSERT(protoKey < JSProto_LIMIT);
|
||||
const Value& v = getPrototype(protoKey);
|
||||
return v.isObject() ? &v.toObject() : nullptr;
|
||||
}
|
||||
|
||||
void setConstructor(JSProtoKey key, const Value& v) {
|
||||
MOZ_ASSERT(key <= JSProto_LIMIT);
|
||||
setSlot(APPLICATION_SLOTS + key, v);
|
||||
|
|
|
@ -1769,7 +1769,8 @@ GlobalHelperThreadState::mergeParseTaskCompartment(JSContext* cx, ParseTask* par
|
|||
if (key != JSProto_Null) {
|
||||
MOZ_ASSERT(key == JSProto_Object || key == JSProto_Array ||
|
||||
key == JSProto_Function || key == JSProto_RegExp);
|
||||
newProto = GetBuiltinPrototypePure(global, key);
|
||||
newProto = global->maybeGetPrototype(key);
|
||||
MOZ_ASSERT(newProto);
|
||||
} else if (protoObj == parseTaskGenFunctionProto) {
|
||||
newProto = global->getGeneratorFunctionPrototype();
|
||||
} else if (protoObj == moduleProto) {
|
||||
|
|
|
@ -4146,10 +4146,10 @@ END_CASE(JSOP_CHECKCLASSHERITAGE)
|
|||
|
||||
CASE(JSOP_BUILTINPROTO)
|
||||
{
|
||||
ReservedRooted<JSObject*> builtin(&rootObject0);
|
||||
MOZ_ASSERT(GET_UINT8(REGS.pc) < JSProto_LIMIT);
|
||||
JSProtoKey key = static_cast<JSProtoKey>(GET_UINT8(REGS.pc));
|
||||
if (!GetBuiltinPrototype(cx, key, &builtin))
|
||||
JSObject* builtin = GlobalObject::getOrCreatePrototype(cx, key);
|
||||
if (!builtin)
|
||||
goto error;
|
||||
PUSH_OBJECT(*builtin);
|
||||
}
|
||||
|
|
|
@ -719,10 +719,13 @@ GetClassForProtoKey(JSProtoKey key)
|
|||
/* static */ ObjectGroup*
|
||||
ObjectGroup::defaultNewGroup(JSContext* cx, JSProtoKey key)
|
||||
{
|
||||
RootedObject proto(cx);
|
||||
if (key != JSProto_Null && !GetBuiltinPrototype(cx, key, &proto))
|
||||
return nullptr;
|
||||
return defaultNewGroup(cx, GetClassForProtoKey(key), TaggedProto(proto.get()));
|
||||
JSObject* proto = nullptr;
|
||||
if (key != JSProto_Null) {
|
||||
proto = GlobalObject::getOrCreatePrototype(cx, key);
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
}
|
||||
return defaultNewGroup(cx, GetClassForProtoKey(key), TaggedProto(proto));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -844,8 +847,8 @@ ObjectGroup::newArrayObject(JSContext* cx,
|
|||
if (p) {
|
||||
group = p->value();
|
||||
} else {
|
||||
RootedObject proto(cx);
|
||||
if (!GetBuiltinPrototype(cx, JSProto_Array, &proto))
|
||||
JSObject* proto = GlobalObject::getOrCreateArrayPrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
|
||||
group = ObjectGroupCompartment::makeGroup(cx, &ArrayObject::class_, taggedProto);
|
||||
|
@ -1167,8 +1170,8 @@ ObjectGroup::newPlainObject(JSContext* cx, IdValuePair* properties, size_t nprop
|
|||
if (!CanShareObjectGroup(properties, nproperties))
|
||||
return NewPlainObjectWithProperties(cx, properties, nproperties, newKind);
|
||||
|
||||
RootedObject proto(cx);
|
||||
if (!GetBuiltinPrototype(cx, JSProto_Object, &proto))
|
||||
JSObject* proto = GlobalObject::getOrCreatePrototype(cx, JSProto_Object);
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
|
||||
|
@ -1416,9 +1419,12 @@ ObjectGroup::allocationSiteGroup(JSContext* cx, JSScript* scriptArg, jsbytecode*
|
|||
}
|
||||
|
||||
RootedScript script(cx, scriptArg);
|
||||
RootedObject proto(cx, protoArg);
|
||||
if (!proto && kind != JSProto_Null && !GetBuiltinPrototype(cx, kind, &proto))
|
||||
return nullptr;
|
||||
JSObject* proto = protoArg;
|
||||
if (!proto && kind != JSProto_Null) {
|
||||
proto = GlobalObject::getOrCreatePrototype(cx, kind);
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rooted<ObjectGroupCompartment::AllocationSiteKey> key(cx,
|
||||
ObjectGroupCompartment::AllocationSiteKey(script, offset, kind, proto));
|
||||
|
@ -1665,8 +1671,8 @@ ObjectGroupCompartment::getStringSplitStringGroup(JSContext* cx)
|
|||
|
||||
const Class* clasp = GetClassForProtoKey(JSProto_Array);
|
||||
|
||||
RootedObject proto(cx);
|
||||
if (!GetBuiltinPrototype(cx, JSProto_Array, &proto))
|
||||
JSObject* proto = GlobalObject::getOrCreateArrayPrototype(cx, cx->global());
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
|
||||
|
||||
|
|
|
@ -231,8 +231,8 @@ intrinsic_GetBuiltinConstructor(JSContext* cx, unsigned argc, Value* vp)
|
|||
RootedId id(cx, AtomToId(atom));
|
||||
JSProtoKey key = JS_IdToProtoKey(cx, id);
|
||||
MOZ_ASSERT(key != JSProto_Null);
|
||||
RootedObject ctor(cx);
|
||||
if (!GetBuiltinConstructor(cx, key, &ctor))
|
||||
JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, key);
|
||||
if (!ctor)
|
||||
return false;
|
||||
args.rval().setObject(*ctor);
|
||||
return true;
|
||||
|
@ -1992,8 +1992,8 @@ intrinsic_ConstructorForTypedArray(JSContext* cx, unsigned argc, Value* vp)
|
|||
// compartment, and never call the constructor in the ArrayBuffer's
|
||||
// compartment from script, we are not guaranteed to have initialized
|
||||
// the constructor.
|
||||
RootedObject ctor(cx);
|
||||
if (!GetBuiltinConstructor(cx, protoKey, &ctor))
|
||||
JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, protoKey);
|
||||
if (!ctor)
|
||||
return false;
|
||||
|
||||
args.rval().setObject(*ctor);
|
||||
|
|
|
@ -3500,7 +3500,7 @@ PreliminaryObjectArray::sweep()
|
|||
JSObject* obj = *ptr;
|
||||
GlobalObject* global = obj->compartment()->unsafeUnbarrieredMaybeGlobal();
|
||||
if (global && !obj->isSingleton()) {
|
||||
JSObject* objectProto = GetBuiltinPrototypePure(global, JSProto_Object);
|
||||
JSObject* objectProto = global->maybeGetPrototype(JSProto_Object);
|
||||
obj->setGroup(objectProto->groupRaw());
|
||||
MOZ_ASSERT(obj->is<NativeObject>());
|
||||
MOZ_ASSERT(obj->getClass() == objectProto->getClass());
|
||||
|
|
|
@ -451,8 +451,12 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
// the time, though, that [[Prototype]] will not be interesting. If
|
||||
// it isn't, we can do some more TI optimizations.
|
||||
RootedObject checkProto(cx);
|
||||
if (proto && !GetBuiltinPrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()), &checkProto))
|
||||
return nullptr;
|
||||
if (proto) {
|
||||
checkProto =
|
||||
GlobalObject::getOrCreatePrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()));
|
||||
if (!checkProto)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoSetNewObjectMetadata metadata(cx);
|
||||
Rooted<TypedArrayObject*> obj(cx);
|
||||
|
@ -876,7 +880,9 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
// this compartment.
|
||||
RootedObject protoRoot(cx, proto);
|
||||
if (!protoRoot) {
|
||||
if (!GetBuiltinPrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()), &protoRoot))
|
||||
protoRoot =
|
||||
GlobalObject::getOrCreatePrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()));
|
||||
if (!protoRoot)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -362,8 +362,16 @@ abstract class OldBaseTest extends BaseRobocopTest {
|
|||
MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mSolo,
|
||||
mDriver.getGeckoLeft(), mDriver.getGeckoTop());
|
||||
meh.dragSync(mScreenMidWidth, mScreenMidHeight+100, mScreenMidWidth, mScreenMidHeight-100);
|
||||
mAsserter.dumpLog("waitForPreferencesText scrolled down");
|
||||
|
||||
foundText = mSolo.waitForText(txt);
|
||||
|
||||
if (!foundText) {
|
||||
meh.dragSync(mScreenMidWidth, mScreenMidHeight-150, mScreenMidWidth, mScreenMidHeight+150);
|
||||
mAsserter.dumpLog("waitForPreferencesText scrolled up");
|
||||
|
||||
foundText = mSolo.waitForText(txt);
|
||||
}
|
||||
}
|
||||
return foundText;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--certificate-path=%(certs_path)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--quiet",
|
||||
|
@ -55,8 +53,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--certificate-path=%(certs_path)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--quiet",
|
||||
|
@ -74,8 +70,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--certificate-path=%(certs_path)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--quiet",
|
||||
|
@ -95,8 +89,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--certificate-path=%(certs_path)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--quiet",
|
||||
|
@ -114,8 +106,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--certificate-path=%(certs_path)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--quiet",
|
||||
|
@ -133,8 +123,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--certificate-path=%(certs_path)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--quiet",
|
||||
|
@ -153,8 +141,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--certificate-path=%(certs_path)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--quiet",
|
||||
|
@ -173,8 +159,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--httpd-path", "%(modules_dir)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--extra-profile-file=fonts",
|
||||
|
@ -185,24 +169,6 @@ config = {
|
|||
],
|
||||
"tests": ["tests/layout/reftests/reftest.list",],
|
||||
},
|
||||
"reftest-debug": {
|
||||
"run_filename": "remotereftest.py",
|
||||
"testsdir": "reftest",
|
||||
"options": [
|
||||
"--app=%(app)s",
|
||||
"--ignore-window-size",
|
||||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--httpd-path", "%(modules_dir)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--extra-profile-file=fonts",
|
||||
"--extra-profile-file=hyphenation",
|
||||
"tests/layout/reftests/reftest.list",
|
||||
],
|
||||
},
|
||||
"crashtest": {
|
||||
"run_filename": "remotereftest.py",
|
||||
"testsdir": "reftest",
|
||||
|
@ -212,8 +178,6 @@ config = {
|
|||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--httpd-path",
|
||||
"%(modules_dir)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
|
@ -221,23 +185,6 @@ config = {
|
|||
],
|
||||
"tests": ["tests/testing/crashtest/crashtests.list",],
|
||||
},
|
||||
"crashtest-debug": {
|
||||
"run_filename": "remotereftest.py",
|
||||
"testsdir": "reftest",
|
||||
"options": [
|
||||
"--app=%(app)s",
|
||||
"--ignore-window-size",
|
||||
"--remote-webserver=%(remote_webserver)s",
|
||||
"--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s",
|
||||
"--httpd-path",
|
||||
"%(modules_dir)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"tests/testing/crashtest/crashtests.list",
|
||||
],
|
||||
},
|
||||
"jsreftest": {
|
||||
"run_filename": "remotereftest.py",
|
||||
"testsdir": "reftest",
|
||||
|
@ -245,28 +192,14 @@ config = {
|
|||
"--app=%(app)s",
|
||||
"--ignore-window-size",
|
||||
"--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
|
||||
"--utility-path=%(utility_path)s",
|
||||
"--httpd-path", "%(modules_dir)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--extra-profile-file=jsreftest/tests/user.js",
|
||||
"--suite=jstestbrowser",
|
||||
],
|
||||
"tests": ["../jsreftest/tests/jstests.list",],
|
||||
},
|
||||
"jsreftest-debug": {
|
||||
"run_filename": "remotereftest.py",
|
||||
"testsdir": "reftest",
|
||||
"options": [
|
||||
"--app=%(app)s",
|
||||
"--ignore-window-size",
|
||||
"--remote-webserver=%(remote_webserver)s", "--xre-path=%(xre_path)s",
|
||||
"--utility-path=%(utility_path)s", "--http-port=%(http_port)s",
|
||||
"--ssl-port=%(ssl_port)s", "--httpd-path", "%(modules_dir)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"../jsreftest/tests/jstests.list",
|
||||
"--extra-profile-file=jsreftest/tests/user.js",
|
||||
],
|
||||
},
|
||||
"xpcshell": {
|
||||
"run_filename": "remotexpcshelltests.py",
|
||||
"testsdir": "xpcshell",
|
||||
|
|
|
@ -34,7 +34,5 @@ config = {
|
|||
"emulator": {
|
||||
"name": "test-1",
|
||||
"device_id": "emulator-5554",
|
||||
"http_port": "8854", # starting http port to use for the mochitest server
|
||||
"ssl_port": "4454", # starting ssl port to use for the server
|
||||
},
|
||||
}
|
||||
|
|
|
@ -31,7 +31,5 @@ config = {
|
|||
"emulator": {
|
||||
"name": "test-1",
|
||||
"device_id": "emulator-5554",
|
||||
"http_port": "8854", # starting http port to use for the mochitest server
|
||||
"ssl_port": "4454", # starting ssl port to use for the server
|
||||
},
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ from mozprocess import ProcessHandler
|
|||
|
||||
from mozharness.base.log import FATAL
|
||||
from mozharness.base.script import BaseScript, PreScriptAction, PostScriptAction
|
||||
from mozharness.base.vcs.vcsbase import VCSMixin
|
||||
from mozharness.mozilla.blob_upload import BlobUploadMixin, blobupload_config_options
|
||||
from mozharness.mozilla.buildbot import TBPL_RETRY, EXIT_STATUS_DICT
|
||||
from mozharness.mozilla.mozbase import MozbaseMixin
|
||||
|
@ -31,7 +30,7 @@ from mozharness.mozilla.testing.testbase import TestingMixin, testing_config_opt
|
|||
from mozharness.mozilla.testing.unittest import EmulatorMixin
|
||||
|
||||
|
||||
class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin, BaseScript,
|
||||
class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, BaseScript,
|
||||
MozbaseMixin):
|
||||
config_options = [[
|
||||
["--test-suite"],
|
||||
|
@ -39,13 +38,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
|||
"dest": "test_suite",
|
||||
"default": None
|
||||
}
|
||||
], [
|
||||
["--adb-path"],
|
||||
{"action": "store",
|
||||
"dest": "adb_path",
|
||||
"default": None,
|
||||
"help": "Path to adb",
|
||||
}
|
||||
], [
|
||||
["--total-chunk"],
|
||||
{"action": "store",
|
||||
|
@ -63,15 +55,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
|||
]] + copy.deepcopy(testing_config_options) + \
|
||||
copy.deepcopy(blobupload_config_options)
|
||||
|
||||
error_list = [
|
||||
]
|
||||
|
||||
virtualenv_requirements = [
|
||||
]
|
||||
|
||||
virtualenv_modules = [
|
||||
]
|
||||
|
||||
app_name = None
|
||||
|
||||
def __init__(self, require_config_file=False):
|
||||
|
@ -87,18 +70,10 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
|||
'install',
|
||||
'run-tests',
|
||||
],
|
||||
default_actions=['clobber',
|
||||
'start-emulator',
|
||||
'download-and-extract',
|
||||
'create-virtualenv',
|
||||
'verify-emulator',
|
||||
'install',
|
||||
'run-tests',
|
||||
],
|
||||
require_config_file=require_config_file,
|
||||
config={
|
||||
'virtualenv_modules': self.virtualenv_modules,
|
||||
'virtualenv_requirements': self.virtualenv_requirements,
|
||||
'virtualenv_modules': [],
|
||||
'virtualenv_requirements': [],
|
||||
'require_test_zip': True,
|
||||
# IP address of the host as seen from the emulator
|
||||
'remote_webserver': '10.0.2.2',
|
||||
|
@ -451,8 +426,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
|||
'remote_webserver': c['remote_webserver'],
|
||||
'xre_path': self.xre_path,
|
||||
'utility_path': self.xre_path,
|
||||
'http_port': self.emulator['http_port'],
|
||||
'ssl_port': self.emulator['ssl_port'],
|
||||
'certs_path': os.path.join(dirs['abs_work_dir'], 'tests/certs'),
|
||||
# TestingMixin._download_and_extract_symbols() will set
|
||||
# self.symbols_path when downloading/extracting.
|
||||
|
@ -791,11 +764,6 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
|||
"""
|
||||
self.start_time = datetime.datetime.now()
|
||||
max_verify_time = datetime.timedelta(minutes=60)
|
||||
aliases = {
|
||||
'reftest-debug': 'reftest',
|
||||
'jsreftest-debug': 'jsreftest',
|
||||
'crashtest-debug': 'crashtest',
|
||||
}
|
||||
|
||||
verify_args = []
|
||||
suites = self._query_suites()
|
||||
|
@ -838,13 +806,12 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
|||
subprocess.list2cmdline(final_cmd)))
|
||||
self.info("##### %s log begins" % self.test_suite)
|
||||
|
||||
# TinderBoxPrintRe does not know about the '-debug' categories
|
||||
suite_category = aliases.get(self.test_suite, self.test_suite)
|
||||
suite_category = self.test_suite
|
||||
parser = self.get_test_output_parser(
|
||||
suite_category,
|
||||
config=self.config,
|
||||
log_obj=self.log_obj,
|
||||
error_list=self.error_list)
|
||||
error_list=[])
|
||||
self.run_command(final_cmd, cwd=cwd, env=env, output_parser=parser)
|
||||
tbpl_status, log_level = parser.evaluate_parser(0)
|
||||
parser.append_tinderboxprint_line(self.test_suite)
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "VTuneProfiler.h"
|
||||
#include "mozilla/Bootstrap.h"
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
VTuneProfiler* VTuneProfiler::mInstance = nullptr;
|
||||
|
||||
void
|
||||
VTuneProfiler::Initialize()
|
||||
{
|
||||
// This is just a 'dirty trick' to find out if the ittnotify DLL was found.
|
||||
// If it wasn't this function always returns 0, otherwise it returns incrementing
|
||||
// numbers, if the library was found this wastes 2 events but that should be okay.
|
||||
__itt_event testEvent = __itt_event_createA("Test event", strlen("Test event"));
|
||||
testEvent = __itt_event_createA("Test event 2", strlen("Test event 2"));
|
||||
|
||||
if (testEvent) {
|
||||
mInstance = new VTuneProfiler();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VTuneProfiler::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VTuneProfiler::TraceInternal(const char* aName, TracingKind aKind)
|
||||
{
|
||||
if (aKind == TRACING_EVENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
string str(aName);
|
||||
|
||||
auto iter = mStrings.find(str);
|
||||
|
||||
__itt_event event;
|
||||
if (iter != mStrings.end()) {
|
||||
event = iter->second;
|
||||
} else {
|
||||
event = __itt_event_createA(aName, str.length());
|
||||
mStrings.insert({ str, event });
|
||||
}
|
||||
|
||||
if (aKind == TRACING_INTERVAL_START) {
|
||||
__itt_event_start(event);
|
||||
} else {
|
||||
__itt_event_end(event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VTuneProfiler::RegisterThreadInternal(const char* aName)
|
||||
{
|
||||
string str(aName);
|
||||
|
||||
if (!str.compare("GeckoMain")) {
|
||||
// Process main thread.
|
||||
switch (XRE_GetProcessType()) {
|
||||
case GeckoProcessType::GeckoProcessType_Default:
|
||||
__itt_thread_set_nameA("Main Process");
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_Content:
|
||||
__itt_thread_set_nameA("Content Process");
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_GMPlugin:
|
||||
__itt_thread_set_nameA("Plugin Process");
|
||||
break;
|
||||
case GeckoProcessType::GeckoProcessType_GPU:
|
||||
__itt_thread_set_nameA("GPU Process");
|
||||
break;
|
||||
default:
|
||||
__itt_thread_set_nameA("Unknown Process");
|
||||
}
|
||||
return;
|
||||
}
|
||||
__itt_thread_set_nameA(aName);
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef VTuneProfiler_h
|
||||
#define VTuneProfiler_h
|
||||
|
||||
// The intent here is to add 0 overhead for regular users. In order to build
|
||||
// the VTune profiler code at all --enable-vtune-instrumentation needs to be
|
||||
// set as a build option. Even then, when none of the environment variables
|
||||
// is specified that allow us to find the ittnotify DLL, these functions
|
||||
// should be minimal overhead. When starting Firefox under VTune, these
|
||||
// env vars will be automatically defined, otherwise INTEL_LIBITTNOTIFY32/64
|
||||
// should be set to point at the ittnotify DLL.
|
||||
#ifndef MOZ_VTUNE_INSTRUMENTATION
|
||||
|
||||
#define VTUNE_INIT()
|
||||
#define VTUNE_SHUTDOWN()
|
||||
|
||||
#define VTUNE_TRACING(name, kind)
|
||||
#define VTUNE_REGISTER_THREAD(name)
|
||||
|
||||
#else
|
||||
|
||||
#include <stddef.h>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
#include "GeckoProfiler.h"
|
||||
|
||||
// This is the regular Intel header, these functions are actually defined for
|
||||
// us inside js/src/vtune by an intel C file which actually dynamically resolves
|
||||
// them to the correct DLL. Through libxul these will 'magically' resolve.
|
||||
#include "vtune/ittnotify.h"
|
||||
|
||||
class VTuneProfiler
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
static void Shutdown();
|
||||
|
||||
static void Trace(const char* aName, TracingKind aKind)
|
||||
{
|
||||
if (mInstance) {
|
||||
mInstance->TraceInternal(aName, aKind);
|
||||
}
|
||||
}
|
||||
static void RegisterThread(const char* aName)
|
||||
{
|
||||
if (mInstance)
|
||||
{
|
||||
mInstance->RegisterThreadInternal(aName);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void TraceInternal(const char* aName, TracingKind aKind);
|
||||
void RegisterThreadInternal(const char* aName);
|
||||
|
||||
// This is null when the ittnotify DLL could not be found.
|
||||
static VTuneProfiler* mInstance;
|
||||
|
||||
std::unordered_map<std::string, __itt_event> mStrings;
|
||||
};
|
||||
|
||||
#define VTUNE_INIT() VTuneProfiler::Initialize()
|
||||
#define VTUNE_SHUTDOWN() VTuneProfiler::Shutdown()
|
||||
|
||||
#define VTUNE_TRACING(name, kind) VTuneProfiler::Trace(name, kind)
|
||||
#define VTUNE_REGISTER_THREAD(name) VTuneProfiler::RegisterThread(name)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* VTuneProfiler_h */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче