зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1688168 - Isolate bidi text in the console. r=nchevobbe
Differential Revision: https://phabricator.services.mozilla.com/D135458
This commit is contained in:
Родитель
6881fd9c1b
Коммит
2ea2ba189e
|
@ -37,6 +37,10 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.objectBox * {
|
||||
unicode-bidi: isolate;
|
||||
}
|
||||
|
||||
.objectBox-number,
|
||||
.objectBox-styleRule,
|
||||
.objectBox-element,
|
||||
|
|
|
@ -178,6 +178,7 @@ support-files =
|
|||
tags = mcb
|
||||
[browser_webconsole_async_stack.js]
|
||||
[browser_webconsole_batching.js]
|
||||
[browser_webconsole_bidi_string_isolation.js]
|
||||
[browser_webconsole_block_mixedcontent_securityerrors.js]
|
||||
tags = mcb
|
||||
[browser_webconsole_cached_messages_cross_domain_iframe.js]
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf8,<!DOCTYPE html>Bidi strings";
|
||||
const rtlOverride = "\u202e";
|
||||
|
||||
add_task(async function() {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
const browser = gBrowser.selectedBrowser;
|
||||
|
||||
/* eslint-disable-next-line no-shadow */
|
||||
await SpecialPowers.spawn(browser, [rtlOverride], rtlOverride => {
|
||||
const { console } = content.wrappedJSObject;
|
||||
|
||||
console.log(Symbol(rtlOverride + "msg01"));
|
||||
console.log([rtlOverride + "msg02"]);
|
||||
console.log({ p: rtlOverride + "msg03" });
|
||||
console.log({ [rtlOverride + "msg04"]: null });
|
||||
console.log(new Set([rtlOverride + "msg05"]));
|
||||
console.log(new Map([[rtlOverride + "msg06", null]]));
|
||||
console.log(new Map([[null, rtlOverride + "msg07"]]));
|
||||
|
||||
const parser = content.document.createElement("div");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
parser.innerHTML = `
|
||||
<div data-test="${rtlOverride}msg08"></div>
|
||||
<div data-${rtlOverride}="msg09"></div>
|
||||
<div-${rtlOverride} msg10></div-${rtlOverride}>
|
||||
`;
|
||||
for (const child of parser.children) {
|
||||
console.log(child);
|
||||
}
|
||||
});
|
||||
|
||||
const texts = [
|
||||
`Symbol("${rtlOverride}msg01")`,
|
||||
`Array [ "${rtlOverride}msg02" ]`,
|
||||
`Object { p: "${rtlOverride}msg03" }`,
|
||||
`Object { "${rtlOverride}msg04": null }`,
|
||||
`Set [ "${rtlOverride}msg05" ]`,
|
||||
`Map { "${rtlOverride}msg06" → null }`,
|
||||
`Map { null → "${rtlOverride}msg07" }`,
|
||||
`<div data-test="${rtlOverride}msg08">`,
|
||||
`<div data-${rtlOverride}="msg09">`,
|
||||
`<div-${rtlOverride} msg10="">`,
|
||||
];
|
||||
for (let i = 0; i < texts.length; ++i) {
|
||||
const msgId = "msg" + String(i + 1).padStart(2, "0");
|
||||
const message = await waitFor(() => findMessage(hud, msgId));
|
||||
const objectBox = message.querySelector(".objectBox");
|
||||
is(objectBox.textContent, texts[i], "Should have all the relevant text");
|
||||
checkRects(objectBox);
|
||||
}
|
||||
});
|
||||
|
||||
function getBoundingClientRect(node) {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
return node.getBoundingClientRect();
|
||||
}
|
||||
// There is no Node.getBoundingClientRect, use a Range instead.
|
||||
const range = document.createRange();
|
||||
range.selectNode(node);
|
||||
return range.getBoundingClientRect();
|
||||
}
|
||||
|
||||
/**
|
||||
* The console prints data build from external strings. They can contain
|
||||
* characters that change the directionality of the text. For example, RTL
|
||||
* characters will flow right to left. However, this should be isolated to
|
||||
* prevent one string from mangling how another one is rendered.
|
||||
* This function uses getBoundingClientRect() to check that the nodes, as a
|
||||
* whole, flow LTR (even if the characters in the node flow RTL).
|
||||
* The bidi algorithm happens at layout time, so we need to check the rects,
|
||||
* DOM operations like textContent would be useless.
|
||||
*/
|
||||
function checkRects(node, parentRect = getBoundingClientRect(node)) {
|
||||
let prevRect;
|
||||
for (const child of node.childNodes) {
|
||||
const rect = getBoundingClientRect(child);
|
||||
ok(rect.x >= parentRect.x, "Rect should start inside parent");
|
||||
ok(
|
||||
rect.x + rect.width <= parentRect.x + parentRect.width,
|
||||
"Rect should end inside parent"
|
||||
);
|
||||
if (prevRect) {
|
||||
ok(
|
||||
rect.x >= prevRect.x + prevRect.width,
|
||||
"Rect should start after previous one"
|
||||
);
|
||||
}
|
||||
prevRect = rect;
|
||||
checkRects(child, rect);
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче