зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
814adb5c46
|
@ -3,14 +3,6 @@ build/clang-plugin/.*
|
|||
# The two templates cannot be formatted
|
||||
config/gcc-stl-wrapper.template.h
|
||||
config/msvc-stl-wrapper.template.h
|
||||
dom/base/test/.*
|
||||
dom/bindings/test/.*
|
||||
dom/media/gtest/.*
|
||||
gfx/testsd/.*
|
||||
.*/gtest/ExampleStylesheet.h
|
||||
image/test/.*
|
||||
ipc/ipdl/test/.*
|
||||
ipc/testshell/.*
|
||||
# Generated code
|
||||
js/src/builtin/intl/TimeZoneDataGenerated.h
|
||||
|
||||
|
@ -35,16 +27,6 @@ layout/style/nsCSSVisitedDependentPropList.h
|
|||
layout/style/nsDOMCSSValueList.h
|
||||
layout/style/nsStyleStructList.h
|
||||
|
||||
media/mtransport/test/.*
|
||||
mfbt/tests/.*
|
||||
storage/test/.*
|
||||
testing/gtest/.*
|
||||
tools/profiler/tests/.*
|
||||
uriloader/exthandler/tests/.*
|
||||
widget/tests/.*
|
||||
xpcom/glue/tests/.*
|
||||
xpcom/tests/.*
|
||||
|
||||
# Generated by protobuf
|
||||
.*/.*.pb.h
|
||||
.*/.*.pb.cc
|
||||
|
|
|
@ -772,7 +772,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dwrote"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2933,7 +2933,7 @@ dependencies = [
|
|||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2961,7 +2961,7 @@ dependencies = [
|
|||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2977,7 +2977,7 @@ dependencies = [
|
|||
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3183,7 +3183,7 @@ dependencies = [
|
|||
"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum dtoa-short 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "068d4026697c1a18f0b0bb8cfcad1b0c151b90d8edb9bf4c235ad68128920d1d"
|
||||
"checksum dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b46afd0d0bbbea88fc083ea293e40865e26a75ec9d38cf5d05a23ac3e2ffe02"
|
||||
"checksum dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f0beca78470f26189a662e72afe7a54c625b4feb06b2d36c207ac15319bd57c5"
|
||||
"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
|
||||
"checksum ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dc8393b3c7352f94092497f6b52019643e493b6b890eb417cdb7c46117e621"
|
||||
"checksum encoding_c 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "769ecb8b33323998e482b218c0d13cd64c267609023b4b7ec3ee740714c318ee"
|
||||
|
|
|
@ -438,16 +438,59 @@ NS_IMPL_ISUPPORTS(nsScriptSecurityManager, nsIScriptSecurityManager)
|
|||
|
||||
///////////////// Security Checks /////////////////
|
||||
|
||||
#if defined(DEBUG) && !defined(ANDROID)
|
||||
static void AssertEvalNotUsingSystemPrincipal(nsIPrincipal* subjectPrincipal,
|
||||
JSContext* cx) {
|
||||
if (!nsContentUtils::IsSystemPrincipal(subjectPrincipal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Preferences::GetBool("security.allow_eval_with_system_principal")) {
|
||||
return;
|
||||
}
|
||||
|
||||
static StaticAutoPtr<nsTArray<nsCString>> sUrisAllowEval;
|
||||
JS::AutoFilename scriptFilename;
|
||||
if (JS::DescribeScriptedCaller(cx, &scriptFilename)) {
|
||||
if (!sUrisAllowEval) {
|
||||
sUrisAllowEval = new nsTArray<nsCString>();
|
||||
nsAutoCString urisAllowEval;
|
||||
Preferences::GetCString("security.uris_using_eval_with_system_principal",
|
||||
urisAllowEval);
|
||||
for (const nsACString& filenameString : urisAllowEval.Split(',')) {
|
||||
sUrisAllowEval->AppendElement(filenameString);
|
||||
}
|
||||
ClearOnShutdown(&sUrisAllowEval);
|
||||
}
|
||||
|
||||
nsAutoCString fileName;
|
||||
fileName = nsAutoCString(scriptFilename.get());
|
||||
// Extract file name alone if scriptFilename contains line number
|
||||
// separated by multiple space delimiters in few cases.
|
||||
int32_t fileNameIndex = fileName.FindChar(' ');
|
||||
if (fileNameIndex != -1) {
|
||||
fileName = Substring(fileName, 0, fileNameIndex);
|
||||
}
|
||||
ToLowerCase(fileName);
|
||||
|
||||
for (auto& uriEntry : *sUrisAllowEval) {
|
||||
if (StringEndsWith(fileName, uriEntry)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "do not use eval with system privileges");
|
||||
}
|
||||
#endif
|
||||
|
||||
bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
|
||||
JSContext* cx, JS::HandleValue aValue) {
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::SubjectPrincipal();
|
||||
|
||||
#if defined(DEBUG) && !defined(ANDROID)
|
||||
if (!(Preferences::GetBool("security.allow_eval_with_system_principal"))) {
|
||||
MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(subjectPrincipal),
|
||||
"do not use eval with system privileges");
|
||||
}
|
||||
AssertEvalNotUsingSystemPrincipal(subjectPrincipal, cx);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
--highlighter-font-size: 11px;
|
||||
--highlighter-infobar-color: hsl(210, 30%, 85%);
|
||||
--highlighter-marker-color: #000;
|
||||
|
||||
--grey-40: #b1b1b3;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -642,6 +644,33 @@
|
|||
|
||||
/* Accessible highlighter */
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar {
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-text {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"role name"
|
||||
"audit audit";
|
||||
grid-template-columns: min-content 1fr;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-role {
|
||||
grid-area: role;
|
||||
color: #9CDCFE;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-name {
|
||||
grid-area: name;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-audit {
|
||||
grid-area: audit;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-bounds {
|
||||
opacity: 0.6;
|
||||
fill: #6a5acd;
|
||||
|
@ -650,7 +679,17 @@
|
|||
:-moz-native-anonymous .accessible-infobar-name,
|
||||
:-moz-native-anonymous .accessible-infobar-audit {
|
||||
color: var(--highlighter-infobar-color);
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-audit .accessible-contrast-ratio:not(:empty):before {
|
||||
content: "";
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
display: inline-flex;
|
||||
background-color: var(--accessibility-highlighter-contrast-ratio-color);
|
||||
box-shadow: 0 0 0 1px var(--grey-40), 4px 3px var(--accessibility-highlighter-contrast-ratio-bg), 4px 3px 0 1px var(--grey-40);
|
||||
margin-inline-start: 3px;
|
||||
margin-inline-end: 9px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-audit .accessible-contrast-ratio:not(:empty):after {
|
||||
|
@ -676,25 +715,17 @@
|
|||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-audit .accessible-contrast-ratio-label,
|
||||
:-moz-native-anonymous .accessible-infobar-audit #accessible-contrast-ratio-max:not(:empty):before {
|
||||
:-moz-native-anonymous .accessible-infobar-audit .accessible-contrast-ratio-separator:before {
|
||||
margin-inline-end: 3px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-audit #accessible-contrast-ratio-max {
|
||||
:-moz-native-anonymous .accessible-infobar-audit .accessible-contrast-ratio-separator:before {
|
||||
content: "-";
|
||||
margin-inline-start: 3px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-audit #accessible-contrast-ratio-max:not(:empty):before {
|
||||
content: "-";
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-name:not(:empty),
|
||||
:-moz-native-anonymous .accessible-infobar-audit:not(:empty) {
|
||||
:-moz-native-anonymous .accessible-infobar-name:not(:empty) {
|
||||
border-inline-start: 1px solid #5a6169;
|
||||
margin-inline-start: 6px;
|
||||
padding-inline-start: 6px;
|
||||
}
|
||||
|
||||
:-moz-native-anonymous .accessible-infobar-role {
|
||||
color: #9CDCFE;
|
||||
}
|
||||
|
|
|
@ -479,14 +479,13 @@ class ContrastRatio extends AuditReport {
|
|||
"id": "contrast-ratio-label",
|
||||
},
|
||||
prefix: this.prefix,
|
||||
text: L10N.getStr("accessibility.contrast.ratio.label"),
|
||||
});
|
||||
|
||||
createNode(this.win, {
|
||||
nodeType: "span",
|
||||
parent: root,
|
||||
attributes: {
|
||||
"class": "contrast-ratio",
|
||||
"class": "contrast-ratio-error",
|
||||
"id": "contrast-ratio-error",
|
||||
},
|
||||
prefix: this.prefix,
|
||||
|
@ -503,6 +502,16 @@ class ContrastRatio extends AuditReport {
|
|||
prefix: this.prefix,
|
||||
});
|
||||
|
||||
createNode(this.win, {
|
||||
nodeType: "span",
|
||||
parent: root,
|
||||
attributes: {
|
||||
"class": "contrast-ratio-separator",
|
||||
"id": "contrast-ratio-separator",
|
||||
},
|
||||
prefix: this.prefix,
|
||||
});
|
||||
|
||||
createNode(this.win, {
|
||||
nodeType: "span",
|
||||
parent: root,
|
||||
|
@ -514,11 +523,14 @@ class ContrastRatio extends AuditReport {
|
|||
});
|
||||
}
|
||||
|
||||
_fillAndStyleContrastValue(el, value, isLargeText, stringName) {
|
||||
_fillAndStyleContrastValue(el, { value, isLargeText, color, backgroundColor }) {
|
||||
value = value.toFixed(2);
|
||||
const style = getContrastRatioScoreStyle(value, isLargeText);
|
||||
this.setTextContent(el, stringName ? L10N.getFormatStr(stringName, value) : value);
|
||||
this.setTextContent(el, value);
|
||||
el.classList.add(style);
|
||||
el.setAttribute("style",
|
||||
`--accessibility-highlighter-contrast-ratio-color: rgba(${color});` +
|
||||
`--accessibility-highlighter-contrast-ratio-bg: rgba(${backgroundColor});`);
|
||||
el.removeAttribute("hidden");
|
||||
}
|
||||
|
||||
|
@ -532,7 +544,7 @@ class ContrastRatio extends AuditReport {
|
|||
*/
|
||||
update({ contrastRatio }) {
|
||||
const els = {};
|
||||
for (const key of ["label", "min", "max", "error"]) {
|
||||
for (const key of ["label", "min", "max", "error", "separator"]) {
|
||||
const el = els[key] = this.getElement(`contrast-ratio-${key}`);
|
||||
if (["min", "max"].includes(key)) {
|
||||
["fail", "AA", "AAA"].forEach(className => el.classList.remove(className));
|
||||
|
@ -540,6 +552,7 @@ class ContrastRatio extends AuditReport {
|
|||
}
|
||||
|
||||
el.setAttribute("hidden", true);
|
||||
el.removeAttribute("style");
|
||||
}
|
||||
|
||||
if (!contrastRatio) {
|
||||
|
@ -547,6 +560,9 @@ class ContrastRatio extends AuditReport {
|
|||
}
|
||||
|
||||
const { isLargeText, error } = contrastRatio;
|
||||
this.setTextContent(els.label,
|
||||
L10N.getFormatStr("accessibility.contrast.ratio.label2",
|
||||
isLargeText ? L10N.getStr("accessibility.contrast.ratio.large") : ""));
|
||||
els.label.removeAttribute("hidden");
|
||||
if (error) {
|
||||
els.error.removeAttribute("hidden");
|
||||
|
@ -554,12 +570,18 @@ class ContrastRatio extends AuditReport {
|
|||
}
|
||||
|
||||
if (contrastRatio.value) {
|
||||
this._fillAndStyleContrastValue(els.min, contrastRatio.value, isLargeText);
|
||||
const { value, color, backgroundColor } = contrastRatio;
|
||||
this._fillAndStyleContrastValue(els.min,
|
||||
{ value, isLargeText, color, backgroundColor });
|
||||
return true;
|
||||
}
|
||||
|
||||
this._fillAndStyleContrastValue(els.min, contrastRatio.min, isLargeText);
|
||||
this._fillAndStyleContrastValue(els.max, contrastRatio.max, isLargeText);
|
||||
const { min, max, color, backgroundColorMin, backgroundColorMax } = contrastRatio;
|
||||
this._fillAndStyleContrastValue(els.min,
|
||||
{ value: min, isLargeText, color, backgroundColor: backgroundColorMin });
|
||||
els.separator.removeAttribute("hidden");
|
||||
this._fillAndStyleContrastValue(els.max,
|
||||
{ value: max, isLargeText, color, backgroundColor: backgroundColorMax });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ const ACCESSIBLE_BOUNDS_SHEET = "data:text/css;charset=utf-8," + encodeURICompon
|
|||
--highlighter-bubble-background-color: hsl(214, 13%, 24%);
|
||||
--highlighter-bubble-border-color: rgba(255, 255, 255, 0.2);
|
||||
--highlighter-bubble-arrow-size: 8px;
|
||||
|
||||
--grey-40: #b1b1b3;
|
||||
}
|
||||
|
||||
.accessible-bounds {
|
||||
|
@ -39,7 +41,6 @@ const ACCESSIBLE_BOUNDS_SHEET = "data:text/css;charset=utf-8," + encodeURICompon
|
|||
position: relative;
|
||||
left: -50%;
|
||||
background-color: var(--highlighter-bubble-background-color);
|
||||
min-width: 75px;
|
||||
border: 1px solid var(--highlighter-bubble-border-color);
|
||||
border-radius: 3px;
|
||||
padding: 5px;
|
||||
|
@ -67,16 +68,47 @@ const ACCESSIBLE_BOUNDS_SHEET = "data:text/css;charset=utf-8," + encodeURICompon
|
|||
}
|
||||
|
||||
.accessible-infobar-text {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"role name"
|
||||
"audit audit";
|
||||
grid-template-columns: min-content 1fr;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.accessible-infobar-role {
|
||||
color: #9CDCFE;
|
||||
grid-area: role;
|
||||
}
|
||||
|
||||
.accessible-infobar-name {
|
||||
grid-area: name;
|
||||
}
|
||||
|
||||
.accessible-infobar-audit {
|
||||
grid-area: audit;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.accessible-infobar-name,
|
||||
.accessible-infobar-audit {
|
||||
color: hsl(210, 30%, 85%);
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.accessible-infobar-audit .accessible-contrast-ratio:not(:empty):before {
|
||||
content: "";
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
display: inline-flex;
|
||||
background-color: var(--accessibility-highlighter-contrast-ratio-color);
|
||||
box-shadow: 0 0 0 1px var(--grey-40),
|
||||
4px 3px var(--accessibility-highlighter-contrast-ratio-bg),
|
||||
4px 3px 0 1px var(--grey-40);
|
||||
margin-inline-start: 3px;
|
||||
margin-inline-end: 9px;
|
||||
}
|
||||
|
||||
.accessible-infobar-audit .accessible-contrast-ratio:not(:empty):after {
|
||||
|
@ -102,27 +134,19 @@ const ACCESSIBLE_BOUNDS_SHEET = "data:text/css;charset=utf-8," + encodeURICompon
|
|||
}
|
||||
|
||||
.accessible-infobar-audit .accessible-contrast-ratio-label,
|
||||
.accessible-infobar-audit #accessible-contrast-ratio-max:not(:empty):before {
|
||||
.accessible-infobar-audit .accessible-contrast-ratio-separator:before {
|
||||
margin-inline-end: 3px;
|
||||
}
|
||||
|
||||
.accessible-infobar-audit #accessible-contrast-ratio-max {
|
||||
.accessible-infobar-audit .accessible-contrast-ratio-separator:before {
|
||||
content: "-";
|
||||
margin-inline-start: 3px;
|
||||
}
|
||||
|
||||
.accessible-infobar-audit #accessible-contrast-ratio-max:not(:empty):before {
|
||||
content: "-";
|
||||
}
|
||||
|
||||
.accessible-infobar-name:not(:empty),
|
||||
.accessible-infobar-audit:not(:empty) {
|
||||
.accessible-infobar-name:not(:empty) {
|
||||
border-inline-start: 1px solid #5a6169;
|
||||
margin-inline-start: 6px;
|
||||
padding-inline-start: 6px;
|
||||
}
|
||||
|
||||
.accessible-infobar-role {
|
||||
color: #9CDCFE;
|
||||
}`);
|
||||
|
||||
/**
|
||||
|
|
|
@ -563,8 +563,8 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
|
|||
* A promise that resolves to a JSON object representing the
|
||||
* response.
|
||||
*/
|
||||
setBreakpoint: function(line, column, condition, noSliding) {
|
||||
if (this.threadActor.state !== "paused") {
|
||||
setBreakpoint: function(line, column, condition, noSliding, inNestedLoop) {
|
||||
if (!inNestedLoop && this.threadActor.state !== "paused") {
|
||||
const errorObject = {
|
||||
error: "wrongState",
|
||||
message: "Cannot set breakpoint while debuggee is running.",
|
||||
|
|
|
@ -80,6 +80,10 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
// server.
|
||||
this._hiddenBreakpoints = new Map();
|
||||
|
||||
// A Set of URLs string to watch for when new sources are found by
|
||||
// the debugger instance.
|
||||
this._onLoadBreakpointURLs = new Set();
|
||||
|
||||
this.global = global;
|
||||
|
||||
this._allEventsListener = this._allEventsListener.bind(this);
|
||||
|
@ -96,9 +100,12 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
this._onOpeningRequest = this._onOpeningRequest.bind(this);
|
||||
EventEmitter.on(this._parent, "window-ready", this._onWindowReady);
|
||||
|
||||
if (Services.obs) {
|
||||
// Set a wrappedJSObject property so |this| can be sent via the observer svc
|
||||
// for the xpcshell harness.
|
||||
this.wrappedJSObject = this;
|
||||
Services.obs.notifyObservers(this, "devtools-thread-instantiated");
|
||||
}
|
||||
},
|
||||
|
||||
// Used by the ObjectActor to keep track of the depth of grip() calls.
|
||||
|
@ -306,6 +313,17 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Tell the thread to automatically add a breakpoint on the first line of
|
||||
* a given file, when it is first loaded.
|
||||
*
|
||||
* This is currently only used by the xpcshell test harness, and unless
|
||||
* we decide to expand the scope of this feature, we should keep it that way.
|
||||
*/
|
||||
setBreakpointOnLoad(urls) {
|
||||
this._onLoadBreakpointURLs = new Set(urls);
|
||||
},
|
||||
|
||||
_findXHRBreakpointIndex(p, m) {
|
||||
return this._xhrBreakpoints.findIndex(
|
||||
({ path, method }) => path === p && method === m);
|
||||
|
@ -2017,6 +2035,12 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
|
|||
}
|
||||
}
|
||||
|
||||
if (this._onLoadBreakpointURLs.has(source.url)) {
|
||||
this.unsafeSynchronize(
|
||||
sourceActor.setBreakpoint(1, undefined, undefined, undefined, true)
|
||||
);
|
||||
}
|
||||
|
||||
this._debuggerSourcesSeen.add(source);
|
||||
return true;
|
||||
},
|
||||
|
|
|
@ -196,18 +196,27 @@ function getContrastRatioFor(node, options = {}) {
|
|||
if (rgba.value) {
|
||||
return {
|
||||
value: colorUtils.calculateContrastRatio(rgba.value, color),
|
||||
color,
|
||||
backgroundColor: rgba.value,
|
||||
isLargeText,
|
||||
};
|
||||
}
|
||||
|
||||
// calculateContrastRatio modifies the array, since we need to use color array twice,
|
||||
// pass its copy to the method.
|
||||
const min = colorUtils.calculateContrastRatio(rgba.min, Array.from(color));
|
||||
const max = colorUtils.calculateContrastRatio(rgba.max, Array.from(color));
|
||||
let min = colorUtils.calculateContrastRatio(rgba.min, color);
|
||||
let max = colorUtils.calculateContrastRatio(rgba.max, color);
|
||||
|
||||
// Flip minimum and maximum contrast ratios if necessary.
|
||||
if (min > max) {
|
||||
[min, max] = [max, min];
|
||||
[rgba.min, rgba.max] = [rgba.max, rgba.min];
|
||||
}
|
||||
|
||||
return {
|
||||
min: min < max ? min : max,
|
||||
max: min < max ? max : min,
|
||||
min,
|
||||
max,
|
||||
color,
|
||||
backgroundColorMin: rgba.min,
|
||||
backgroundColorMax: rgba.max,
|
||||
isLargeText,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1197,6 +1197,10 @@ function blendColors(foregroundColor, backgroundColor = [ 255, 255, 255, 1 ]) {
|
|||
* @return {Number} The calculated luminance.
|
||||
*/
|
||||
function calculateContrastRatio(backgroundColor, textColor) {
|
||||
// Do not modify given colors.
|
||||
backgroundColor = Array.from(backgroundColor);
|
||||
textColor = Array.from(textColor);
|
||||
|
||||
backgroundColor = blendColors(backgroundColor);
|
||||
textColor = blendColors(textColor, backgroundColor);
|
||||
|
||||
|
|
|
@ -11,6 +11,13 @@ accessibility.contrast.ratio=Contrast: %S
|
|||
# contrast ratio, used when the tool is unable to calculate the contrast ratio value.
|
||||
accessibility.contrast.ratio.error=Unable to calculate
|
||||
|
||||
# LOCALIZATION NOTE (accessibility.contrast.ratio.label): A title text for the color
|
||||
# contrast ratio description, used together with the actual values.
|
||||
accessibility.contrast.ratio.label=Contrast:
|
||||
# LOCALIZATION NOTE (accessibility.contrast.ratio.label2): A title text for the color
|
||||
# contrast ratio description, used together with the actual values. %S in the
|
||||
# content will optionally be replaced by the text that indicates that large text is being
|
||||
# analyzed (see accessibility.contrast.ratio.large).
|
||||
accessibility.contrast.ratio.label2=Contrast%S:
|
||||
|
||||
# LOCALIZATION NOTE (accessibility.contrast.ratio.large): A title text for the color
|
||||
# contrast ratio that specifies that the color contrast criteria used is if for large
|
||||
# text.
|
||||
accessibility.contrast.ratio.large=\u0020(large text)
|
||||
|
|
|
@ -23,7 +23,7 @@ default-features = false
|
|||
features = ["capture", "serialize_program"]
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
dwrote = "0.6.2"
|
||||
dwrote = "0.6.3"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.6"
|
||||
|
|
|
@ -1 +1 @@
|
|||
22f3f356ea1a9fe2760cd4a609cba78614e428c4
|
||||
d2c673ada607f29846c3d1ac8ca7d2b272ba1b2d
|
||||
|
|
|
@ -362,7 +362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "dwrote"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1541,7 +1541,7 @@ dependencies = [
|
|||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1593,7 +1593,7 @@ dependencies = [
|
|||
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1672,7 +1672,7 @@ dependencies = [
|
|||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1800,7 +1800,7 @@ dependencies = [
|
|||
"checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a"
|
||||
"checksum downcast-rs 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "18df8ce4470c189d18aa926022da57544f31e154631eb4cfe796aea97051fe6c"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum dwrote 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b46afd0d0bbbea88fc083ea293e40865e26a75ec9d38cf5d05a23ac3e2ffe02"
|
||||
"checksum dwrote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f0beca78470f26189a662e72afe7a54c625b4feb06b2d36c207ac15319bd57c5"
|
||||
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
|
||||
"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
|
||||
"checksum euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dbbf962bb6f877239a34491f2e0a12c6b824f389bc789eb90f1d70d4780b0727"
|
||||
|
|
|
@ -74,7 +74,7 @@ rand = "0.4"
|
|||
freetype = { version = "0.4", default-features = false }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
dwrote = "0.6.2"
|
||||
dwrote = "0.6.3"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.6"
|
||||
|
|
|
@ -156,17 +156,6 @@ pub struct DisplayListFlattener<'a> {
|
|||
/// The root picture index for this flattener. This is the picture
|
||||
/// to start the culling phase from.
|
||||
pub root_pic_index: PictureIndex,
|
||||
|
||||
/// TODO(gw): This is a complete hack that relies on knowledge of
|
||||
/// what the Gecko display list looks like. It's used
|
||||
/// for now to work out which scroll root to use to
|
||||
/// create the picture cache for the content. It's only
|
||||
/// ever used if picture caching is enabled in the
|
||||
/// RendererOptions struct. We will need to work out
|
||||
/// a better API to avoid this, before we enable it
|
||||
/// for all users. Another alternative is that this
|
||||
/// will disappear itself when document splitting is used.
|
||||
picture_cache_scroll_root: Option<SpatialNodeIndex>,
|
||||
}
|
||||
|
||||
impl<'a> DisplayListFlattener<'a> {
|
||||
|
@ -204,7 +193,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
clip_store: ClipStore::new(),
|
||||
resources,
|
||||
root_pic_index: PictureIndex(0),
|
||||
picture_cache_scroll_root: None,
|
||||
};
|
||||
|
||||
flattener.push_root(
|
||||
|
@ -220,12 +208,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
debug_assert!(flattener.sc_stack.is_empty());
|
||||
|
||||
// If picture caching is enabled, splice up the root
|
||||
// stacking context to enable correct surface caching.
|
||||
flattener.setup_picture_caching(
|
||||
root_pipeline_id,
|
||||
);
|
||||
|
||||
new_scene.root_pipeline_id = Some(root_pipeline_id);
|
||||
new_scene.pipeline_epochs = scene.pipeline_epochs.clone();
|
||||
new_scene.pipelines = scene.pipelines.clone();
|
||||
|
@ -245,7 +227,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
/// content frame is that should get surface caching.
|
||||
fn setup_picture_caching(
|
||||
&mut self,
|
||||
root_pipeline_id: PipelineId,
|
||||
primitives: &mut Vec<PrimitiveInstance>,
|
||||
) {
|
||||
if !self.config.enable_picture_caching {
|
||||
return;
|
||||
|
@ -276,25 +258,36 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// most of the content is embedded in its own picture.
|
||||
//
|
||||
|
||||
// See if we found a scroll root for the cached surface root.
|
||||
if let Some(picture_cache_scroll_root) = self.picture_cache_scroll_root {
|
||||
// Get the list of existing primitives in the main stacking context.
|
||||
let mut old_prim_list = mem::replace(
|
||||
&mut self.prim_store.pictures[self.root_pic_index.0].prim_list,
|
||||
PrimitiveList::empty(),
|
||||
);
|
||||
|
||||
// Find the first primitive which has the desired scroll root.
|
||||
let first_index = old_prim_list.prim_instances.iter().position(|instance| {
|
||||
let mut main_scroll_root = None;
|
||||
|
||||
let first_index = primitives.iter().position(|instance| {
|
||||
let scroll_root = self.find_scroll_root(
|
||||
instance.spatial_node_index,
|
||||
);
|
||||
|
||||
scroll_root == picture_cache_scroll_root
|
||||
}).unwrap_or(old_prim_list.prim_instances.len());
|
||||
if scroll_root == ROOT_SPATIAL_NODE_INDEX {
|
||||
false
|
||||
} else {
|
||||
debug_assert!(main_scroll_root.is_none());
|
||||
main_scroll_root = Some(scroll_root);
|
||||
true
|
||||
}
|
||||
}).unwrap_or(primitives.len());
|
||||
|
||||
let main_scroll_root = match main_scroll_root {
|
||||
Some(main_scroll_root) => main_scroll_root,
|
||||
None => ROOT_SPATIAL_NODE_INDEX,
|
||||
};
|
||||
|
||||
// Get the list of existing primitives in the main stacking context.
|
||||
let mut old_prim_list = mem::replace(
|
||||
primitives,
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
// Split off the preceding primtives.
|
||||
let mut remaining_prims = old_prim_list.prim_instances.split_off(first_index);
|
||||
let mut remaining_prims = old_prim_list.split_off(first_index);
|
||||
|
||||
// Find the first primitive in reverse order that is not the root scroll node.
|
||||
let last_index = remaining_prims.iter().rposition(|instance| {
|
||||
|
@ -305,7 +298,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
scroll_root != ROOT_SPATIAL_NODE_INDEX
|
||||
}).unwrap_or(remaining_prims.len() - 1);
|
||||
|
||||
let preceding_prims = old_prim_list.prim_instances;
|
||||
let preceding_prims = old_prim_list;
|
||||
let trailing_prims = remaining_prims.split_off(last_index + 1);
|
||||
|
||||
let prim_list = PrimitiveList::new(
|
||||
|
@ -336,12 +329,12 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
let pic_index = self.prim_store.pictures.alloc().init(PicturePrimitive::new_image(
|
||||
Some(PictureCompositeMode::TileCache { clear_color: ColorF::new(1.0, 1.0, 1.0, 1.0) }),
|
||||
Picture3DContext::Out,
|
||||
root_pipeline_id,
|
||||
self.scene.root_pipeline_id.unwrap(),
|
||||
None,
|
||||
true,
|
||||
RasterSpace::Screen,
|
||||
prim_list,
|
||||
picture_cache_scroll_root,
|
||||
main_scroll_root,
|
||||
LayoutRect::max_rect(),
|
||||
&self.clip_store,
|
||||
));
|
||||
|
@ -353,21 +346,14 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pic_index: PictureIndex(pic_index)
|
||||
},
|
||||
ClipChainId::NONE,
|
||||
picture_cache_scroll_root,
|
||||
main_scroll_root,
|
||||
);
|
||||
|
||||
// This contains the tile caching picture, with preceding and
|
||||
// trailing primitives outside the main scroll root.
|
||||
let mut new_prim_list = preceding_prims;
|
||||
new_prim_list.push(instance);
|
||||
new_prim_list.extend(trailing_prims);
|
||||
|
||||
// Finally, store the sliced primitive list in the root picture.
|
||||
self.prim_store.pictures[self.root_pic_index.0].prim_list = PrimitiveList::new(
|
||||
new_prim_list,
|
||||
&self.resources,
|
||||
);
|
||||
}
|
||||
primitives.extend(preceding_prims);
|
||||
primitives.push(instance);
|
||||
primitives.extend(trailing_prims);
|
||||
}
|
||||
|
||||
/// Find the spatial node that is the scroll root for a given
|
||||
|
@ -556,7 +542,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
self.add_clip_node(info.clip_id, clip_and_scroll_ids, clip_region);
|
||||
|
||||
let node_index = self.add_scroll_frame(
|
||||
self.add_scroll_frame(
|
||||
info.scroll_frame_id,
|
||||
info.clip_id,
|
||||
info.external_id,
|
||||
|
@ -566,14 +552,6 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
info.scroll_sensitivity,
|
||||
ScrollFrameKind::Explicit,
|
||||
);
|
||||
|
||||
// TODO(gw): See description of picture_cache_scroll_root field for information
|
||||
// about this temporary hack. What it's trying to identify is the first
|
||||
// scroll root within the first iframe that we encounter in the display
|
||||
// list.
|
||||
if self.picture_cache_scroll_root.is_none() && pipeline_id != self.scene.root_pipeline_id.unwrap() {
|
||||
self.picture_cache_scroll_root = Some(node_index);
|
||||
}
|
||||
}
|
||||
|
||||
fn flatten_reference_frame(
|
||||
|
@ -1228,6 +1206,9 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
let create_tile_cache = is_pipeline_root &&
|
||||
self.sc_stack.len() == 2;
|
||||
|
||||
// Get the transform-style of the parent stacking context,
|
||||
// which determines if we *might* need to draw this on
|
||||
// an intermediate surface for plane splitting purposes.
|
||||
|
@ -1317,11 +1298,12 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
should_isolate,
|
||||
transform_style,
|
||||
context_3d,
|
||||
create_tile_cache,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn pop_stacking_context(&mut self) {
|
||||
let stacking_context = self.sc_stack.pop().unwrap();
|
||||
let mut stacking_context = self.sc_stack.pop().unwrap();
|
||||
|
||||
// If we encounter a stacking context that is effectively a no-op, then instead
|
||||
// of creating a picture, just append the primitive list to the parent stacking
|
||||
|
@ -1342,6 +1324,12 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
if stacking_context.create_tile_cache {
|
||||
self.setup_picture_caching(
|
||||
&mut stacking_context.primitives,
|
||||
);
|
||||
}
|
||||
|
||||
// An arbitrary large clip rect. For now, we don't
|
||||
// specify a clip specific to the stacking context.
|
||||
// However, now that they are represented as Picture
|
||||
|
@ -2533,6 +2521,9 @@ struct FlattenedStackingContext {
|
|||
|
||||
/// Defines the relationship to a preserve-3D hiearachy.
|
||||
context_3d: Picture3DContext<PrimitiveInstance>,
|
||||
|
||||
/// If true, create a tile cache for this stacking context.
|
||||
create_tile_cache: bool,
|
||||
}
|
||||
|
||||
impl FlattenedStackingContext {
|
||||
|
@ -2582,6 +2573,11 @@ impl FlattenedStackingContext {
|
|||
return false;
|
||||
}
|
||||
|
||||
// If the pipelines are different, we care for purposes of selecting tile caches
|
||||
if self.pipeline_id != parent.pipeline_id {
|
||||
return false;
|
||||
}
|
||||
|
||||
// It is redundant!
|
||||
true
|
||||
}
|
||||
|
|
|
@ -160,7 +160,9 @@ impl<'a> From<&'a LayoutToWorldTransform> for FontTransform {
|
|||
}
|
||||
}
|
||||
|
||||
pub const FONT_SIZE_LIMIT: f64 = 1024.0;
|
||||
// Some platforms (i.e. Windows) may have trouble rasterizing glyphs above this size.
|
||||
// Ensure glyph sizes are reasonably limited to avoid that scenario.
|
||||
pub const FONT_SIZE_LIMIT: f64 = 512.0;
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
|
|
@ -20,7 +20,7 @@ use gpu_types::{TransformPalette, TransformPaletteId, UvRectKind};
|
|||
use internal_types::FastHashSet;
|
||||
use plane_split::{Clipper, Polygon, Splitter};
|
||||
use prim_store::{PictureIndex, PrimitiveInstance, SpaceMapper, VisibleFace, PrimitiveInstanceKind};
|
||||
use prim_store::{get_raster_rects, CoordinateSpaceMapping};
|
||||
use prim_store::{get_raster_rects, CoordinateSpaceMapping, PointKey};
|
||||
use prim_store::{OpacityBindingStorage, PrimitiveTemplateKind, ImageInstanceStorage, OpacityBindingIndex, SizeKey};
|
||||
use render_backend::FrameResources;
|
||||
use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle, TileBlit};
|
||||
|
@ -78,7 +78,8 @@ pub type TileRect = TypedRect<i32, TileCoordinate>;
|
|||
/// The size in device pixels of a cached tile. The currently chosen
|
||||
/// size is arbitrary. We should do some profiling to find the best
|
||||
/// size for real world pages.
|
||||
pub const TILE_SIZE_DP: i32 = 512;
|
||||
pub const TILE_SIZE_WIDTH: i32 = 1024;
|
||||
pub const TILE_SIZE_HEIGHT: i32 = 256;
|
||||
|
||||
/// Information about the state of a transform dependency.
|
||||
#[derive(Debug)]
|
||||
|
@ -247,13 +248,27 @@ impl Tile {
|
|||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct TileTransformIndex(u32);
|
||||
|
||||
/// Defines a key that uniquely identifies a primitive instance.
|
||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
||||
pub struct PrimitiveDescriptor {
|
||||
/// Uniquely identifies the content of the primitive template.
|
||||
prim_uid: ItemUid,
|
||||
/// The origin in local space of this primitive.
|
||||
origin: PointKey,
|
||||
/// The first clip in the clip_uids array of clips that affect this tile.
|
||||
first_clip: u16,
|
||||
/// The number of clips that affect this primitive instance.
|
||||
clip_count: u16,
|
||||
}
|
||||
|
||||
/// Uniquely describes the content of this tile, in a way that can be
|
||||
/// (reasonably) efficiently hashed and compared.
|
||||
#[derive(Debug, Eq, PartialEq, Hash)]
|
||||
pub struct TileDescriptor {
|
||||
/// List of primitive unique identifiers. The uid is guaranteed
|
||||
/// to uniquely describe the content of the primitive.
|
||||
pub prim_uids: Vec<ItemUid>,
|
||||
/// List of primitive instance unique identifiers. The uid is guaranteed
|
||||
/// to uniquely describe the content of the primitive template, while
|
||||
/// the other parameters describe the clip chain and instance params.
|
||||
pub prims: Vec<PrimitiveDescriptor>,
|
||||
|
||||
/// List of clip node unique identifiers. The uid is guaranteed
|
||||
/// to uniquely describe the content of the clip node.
|
||||
|
@ -288,7 +303,7 @@ impl TileDescriptor {
|
|||
raster_transform: TransformKey,
|
||||
) -> Self {
|
||||
TileDescriptor {
|
||||
prim_uids: Vec::new(),
|
||||
prims: Vec::new(),
|
||||
clip_uids: Vec::new(),
|
||||
transform_ids: Vec::new(),
|
||||
opacity_bindings: Vec::new(),
|
||||
|
@ -302,7 +317,7 @@ impl TileDescriptor {
|
|||
/// Clear the dependency information for a tile, when the dependencies
|
||||
/// are being rebuilt.
|
||||
fn clear(&mut self) {
|
||||
self.prim_uids.clear();
|
||||
self.prims.clear();
|
||||
self.clip_uids.clear();
|
||||
self.transform_ids.clear();
|
||||
self.transforms.clear();
|
||||
|
@ -416,8 +431,8 @@ impl TileCache {
|
|||
let world_tile_rect = WorldRect::from_floats(
|
||||
0.0,
|
||||
0.0,
|
||||
TILE_SIZE_DP as f32 / frame_context.device_pixel_scale.0,
|
||||
TILE_SIZE_DP as f32 / frame_context.device_pixel_scale.0,
|
||||
TILE_SIZE_WIDTH as f32 / frame_context.device_pixel_scale.0,
|
||||
TILE_SIZE_HEIGHT as f32 / frame_context.device_pixel_scale.0,
|
||||
);
|
||||
let local_tile_rect = world_mapper
|
||||
.unmap(&world_tile_rect)
|
||||
|
@ -556,15 +571,32 @@ impl TileCache {
|
|||
|
||||
// Get the tile coordinates in the picture space.
|
||||
let pic_rect = TypedRect::from_untyped(&pic_rect.to_untyped());
|
||||
let local_pic_rect = pic_rect.translate(&-self.local_origin.to_vector());
|
||||
|
||||
let x0 = (local_pic_rect.origin.x / self.local_tile_size.width).floor() as i32;
|
||||
let y0 = (local_pic_rect.origin.y / self.local_tile_size.height).floor() as i32;
|
||||
let x1 = ((local_pic_rect.origin.x + local_pic_rect.size.width) / self.local_tile_size.width).ceil() as i32;
|
||||
let y1 = ((local_pic_rect.origin.y + local_pic_rect.size.height) / self.local_tile_size.height).ceil() as i32;
|
||||
let (p0, p1) = self.get_tile_coords_for_rect(&pic_rect);
|
||||
|
||||
// Update the tile array allocation if needed.
|
||||
self.reconfigure_tiles_if_required(x0, y0, x1, y1);
|
||||
self.reconfigure_tiles_if_required(p0.x, p0.y, p1.x, p1.y);
|
||||
}
|
||||
|
||||
/// Get the tile coordinates for a given rectangle.
|
||||
fn get_tile_coords_for_rect(
|
||||
&self,
|
||||
rect: &LayoutRect,
|
||||
) -> (TileOffset, TileOffset) {
|
||||
// Translate the rectangle into the virtual tile space
|
||||
let origin = rect.origin - self.local_origin;
|
||||
|
||||
// Get the tile coordinates in the picture space.
|
||||
let p0 = TileOffset::new(
|
||||
(origin.x / self.local_tile_size.width).floor() as i32,
|
||||
(origin.y / self.local_tile_size.height).floor() as i32,
|
||||
);
|
||||
|
||||
let p1 = TileOffset::new(
|
||||
((origin.x + rect.size.width) / self.local_tile_size.width).ceil() as i32,
|
||||
((origin.y + rect.size.height) / self.local_tile_size.height).ceil() as i32,
|
||||
);
|
||||
|
||||
(p0, p1)
|
||||
}
|
||||
|
||||
/// Resize the 2D tiles array if needed in order to fit dependencies
|
||||
|
@ -692,14 +724,8 @@ impl TileCache {
|
|||
return;
|
||||
}
|
||||
|
||||
// Translate the rectangle into the virtual tile space
|
||||
let origin = rect.origin - self.local_origin;
|
||||
|
||||
// Get the tile coordinates in the picture space.
|
||||
let x0 = (origin.x / self.local_tile_size.width).floor() as i32;
|
||||
let y0 = (origin.y / self.local_tile_size.height).floor() as i32;
|
||||
let x1 = ((origin.x + rect.size.width) / self.local_tile_size.width).ceil() as i32;
|
||||
let y1 = ((origin.y + rect.size.height) / self.local_tile_size.height).ceil() as i32;
|
||||
let (p0, p1) = self.get_tile_coords_for_rect(&rect);
|
||||
|
||||
// Build the list of resources that this primitive has dependencies on.
|
||||
let mut opacity_bindings: SmallVec<[PropertyBindingId; 4]> = SmallVec::new();
|
||||
|
@ -795,8 +821,8 @@ impl TileCache {
|
|||
|
||||
// Normalize the tile coordinates before adding to tile dependencies.
|
||||
// For each affected tile, mark any of the primitive dependencies.
|
||||
for y in y0 - self.tile_rect.origin.y .. y1 - self.tile_rect.origin.y {
|
||||
for x in x0 - self.tile_rect.origin.x .. x1 - self.tile_rect.origin.x {
|
||||
for y in p0.y - self.tile_rect.origin.y .. p1.y - self.tile_rect.origin.y {
|
||||
for x in p0.x - self.tile_rect.origin.x .. p1.x - self.tile_rect.origin.x {
|
||||
let index = (y * self.tile_rect.size.width + x) as usize;
|
||||
let tile = &mut self.tiles[index];
|
||||
|
||||
|
@ -835,7 +861,12 @@ impl TileCache {
|
|||
}
|
||||
|
||||
// Update the tile descriptor, used for tile comparison during scene swaps.
|
||||
tile.descriptor.prim_uids.push(prim_instance.uid());
|
||||
tile.descriptor.prims.push(PrimitiveDescriptor {
|
||||
prim_uid: prim_instance.uid(),
|
||||
origin: prim_instance.prim_origin.into(),
|
||||
first_clip: tile.descriptor.clip_uids.len() as u16,
|
||||
clip_count: clip_chain_uids.len() as u16,
|
||||
});
|
||||
tile.descriptor.clip_uids.extend_from_slice(&clip_chain_uids);
|
||||
}
|
||||
}
|
||||
|
@ -2184,8 +2215,8 @@ impl PicturePrimitive {
|
|||
// we will need to correctly select an opacity
|
||||
// here and a blend mode in batch.rs.
|
||||
let descriptor = ImageDescriptor::new(
|
||||
TILE_SIZE_DP,
|
||||
TILE_SIZE_DP,
|
||||
TILE_SIZE_WIDTH,
|
||||
TILE_SIZE_HEIGHT,
|
||||
ImageFormat::BGRA8,
|
||||
true,
|
||||
false,
|
||||
|
@ -2235,8 +2266,8 @@ impl PicturePrimitive {
|
|||
// Set up the blit command now that we know where the dest
|
||||
// rect is in the texture cache.
|
||||
let offset = DeviceIntPoint::new(
|
||||
(x - dirty_region.tile_offset.x) * TILE_SIZE_DP,
|
||||
(y - dirty_region.tile_offset.y) * TILE_SIZE_DP,
|
||||
(x - dirty_region.tile_offset.x) * TILE_SIZE_WIDTH,
|
||||
(y - dirty_region.tile_offset.y) * TILE_SIZE_HEIGHT,
|
||||
);
|
||||
|
||||
blits.push(TileBlit {
|
||||
|
|
|
@ -253,7 +253,7 @@ impl FontContext {
|
|||
size: f32,
|
||||
transform: Option<dwrote::DWRITE_MATRIX>,
|
||||
bitmaps: bool,
|
||||
) -> dwrote::GlyphRunAnalysis {
|
||||
) -> (dwrote::GlyphRunAnalysis, dwrote::DWRITE_TEXTURE_TYPE, dwrote::RECT) {
|
||||
let face = self.get_font_face(font);
|
||||
let glyph = key.index() as u16;
|
||||
let advance = 0.0f32;
|
||||
|
@ -282,7 +282,7 @@ impl FontContext {
|
|||
bitmaps,
|
||||
);
|
||||
|
||||
dwrote::GlyphRunAnalysis::create(
|
||||
let analysis = dwrote::GlyphRunAnalysis::create(
|
||||
&glyph_run,
|
||||
1.0,
|
||||
transform,
|
||||
|
@ -290,7 +290,28 @@ impl FontContext {
|
|||
dwrite_measure_mode,
|
||||
0.0,
|
||||
0.0,
|
||||
)
|
||||
);
|
||||
let texture_type = dwrite_texture_type(font.render_mode);
|
||||
let bounds = analysis.get_alpha_texture_bounds(texture_type);
|
||||
// If the bounds are empty, then we might not be able to render the glyph with cleartype.
|
||||
// Try again with aliased rendering to check if that works instead.
|
||||
if font.render_mode != FontRenderMode::Mono &&
|
||||
(bounds.left == bounds.right || bounds.top == bounds.bottom) {
|
||||
let analysis2 = dwrote::GlyphRunAnalysis::create(
|
||||
&glyph_run,
|
||||
1.0,
|
||||
transform,
|
||||
dwrote::DWRITE_RENDERING_MODE_ALIASED,
|
||||
dwrite_measure_mode,
|
||||
0.0,
|
||||
0.0,
|
||||
);
|
||||
let bounds2 = analysis2.get_alpha_texture_bounds(dwrote::DWRITE_TEXTURE_ALIASED_1x1);
|
||||
if bounds2.left != bounds2.right && bounds2.top != bounds2.bottom {
|
||||
return (analysis2, dwrote::DWRITE_TEXTURE_ALIASED_1x1, bounds2);
|
||||
}
|
||||
}
|
||||
(analysis, texture_type, bounds)
|
||||
}
|
||||
|
||||
pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
|
||||
|
@ -334,11 +355,7 @@ impl FontContext {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let analysis = self.create_glyph_analysis(font, key, size, transform, bitmaps);
|
||||
|
||||
let texture_type = dwrite_texture_type(font.render_mode);
|
||||
|
||||
let bounds = analysis.get_alpha_texture_bounds(texture_type);
|
||||
let (_, _, bounds) = self.create_glyph_analysis(font, key, size, transform, bitmaps);
|
||||
|
||||
let width = (bounds.right - bounds.left) as i32;
|
||||
let height = (bounds.bottom - bounds.top) as i32;
|
||||
|
@ -373,11 +390,12 @@ impl FontContext {
|
|||
fn convert_to_bgra(
|
||||
&self,
|
||||
pixels: &[u8],
|
||||
texture_type: dwrote::DWRITE_TEXTURE_TYPE,
|
||||
render_mode: FontRenderMode,
|
||||
bitmaps: bool,
|
||||
) -> Vec<u8> {
|
||||
match (render_mode, bitmaps) {
|
||||
(FontRenderMode::Mono, _) => {
|
||||
match (texture_type, render_mode, bitmaps) {
|
||||
(dwrote::DWRITE_TEXTURE_ALIASED_1x1, _, _) => {
|
||||
let mut bgra_pixels: Vec<u8> = vec![0; pixels.len() * 4];
|
||||
for i in 0 .. pixels.len() {
|
||||
let alpha = pixels[i];
|
||||
|
@ -388,7 +406,18 @@ impl FontContext {
|
|||
}
|
||||
bgra_pixels
|
||||
}
|
||||
(FontRenderMode::Alpha, _) | (_, true) => {
|
||||
(_, FontRenderMode::Subpixel, false) => {
|
||||
let length = pixels.len() / 3;
|
||||
let mut bgra_pixels: Vec<u8> = vec![0; length * 4];
|
||||
for i in 0 .. length {
|
||||
bgra_pixels[i * 4 + 0] = pixels[i * 3 + 2];
|
||||
bgra_pixels[i * 4 + 1] = pixels[i * 3 + 1];
|
||||
bgra_pixels[i * 4 + 2] = pixels[i * 3 + 0];
|
||||
bgra_pixels[i * 4 + 3] = 0xff;
|
||||
}
|
||||
bgra_pixels
|
||||
}
|
||||
_ => {
|
||||
let length = pixels.len() / 3;
|
||||
let mut bgra_pixels: Vec<u8> = vec![0; length * 4];
|
||||
for i in 0 .. length {
|
||||
|
@ -401,17 +430,6 @@ impl FontContext {
|
|||
}
|
||||
bgra_pixels
|
||||
}
|
||||
(FontRenderMode::Subpixel, false) => {
|
||||
let length = pixels.len() / 3;
|
||||
let mut bgra_pixels: Vec<u8> = vec![0; length * 4];
|
||||
for i in 0 .. length {
|
||||
bgra_pixels[i * 4 + 0] = pixels[i * 3 + 2];
|
||||
bgra_pixels[i * 4 + 1] = pixels[i * 3 + 1];
|
||||
bgra_pixels[i * 4 + 2] = pixels[i * 3 + 0];
|
||||
bgra_pixels[i * 4 + 3] = 0xff;
|
||||
}
|
||||
bgra_pixels
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,13 +486,10 @@ impl FontContext {
|
|||
None
|
||||
};
|
||||
|
||||
let analysis = self.create_glyph_analysis(font, key, size, transform, bitmaps);
|
||||
let texture_type = dwrite_texture_type(font.render_mode);
|
||||
let (analysis, texture_type, bounds) = self.create_glyph_analysis(font, key, size, transform, bitmaps);
|
||||
|
||||
let bounds = analysis.get_alpha_texture_bounds(texture_type);
|
||||
let width = (bounds.right - bounds.left) as i32;
|
||||
let height = (bounds.bottom - bounds.top) as i32;
|
||||
|
||||
// Alpha texture bounds can sometimes return an empty rect
|
||||
// Such as for spaces
|
||||
if width == 0 || height == 0 {
|
||||
|
@ -482,7 +497,7 @@ impl FontContext {
|
|||
}
|
||||
|
||||
let pixels = analysis.create_alpha_texture(texture_type, bounds);
|
||||
let mut bgra_pixels = self.convert_to_bgra(&pixels, font.render_mode, bitmaps);
|
||||
let mut bgra_pixels = self.convert_to_bgra(&pixels, texture_type, font.render_mode, bitmaps);
|
||||
|
||||
// These are the default values we use in Gecko.
|
||||
// We use a gamma value of 2.3 for gdi fonts
|
||||
|
@ -509,13 +524,21 @@ impl FontContext {
|
|||
));
|
||||
gamma_lut.preblend(&mut bgra_pixels, font.color);
|
||||
|
||||
let format = if bitmaps {
|
||||
GlyphFormat::Bitmap
|
||||
} else if texture_type == dwrote::DWRITE_TEXTURE_ALIASED_1x1 {
|
||||
font.get_alpha_glyph_format()
|
||||
} else {
|
||||
font.get_glyph_format()
|
||||
};
|
||||
|
||||
GlyphRasterResult::Bitmap(RasterizedGlyph {
|
||||
left: bounds.left as f32,
|
||||
top: -bounds.top as f32,
|
||||
width,
|
||||
height,
|
||||
scale: (if bitmaps { scale / y_scale } else { scale }) as f32,
|
||||
format: if bitmaps { GlyphFormat::Bitmap } else { font.get_glyph_format() },
|
||||
format,
|
||||
bytes: bgra_pixels,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -29,4 +29,4 @@ core-foundation = "0.6"
|
|||
core-graphics = "0.17.1"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
dwrote = "0.6.2"
|
||||
dwrote = "0.6.3"
|
||||
|
|
|
@ -39,7 +39,7 @@ headless = [ "osmesa-sys", "osmesa-src" ]
|
|||
pathfinder = [ "webrender/pathfinder" ]
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
dwrote = "0.6.2"
|
||||
dwrote = "0.6.3"
|
||||
mozangle = {version = "0.1.5", features = ["egl"]}
|
||||
|
||||
[target.'cfg(all(unix, not(target_os = "android")))'.dependencies]
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
== decorations.yaml decorations-ref.yaml
|
||||
fuzzy(1,173) == decorations-suite.yaml decorations-suite.png
|
||||
== 1658.yaml 1658-ref.yaml
|
||||
== split-batch.yaml split-batch-ref.yaml
|
||||
fuzzy(1,5) == split-batch.yaml split-batch-ref.yaml
|
||||
== shadow-red.yaml shadow-red-ref.yaml
|
||||
fuzzy(1,735) == shadow-grey.yaml shadow-grey-ref.yaml
|
||||
fuzzy(1,663) == shadow-grey-transparent.yaml shadow-grey-ref.yaml
|
||||
|
|
|
@ -52,6 +52,9 @@
|
|||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef XP_LINUX
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
@ -10935,6 +10938,16 @@ int main(int argc, char** argv, char** envp) {
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow dumping on Linux with the fuzzing flag set, even when running with
|
||||
* the suid/sgid flag set on the shell.
|
||||
*/
|
||||
#ifdef XP_LINUX
|
||||
if (op.getBoolOption("fuzzing-safe")) {
|
||||
prctl(PR_SET_DUMPABLE, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Process OOM options as early as possible so that we can observe as many
|
||||
|
|
|
@ -16,6 +16,20 @@ here = os.path.abspath(os.path.dirname(__file__))
|
|||
setup_args = [False, 'reftest', 'reftest']
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def normalize():
|
||||
"""A function that can take a relative path and append it to the 'files'
|
||||
directory which contains the data necessary to run these tests.
|
||||
"""
|
||||
|
||||
def inner(path):
|
||||
if os.path.isabs(path):
|
||||
return path
|
||||
return os.path.join(here, 'files', path)
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
@pytest.fixture # noqa: F811
|
||||
def parser(setup_test_harness):
|
||||
setup_test_harness(*setup_args)
|
||||
|
@ -24,20 +38,17 @@ def parser(setup_test_harness):
|
|||
|
||||
|
||||
@pytest.fixture # noqa: F811
|
||||
def runtests(setup_test_harness, binary, parser):
|
||||
def get_reftest(setup_test_harness, binary, parser):
|
||||
setup_test_harness(*setup_args)
|
||||
runreftest = pytest.importorskip('runreftest')
|
||||
harness_root = runreftest.SCRIPT_DIRECTORY
|
||||
|
||||
buf = StringIO()
|
||||
build = parser.build_obj
|
||||
options = vars(parser.parse_args([]))
|
||||
options.update({
|
||||
'app': binary,
|
||||
'focusFilterMode': 'non-needs-focus',
|
||||
'log_raw': [buf],
|
||||
'suite': 'reftest',
|
||||
'specialPowersExtensionPath': os.path.join(harness_root, 'specialpowers'),
|
||||
})
|
||||
|
||||
if not os.path.isdir(build.bindir):
|
||||
|
@ -47,6 +58,7 @@ def runtests(setup_test_harness, binary, parser):
|
|||
'reftestExtensionPath': os.path.join(harness_root, 'reftest'),
|
||||
'sandboxReadWhitelist': [here, os.environ['PYTHON_TEST_TMP']],
|
||||
'utilityPath': os.path.join(package_root, 'bin'),
|
||||
'specialPowersExtensionPath': os.path.join(harness_root, 'specialpowers'),
|
||||
})
|
||||
|
||||
if 'MOZ_FETCHES_DIR' in os.environ:
|
||||
|
@ -55,21 +67,43 @@ def runtests(setup_test_harness, binary, parser):
|
|||
options.update({
|
||||
'extraProfileFiles': [os.path.join(build.topobjdir, 'dist', 'plugins')],
|
||||
'sandboxReadWhitelist': [build.topobjdir, build.topsrcdir],
|
||||
'specialPowersExtensionPath': os.path.join(
|
||||
build.distdir, 'xpi-stage', 'specialpowers'),
|
||||
})
|
||||
|
||||
def normalize(test):
|
||||
if os.path.isabs(test):
|
||||
return test
|
||||
return os.path.join(here, 'files', test)
|
||||
def inner(**opts):
|
||||
options.update(opts)
|
||||
config = Namespace(**options)
|
||||
|
||||
# This is pulled from `runreftest.run_test_harness` minus some error
|
||||
# checking that isn't necessary in this context. It should stay roughly
|
||||
# in sync.
|
||||
reftest = runreftest.RefTest(config.suite)
|
||||
parser.validate(config, reftest)
|
||||
|
||||
config.app = reftest.getFullPath(config.app)
|
||||
assert os.path.exists(config.app)
|
||||
|
||||
if config.xrePath is None:
|
||||
config.xrePath = os.path.dirname(config.app)
|
||||
|
||||
return reftest, config
|
||||
return inner
|
||||
|
||||
|
||||
@pytest.fixture # noqa: F811
|
||||
def runtests(get_reftest, normalize):
|
||||
|
||||
def inner(*tests, **opts):
|
||||
assert len(tests) > 0
|
||||
tests = map(normalize, tests)
|
||||
opts['tests'] = map(normalize, tests)
|
||||
|
||||
options['tests'] = tests
|
||||
options.update(opts)
|
||||
buf = StringIO()
|
||||
opts['log_raw'] = [buf]
|
||||
|
||||
reftest, options = get_reftest(**opts)
|
||||
result = reftest.runTests(options.tests, options)
|
||||
|
||||
result = runreftest.run_test_harness(parser, Namespace(**options))
|
||||
out = json.loads('[' + ','.join(buf.getvalue().splitlines()) + ']')
|
||||
buf.close()
|
||||
return result, out
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>scripttest-pass</title>
|
||||
<script type="text/javascript">
|
||||
function getTestCases()
|
||||
{
|
||||
return [
|
||||
{ testPassed: (function () { return true; }), testDescription: (function () { return "passed"; }) }
|
||||
];
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>scripttest-pass</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
== green.html green.html
|
||||
!= green.html red.html
|
||||
load green.html
|
||||
script scripttest-pass.html
|
||||
print green.html green.html
|
|
@ -3,4 +3,5 @@ subsuite=reftest
|
|||
sequential=true
|
||||
skip-if = python == 3
|
||||
|
||||
[test_reftest_manifest_parser.py]
|
||||
[test_reftest_output.py]
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# 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/.
|
||||
|
||||
import mozunit
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def parse(get_reftest, normalize):
|
||||
output = pytest.importorskip("output")
|
||||
|
||||
reftest, options = get_reftest(tests=["dummy"])
|
||||
reftest._populate_logger(options)
|
||||
reftest.outputHandler = output.OutputHandler(
|
||||
reftest.log, options.utilityPath, options.symbolsPath)
|
||||
|
||||
def resolve(path):
|
||||
path = normalize(path)
|
||||
return "file://{}".format(path)
|
||||
|
||||
def inner(*manifests):
|
||||
assert len(manifests) > 0
|
||||
manifests = {m: None for m in map(resolve, manifests)}
|
||||
return reftest.getActiveTests(manifests, options)
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
def test_parse_test_types(parse):
|
||||
tests = parse('types.list')
|
||||
assert tests[0]['type'] == '=='
|
||||
assert tests[1]['type'] == '!='
|
||||
assert tests[2]['type'] == 'load'
|
||||
assert tests[3]['type'] == 'script'
|
||||
assert tests[4]['type'] == 'print'
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mozunit.main()
|
|
@ -243,6 +243,8 @@ std::vector<webrtc::VideoStream> VideoStreamFactory::CreateEncoderStreams(
|
|||
}
|
||||
streams.push_back(video_stream);
|
||||
}
|
||||
|
||||
MOZ_RELEASE_ASSERT(streams.size(), "Should configure at least one stream");
|
||||
return streams;
|
||||
}
|
||||
|
||||
|
|
|
@ -2656,6 +2656,7 @@ pref("csp.overrule_about_uris_without_csp_whitelist", false);
|
|||
pref("csp.skip_about_page_has_csp_assert", false);
|
||||
// assertion flag will be set to false after fixing Bug 1473549
|
||||
pref("security.allow_eval_with_system_principal", true);
|
||||
pref("security.uris_using_eval_with_system_principal", "autocomplete.xml,redux.js,react-redux.js,content-task.js,content-task.js,tree.xml,dialog.xml,preferencesbindings.js,wizard.xml,lodash.js,jszip.js,ajv-4.1.1.js,updates.js,setup,jsol.js");
|
||||
#endif
|
||||
|
||||
// Default Content Security Policy to apply to signed contents.
|
||||
|
|
|
@ -960,9 +960,9 @@ public static final ElementName LINE = new ElementName("line", "line",
|
|||
// CPPONLY: NS_NewSVGLineElement,
|
||||
TreeBuilder.OTHER);
|
||||
public static final ElementName MARQUEE = new ElementName("marquee", "marquee",
|
||||
// CPPONLY: NS_NewHTMLDivElement,
|
||||
// CPPONLY: NS_NewSVGUnknownElement,
|
||||
TreeBuilder.MARQUEE_OR_APPLET | SPECIAL | SCOPING);
|
||||
// CPPONLY: NS_NewHTMLMarqueeElement,
|
||||
// CPPONLY: NS_NewSVGUnknownElement,
|
||||
TreeBuilder.MARQUEE_OR_APPLET | SPECIAL | SCOPING);
|
||||
public static final ElementName POLYLINE = new ElementName("polyline", "polyline",
|
||||
// CPPONLY: NS_NewHTMLUnknownElement,
|
||||
// CPPONLY: NS_NewSVGPolylineElement,
|
||||
|
|
|
@ -3298,17 +3298,19 @@ public abstract class TreeBuilder<T> implements TokenHandler,
|
|||
}
|
||||
}
|
||||
}
|
||||
String charset = null;
|
||||
if (start != -1) {
|
||||
if (end == -1) {
|
||||
if (charsetState == CHARSET_UNQUOTED) {
|
||||
end = buffer.length;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
charset = Portability.newStringFromBuffer(buffer, start, end
|
||||
- start
|
||||
}
|
||||
return Portability.newStringFromBuffer(buffer, start, end - start
|
||||
// CPPONLY: , tb, false
|
||||
);
|
||||
}
|
||||
return charset;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkMetaCharset(HtmlAttributes attributes)
|
||||
|
|
|
@ -2289,15 +2289,18 @@ nsHtml5String nsHtml5TreeBuilder::extractCharsetFromContent(
|
|||
}
|
||||
}
|
||||
charsetloop_end:;
|
||||
nsHtml5String charset = nullptr;
|
||||
if (start != -1) {
|
||||
if (end == -1) {
|
||||
if (charsetState == CHARSET_UNQUOTED) {
|
||||
end = buffer.length;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
charset = nsHtml5Portability::newStringFromBuffer(buffer, start,
|
||||
end - start, tb, false);
|
||||
}
|
||||
return charset;
|
||||
return nsHtml5Portability::newStringFromBuffer(buffer, start, end - start,
|
||||
tb, false);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes) {
|
||||
|
|
|
@ -10,7 +10,7 @@ playback_cls = {
|
|||
}
|
||||
|
||||
|
||||
def get_playback(config):
|
||||
def get_playback(config, android_device=None):
|
||||
tool_name = config.get('playback_tool', None)
|
||||
if tool_name is None:
|
||||
LOG.critical("playback_tool name not found in config")
|
||||
|
@ -20,4 +20,4 @@ def get_playback(config):
|
|||
return None
|
||||
|
||||
cls = playback_cls.get(tool_name)
|
||||
return cls(config)
|
||||
return cls(config, android_device)
|
||||
|
|
|
@ -11,8 +11,9 @@ from abc import ABCMeta, abstractmethod
|
|||
class Playback(object):
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self, config):
|
||||
def __init__(self, config, android_device=None):
|
||||
self.config = config
|
||||
self.android_device = android_device
|
||||
|
||||
@abstractmethod
|
||||
def download(self):
|
||||
|
|
|
@ -90,12 +90,13 @@ POLICIES_CONTENT_OFF = '''{
|
|||
|
||||
class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
|
||||
|
||||
def __init__(self, config):
|
||||
def __init__(self, config, android_device=None):
|
||||
self.config = config
|
||||
self.mitmproxy_proc = None
|
||||
self.mitmdump_path = None
|
||||
self.recordings = config.get('playback_recordings', None)
|
||||
self.browser_path = config.get('binary', None)
|
||||
self.android_device = android_device
|
||||
|
||||
# raptor_dir is where we will download all mitmproxy required files
|
||||
# when running locally it comes from obj_path via mozharness/mach
|
||||
|
@ -202,9 +203,15 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
|
|||
# for google chromium this is not necessary as chromium will be
|
||||
# started with --ignore-certificate-errors cmd line arg
|
||||
if self.config['app'] == "firefox":
|
||||
# install the generated CA certificate into Firefox
|
||||
self.install_mitmproxy_cert(self.mitmproxy_proc,
|
||||
# install the generated CA certificate into Firefox desktop
|
||||
self.install_mitmproxy_cert_desktop(self.mitmproxy_proc,
|
||||
self.browser_path)
|
||||
elif self.config['app'] == "geckoview":
|
||||
# install the generated CA certificate into android geckoview
|
||||
self.install_mitmproxy_cert_android(self.mitmproxy_proc,
|
||||
self.browser_path)
|
||||
else:
|
||||
return
|
||||
|
||||
def start(self):
|
||||
# if on windows, the mitmdump_path was already set when creating py3 env
|
||||
|
@ -223,19 +230,14 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
|
|||
self.turn_off_browser_proxy()
|
||||
return
|
||||
|
||||
def install_mitmproxy_cert(self, mitmproxy_proc, browser_path):
|
||||
def install_mitmproxy_cert_desktop(self, mitmproxy_proc, browser_path):
|
||||
"""Install the CA certificate generated by mitmproxy, into Firefox
|
||||
1. Create a directory called distribution in the same directory as the Firefox executable
|
||||
2. Create a file called policies.json with:
|
||||
{
|
||||
"policies": {
|
||||
"certificates": {
|
||||
"Install": ["FULL_PATH_TO_CERT"]
|
||||
}
|
||||
}
|
||||
}
|
||||
1. Create a dir called 'distribution' in the same directory as the Firefox executable
|
||||
2. Create the policies.json file inside that folder; which points to the certificate
|
||||
location, and turns on the the browser proxy settings
|
||||
"""
|
||||
LOG.info("Installing mitmproxy CA certficate into Firefox")
|
||||
|
||||
# browser_path is the exe, we want the folder
|
||||
self.policies_dir = os.path.dirname(browser_path)
|
||||
# on macosx we need to remove the last folders 'MacOS'
|
||||
|
@ -262,11 +264,68 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
|
|||
'host': self.config['host']})
|
||||
|
||||
# cannot continue if failed to add CA cert to Firefox, need to check
|
||||
if not self.is_mitmproxy_cert_installed():
|
||||
LOG.error('Aborting: failed to install mitmproxy CA cert into Firefox')
|
||||
if not self.is_mitmproxy_cert_installed_desktop():
|
||||
LOG.error('Aborting: failed to install mitmproxy CA cert into Firefox desktop')
|
||||
self.stop_mitmproxy_playback()
|
||||
sys.exit()
|
||||
|
||||
def install_mitmproxy_cert_android(self, mitmproxy_proc, browser_path):
|
||||
"""Install the CA certificate generated by mitmproxy, into geckoview android
|
||||
1. Get the `certutil` tool.
|
||||
2. Create an NSS certificate database in the geckoview browser profile dir.
|
||||
`certutil -N -d sql:<path to profile> --empty-password`
|
||||
3. Import the mitmproxy certificate into the database.
|
||||
`certutil -A -d sql:<path to profile> -n "some nickname" -t TC,, -a -i <path to CA.pem>`
|
||||
"""
|
||||
# get the certutil tool
|
||||
if self.config.get("obj_path", None) is not None:
|
||||
# when running locally, it is found in the Firefox desktop build (..obj../dist/bin)
|
||||
self.certutil = os.path.join(self.config['obj_path'], 'dist', 'bin')
|
||||
else:
|
||||
# in production it is already downloaded on the host automation machines via hostutils
|
||||
# self.certutil = TODO
|
||||
LOG.info("TODO: where is the path in production to certutil/hostutils?")
|
||||
|
||||
bin_suffix = mozinfo.info.get('bin_suffix', '')
|
||||
self.certutil = os.path.join(self.certutil, "certutil" + bin_suffix)
|
||||
|
||||
if os.path.isfile(self.certutil):
|
||||
LOG.info("certutil is found at: %s" % self.certutil)
|
||||
else:
|
||||
LOG.critical("unable to find certutil at %s" % self.certutil)
|
||||
|
||||
# DEFAULT_CERT_PATH has local path and name of mitmproxy cert i.e.
|
||||
# /home/cltbld/.mitmproxy/mitmproxy-ca-cert.cer
|
||||
self.local_cert_path = DEFAULT_CERT_PATH
|
||||
|
||||
# create cert db
|
||||
param1 = "sql:%s/" % self.config['local_profile_dir']
|
||||
command = [self.certutil, '-N', '-d', param1, '--empty-password']
|
||||
|
||||
LOG.info("creating nss cert database using command: %s" % ' '.join(command))
|
||||
cmd_proc = subprocess.Popen(command, env=os.environ.copy())
|
||||
time.sleep(3)
|
||||
cmd_terminated = cmd_proc.poll()
|
||||
if cmd_terminated is None: # None value indicates process hasn't terminated
|
||||
LOG.critical("nss cert db creation command failed to complete")
|
||||
|
||||
# import mitmproxy cert into the db
|
||||
command = [self.certutil, '-A', '-d', param1, '-n',
|
||||
'mitmproxy-cert', '-t', 'TC,,', '-a', '-i', self.local_cert_path]
|
||||
|
||||
LOG.info("importing mitmproxy cert into db using command: %s" % ' '.join(command))
|
||||
cmd_proc = subprocess.Popen(command, env=os.environ.copy())
|
||||
time.sleep(3)
|
||||
cmd_terminated = cmd_proc.poll()
|
||||
if cmd_terminated is None: # None value indicates process hasn't terminated
|
||||
LOG.critical("command to import mitmproxy cert into cert db failed to complete")
|
||||
|
||||
# cannot continue if failed to add CA cert to Firefox, need to check
|
||||
# if not self.is_mitmproxy_cert_installed_android():
|
||||
# LOG.error('Aborting: failed to install mitmproxy CA cert into Firefox')
|
||||
# self.stop_mitmproxy_playback()
|
||||
# sys.exit()
|
||||
|
||||
def write_policies_json(self, location, policies_content):
|
||||
policies_file = os.path.join(location, "policies.json")
|
||||
LOG.info("writing: %s" % policies_file)
|
||||
|
@ -281,7 +340,7 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
|
|||
with open(policies_file, 'r') as fd:
|
||||
return fd.read()
|
||||
|
||||
def is_mitmproxy_cert_installed(self):
|
||||
def is_mitmproxy_cert_installed_desktop(self):
|
||||
"""Verify mitmxproy CA cert was added to Firefox"""
|
||||
try:
|
||||
# read autoconfig file, confirm mitmproxy cert is in there
|
||||
|
@ -300,6 +359,11 @@ class Mitmproxy(Playback, Python3Virtualenv, TestingMixin, MercurialScript):
|
|||
return False
|
||||
return True
|
||||
|
||||
def is_mitmproxy_cert_installed_android(self):
|
||||
"""Verify mitmxproy CA cert was added to Firefox"""
|
||||
LOG.info("* TODO: verify cert is installed on android")
|
||||
return False
|
||||
|
||||
def start_mitmproxy_playback(self,
|
||||
mitmdump_path,
|
||||
mitmproxy_recording_path,
|
||||
|
|
|
@ -28,8 +28,6 @@ else:
|
|||
mozharness_dir = os.path.join(here, '../../../mozharness')
|
||||
sys.path.insert(0, mozharness_dir)
|
||||
|
||||
from mozharness.mozilla.firefox.autoconfig import _cfg_file_path, _autoconfig_path
|
||||
|
||||
webext_dir = os.path.join(os.path.dirname(here), 'webext')
|
||||
sys.path.insert(0, here)
|
||||
|
||||
|
@ -50,16 +48,6 @@ from results import RaptorResultsHandler
|
|||
from gecko_profile import GeckoProfile
|
||||
|
||||
|
||||
def remove_autoconfig(binary):
|
||||
bindir = os.path.dirname(binary)
|
||||
mozillacfg = _cfg_file_path(bindir)
|
||||
if os.path.isfile(mozillacfg):
|
||||
os.unlink(mozillacfg)
|
||||
autoconfig = _autoconfig_path(bindir)
|
||||
if os.path.isfile(autoconfig):
|
||||
os.unlink(autoconfig)
|
||||
|
||||
|
||||
class Raptor(object):
|
||||
"""Container class for Raptor"""
|
||||
|
||||
|
@ -86,6 +74,7 @@ class Raptor(object):
|
|||
self.benchmark = None
|
||||
self.gecko_profiler = None
|
||||
self.post_startup_delay = 30000
|
||||
self.device = None
|
||||
|
||||
# debug mode is currently only supported when running locally
|
||||
self.debug_mode = debug_mode if self.config['run_local'] else False
|
||||
|
@ -101,9 +90,6 @@ class Raptor(object):
|
|||
self.profile = create_profile('firefox')
|
||||
else:
|
||||
self.profile = create_profile(self.config['app'])
|
||||
# Clear any existing mozilla.cfg file to prevent earlier
|
||||
# runs using mitmproxy from interfering with settings.
|
||||
remove_autoconfig(binary)
|
||||
|
||||
# Merge in base profiles
|
||||
with open(os.path.join(self.profile_data_dir, 'profiles.json'), 'r') as fh:
|
||||
|
@ -114,6 +100,9 @@ class Raptor(object):
|
|||
self.log.info("Merging profile: {}".format(path))
|
||||
self.profile.merge(path)
|
||||
|
||||
# add profile dir to our config
|
||||
self.config['local_profile_dir'] = self.profile.profile
|
||||
|
||||
# create results holder
|
||||
self.results_handler = RaptorResultsHandler()
|
||||
|
||||
|
@ -177,6 +166,13 @@ class Raptor(object):
|
|||
if test.get('type') == "benchmark":
|
||||
self.benchmark = Benchmark(self.config, test)
|
||||
benchmark_port = int(self.benchmark.port)
|
||||
|
||||
# for android we must make the benchmarks server available to the device
|
||||
if self.config['app'] == "geckoview" and self.config['host'] \
|
||||
in ('localhost', '127.0.0.1'):
|
||||
self.log.info("making the raptor benchmarks server port available to device")
|
||||
_tcp_port = "tcp:%s" % benchmark_port
|
||||
self.device.create_socket_connection('reverse', _tcp_port, _tcp_port)
|
||||
else:
|
||||
benchmark_port = 0
|
||||
|
||||
|
@ -188,12 +184,6 @@ class Raptor(object):
|
|||
b_port=benchmark_port,
|
||||
debug_mode=1 if self.debug_mode else 0)
|
||||
|
||||
# for android we must make the benchmarks server available to the device
|
||||
if self.config['app'] == "geckoview" and self.config['host'] in ('localhost', '127.0.0.1'):
|
||||
self.log.info("making the raptor benchmarks server port available to device")
|
||||
_tcp_port = "tcp:%s" % benchmark_port
|
||||
self.device.create_socket_connection('reverse', _tcp_port, _tcp_port)
|
||||
|
||||
# must intall raptor addon each time because we dynamically update some content
|
||||
# note: for chrome the addon is just a list of paths that ultimately are added
|
||||
# to the chromium command line '--load-extension' argument
|
||||
|
@ -213,11 +203,30 @@ class Raptor(object):
|
|||
if self.config['app'] in ["firefox", "geckoview"]:
|
||||
webext_id = self.profile.addons.addon_details(raptor_webext)['id']
|
||||
|
||||
# for android/geckoview, create a top-level raptor folder on the device
|
||||
# sdcard; if it already exists remove it so we start fresh each time
|
||||
if self.config['app'] == "geckoview":
|
||||
self.device_raptor_dir = "/sdcard/raptor"
|
||||
self.config['device_raptor_dir'] = self.device_raptor_dir
|
||||
if self.device.is_dir(self.device_raptor_dir):
|
||||
self.log.info("deleting existing device raptor dir: %s" % self.device_raptor_dir)
|
||||
self.device.rm(self.device_raptor_dir, recursive=True)
|
||||
self.log.info("creating raptor folder on sdcard: %s" % self.device_raptor_dir)
|
||||
self.device.mkdir(self.device_raptor_dir)
|
||||
self.device.chmod(self.device_raptor_dir, recursive=True)
|
||||
|
||||
# some tests require tools to playback the test pages
|
||||
if test.get('playback', None) is not None:
|
||||
self.get_playback_config(test)
|
||||
# startup the playback tool
|
||||
self.playback = get_playback(self.config)
|
||||
self.playback = get_playback(self.config, self.device)
|
||||
|
||||
# for android we must make the playback server available to the device
|
||||
if self.config['app'] == "geckoview" and self.config['host'] \
|
||||
in ('localhost', '127.0.0.1'):
|
||||
self.log.info("making the raptor playback server port available to device")
|
||||
_tcp_port = "tcp:8080"
|
||||
self.device.create_socket_connection('reverse', _tcp_port, _tcp_port)
|
||||
|
||||
if self.config['app'] in ("geckoview", "firefox") and \
|
||||
self.config['host'] not in ('localhost', '127.0.0.1'):
|
||||
|
@ -230,19 +239,36 @@ class Raptor(object):
|
|||
with open(userjspath, 'w') as userjsfile:
|
||||
userjsfile.writelines(prefs)
|
||||
|
||||
# for geckoview we must copy the profile onto the device and set perms
|
||||
# for geckoview/android pageload playback we can't use a policy to turn on the
|
||||
# proxy; we need to set prefs instead; note that the 'host' may be different
|
||||
# than '127.0.0.1' so we must set the prefs accordingly
|
||||
if self.config['app'] == "geckoview" and test.get('playback', None) is not None:
|
||||
self.log.info("setting profile prefs to turn on the geckoview browser proxy")
|
||||
no_proxies_on = "localhost, 127.0.0.1, %s" % self.config['host']
|
||||
proxy_prefs = {}
|
||||
proxy_prefs["network.proxy.type"] = 1
|
||||
proxy_prefs["network.proxy.http"] = self.config['host']
|
||||
proxy_prefs["network.proxy.http_port"] = 8080
|
||||
proxy_prefs["network.proxy.ssl"] = self.config['host']
|
||||
proxy_prefs["network.proxy.ssl_port"] = 8080
|
||||
proxy_prefs["network.proxy.no_proxies_on"] = no_proxies_on
|
||||
self.profile.set_preferences(proxy_prefs)
|
||||
|
||||
# now some final settings, and then startup of the browser under test
|
||||
if self.config['app'] == "geckoview":
|
||||
# for android/geckoview we must copy the profile onto the device and set perms
|
||||
if not self.device.is_app_installed(self.config['binary']):
|
||||
raise Exception('%s is not installed' % self.config['binary'])
|
||||
|
||||
self.log.info("copying firefox profile onto the android device")
|
||||
self.device_profile = "/sdcard/raptor-profile"
|
||||
self.device_profile = os.path.join(self.device_raptor_dir, "profile")
|
||||
if self.device.is_dir(self.device_profile):
|
||||
self.log.info("deleting existing device profile folder: %s" % self.device_profile)
|
||||
self.device.rm(self.device_profile, recursive=True)
|
||||
self.log.info("creating profile folder on device: %s" % self.device_profile)
|
||||
self.device.mkdir(self.device_profile)
|
||||
self.log.info("copying firefox profile onto the device")
|
||||
self.log.info("note: the profile folder being copied is: %s" % self.profile.profile)
|
||||
self.log.info('the adb push cmd copies that profile dir to a new temp dir before copy')
|
||||
self.device.push(self.profile.profile, self.device_profile)
|
||||
|
||||
self.log.info("setting permisions to profile dir on the device")
|
||||
self.device.chmod(self.device_profile, recursive=True)
|
||||
|
||||
# now start the geckoview app
|
||||
|
@ -425,7 +451,6 @@ class Raptor(object):
|
|||
self.device.remove_socket_connections('reverse')
|
||||
else:
|
||||
pass
|
||||
remove_autoconfig(self.config['binary'])
|
||||
self.log.info("finished")
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<meta http-equiv="Content-Type" content='charset="windows-1251'>
|
||||
<meta charset=windows-1250>
|
||||
<title></title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<link rel=help href="https://html.spec.whatwg.org/#algorithm-for-extracting-a-character-encoding-from-a-meta-element">
|
||||
<script>
|
||||
test(function() {
|
||||
assert_equals(document.characterSet, "windows-1250");
|
||||
});
|
||||
</script>
|
|
@ -397,7 +397,6 @@ function _setupDebuggerServer(breakpointFiles, callback) {
|
|||
"See also https://bugzil.la/1215378.");
|
||||
}
|
||||
let { DebuggerServer } = require("devtools/server/main");
|
||||
let { OriginalLocation } = require("devtools/server/actors/common");
|
||||
DebuggerServer.init();
|
||||
DebuggerServer.registerAllActors();
|
||||
let { createRootActor } = require("resource://testing-common/dbg-actors.js");
|
||||
|
@ -406,29 +405,14 @@ function _setupDebuggerServer(breakpointFiles, callback) {
|
|||
|
||||
// An observer notification that tells us when we can "resume" script
|
||||
// execution.
|
||||
const TOPICS = ["devtools-thread-resumed", "xpcshell-test-devtools-shutdown"];
|
||||
const TOPICS = ["devtools-thread-instantiated", "devtools-thread-resumed", "xpcshell-test-devtools-shutdown"];
|
||||
let observe = function(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "devtools-thread-resumed":
|
||||
// Exceptions in here aren't reported and block the debugger from
|
||||
// resuming, so...
|
||||
try {
|
||||
// Add a breakpoint for the first line in our test files.
|
||||
let threadActor = subject.wrappedJSObject;
|
||||
for (let file of breakpointFiles) {
|
||||
// Pass an empty `source` object to workaround `source` function assertion
|
||||
let sourceActor = threadActor.sources.source({originalUrl: file, source: {}});
|
||||
sourceActor._getOrCreateBreakpointActor(new OriginalLocation(sourceActor, 1));
|
||||
}
|
||||
} catch (ex) {
|
||||
info("Failed to initialize breakpoints: " + ex + "\n" + ex.stack);
|
||||
}
|
||||
break;
|
||||
case "xpcshell-test-devtools-shutdown":
|
||||
// the debugger has shutdown before we got a resume event - nothing
|
||||
// special to do here.
|
||||
break;
|
||||
if (topic === "devtools-thread-instantiated") {
|
||||
const threadActor = subject.wrappedJSObject;
|
||||
threadActor.setBreakpointOnLoad(breakpointFiles);
|
||||
return;
|
||||
}
|
||||
|
||||
for (let topicToRemove of TOPICS) {
|
||||
_Services.obs.removeObserver(observe, topicToRemove);
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"7e1fc76f204e32123bd7c8964377fa5b5231187f312683210393360ead036908","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","appveyor.yml":"7c1e0718a363d3567cecd1ef772d4e17c2a17f18906dc464dce8a2411adff6be","src/bitmap_render_target.rs":"fc13525d7459515e4bf9769c8a8961b046b4d1ba4042591aaf0925dd5edebf64","src/com_helpers.rs":"02535b27bfb0cee6e4d8db3abd22f2d2e8137a4ce3ab3504beaf4fa3ca9370df","src/comptr.rs":"84794cf04b772398e75fdb5d55fd8fa015abf26c61b1f9c761a597133682b2e1","src/font.rs":"a79b944f2f5125bbef9e24921355dc6996f073e3742ddd410b8efaa0df3a3ee2","src/font_collection.rs":"67cd566714f4c0a20cba24dd064ba471e75016fa2672b2153a19878e6b71f24d","src/font_collection_impl.rs":"a585a6ce62083b3346d67619ea47fec46423a7fb04cc11372828389ab26c5a05","src/font_face.rs":"7f78c4132df39857d8118ac3eacbb57e11bca1d69f9d7f8e1c1c24b7a2b69749","src/font_family.rs":"4e948542dba0c158187d0cb2d72343c443380480cacd12894070d0ef1351dd0a","src/font_file.rs":"1c012d0b436c2831d31cd76f77a59dab1edc5d63881c495eb486cd4febe23031","src/font_file_loader_impl.rs":"71c4153971dbfc21d42ba2e33f159fcb145f7dcfbd17e856e9fd75f0571d41e0","src/gdi_interop.rs":"04dbef7c34bb0fe62c4f2c2ceca62ca94c75a964d744b29b3322a6c3bbb4eabd","src/geometry_sink_impl.rs":"d615de212e55b8b8d95c8d605fc5d78044b4ae4dfd846f706911a16cc3afc049","src/glyph_run_analysis.rs":"3b2a351422098a19e8f490421e5b19227fc14a41a0df97d488c536fd1d4b552c","src/helpers.rs":"2f3c57642b24b80c45bbd012e7d6ca1fc524b1b42a8be004cb9b52ea13f4166d","src/lib.rs":"b634e62dd088d804429f451ba9f14aaab0b6a1179042d70fed825f3253ffacfb","src/outline_builder.rs":"0f5c842b2ffe75e21d68f93be6a3834c120bd43303d4e490fdfee9f4f964cdc4","src/rendering_params.rs":"850a51143790f5d29422dc49cbceddc232d814ecd0e6933434ad644e6eec539b","src/test.rs":"158aa4d03655f4efef00327fe72a03dfb504659176aa0eef976ca2485b2c1d74","src/types.rs":"587aea2e50720e85b28efe237c8ea10bc45b52049ca724447a0fc9b0e6672b11"},"package":"7b46afd0d0bbbea88fc083ea293e40865e26a75ec9d38cf5d05a23ac3e2ffe02"}
|
||||
{"files":{"Cargo.toml":"5f9a26a7a0f3fffc7093b0ac9e2fd84db133ba5516a9bfb53ed4f842b350564f","README.md":"d69d75705e2582721cbfb2d3b4b2af052c71679057a0b2ac53a22c03f1755bba","appveyor.yml":"7c1e0718a363d3567cecd1ef772d4e17c2a17f18906dc464dce8a2411adff6be","src/bitmap_render_target.rs":"fc13525d7459515e4bf9769c8a8961b046b4d1ba4042591aaf0925dd5edebf64","src/com_helpers.rs":"02535b27bfb0cee6e4d8db3abd22f2d2e8137a4ce3ab3504beaf4fa3ca9370df","src/comptr.rs":"84794cf04b772398e75fdb5d55fd8fa015abf26c61b1f9c761a597133682b2e1","src/font.rs":"a79b944f2f5125bbef9e24921355dc6996f073e3742ddd410b8efaa0df3a3ee2","src/font_collection.rs":"67cd566714f4c0a20cba24dd064ba471e75016fa2672b2153a19878e6b71f24d","src/font_collection_impl.rs":"a585a6ce62083b3346d67619ea47fec46423a7fb04cc11372828389ab26c5a05","src/font_face.rs":"7f78c4132df39857d8118ac3eacbb57e11bca1d69f9d7f8e1c1c24b7a2b69749","src/font_family.rs":"4e948542dba0c158187d0cb2d72343c443380480cacd12894070d0ef1351dd0a","src/font_file.rs":"1c012d0b436c2831d31cd76f77a59dab1edc5d63881c495eb486cd4febe23031","src/font_file_loader_impl.rs":"71c4153971dbfc21d42ba2e33f159fcb145f7dcfbd17e856e9fd75f0571d41e0","src/gdi_interop.rs":"04dbef7c34bb0fe62c4f2c2ceca62ca94c75a964d744b29b3322a6c3bbb4eabd","src/geometry_sink_impl.rs":"d615de212e55b8b8d95c8d605fc5d78044b4ae4dfd846f706911a16cc3afc049","src/glyph_run_analysis.rs":"3b2a351422098a19e8f490421e5b19227fc14a41a0df97d488c536fd1d4b552c","src/helpers.rs":"2f3c57642b24b80c45bbd012e7d6ca1fc524b1b42a8be004cb9b52ea13f4166d","src/lib.rs":"d6a109158cb69cf4a113722169ba8b339d9d38eccb2c9d6b2fe68dd40da22814","src/outline_builder.rs":"0f5c842b2ffe75e21d68f93be6a3834c120bd43303d4e490fdfee9f4f964cdc4","src/rendering_params.rs":"850a51143790f5d29422dc49cbceddc232d814ecd0e6933434ad644e6eec539b","src/test.rs":"158aa4d03655f4efef00327fe72a03dfb504659176aa0eef976ca2485b2c1d74","src/types.rs":"587aea2e50720e85b28efe237c8ea10bc45b52049ca724447a0fc9b0e6672b11"},"package":"f0beca78470f26189a662e72afe7a54c625b4feb06b2d36c207ac15319bd57c5"}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "dwrote"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
authors = ["Vladimir Vukicevic <vladimir@pobox.com>"]
|
||||
description = "Lightweight binding to DirectWrite."
|
||||
license = "MPL-2.0"
|
||||
|
|
|
@ -65,6 +65,7 @@ pub use winapi::um::dwrite::{DWRITE_RENDERING_MODE};
|
|||
pub use winapi::um::dwrite::{DWRITE_TEXTURE_TYPE};
|
||||
pub use winapi::um::dwrite_3::{DWRITE_FONT_AXIS_VALUE};
|
||||
pub use winapi::um::dcommon::{DWRITE_MEASURING_MODE};
|
||||
pub use winapi::shared::windef::RECT;
|
||||
use winapi::um::libloaderapi::{GetProcAddress, LoadLibraryW};
|
||||
|
||||
#[macro_use] mod com_helpers;
|
||||
|
|
|
@ -66,10 +66,6 @@ if (Cu) {
|
|||
XPCOMUtils.defineLazyServiceGetter(this, "FinalizationWitnessService",
|
||||
"@mozilla.org/toolkit/finalizationwitness;1",
|
||||
"nsIFinalizationWitnessService");
|
||||
|
||||
// For now, we're worried about add-ons using Promises with CPOWs, so we'll
|
||||
// permit them in this scope, but this support will go away soon.
|
||||
Cu.permitCPOWsInScope(this);
|
||||
}
|
||||
|
||||
const STATUS_PENDING = 0;
|
||||
|
|
|
@ -87,10 +87,6 @@ var EXPORTED_SYMBOLS = [
|
|||
|
||||
// Globals
|
||||
|
||||
// For now, we're worried about add-ons using Tasks with CPOWs, so we'll
|
||||
// permit them in this scope, but this support will go away soon.
|
||||
Cu.permitCPOWsInScope(this);
|
||||
|
||||
// The following error types are considered programmer errors, which should be
|
||||
// reported (possibly redundantly) so as to let programmers fix their code.
|
||||
const ERRORS_TO_REPORT = ["EvalError", "RangeError", "ReferenceError", "TypeError"];
|
||||
|
|
Загрузка…
Ссылка в новой задаче