зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. r=merge a=merge CLOSED TREE
This commit is contained in:
Коммит
7356e0ba3b
|
@ -11,19 +11,17 @@
|
|||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
<binding id="ctrlTab-preview" extends="chrome://global/content/bindings/button.xml#button-base">
|
||||
<content pack="center">
|
||||
<xul:stack>
|
||||
<xul:vbox class="ctrlTab-preview-inner" align="center" pack="center"
|
||||
xbl:inherits="width=canvaswidth">
|
||||
<xul:hbox class="tabPreview-canvas" xbl:inherits="style=canvasstyle">
|
||||
<children/>
|
||||
</xul:hbox>
|
||||
<xul:label xbl:inherits="value=label" crop="end" class="plain"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox class="ctrlTab-preview-inner">
|
||||
<xul:hbox class="ctrlTab-canvas" xbl:inherits="style=canvasstyle,width=canvaswidth">
|
||||
<children/>
|
||||
</xul:hbox>
|
||||
<xul:hbox class="ctrlTab-favicon-container" xbl:inherits="hidden=noicon">
|
||||
<xul:image class="ctrlTab-favicon" xbl:inherits="src=image"/>
|
||||
</xul:hbox>
|
||||
</xul:stack>
|
||||
<xul:label class="ctrlTab-label plain" xbl:inherits="value=label" crop="end"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
<handlers>
|
||||
<handler event="mouseover" action="ctrlTab._mouseOverFocus(this);"/>
|
||||
<handler event="command" action="ctrlTab.pick(this);"/>
|
||||
|
|
|
@ -912,35 +912,6 @@ html|*#fullscreen-exit-button {
|
|||
|
||||
/* ::::: Ctrl-Tab Panel ::::: */
|
||||
|
||||
.ctrlTab-preview > html|img,
|
||||
.ctrlTab-preview > html|canvas {
|
||||
min-width: inherit;
|
||||
max-width: inherit;
|
||||
min-height: inherit;
|
||||
max-height: inherit;
|
||||
}
|
||||
|
||||
.ctrlTab-favicon-container {
|
||||
-moz-box-align: start;
|
||||
%ifdef XP_MACOSX
|
||||
-moz-box-pack: end;
|
||||
%else
|
||||
-moz-box-pack: start;
|
||||
%endif
|
||||
}
|
||||
|
||||
.ctrlTab-favicon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
|
||||
@media (resolution: 2dppx) {
|
||||
.ctrlTab-favicon {
|
||||
image-rendering: -moz-crisp-edges;
|
||||
}
|
||||
}
|
||||
|
||||
.ctrlTab-preview {
|
||||
-moz-binding: url("chrome://browser/content/browser-tabPreviews.xml#ctrlTab-preview");
|
||||
}
|
||||
|
|
|
@ -245,7 +245,7 @@
|
|||
icon="save" id="imagesaveasbutton"
|
||||
oncommand="saveMedia();"/>
|
||||
</hbox>
|
||||
<vbox id="imagecontainerbox" class="inset iframe" flex="1" pack="center">
|
||||
<vbox id="imagecontainerbox" flex="1" pack="center">
|
||||
<hbox id="theimagecontainer" pack="center">
|
||||
<image id="thepreviewimage"/>
|
||||
</hbox>
|
||||
|
|
|
@ -22,8 +22,10 @@
|
|||
}
|
||||
|
||||
#topBar {
|
||||
-moz-appearance: listbox;
|
||||
margin: 8px 8px 0;
|
||||
border-bottom: 1px solid ThreeDShadow;
|
||||
padding-inline-start: 10px;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
#generalTab {
|
||||
|
@ -51,8 +53,8 @@
|
|||
padding-right: 2px;
|
||||
}
|
||||
|
||||
deck {
|
||||
padding: 10px 10px 10px 10px;
|
||||
#mainDeck {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
|
@ -67,7 +69,7 @@ tree {
|
|||
textbox {
|
||||
background: transparent !important;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
margin-top: 1px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
@ -76,14 +78,11 @@ textbox.header {
|
|||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
.iframe {
|
||||
#imagecontainerbox {
|
||||
margin: .5em;
|
||||
background: white;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.fixedsize {
|
||||
height: 8.5em;
|
||||
border: 1px solid ThreeDLightShadow;
|
||||
}
|
||||
|
||||
textbox[disabled] {
|
||||
|
@ -162,11 +161,6 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
color: graytext;
|
||||
}
|
||||
|
||||
#mediaPreviewBox .inset {
|
||||
-moz-appearance: listbox;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Feeds Tab */
|
||||
#feedPanel {
|
||||
margin-left: 2px;
|
||||
|
@ -183,7 +177,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
padding-inline-start: 7px;
|
||||
padding-inline-end: 7px;
|
||||
min-height: 25px;
|
||||
border-bottom: 1px dotted #C0C0C0;
|
||||
border-bottom: 1px dotted ThreeDShadow;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
|
@ -194,11 +188,6 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
|
||||
#feedListbox {
|
||||
margin-bottom: 0;
|
||||
border: 2px solid;
|
||||
-moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
}
|
||||
|
||||
.feedTitle {
|
||||
|
@ -206,31 +195,18 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
}
|
||||
|
||||
/* Permissions Tab */
|
||||
#permPanel {
|
||||
margin-left: 6px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
#permList {
|
||||
-moz-appearance: listbox;
|
||||
margin-top: .5em;
|
||||
margin: .5em;
|
||||
overflow: auto;
|
||||
border: 2px solid;
|
||||
-moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
background-color: -moz-field;
|
||||
color: -moz-FieldText;
|
||||
}
|
||||
|
||||
.permission {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-inline-start: 7px;
|
||||
padding-inline-end: 7px;
|
||||
padding: 6px 7px;
|
||||
min-height: 25px;
|
||||
border-bottom: 1px dotted #C0C0C0;
|
||||
border-bottom: 1px dotted ThreeDShadow;
|
||||
}
|
||||
|
||||
.permissionLabel {
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
text-shadow: rgba(0, 0, 0, 0.4) 0 1px;
|
||||
}
|
||||
|
||||
deck {
|
||||
padding: 10px 10px 10px 10px;
|
||||
#mainDeck {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
|
@ -53,7 +53,7 @@ tree {
|
|||
textbox {
|
||||
background: transparent !important;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
margin-top: 1px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
@ -62,14 +62,11 @@ textbox.header {
|
|||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
.iframe {
|
||||
#imagecontainerbox {
|
||||
margin: .5em;
|
||||
background: white;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.fixedsize {
|
||||
height: 8.5em;
|
||||
border: 1px solid ThreeDLightShadow;
|
||||
}
|
||||
|
||||
textbox[disabled] {
|
||||
|
@ -146,7 +143,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
padding-inline-start: 7px;
|
||||
padding-inline-end: 7px;
|
||||
min-height: 25px;
|
||||
border-bottom: 1px dotted #C0C0C0;
|
||||
border-bottom: 1px dotted ThreeDShadow;
|
||||
}
|
||||
|
||||
#feedListbox richlistitem[selected="true"] {
|
||||
|
@ -154,37 +151,22 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
#feedListbox {
|
||||
border: 2px solid;
|
||||
-moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
}
|
||||
|
||||
.feedTitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Permissions Tab */
|
||||
#permList {
|
||||
margin-top: .5em;
|
||||
margin: .5em;
|
||||
overflow: auto;
|
||||
border: 2px solid;
|
||||
-moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
background-color: -moz-field;
|
||||
-moz-appearance: listbox;
|
||||
color: -moz-fieldtext;
|
||||
}
|
||||
|
||||
.permission {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-inline-start: 7px;
|
||||
padding-inline-end: 7px;
|
||||
padding: 6px 7px;
|
||||
min-height: 25px;
|
||||
border-bottom: 1px dotted #C0C0C0;
|
||||
border-bottom: 1px dotted ThreeDShadow;
|
||||
}
|
||||
|
||||
.permissionLabel {
|
||||
|
@ -193,6 +175,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
|
||||
.permission:hover {
|
||||
background-color: -moz-dialog;
|
||||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
/* Security Tab */
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
%ifdef XP_MACOSX
|
||||
-moz-window-shadow: none;
|
||||
%endif
|
||||
background: hsla(0,0%,33%,.85);
|
||||
background: hsla(0,0%,40%,.85);
|
||||
color: white;
|
||||
border-style: none;
|
||||
padding: 20px 10px 10px;
|
||||
|
@ -21,19 +21,34 @@
|
|||
text-shadow: 0 0 1px hsl(0,0%,12%), 0 0 2px hsl(0,0%,12%);
|
||||
}
|
||||
|
||||
.ctrlTab-preview > html|img,
|
||||
.ctrlTab-preview > html|canvas {
|
||||
min-width: inherit;
|
||||
max-width: inherit;
|
||||
min-height: inherit;
|
||||
max-height: inherit;
|
||||
}
|
||||
|
||||
.ctrlTab-favicon-container {
|
||||
position: relative;
|
||||
-moz-box-pack: end;
|
||||
}
|
||||
|
||||
.ctrlTab-favicon[src] {
|
||||
background-color: white;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.ctrlTab-preview-inner > .tabPreview-canvas {
|
||||
box-shadow: 1px 1px 2px hsl(0,0%,12%);
|
||||
}
|
||||
|
||||
.ctrlTab-preview:not(#ctrlTab-showAll) > * > .ctrlTab-preview-inner > .tabPreview-canvas {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
margin-top: -44px;
|
||||
margin-bottom: 2px;
|
||||
margin-inline-end: -6px;
|
||||
padding: 5px;
|
||||
background-color: #F9F9FA;
|
||||
border-radius: 6px;
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.ctrlTab-preview:not(#ctrlTab-showAll) > .ctrlTab-preview-inner > .ctrlTab-canvas {
|
||||
box-shadow: 1px 1px 2px hsl(0,0%,12%);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ctrlTab-preview-inner {
|
||||
|
@ -42,19 +57,23 @@
|
|||
border-radius: .5em;
|
||||
}
|
||||
|
||||
.ctrlTab-preview:not(#ctrlTab-showAll) > * > .ctrlTab-preview-inner {
|
||||
.ctrlTab-preview:not(#ctrlTab-showAll) > .ctrlTab-preview-inner {
|
||||
margin: -10px -10px 0;
|
||||
}
|
||||
|
||||
#ctrlTab-showAll:not(:focus) > * > .ctrlTab-preview-inner {
|
||||
#ctrlTab-showAll:not(:focus) > .ctrlTab-preview-inner {
|
||||
background-color: rgba(255,255,255,.2);
|
||||
}
|
||||
|
||||
.ctrlTab-preview:focus > * > .ctrlTab-preview-inner {
|
||||
.ctrlTab-preview:focus > .ctrlTab-preview-inner {
|
||||
color: white;
|
||||
background-color: rgba(0,0,0,.6);
|
||||
background-color: rgba(0,0,0,.75);
|
||||
text-shadow: none;
|
||||
border-color: white;
|
||||
border-color: #45a1ff;
|
||||
}
|
||||
|
||||
.ctrlTab-label {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#ctrlTab-showAll {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
}
|
||||
|
||||
#topBar {
|
||||
border-bottom: 2px groove ThreeDFace;
|
||||
border-bottom: 1px solid ThreeDLightShadow;
|
||||
padding-inline-start: 10px;
|
||||
background-color: -moz-Field;
|
||||
color: -moz-FieldText;
|
||||
|
@ -38,7 +38,8 @@
|
|||
-moz-image-region: rect(0px, 32px, 32px, 0px)
|
||||
}
|
||||
|
||||
#generalTab:hover, #generalTab[selected="true"] {
|
||||
#generalTab:hover,
|
||||
#generalTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 32px, 64px, 0px)
|
||||
}
|
||||
|
||||
|
@ -46,7 +47,8 @@
|
|||
-moz-image-region: rect(0px, 64px, 32px, 32px)
|
||||
}
|
||||
|
||||
#mediaTab:hover, #mediaTab[selected="true"] {
|
||||
#mediaTab:hover,
|
||||
#mediaTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 64px, 64px, 32px)
|
||||
}
|
||||
|
||||
|
@ -54,7 +56,8 @@
|
|||
-moz-image-region: rect(0px, 96px, 32px, 64px)
|
||||
}
|
||||
|
||||
#feedTab:hover, #feedTab[selected="true"] {
|
||||
#feedTab:hover,
|
||||
#feedTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 96px, 64px, 64px)
|
||||
}
|
||||
|
||||
|
@ -62,7 +65,8 @@
|
|||
-moz-image-region: rect(0px, 128px, 32px, 96px)
|
||||
}
|
||||
|
||||
#permTab:hover, #permTab[selected="true"] {
|
||||
#permTab:hover,
|
||||
#permTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 128px, 64px, 96px)
|
||||
}
|
||||
|
||||
|
@ -70,12 +74,13 @@
|
|||
-moz-image-region: rect(0px, 160px, 32px, 128px)
|
||||
}
|
||||
|
||||
#securityTab:hover, #securityTab[selected="true"] {
|
||||
#securityTab:hover,
|
||||
#securityTab[selected="true"] {
|
||||
-moz-image-region: rect(32px, 160px, 64px, 128px)
|
||||
}
|
||||
|
||||
deck {
|
||||
padding: 10px 10px 10px 10px;
|
||||
#mainDeck {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
|
@ -90,7 +95,7 @@ tree {
|
|||
textbox {
|
||||
background: transparent !important;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
margin-top: 1px;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
@ -99,14 +104,11 @@ textbox.header {
|
|||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
.iframe {
|
||||
#imagecontainerbox {
|
||||
margin: .5em;
|
||||
background: white;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.fixedsize {
|
||||
height: 8.5em;
|
||||
border: 1px solid ThreeDLightShadow;
|
||||
}
|
||||
|
||||
textbox[disabled] {
|
||||
|
@ -188,7 +190,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
padding-inline-start: 7px;
|
||||
padding-inline-end: 7px;
|
||||
min-height: 25px;
|
||||
border-bottom: 1px dotted #C0C0C0;
|
||||
border-bottom: 1px dotted ThreeDShadow;
|
||||
}
|
||||
|
||||
#feedListbox richlistitem[selected="true"] {
|
||||
|
@ -196,37 +198,22 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
#feedListbox {
|
||||
border: 2px solid;
|
||||
-moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
}
|
||||
|
||||
.feedTitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Permissions Tab */
|
||||
#permList {
|
||||
margin-top: .5em;
|
||||
margin: .5em;
|
||||
overflow: auto;
|
||||
border: 2px solid;
|
||||
-moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
-moz-border-right-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-bottom-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
|
||||
background-color: -moz-field;
|
||||
-moz-appearance: listbox;
|
||||
color: -moz-fieldtext;
|
||||
}
|
||||
|
||||
.permission {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
padding-inline-start: 7px;
|
||||
padding-inline-end: 7px;
|
||||
padding: 6px 7px;
|
||||
min-height: 25px;
|
||||
border-bottom: 1px dotted #C0C0C0;
|
||||
border-bottom: 1px dotted ThreeDShadow;
|
||||
}
|
||||
|
||||
.permissionLabel {
|
||||
|
@ -235,6 +222,7 @@ treechildren::-moz-tree-cell-text(broken) {
|
|||
|
||||
.permission:hover {
|
||||
background-color: -moz-dialog;
|
||||
color: -moz-dialogText;
|
||||
}
|
||||
|
||||
/* Security Tab */
|
||||
|
|
|
@ -104,13 +104,7 @@ if test -z "$platform"; then
|
|||
esac
|
||||
fi
|
||||
|
||||
if test -z "$bucket"; then
|
||||
case "$platform" in
|
||||
win*) : ;;
|
||||
*)
|
||||
export CCACHE=ccache
|
||||
esac
|
||||
else
|
||||
if test -n "$bucket"; then
|
||||
mk_add_options "export SCCACHE_BUCKET=$bucket"
|
||||
case "$master" in
|
||||
*us[ew][12].mozilla.com*|*euc1.mozilla.com*)
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
.requests-list-headers-wrapper {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/IdleDeadline.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
|
@ -433,5 +434,32 @@ ChromeUtils::IsOriginAttributesEqual(const dom::OriginAttributesDictionary& aA,
|
|||
aA.mPrivateBrowsingId == aB.mPrivateBrowsingId;
|
||||
}
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
/* static */ void
|
||||
ChromeUtils::GetRecentJSDevError(GlobalObject& aGlobal,
|
||||
JS::MutableHandleValue aRetval,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
aRetval.setUndefined();
|
||||
auto runtime = CycleCollectedJSRuntime::Get();
|
||||
MOZ_ASSERT(runtime);
|
||||
|
||||
auto cx = aGlobal.Context();
|
||||
if (!runtime->GetRecentDevError(cx, aRetval)) {
|
||||
aRv.NoteJSContextException(cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ChromeUtils::ClearRecentJSDevError(GlobalObject&)
|
||||
{
|
||||
auto runtime = CycleCollectedJSRuntime::Get();
|
||||
MOZ_ASSERT(runtime);
|
||||
|
||||
runtime->ClearRecentDevError();
|
||||
}
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -148,6 +148,12 @@ public:
|
|||
IdleRequestCallback& callback,
|
||||
const IdleRequestOptions& options,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static void GetRecentJSDevError(GlobalObject& aGlobal,
|
||||
JS::MutableHandleValue aRetval,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static void ClearRecentJSDevError(GlobalObject& aGlobal);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -11000,7 +11000,7 @@ template <prototypes::ID PrototypeID, class NativeType, typename T>
|
|||
static Result<Ok, nsresult>
|
||||
ExtractExceptionValues(JSContext* aCx,
|
||||
JS::HandleObject aObj,
|
||||
nsACString& aSourceSpecOut,
|
||||
nsAString& aSourceSpecOut,
|
||||
uint32_t* aLineOut,
|
||||
uint32_t* aColumnOut,
|
||||
nsString& aMessageOut)
|
||||
|
@ -11008,10 +11008,8 @@ ExtractExceptionValues(JSContext* aCx,
|
|||
RefPtr<T> exn;
|
||||
MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn)));
|
||||
|
||||
nsAutoString filename;
|
||||
exn->GetFilename(aCx, filename);
|
||||
if (!filename.IsEmpty()) {
|
||||
CopyUTF16toUTF8(filename, aSourceSpecOut);
|
||||
exn->GetFilename(aCx, aSourceSpecOut);
|
||||
if (!aSourceSpecOut.IsEmpty()) {
|
||||
*aLineOut = exn->LineNumber(aCx);
|
||||
*aColumnOut = exn->ColumnNumber();
|
||||
}
|
||||
|
@ -11032,6 +11030,19 @@ nsContentUtils::ExtractErrorValues(JSContext* aCx,
|
|||
uint32_t* aLineOut,
|
||||
uint32_t* aColumnOut,
|
||||
nsString& aMessageOut)
|
||||
{
|
||||
nsAutoString sourceSpec;
|
||||
ExtractErrorValues(aCx, aValue, sourceSpec, aLineOut, aColumnOut, aMessageOut);
|
||||
CopyUTF16toUTF8(sourceSpec, aSourceSpecOut);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::ExtractErrorValues(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
nsAString& aSourceSpecOut,
|
||||
uint32_t* aLineOut,
|
||||
uint32_t* aColumnOut,
|
||||
nsString& aMessageOut)
|
||||
{
|
||||
MOZ_ASSERT(aLineOut);
|
||||
MOZ_ASSERT(aColumnOut);
|
||||
|
@ -11053,7 +11064,7 @@ nsContentUtils::ExtractErrorValues(JSContext* aCx,
|
|||
0); // window ID
|
||||
|
||||
if (!report->mFileName.IsEmpty()) {
|
||||
CopyUTF16toUTF8(report->mFileName, aSourceSpecOut);
|
||||
aSourceSpecOut = report->mFileName;
|
||||
*aLineOut = report->mLineNumber;
|
||||
*aColumnOut = report->mColumn;
|
||||
}
|
||||
|
|
|
@ -1136,6 +1136,14 @@ public:
|
|||
|
||||
static bool PrefetchPreloadEnabled(nsIDocShell* aDocShell);
|
||||
|
||||
static void
|
||||
ExtractErrorValues(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
nsAString& aSourceSpecOut, uint32_t *aLineOut,
|
||||
uint32_t *aColumnOut, nsString& aMessageOut);
|
||||
|
||||
// Variant on `ExtractErrorValues` with a `nsACString`. This
|
||||
// method is provided for backwards compatibility. Prefer the
|
||||
// faster method above for your code.
|
||||
static void
|
||||
ExtractErrorValues(JSContext* aCx, JS::Handle<JS::Value> aValue,
|
||||
nsACString& aSourceSpecOut, uint32_t *aLineOut,
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
function errors() {
|
||||
return [
|
||||
// The following two errors MUST NOT be captured.
|
||||
new Error("This is an error: " + Math.random()),
|
||||
new RangeError("This is a RangeError: " + Math.random()),
|
||||
"This is a string: " + Math.random(),
|
||||
null,
|
||||
undefined,
|
||||
Math.random(),
|
||||
{},
|
||||
|
||||
// The following errors MUST be captured.
|
||||
new TypeError("This is a TypeError: " + Math.random()),
|
||||
new SyntaxError("This is a SyntaxError: " + Math.random()),
|
||||
new ReferenceError("This is a ReferenceError: " + Math.random())
|
||||
]
|
||||
}
|
||||
|
||||
function isDeveloperError(e) {
|
||||
if (e == null || typeof e != "object") {
|
||||
return false;
|
||||
}
|
||||
|
||||
return e.constructor == TypeError
|
||||
|| e.constructor == SyntaxError
|
||||
|| e.constructor == ReferenceError;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
ChromeUtils.clearRecentJSDevError();
|
||||
Assert.equal(ChromeUtils.recentJSDevError, undefined);
|
||||
|
||||
for (let exn of errors()) {
|
||||
ChromeUtils.clearRecentJSDevError();
|
||||
try {
|
||||
throw exn;
|
||||
} catch (e) {
|
||||
// Discard error.
|
||||
}
|
||||
if (isDeveloperError(exn)) {
|
||||
Assert.equal(ChromeUtils.recentJSDevError.message, "" + exn);
|
||||
} else {
|
||||
Assert.equal(ChromeUtils.recentJSDevError, undefined);
|
||||
}
|
||||
ChromeUtils.clearRecentJSDevError();
|
||||
Assert.equal(ChromeUtils.recentJSDevError, undefined);
|
||||
}
|
||||
};
|
||||
|
|
@ -54,4 +54,7 @@ head = head_xml.js
|
|||
[test_chromeutils_base64.js]
|
||||
[test_generate_xpath.js]
|
||||
head = head_xml.js
|
||||
[test_js_dev_error_interceptor.js]
|
||||
# This feature is implemented only in NIGHTLY.
|
||||
run-if = nightly_build
|
||||
|
||||
|
|
|
@ -89,6 +89,40 @@ namespace ChromeUtils {
|
|||
ArrayBuffer base64URLDecode(ByteString string,
|
||||
Base64URLDecodeOptions options);
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
|
||||
/**
|
||||
* If the chrome code has thrown a JavaScript Dev Error
|
||||
* in the current JSRuntime. the first such error, or `undefined`
|
||||
* otherwise.
|
||||
*
|
||||
* A JavaScript Dev Error is an exception thrown by JavaScript
|
||||
* code that matches both conditions:
|
||||
* - it was thrown by chrome code;
|
||||
* - it is either a `ReferenceError`, a `TypeError` or a `SyntaxError`.
|
||||
*
|
||||
* Such errors are stored regardless of whether they have been
|
||||
* caught.
|
||||
*
|
||||
* This mechanism is designed to help ensure that the code of
|
||||
* Firefox is free from Dev Errors, even if they are accidentally
|
||||
* caught by clients.
|
||||
*
|
||||
* The object returned is not an exception. It has fields:
|
||||
* - DOMString stack
|
||||
* - DOMString filename
|
||||
* - DOMString lineNumber
|
||||
* - DOMString message
|
||||
*/
|
||||
[Throws]
|
||||
readonly attribute any recentJSDevError;
|
||||
|
||||
/**
|
||||
* Reset `recentJSDevError` to `undefined` for the current JSRuntime.
|
||||
*/
|
||||
void clearRecentJSDevError();
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
/**
|
||||
* IF YOU ADD NEW METHODS HERE, MAKE SURE THEY ARE THREAD-SAFE.
|
||||
*/
|
||||
|
|
|
@ -363,6 +363,7 @@ GENERATED_WEBIDL_FILES = [
|
|||
]
|
||||
|
||||
PREPROCESSED_WEBIDL_FILES = [
|
||||
'ChromeUtils.webidl',
|
||||
'Navigator.webidl',
|
||||
'Node.webidl',
|
||||
'Window.webidl',
|
||||
|
@ -425,7 +426,6 @@ WEBIDL_FILES = [
|
|||
'CheckerboardReportService.webidl',
|
||||
'ChildNode.webidl',
|
||||
'ChromeNodeList.webidl',
|
||||
'ChromeUtils.webidl',
|
||||
'Client.webidl',
|
||||
'Clients.webidl',
|
||||
'ClipboardEvent.webidl',
|
||||
|
|
|
@ -137,6 +137,13 @@ if CONFIG['ENABLE_STREAMS']:
|
|||
'testReadableStream.cpp',
|
||||
]
|
||||
|
||||
|
||||
if CONFIG['NIGHTLY_BUILD']:
|
||||
# The Error interceptor only exists on Nightly.
|
||||
UNIFIED_SOURCES += [
|
||||
'testErrorInterceptor.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['JS_BUILD_BINAST'] and CONFIG['JS_STANDALONE']:
|
||||
# Standalone builds leave the source directory untouched,
|
||||
# which lets us run tests with the data files intact.
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
#include "jsapi.h"
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
#include "vm/StringBuffer.h"
|
||||
|
||||
// Tests for JS_GetErrorInterceptorCallback and JS_SetErrorInterceptorCallback.
|
||||
|
||||
|
||||
namespace {
|
||||
const double EXN_VALUE = 3.14;
|
||||
|
||||
static JS::PersistentRootedString gLatestMessage;
|
||||
|
||||
// An interceptor that stores the error in `gLatestMessage`.
|
||||
struct SimpleInterceptor: JSErrorInterceptor {
|
||||
virtual void interceptError(JSContext* cx, const JS::Value& val) override {
|
||||
js::StringBuffer buffer(cx);
|
||||
if (!ValueToStringBuffer(cx, val, buffer))
|
||||
MOZ_CRASH("Could not convert to string buffer");
|
||||
gLatestMessage = buffer.finishString();
|
||||
if (!gLatestMessage)
|
||||
MOZ_CRASH("Could not convert to string");
|
||||
}
|
||||
};
|
||||
|
||||
bool equalStrings(JSContext* cx, JSString* a, JSString* b) {
|
||||
int32_t result = 0;
|
||||
if (!JS_CompareStrings(cx, a, b, &result))
|
||||
MOZ_CRASH("Could not compare strings");
|
||||
return result == 0;
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_TEST(testErrorInterceptor)
|
||||
{
|
||||
// Run the following snippets.
|
||||
const char* SAMPLES[] = {
|
||||
"throw new Error('I am an Error')\0",
|
||||
"throw new TypeError('I am a TypeError')\0",
|
||||
"throw new ReferenceError('I am a ReferenceError')\0",
|
||||
"throw new SyntaxError('I am a SyntaxError')\0",
|
||||
"throw 5\0",
|
||||
"undefined[0]\0",
|
||||
"foo[0]\0",
|
||||
"b[\0",
|
||||
};
|
||||
// With the simpleInterceptor, we should end up with the following error:
|
||||
const char* TO_STRING[] = {
|
||||
"Error: I am an Error\0",
|
||||
"TypeError: I am a TypeError\0",
|
||||
"ReferenceError: I am a ReferenceError\0",
|
||||
"SyntaxError: I am a SyntaxError\0",
|
||||
"5\0",
|
||||
"TypeError: undefined has no properties\0",
|
||||
"ReferenceError: foo is not defined\0",
|
||||
"SyntaxError: expected expression, got end of script\0",
|
||||
};
|
||||
MOZ_ASSERT(mozilla::ArrayLength(SAMPLES) == mozilla::ArrayLength(TO_STRING));
|
||||
|
||||
|
||||
// Save original callback.
|
||||
JSErrorInterceptor* original = JS_GetErrorInterceptorCallback(cx->runtime());
|
||||
gLatestMessage.init(cx);
|
||||
|
||||
// Test without callback.
|
||||
JS_SetErrorInterceptorCallback(cx->runtime(), nullptr);
|
||||
CHECK(gLatestMessage == nullptr);
|
||||
|
||||
for (auto sample: SAMPLES) {
|
||||
if (execDontReport(sample, __FILE__, __LINE__))
|
||||
MOZ_CRASH("This sample should have failed");
|
||||
CHECK(JS_IsExceptionPending(cx));
|
||||
CHECK(gLatestMessage == nullptr);
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
|
||||
// Test with callback.
|
||||
SimpleInterceptor simpleInterceptor;
|
||||
JS_SetErrorInterceptorCallback(cx->runtime(), &simpleInterceptor);
|
||||
|
||||
// Test that we return the right callback.
|
||||
CHECK_EQUAL(JS_GetErrorInterceptorCallback(cx->runtime()), &simpleInterceptor);
|
||||
|
||||
// This shouldn't cause any error.
|
||||
EXEC("function bar() {}");
|
||||
CHECK(gLatestMessage == nullptr);
|
||||
|
||||
// Test error throwing with a callback that succeeds.
|
||||
for (size_t i = 0; i < mozilla::ArrayLength(SAMPLES); ++i) {
|
||||
// This should cause the appropriate error.
|
||||
if (execDontReport(SAMPLES[i], __FILE__, __LINE__))
|
||||
MOZ_CRASH("This sample should have failed");
|
||||
CHECK(JS_IsExceptionPending(cx));
|
||||
|
||||
// Check result of callback.
|
||||
CHECK(gLatestMessage != nullptr);
|
||||
CHECK(js::StringEqualsAscii(&gLatestMessage->asLinear(), TO_STRING[i]));
|
||||
|
||||
// Check the final error.
|
||||
JS::RootedValue exn(cx);
|
||||
CHECK(JS_GetPendingException(cx, &exn));
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
js::StringBuffer buffer(cx);
|
||||
CHECK(ValueToStringBuffer(cx, exn, buffer));
|
||||
CHECK(equalStrings(cx, buffer.finishString(), gLatestMessage));
|
||||
|
||||
// Cleanup.
|
||||
gLatestMessage = nullptr;
|
||||
}
|
||||
|
||||
// Test again without callback.
|
||||
JS_SetErrorInterceptorCallback(cx->runtime(), nullptr);
|
||||
for (size_t i = 0; i < mozilla::ArrayLength(SAMPLES); ++i) {
|
||||
if (execDontReport(SAMPLES[i], __FILE__, __LINE__))
|
||||
MOZ_CRASH("This sample should have failed");
|
||||
CHECK(JS_IsExceptionPending(cx));
|
||||
|
||||
// Check that the callback wasn't called.
|
||||
CHECK(gLatestMessage == nullptr);
|
||||
|
||||
// Check the final error.
|
||||
JS::RootedValue exn(cx);
|
||||
CHECK(JS_GetPendingException(cx, &exn));
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
js::StringBuffer buffer(cx);
|
||||
CHECK(ValueToStringBuffer(cx, exn, buffer));
|
||||
CHECK(js::StringEqualsAscii(buffer.finishString(), TO_STRING[i]));
|
||||
|
||||
// Cleanup.
|
||||
gLatestMessage = nullptr;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
JS_SetErrorInterceptorCallback(cx->runtime(), original);
|
||||
gLatestMessage = nullptr;
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(testErrorInterceptor)
|
|
@ -653,6 +653,40 @@ JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback)
|
|||
cx->runtime()->compartmentNameCallback = callback;
|
||||
}
|
||||
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetErrorInterceptorCallback(JSRuntime* rt, JSErrorInterceptor* callback)
|
||||
{
|
||||
rt->errorInterception.interceptor = callback;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSErrorInterceptor*)
|
||||
JS_GetErrorInterceptorCallback(JSRuntime* rt)
|
||||
{
|
||||
return rt->errorInterception.interceptor;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(Maybe<JSExnType>)
|
||||
JS_GetErrorType(const JS::Value& val)
|
||||
{
|
||||
// All errors are objects.
|
||||
if (!val.isObject())
|
||||
return mozilla::Nothing();
|
||||
|
||||
const JSObject& obj = val.toObject();
|
||||
|
||||
// All errors are `ErrorObject`.
|
||||
if (!obj.is<js::ErrorObject>()) {
|
||||
// Not one of the primitive errors.
|
||||
return mozilla::Nothing();
|
||||
}
|
||||
|
||||
const js::ErrorObject& err = obj.as<js::ErrorObject>();
|
||||
return mozilla::Some(err.type());
|
||||
}
|
||||
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks)
|
||||
{
|
||||
|
|
|
@ -680,6 +680,18 @@ typedef void
|
|||
using JSExternalStringSizeofCallback =
|
||||
size_t (*)(JSString* str, mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
||||
/**
|
||||
* Callback used to intercept JavaScript errors.
|
||||
*/
|
||||
struct JSErrorInterceptor {
|
||||
/**
|
||||
* This method is called whenever an error has been raised from JS code.
|
||||
*
|
||||
* This method MUST be infallible.
|
||||
*/
|
||||
virtual void interceptError(JSContext* cx, const JS::Value& error) = 0;
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
static MOZ_ALWAYS_INLINE JS::Value
|
||||
|
@ -1327,6 +1339,33 @@ JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks)
|
|||
extern JS_PUBLIC_API(void)
|
||||
JS_SetExternalStringSizeofCallback(JSContext* cx, JSExternalStringSizeofCallback callback);
|
||||
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
|
||||
// Set a callback that will be called whenever an error
|
||||
// is thrown in this runtime. This is designed as a mechanism
|
||||
// for logging errors. Note that the VM makes no attempt to sanitize
|
||||
// the contents of the error (so it may contain private data)
|
||||
// or to sort out among errors (so it may not be the error you
|
||||
// are interested in or for the component in which you are
|
||||
// interested).
|
||||
//
|
||||
// If the callback sets a new error, this new error
|
||||
// will replace the original error.
|
||||
//
|
||||
// May be `nullptr`.
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetErrorInterceptorCallback(JSRuntime*, JSErrorInterceptor* callback);
|
||||
|
||||
extern JS_PUBLIC_API(JSErrorInterceptor*)
|
||||
JS_GetErrorInterceptorCallback(JSRuntime*);
|
||||
|
||||
// Examine a value to determine if it is one of the built-in Error types.
|
||||
// If so, return the error type.
|
||||
extern JS_PUBLIC_API(mozilla::Maybe<JSExnType>)
|
||||
JS_GetErrorType(const JS::Value& val);
|
||||
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetCompartmentPrivate(JSCompartment* compartment, void* data);
|
||||
|
||||
|
|
|
@ -434,6 +434,31 @@ JSContext::minorGC(JS::gcreason::Reason reason)
|
|||
inline void
|
||||
JSContext::setPendingException(const js::Value& v)
|
||||
{
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
do {
|
||||
// Do not intercept exceptions if we are already
|
||||
// in the exception interceptor. That would lead
|
||||
// to infinite recursion.
|
||||
if (this->runtime()->errorInterception.isExecuting)
|
||||
break;
|
||||
|
||||
// Check whether we have an interceptor at all.
|
||||
if (!this->runtime()->errorInterception.interceptor)
|
||||
break;
|
||||
|
||||
// Make sure that we do not call the interceptor from within
|
||||
// the interceptor.
|
||||
this->runtime()->errorInterception.isExecuting = true;
|
||||
|
||||
// The interceptor must be infallible.
|
||||
const mozilla::DebugOnly<bool> wasExceptionPending = this->isExceptionPending();
|
||||
this->runtime()->errorInterception.interceptor->interceptError(this, v);
|
||||
MOZ_ASSERT(wasExceptionPending == this->isExceptionPending());
|
||||
|
||||
this->runtime()->errorInterception.isExecuting = false;
|
||||
} while (false);
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
|
||||
// overRecursed_ is set after the fact by ReportOverRecursed.
|
||||
this->overRecursed_ = false;
|
||||
this->throwing = true;
|
||||
|
|
|
@ -1081,6 +1081,30 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
|
|||
void* wasmUnwindPC() const {
|
||||
return wasmUnwindPC_;
|
||||
}
|
||||
|
||||
public:
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
// Support for informing the embedding of any error thrown.
|
||||
// This mechanism is designed to let the embedding
|
||||
// log/report/fail in case certain errors are thrown
|
||||
// (e.g. SyntaxError, ReferenceError or TypeError
|
||||
// in critical code).
|
||||
struct ErrorInterceptionSupport {
|
||||
ErrorInterceptionSupport()
|
||||
: isExecuting(false)
|
||||
, interceptor(nullptr)
|
||||
{ }
|
||||
|
||||
// true if the error interceptor is currently executing,
|
||||
// false otherwise. Used to avoid infinite loops.
|
||||
bool isExecuting;
|
||||
|
||||
// if non-null, any call to `setPendingException`
|
||||
// in this runtime will trigger the call to `interceptor`
|
||||
JSErrorInterceptor* interceptor;
|
||||
};
|
||||
ErrorInterceptionSupport errorInterception;
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
|
|
@ -1159,4 +1159,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1522348268251000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1522434806681000);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1524767455585000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1524853993707000);
|
||||
%%
|
||||
0-1.party, 1
|
||||
0.me.uk, 1
|
||||
|
@ -656,7 +656,6 @@ academicexperts.us, 1
|
|||
academie-de-police.ch, 1
|
||||
academy4.net, 1
|
||||
academytv.com.au, 1
|
||||
acadianapatios.com, 1
|
||||
acampar.com.br, 1
|
||||
acaonegocios.com.br, 1
|
||||
acara-yoga.de, 1
|
||||
|
@ -2654,6 +2653,7 @@ azabani.com, 1
|
|||
azamra.com, 1
|
||||
azia.info, 1
|
||||
azimut.fr, 1
|
||||
azino777.ru, 1
|
||||
azlk-team.ru, 1
|
||||
azort.com, 1
|
||||
azrazalea.net, 1
|
||||
|
@ -4245,7 +4245,6 @@ bramvanaken.be, 1
|
|||
bran.land, 1
|
||||
bran.soy, 1
|
||||
branch-bookkeeper.com, 1
|
||||
branchzero.com, 1
|
||||
brandbil.dk, 1
|
||||
brandbuilderwebsites.com, 1
|
||||
brandcodeconsulting.com, 1
|
||||
|
@ -5427,7 +5426,6 @@ cheapssl.com.tr, 1
|
|||
cheapticket.in, 1
|
||||
cheapwritinghelp.com, 1
|
||||
cheapwritingservice.com, 1
|
||||
cheatturnitin.com, 1
|
||||
chebwebb.com, 1
|
||||
check.torproject.org, 0
|
||||
checkecert.nl, 1
|
||||
|
@ -5670,7 +5668,6 @@ ciderclub.com, 1
|
|||
cie-theatre-montfaucon.ch, 1
|
||||
cielbleu.org, 1
|
||||
cielly.com, 1
|
||||
cienbeaute-lidl.fr, 1
|
||||
cifop-numerique.fr, 1
|
||||
cig-dem.com, 1
|
||||
cigar-cartel.com, 1
|
||||
|
@ -5722,7 +5719,7 @@ cirugiasplasticas.com.mx, 1
|
|||
cirujanooral.com, 1
|
||||
cirurgicagervasio.com.br, 1
|
||||
cirurgicalucena.com.br, 1
|
||||
ciscodude.net, 0
|
||||
ciscodude.net, 1
|
||||
cisoaid.com, 1
|
||||
ciss.ltd, 1
|
||||
cisy.me, 1
|
||||
|
@ -5893,7 +5890,6 @@ cloudcaprice.net, 1
|
|||
cloudcloudcloud.cloud, 1
|
||||
cloudflare.com, 1
|
||||
cloudflareonazure.com, 1
|
||||
cloudfren.com, 1
|
||||
cloudia.org, 1
|
||||
cloudily.com, 1
|
||||
cloudimproved.com, 1
|
||||
|
@ -6292,7 +6288,7 @@ concursopublico.com.br, 1
|
|||
concursos.com.br, 1
|
||||
concursosabertos.com.br, 1
|
||||
condecom.com.br, 1
|
||||
condepenalba.com, 1
|
||||
condepenalba.com, 0
|
||||
condesaelectronics.com, 1
|
||||
condosforcash.com, 1
|
||||
condroz-motors.be, 1
|
||||
|
@ -7318,7 +7314,6 @@ davidschadlich.com, 1
|
|||
davidscherzer.at, 1
|
||||
davidschlachter.com, 1
|
||||
davidstuff.net, 1
|
||||
davie3.com, 1
|
||||
davimun.org, 1
|
||||
davisroi.com, 1
|
||||
davo-usedcars.be, 1
|
||||
|
@ -7630,6 +7625,7 @@ derehamcastles.co.uk, 1
|
|||
derekkent.com, 1
|
||||
derekseaman.com, 1
|
||||
derekseaman.studio, 1
|
||||
dergeilstestammderwelt.de, 1
|
||||
derhil.de, 1
|
||||
derivativeshub.pro, 1
|
||||
derive.cc, 1
|
||||
|
@ -7743,7 +7739,6 @@ devh.de, 1
|
|||
devh.net, 1
|
||||
deviant.email, 1
|
||||
devillers-occasions.be, 1
|
||||
devilshakerz.com, 1
|
||||
deviltracks.net, 1
|
||||
deviltraxxx.de, 1
|
||||
devinfo.net, 0
|
||||
|
@ -7846,6 +7841,7 @@ dicionarioetimologico.com.br, 1
|
|||
dick.red, 1
|
||||
dickieslife.com, 1
|
||||
dickpics.ru, 1
|
||||
dicoding.com, 1
|
||||
didacte.com, 1
|
||||
didche.net, 1
|
||||
diddens.de, 1
|
||||
|
@ -8021,7 +8017,7 @@ disconformity.net, 1
|
|||
discord-chan.net, 1
|
||||
discordapp.com, 1
|
||||
discordghost.space, 1
|
||||
discotek.club, 0
|
||||
discotek.club, 1
|
||||
discount24.de, 1
|
||||
discountmania.eu, 1
|
||||
discountmetaux.fr, 1
|
||||
|
@ -8843,7 +8839,6 @@ echoworld.ch, 1
|
|||
ecirtam.net, 1
|
||||
eckel.co, 1
|
||||
eclipse.ws, 1
|
||||
ecnetworker.com, 1
|
||||
eco-derattizzazione.it, 1
|
||||
eco-work.it, 1
|
||||
ecoccinelles.ch, 1
|
||||
|
@ -11341,6 +11336,7 @@ g4w.co, 1
|
|||
gaanbaksho.com.au, 1
|
||||
gaasuper6.com, 1
|
||||
gabemack.com, 1
|
||||
gabethebabetv.com, 1
|
||||
gabriel.to, 1
|
||||
gabriele-kluge.de, 1
|
||||
gabrielsimonet.ch, 1
|
||||
|
@ -11681,6 +11677,7 @@ gerald-zojer.com, 1
|
|||
geraldsonrealty.com, 1
|
||||
gerardobsd.com, 1
|
||||
gerardozamudio.mx, 1
|
||||
geri.be, 1
|
||||
germandarknes.net, 1
|
||||
germansoldiers.net, 1
|
||||
germanssky.de, 1
|
||||
|
@ -12171,6 +12168,7 @@ graeber.com, 1
|
|||
graetnew.com, 1
|
||||
graf.re, 1
|
||||
grafcaps.com, 1
|
||||
graffen.dk, 1
|
||||
grafmurr.de, 1
|
||||
grahamofthewheels.com, 1
|
||||
grailians.com, 1
|
||||
|
@ -14070,7 +14068,6 @@ impact.health.nz, 1
|
|||
impacter.eu, 1
|
||||
impactfestival.be, 1
|
||||
impactpub.ch, 1
|
||||
impakho.com, 1
|
||||
impas.se, 1
|
||||
imperdin.com, 1
|
||||
imperdintechnologies.com, 1
|
||||
|
@ -14405,7 +14402,6 @@ internetpro.me, 1
|
|||
internetradiocharts.de, 1
|
||||
internetstaff.com, 1
|
||||
internetzentrale.net, 1
|
||||
internshipandwork.ru, 1
|
||||
interociter-enterprises.com, 1
|
||||
interracial.dating, 1
|
||||
intersectraven.net, 1
|
||||
|
@ -14692,7 +14688,6 @@ it-world.eu, 1
|
|||
it.search.yahoo.com, 0
|
||||
itactiq.com, 1
|
||||
itactiq.info, 1
|
||||
itad.top, 1
|
||||
ital-gamma.be, 1
|
||||
italia-store.com, 1
|
||||
italiachegioca.com, 1
|
||||
|
@ -14772,7 +14767,6 @@ itswincer.com, 1
|
|||
ittop-gabon.com, 1
|
||||
itzap.com.au, 1
|
||||
ivanbenito.com, 1
|
||||
ivancacic.com, 0
|
||||
ivanilla.org, 1
|
||||
ivanmeade.com, 1
|
||||
ivanpolchenko.com, 1
|
||||
|
@ -15615,6 +15609,7 @@ jutlander.dk, 1
|
|||
juventusclublugano.ch, 1
|
||||
juventusmania1897.com, 1
|
||||
juwelierstoopman.nl, 1
|
||||
juzgalo.com, 1
|
||||
jva-wuerzburg.de, 1
|
||||
jvanerp.nl, 1
|
||||
jvbouncycastlehire.co.uk, 1
|
||||
|
@ -15630,6 +15625,7 @@ jwolt-lx.com, 1
|
|||
jwschuepfheim.ch, 1
|
||||
jxir.de, 1
|
||||
jyggen.com, 1
|
||||
jym.fit, 1
|
||||
jyoti-fairworks.org, 1
|
||||
jzbk.org, 1
|
||||
k-homes.net, 1
|
||||
|
@ -15708,7 +15704,6 @@ kalsbouncies.com, 1
|
|||
kaltenbrunner.it, 1
|
||||
kalterersee.ch, 1
|
||||
kamalame.co, 1
|
||||
kamikaichimaru.com, 1
|
||||
kamitech.ch, 1
|
||||
kamixa.se, 1
|
||||
kana.me, 1
|
||||
|
@ -16342,7 +16337,6 @@ kokensupport.com, 1
|
|||
koketteriet.se, 1
|
||||
kokumoto.com, 1
|
||||
koldanews.com, 1
|
||||
kolin.org, 1
|
||||
kolizaskrap.bg, 1
|
||||
kolja-engelmann.de, 1
|
||||
kolkataflowermall.com, 1
|
||||
|
@ -16385,7 +16379,7 @@ konsertoversikt.no, 1
|
|||
konst.se, 1
|
||||
kontakthuman.hu, 1
|
||||
kontaxis.org, 1
|
||||
kontorhaus-schlachte.de, 0
|
||||
kontorhaus-schlachte.de, 1
|
||||
konventseliten.se, 1
|
||||
konyalian.com, 1
|
||||
konzertheld.de, 1
|
||||
|
@ -17765,6 +17759,7 @@ loritaboegl.de, 1
|
|||
losebellyfat.pro, 1
|
||||
losless.fr, 1
|
||||
loss.no, 1
|
||||
lostandcash.com, 1
|
||||
lostarq.com, 1
|
||||
lostingames.de, 1
|
||||
lostkeys.co.uk, 1
|
||||
|
@ -17888,6 +17883,7 @@ lucysan.net, 1
|
|||
ludikovsky.name, 1
|
||||
ludovic-muller.fr, 1
|
||||
ludwig.im, 1
|
||||
ludwiggrill.de, 1
|
||||
ludwigpro.net, 1
|
||||
luehne.de, 1
|
||||
luelistan.net, 1
|
||||
|
@ -18311,7 +18307,6 @@ manneguiden.no, 1
|
|||
mannford.com, 1
|
||||
mannheimbloggt.tk, 1
|
||||
manns-solutions.co.uk, 1
|
||||
manns-solutions.ru, 1
|
||||
mannschafft.ch, 1
|
||||
mannsolutions.co.uk, 1
|
||||
manoirdecontres.com, 1
|
||||
|
@ -19815,7 +19810,7 @@ mplusm.eu, 1
|
|||
mpn.poker, 1
|
||||
mpnpokertour.com, 1
|
||||
mpodraza.pl, 1
|
||||
mpreserver.com, 0
|
||||
mpreserver.com, 1
|
||||
mpserver12.org, 1
|
||||
mpsgarage.com.au, 1
|
||||
mpsoundcraft.com, 1
|
||||
|
@ -21360,7 +21355,6 @@ nystudio107.com, 1
|
|||
nyxi.eu, 1
|
||||
nyyu.tk, 1
|
||||
nzb.cat, 0
|
||||
nzmk.cz, 0
|
||||
nzstudy.ac.nz, 1
|
||||
o-loska.cz, 1
|
||||
o-sp.com, 1
|
||||
|
@ -21423,7 +21417,6 @@ ochsundjunior.ch, 1
|
|||
ocim.ch, 1
|
||||
ockendenhemming.co.uk, 1
|
||||
ocloud.fr, 1
|
||||
ocmeulebeke.be, 1
|
||||
ocolere.ch, 1
|
||||
ocotg.com, 1
|
||||
ocrn.nl, 1
|
||||
|
@ -23139,6 +23132,7 @@ poinsot.info, 1
|
|||
pointaction.com, 1
|
||||
pointagri.com, 1
|
||||
pointhost.de, 1
|
||||
pointiswunderland.de, 1
|
||||
points4unitedway.com, 1
|
||||
pointsixtyfive.com, 1
|
||||
pointum.com, 1
|
||||
|
@ -23626,7 +23620,6 @@ promoterms.com.au, 1
|
|||
promotiongeeks.com, 0
|
||||
pronto-intervento.net, 1
|
||||
proobec.cz, 1
|
||||
proofwiki.org, 1
|
||||
proos.nl, 1
|
||||
proovn.com, 1
|
||||
propagandablog.de, 1
|
||||
|
@ -23932,7 +23925,6 @@ qq-navi.com, 1
|
|||
qqj.net, 1
|
||||
qqvips.com, 1
|
||||
qrcontagion.com, 1
|
||||
qredo.com, 1
|
||||
qrforex.com, 1
|
||||
qrlfinancial.com, 1
|
||||
qrpth.eu, 1
|
||||
|
@ -24949,7 +24941,6 @@ roguetechhub.org, 1
|
|||
rohanbassett.com, 1
|
||||
rohedaten.de, 1
|
||||
rohitagr.com, 1
|
||||
rohlik.cz, 1
|
||||
rointe.online, 1
|
||||
roiscroll.com, 1
|
||||
rokki.ch, 1
|
||||
|
@ -25301,6 +25292,7 @@ sadbox.es, 1
|
|||
sadbox.org, 1
|
||||
sadhawkict.org, 1
|
||||
sadmansh.com, 1
|
||||
sadsu.com, 1
|
||||
saengsook.com, 1
|
||||
saengsuk.com, 1
|
||||
safar.sk, 1
|
||||
|
@ -25330,7 +25322,6 @@ safetyrisk.net, 1
|
|||
safezone.cc, 1
|
||||
safire.ac.za, 1
|
||||
sagedocumentmanager.com, 1
|
||||
sagemontchurch.org, 1
|
||||
sagerus.com, 1
|
||||
sagsmarseille.com, 1
|
||||
sahar.io, 1
|
||||
|
@ -25643,7 +25634,6 @@ schamlosharmlos.de, 1
|
|||
schaper-sport.com, 1
|
||||
schatmeester.be, 1
|
||||
schatzibaers.de, 1
|
||||
schau-rein.co.at, 1
|
||||
schawe.me, 1
|
||||
schd.io, 1
|
||||
scheduleme.io, 1
|
||||
|
@ -26283,7 +26273,6 @@ shan.io, 0
|
|||
shanae.nl, 1
|
||||
shanetully.com, 1
|
||||
shanewadleigh.com, 1
|
||||
shang-yu.cn, 1
|
||||
shannoneichorn.com, 1
|
||||
shansing.cn, 1
|
||||
shansing.com, 1
|
||||
|
@ -26715,7 +26704,6 @@ sinonimosonline.com, 1
|
|||
sinonimosonline.com.br, 1
|
||||
sinoscandinavia.se, 1
|
||||
sinquin.eu, 1
|
||||
sinsojb.me, 1
|
||||
sint-joris.nl, 1
|
||||
sinterama.biz, 1
|
||||
sintesysglobal.com, 1
|
||||
|
@ -26729,7 +26717,6 @@ sirbouncelot.co.uk, 1
|
|||
sirena.co.jp, 1
|
||||
sirenslove.com, 1
|
||||
siriuspup.com, 1
|
||||
siroop.ch, 1
|
||||
sirtaptap.com, 1
|
||||
sirtuins.com, 1
|
||||
sistel.es, 1
|
||||
|
@ -28244,7 +28231,6 @@ swfmax.com, 1
|
|||
swift-devedge.de, 1
|
||||
swiftconf.com, 1
|
||||
swiftqueue.com, 1
|
||||
swiggy.com, 1
|
||||
swilly.org, 1
|
||||
swimbee.nl, 1
|
||||
swimturk.com.tr, 1
|
||||
|
@ -28609,7 +28595,7 @@ teamnorthgermany.de, 1
|
|||
teampaddymurphy.ch, 1
|
||||
teampaddymurphy.ie, 1
|
||||
teamtouring.net, 1
|
||||
teamtrack.uk, 0
|
||||
teamtrack.uk, 1
|
||||
teamupturn.com, 1
|
||||
teamupturn.org, 1
|
||||
teamx-gaming.de, 1
|
||||
|
@ -29304,6 +29290,7 @@ tianshili.me, 1
|
|||
tianxicaipiao.com, 1
|
||||
tianxicaipiao.win, 1
|
||||
tianxicp.com, 1
|
||||
tibbitshall.ca, 1
|
||||
tibipg.com, 1
|
||||
tibovanheule.site, 1
|
||||
ticfleet.com, 1
|
||||
|
@ -29576,6 +29563,7 @@ tollsjekk.no, 1
|
|||
tom-geiger.de, 1
|
||||
tom-kunze.de, 1
|
||||
tom-maxwell.com, 1
|
||||
tom.horse, 1
|
||||
tomabrafix.de, 1
|
||||
tomandshirley.com, 1
|
||||
tomasjacik.cz, 1
|
||||
|
@ -29943,7 +29931,7 @@ treasuredinheritanceministry.com, 1
|
|||
treasurydirect.gov, 1
|
||||
treasuryhunt.gov, 1
|
||||
treasuryscams.gov, 1
|
||||
treebaglia.xyz, 0
|
||||
treebaglia.xyz, 1
|
||||
treehousebydesign.com, 1
|
||||
treehouseresort.nl, 1
|
||||
trees.chat, 1
|
||||
|
@ -30518,6 +30506,7 @@ unseen.tw, 1
|
|||
unser-gartenforum.de, 1
|
||||
unsuspicious.click, 1
|
||||
unterfrankenclan.de, 1
|
||||
unterkunft.guru, 1
|
||||
unterschicht.tv, 1
|
||||
untethereddog.com, 1
|
||||
untoldstory.eu, 1
|
||||
|
@ -30576,6 +30565,7 @@ urbanietz-immobilien.de, 1
|
|||
urbanmelbourne.info, 1
|
||||
urbannewsservice.com, 1
|
||||
urbansparrow.in, 1
|
||||
urbanstylestaging.com, 1
|
||||
urbanwildlifealliance.org, 1
|
||||
urbexdk.nl, 1
|
||||
urcentral.com, 1
|
||||
|
@ -31294,7 +31284,6 @@ voyageschine.com, 1
|
|||
voyagesdetective.fr, 1
|
||||
vozami.com, 1
|
||||
vpc-display.com, 1
|
||||
vpls.co.th, 1
|
||||
vpn.ht, 1
|
||||
vpnservice.nl, 1
|
||||
vpnzoom.com, 1
|
||||
|
@ -31494,7 +31483,6 @@ waterschaplimburg.nl, 1
|
|||
watertrails.io, 1
|
||||
waterworkscondos.com, 1
|
||||
watsonwork.me, 1
|
||||
wattechweb.com, 1
|
||||
wave-ola.es, 1
|
||||
wavesboardshop.com, 1
|
||||
wavesoftime.com, 1
|
||||
|
@ -31509,7 +31497,6 @@ waytt.cf, 0
|
|||
waze.com, 1
|
||||
wbci.us, 1
|
||||
wbg-vs.de, 1
|
||||
wbit.co.il, 1
|
||||
wbt-solutions.ch, 1
|
||||
wbt-solutions.net, 1
|
||||
wbuntu.com, 1
|
||||
|
@ -32053,7 +32040,6 @@ windhaven.nl, 0
|
|||
windholz.us, 1
|
||||
windowcleaningexperts.net, 1
|
||||
windows10insider.com, 1
|
||||
windowsforum.com, 1
|
||||
windowsnerd.com, 1
|
||||
windowstech.it, 1
|
||||
windowwellcovers.com, 1
|
||||
|
@ -32406,9 +32392,8 @@ wvg.myds.me, 1
|
|||
wvw-8522.com, 1
|
||||
wvw698.com, 1
|
||||
wweforums.net, 1
|
||||
wweichen.com.cn, 0
|
||||
wweichen.com.cn, 1
|
||||
wwgc2011.se, 1
|
||||
wwv-8522.com, 1
|
||||
www-33445.com, 1
|
||||
www-49889.com, 1
|
||||
www-62755.com, 1
|
||||
|
@ -33203,7 +33188,6 @@ zaratan.fr, 1
|
|||
zargaripour.com, 1
|
||||
zarmarket.org, 1
|
||||
zarpo.com.br, 1
|
||||
zary.me, 1
|
||||
zaufanatrzeciastrona.pl, 1
|
||||
zavec.com.ec, 1
|
||||
zavetaji.lv, 1
|
||||
|
@ -33348,7 +33332,6 @@ zittingskalender.be, 1
|
|||
zivava.ge, 1
|
||||
zivmergers.com, 1
|
||||
zivver.com, 1
|
||||
zivy-ruzenec.cz, 0
|
||||
zivyruzenec.cz, 0
|
||||
zixiao.wang, 1
|
||||
zk.gd, 1
|
||||
|
|
|
@ -1382,7 +1382,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
.map(|argument| argument.to_css_string())
|
||||
.collect();
|
||||
|
||||
let mut draw_result = match state.layout_context.registered_painters.get(&name) {
|
||||
let draw_result = match state.layout_context.registered_painters.get(&name) {
|
||||
Some(painter) => {
|
||||
debug!("Drawing a paint image {}({},{}).", name, size_in_px.width, size_in_px.height);
|
||||
let properties = painter.properties().iter()
|
||||
|
@ -1397,19 +1397,22 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
},
|
||||
};
|
||||
|
||||
let webrender_image = WebRenderImageInfo {
|
||||
width: draw_result.width,
|
||||
height: draw_result.height,
|
||||
format: draw_result.format,
|
||||
key: draw_result.image_key,
|
||||
};
|
||||
if let Ok(draw_result) = draw_result {
|
||||
let webrender_image = WebRenderImageInfo {
|
||||
width: draw_result.width,
|
||||
height: draw_result.height,
|
||||
format: draw_result.format,
|
||||
key: draw_result.image_key,
|
||||
};
|
||||
|
||||
for url in draw_result.missing_image_urls.drain(..) {
|
||||
debug!("Requesting missing image URL {}.", url);
|
||||
state.layout_context.get_webrender_image_for_url(self.node, url, UsePlaceholder::No);
|
||||
for url in draw_result.missing_image_urls.into_iter() {
|
||||
debug!("Requesting missing image URL {}.", url);
|
||||
state.layout_context.get_webrender_image_for_url(self.node, url, UsePlaceholder::No);
|
||||
}
|
||||
Some(webrender_image)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
Some(webrender_image)
|
||||
}
|
||||
|
||||
fn build_display_list_for_background_gradient(&self,
|
||||
|
|
|
@ -100,8 +100,8 @@ use script_layout_interface::rpc::{LayoutRPC, MarginStyleResponse, NodeOverflowR
|
|||
use script_layout_interface::rpc::TextIndexResponse;
|
||||
use script_layout_interface::wrapper_traits::LayoutNode;
|
||||
use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg};
|
||||
use script_traits::{DrawAPaintImageResult, PaintWorkletError};
|
||||
use script_traits::{ScrollState, UntrustedNodeAddress};
|
||||
use script_traits::DrawAPaintImageResult;
|
||||
use script_traits::Painter;
|
||||
use selectors::Element;
|
||||
use servo_arc::Arc as ServoArc;
|
||||
|
@ -1787,7 +1787,7 @@ impl Painter for RegisteredPainterImpl {
|
|||
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
properties: Vec<(Atom, String)>,
|
||||
arguments: Vec<String>)
|
||||
-> DrawAPaintImageResult
|
||||
-> Result<DrawAPaintImageResult, PaintWorkletError>
|
||||
{
|
||||
self.painter.draw_a_paint_image(size, device_pixel_ratio, properties, arguments)
|
||||
}
|
||||
|
|
|
@ -45,9 +45,10 @@ use js::rust::Runtime;
|
|||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::image::base::PixelFormat;
|
||||
use net_traits::image_cache::ImageCache;
|
||||
use script_traits::DrawAPaintImageResult;
|
||||
use script_traits::{DrawAPaintImageResult, PaintWorkletError};
|
||||
use script_traits::Painter;
|
||||
use servo_atoms::Atom;
|
||||
use servo_config::prefs::PREFS;
|
||||
use servo_url::ServoUrl;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
|
@ -58,6 +59,8 @@ use std::sync::Arc;
|
|||
use std::sync::Mutex;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use style_traits::CSSPixel;
|
||||
use style_traits::DevicePixel;
|
||||
use style_traits::SpeculativePainter;
|
||||
|
@ -343,7 +346,7 @@ impl PaintWorkletGlobalScope {
|
|||
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
properties: Vec<(Atom, String)>,
|
||||
arguments: Vec<String>)
|
||||
-> DrawAPaintImageResult {
|
||||
-> Result<DrawAPaintImageResult, PaintWorkletError> {
|
||||
let name = self.name.clone();
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
let task = PaintWorkletTask::DrawAPaintImage(name,
|
||||
|
@ -354,7 +357,14 @@ impl PaintWorkletGlobalScope {
|
|||
sender);
|
||||
self.executor.lock().expect("Locking a painter.")
|
||||
.schedule_a_worklet_task(WorkletTask::Paint(task));
|
||||
receiver.recv().expect("Worklet thread died?")
|
||||
|
||||
let timeout = PREFS.get("dom.worklet.timeout_ms")
|
||||
.as_u64()
|
||||
.unwrap_or(10u64);
|
||||
|
||||
let timeout_duration = Duration::from_millis(timeout);
|
||||
receiver.recv_timeout(timeout_duration)
|
||||
.map_err(|e| PaintWorkletError::from(e))
|
||||
}
|
||||
}
|
||||
Box::new(WorkletPainter {
|
||||
|
@ -364,6 +374,60 @@ impl PaintWorkletGlobalScope {
|
|||
}
|
||||
}
|
||||
|
||||
/// Tasks which can be peformed by a paint worklet
|
||||
pub enum PaintWorkletTask {
|
||||
DrawAPaintImage(Atom,
|
||||
TypedSize2D<f32, CSSPixel>,
|
||||
TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
Vec<(Atom, String)>,
|
||||
Vec<String>,
|
||||
Sender<DrawAPaintImageResult>),
|
||||
SpeculativelyDrawAPaintImage(Atom,
|
||||
Vec<(Atom, String)>,
|
||||
Vec<String>),
|
||||
}
|
||||
|
||||
/// A paint definition
|
||||
/// <https://drafts.css-houdini.org/css-paint-api/#paint-definition>
|
||||
/// This type is dangerous, because it contains uboxed `Heap<JSVal>` values,
|
||||
/// which can't be moved.
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
#[must_root]
|
||||
struct PaintDefinition {
|
||||
class_constructor: Heap<JSVal>,
|
||||
paint_function: Heap<JSVal>,
|
||||
constructor_valid_flag: Cell<bool>,
|
||||
context_alpha_flag: bool,
|
||||
// TODO: this should be a list of CSS syntaxes.
|
||||
input_arguments_len: usize,
|
||||
// TODO: the spec calls for fresh rendering contexts each time a paint image is drawn,
|
||||
// but to avoid having the primary worklet thread create a new renering context,
|
||||
// we recycle them.
|
||||
context: Dom<PaintRenderingContext2D>,
|
||||
}
|
||||
|
||||
impl PaintDefinition {
|
||||
fn new(class_constructor: HandleValue,
|
||||
paint_function: HandleValue,
|
||||
alpha: bool,
|
||||
input_arguments_len: usize,
|
||||
context: &PaintRenderingContext2D)
|
||||
-> Box<PaintDefinition>
|
||||
{
|
||||
let result = Box::new(PaintDefinition {
|
||||
class_constructor: Heap::default(),
|
||||
paint_function: Heap::default(),
|
||||
constructor_valid_flag: Cell::new(true),
|
||||
context_alpha_flag: alpha,
|
||||
input_arguments_len: input_arguments_len,
|
||||
context: Dom::from_ref(context),
|
||||
});
|
||||
result.class_constructor.set(class_constructor.get());
|
||||
result.paint_function.set(paint_function.get());
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope {
|
||||
#[allow(unsafe_code)]
|
||||
#[allow(unrooted_must_root)]
|
||||
|
@ -445,58 +509,14 @@ impl PaintWorkletGlobalScopeMethods for PaintWorkletGlobalScope {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Tasks which can be peformed by a paint worklet
|
||||
pub enum PaintWorkletTask {
|
||||
DrawAPaintImage(Atom,
|
||||
TypedSize2D<f32, CSSPixel>,
|
||||
TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
Vec<(Atom, String)>,
|
||||
Vec<String>,
|
||||
Sender<DrawAPaintImageResult>),
|
||||
SpeculativelyDrawAPaintImage(Atom,
|
||||
Vec<(Atom, String)>,
|
||||
Vec<String>),
|
||||
}
|
||||
|
||||
/// A paint definition
|
||||
/// <https://drafts.css-houdini.org/css-paint-api/#paint-definition>
|
||||
/// This type is dangerous, because it contains uboxed `Heap<JSVal>` values,
|
||||
/// which can't be moved.
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
#[must_root]
|
||||
struct PaintDefinition {
|
||||
class_constructor: Heap<JSVal>,
|
||||
paint_function: Heap<JSVal>,
|
||||
constructor_valid_flag: Cell<bool>,
|
||||
context_alpha_flag: bool,
|
||||
// TODO: this should be a list of CSS syntaxes.
|
||||
input_arguments_len: usize,
|
||||
// TODO: the spec calls for fresh rendering contexts each time a paint image is drawn,
|
||||
// but to avoid having the primary worklet thread create a new renering context,
|
||||
// we recycle them.
|
||||
context: Dom<PaintRenderingContext2D>,
|
||||
}
|
||||
|
||||
impl PaintDefinition {
|
||||
fn new(class_constructor: HandleValue,
|
||||
paint_function: HandleValue,
|
||||
alpha: bool,
|
||||
input_arguments_len: usize,
|
||||
context: &PaintRenderingContext2D)
|
||||
-> Box<PaintDefinition>
|
||||
{
|
||||
let result = Box::new(PaintDefinition {
|
||||
class_constructor: Heap::default(),
|
||||
paint_function: Heap::default(),
|
||||
constructor_valid_flag: Cell::new(true),
|
||||
context_alpha_flag: alpha,
|
||||
input_arguments_len: input_arguments_len,
|
||||
context: Dom::from_ref(context),
|
||||
});
|
||||
result.class_constructor.set(class_constructor.get());
|
||||
result.paint_function.set(paint_function.get());
|
||||
result
|
||||
/// This is a blocking sleep function available in the paint worklet
|
||||
/// global scope behind the dom.worklet.enabled +
|
||||
/// dom.worklet.blockingsleep.enabled prefs. It is to be used only for
|
||||
/// testing, e.g., timeouts, where otherwise one would need busy waiting
|
||||
/// to make sure a certain timeout is triggered.
|
||||
/// check-tidy: no specs after this line
|
||||
fn Sleep(&self, ms: u64) {
|
||||
thread::sleep(Duration::from_millis(ms));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,4 +6,8 @@
|
|||
[Global=(Worklet,PaintWorklet), Pref="dom.worklet.enabled", Exposed=PaintWorklet]
|
||||
interface PaintWorkletGlobalScope : WorkletGlobalScope {
|
||||
[Throws] void registerPaint(DOMString name, VoidFunction paintCtor);
|
||||
// This function is to be used only for testing, and should not be
|
||||
// accessible outside of that use.
|
||||
[Pref="dom.worklet.blockingsleep.enabled"]
|
||||
void sleep(unsigned long long ms);
|
||||
};
|
||||
|
|
|
@ -869,7 +869,7 @@ pub trait Painter: SpeculativePainter {
|
|||
zoom: TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
properties: Vec<(Atom, String)>,
|
||||
arguments: Vec<String>)
|
||||
-> DrawAPaintImageResult;
|
||||
-> Result<DrawAPaintImageResult, PaintWorkletError>;
|
||||
}
|
||||
|
||||
impl fmt::Debug for Painter {
|
||||
|
|
|
@ -88,6 +88,17 @@ def get_digest_data(config, run, taskdesc):
|
|||
if deps:
|
||||
data.extend(sorted(deps.values()))
|
||||
|
||||
# If the task uses an in-tree docker image, we want it to influence
|
||||
# the index path as well. Ideally, the content of the docker image itself
|
||||
# should have an influence, but at the moment, we can't get that
|
||||
# information here. So use the docker image name as a proxy. Not a lot of
|
||||
# changes to docker images actually have an impact on the resulting
|
||||
# toolchain artifact, so we'll just rely on such important changes to be
|
||||
# accompanied with a docker image name change.
|
||||
image = taskdesc['worker'].get('docker-image', {}).get('in-tree')
|
||||
if image:
|
||||
data.extend(image)
|
||||
|
||||
# Likewise script arguments should influence the index.
|
||||
args = run.get('arguments')
|
||||
if args:
|
||||
|
|
|
@ -64,6 +64,10 @@
|
|||
#include <gtk/gtkprivate.h>
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_WAYLAND)
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
|
||||
|
@ -1709,16 +1713,22 @@ nsWindow::GetNativeData(uint32_t aDataType)
|
|||
#ifdef MOZ_X11
|
||||
GdkDisplay* gdkDisplay = gdk_display_get_default();
|
||||
if (GDK_IS_X11_DISPLAY(gdkDisplay)) {
|
||||
return GDK_DISPLAY_XDISPLAY(gdkDisplay);
|
||||
return GDK_DISPLAY_XDISPLAY(gdkDisplay);
|
||||
}
|
||||
#endif /* MOZ_X11 */
|
||||
// Don't bother to return native display on Wayland as it's for
|
||||
// X11 only NPAPI plugins.
|
||||
return nullptr;
|
||||
}
|
||||
case NS_NATIVE_SHELLWIDGET:
|
||||
return GetToplevelWidget();
|
||||
|
||||
case NS_NATIVE_SHAREABLE_WINDOW:
|
||||
return (void *) GDK_WINDOW_XID(gdk_window_get_toplevel(mGdkWindow));
|
||||
if (mIsX11Display) {
|
||||
return (void *) GDK_WINDOW_XID(gdk_window_get_toplevel(mGdkWindow));
|
||||
}
|
||||
NS_WARNING("nsWindow::GetNativeData(): NS_NATIVE_SHAREABLE_WINDOW is not handled on Wayland!");
|
||||
return nullptr;
|
||||
case NS_RAW_NATIVE_IME_CONTEXT: {
|
||||
void* pseudoIMEContext = GetPseudoIMEContext();
|
||||
if (pseudoIMEContext) {
|
||||
|
@ -2140,7 +2150,7 @@ nsWindow::OnExposeEvent(cairo_t *cr)
|
|||
|
||||
LOGDRAW(("sending expose event [%p] %p 0x%lx (rects follow):\n",
|
||||
(void *)this, (void *)mGdkWindow,
|
||||
gdk_x11_window_get_xid(mGdkWindow)));
|
||||
mIsX11Display ? gdk_x11_window_get_xid(mGdkWindow) : 0));
|
||||
|
||||
// Our bounds may have changed after calling WillPaintWindow. Clip
|
||||
// to the new bounds here. The region is relative to this
|
||||
|
@ -3652,10 +3662,14 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
// which will use a Window with the override-redirect attribute
|
||||
// (for temporary windows).
|
||||
// For long-lived windows, their stacking order is managed by the
|
||||
// window manager, as indicated by GTK_WINDOW_TOPLEVEL ...
|
||||
GtkWindowType type =
|
||||
mWindowType != eWindowType_popup || aInitData->mNoAutoHide ?
|
||||
GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
|
||||
// window manager, as indicated by GTK_WINDOW_TOPLEVEL.
|
||||
// For Wayland we have to always use GTK_WINDOW_POPUP to control
|
||||
// popup window position.
|
||||
GtkWindowType type = GTK_WINDOW_TOPLEVEL;
|
||||
if (mWindowType == eWindowType_popup) {
|
||||
type = (mIsX11Display && aInitData->mNoAutoHide) ?
|
||||
GTK_WINDOW_TOPLEVEL : GTK_WINDOW_POPUP;
|
||||
}
|
||||
mShell = gtk_window_new(type);
|
||||
|
||||
bool useAlphaVisual = (mWindowType == eWindowType_popup &&
|
||||
|
@ -3727,9 +3741,11 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
#ifdef MOZ_X11
|
||||
// ... but when the window manager offers focus through
|
||||
// WM_TAKE_FOCUS, focus is requested on the parent window.
|
||||
gtk_widget_realize(mShell);
|
||||
gdk_window_add_filter(gtk_widget_get_window(mShell),
|
||||
popup_take_focus_filter, nullptr);
|
||||
if (mIsX11Display) {
|
||||
gtk_widget_realize(mShell);
|
||||
gdk_window_add_filter(gtk_widget_get_window(mShell),
|
||||
popup_take_focus_filter, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -3741,7 +3757,11 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
else {
|
||||
switch (aInitData->mPopupHint) {
|
||||
case ePopupTypeMenu:
|
||||
gtkTypeHint = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
|
||||
// Use GDK_WINDOW_TYPE_HINT_UTILITY on Wayland which
|
||||
// guides Gtk to create the popup as subsurface
|
||||
// instead of xdg_shell popup (see Bug 1423598).
|
||||
gtkTypeHint = mIsX11Display ? GDK_WINDOW_TYPE_HINT_POPUP_MENU :
|
||||
GDK_WINDOW_TYPE_HINT_UTILITY;
|
||||
break;
|
||||
case ePopupTypeTooltip:
|
||||
gtkTypeHint = GDK_WINDOW_TYPE_HINT_TOOLTIP;
|
||||
|
@ -3793,9 +3813,12 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
* 2) We're running on Gtk+ and client side decorations
|
||||
* are drawn by Gtk+ to mShell. Content is rendered to mContainer
|
||||
* and we listen to the Gtk+ events on mContainer.
|
||||
* 3) We're running on Wayland. All gecko content is rendered
|
||||
* to mContainer and we listen to the Gtk+ events on mContainer.
|
||||
*/
|
||||
GtkStyleContext* style = gtk_widget_get_style_context(mShell);
|
||||
drawToContainer =
|
||||
!mIsX11Display ||
|
||||
(mIsCSDAvailable && GetCSDSupportLevel() == CSD_SUPPORT_FLAT ) ||
|
||||
gtk_style_context_has_class(style, "csd");
|
||||
#endif
|
||||
|
@ -4044,7 +4067,7 @@ nsWindow::Create(nsIWidget* aParent,
|
|||
if (mShell) {
|
||||
LOG(("\tmShell %p mContainer %p mGdkWindow %p 0x%lx\n",
|
||||
mShell, mContainer, mGdkWindow,
|
||||
gdk_x11_window_get_xid(mGdkWindow)));
|
||||
mIsX11Display ? gdk_x11_window_get_xid(mGdkWindow) : 0));
|
||||
} else if (mContainer) {
|
||||
LOG(("\tmContainer %p mGdkWindow %p\n", mContainer, mGdkWindow));
|
||||
}
|
||||
|
@ -4789,6 +4812,12 @@ nsWindow::GrabPointer(guint32 aTime)
|
|||
if (!mGdkWindow)
|
||||
return;
|
||||
|
||||
if (!mIsX11Display) {
|
||||
// Don't to the grab on Wayland as it causes a regression
|
||||
// from Bug 1377084.
|
||||
return;
|
||||
}
|
||||
|
||||
gint retval;
|
||||
retval = gdk_pointer_grab(mGdkWindow, TRUE,
|
||||
(GdkEventMask)(GDK_BUTTON_PRESS_MASK |
|
||||
|
@ -4822,6 +4851,13 @@ nsWindow::ReleaseGrabs(void)
|
|||
LOG(("ReleaseGrabs\n"));
|
||||
|
||||
mRetryPointerGrab = false;
|
||||
|
||||
if (!mIsX11Display) {
|
||||
// Don't to the ungrab on Wayland as it causes a regression
|
||||
// from Bug 1377084.
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_pointer_ungrab(GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
|
@ -7099,3 +7135,19 @@ nsWindow::IsComposited() const
|
|||
(gdk_window_get_visual(mGdkWindow)
|
||||
== gdk_screen_get_rgba_visual(gdkScreen));
|
||||
}
|
||||
|
||||
#ifdef MOZ_WAYLAND
|
||||
wl_display*
|
||||
nsWindow::GetWaylandDisplay()
|
||||
{
|
||||
GdkDisplay* gdkDisplay = gdk_display_get_default();
|
||||
return mIsX11Display ? nullptr :
|
||||
gdk_wayland_display_get_wl_display(gdkDisplay);
|
||||
}
|
||||
|
||||
wl_surface*
|
||||
nsWindow::GetWaylandSurface()
|
||||
{
|
||||
return moz_container_get_wl_surface(MOZ_CONTAINER(mContainer));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
#ifdef MOZ_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif /* MOZ_X11 */
|
||||
#ifdef MOZ_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
#include "mozilla/widget/WindowSurface.h"
|
||||
#include "mozilla/widget/WindowSurfaceProvider.h"
|
||||
|
@ -348,8 +351,13 @@ public:
|
|||
nsIObserver* aObserver) override;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MOZ_X11
|
||||
Display* XDisplay() { return mXDisplay; }
|
||||
#endif
|
||||
#ifdef MOZ_WAYLAND
|
||||
wl_display* GetWaylandDisplay();
|
||||
wl_surface* GetWaylandSurface();
|
||||
#endif
|
||||
virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
|
||||
|
||||
|
|
|
@ -97,6 +97,11 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "xpcpublic.h"
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
// For performance reasons, we make the JS Dev Error Interceptor a Nightly-only feature.
|
||||
#define MOZ_JS_DEV_ERROR_INTERCEPTOR = 1
|
||||
#endif // NIGHTLY_BUILD
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -556,11 +561,18 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSContext* aCx)
|
|||
js::SetScriptEnvironmentPreparer(aCx, &mEnvironmentPreparer);
|
||||
|
||||
JS::dbg::SetDebuggerMallocSizeOf(aCx, moz_malloc_size_of);
|
||||
|
||||
#ifdef MOZ_JS_DEV_ERROR_INTERCEPTOR
|
||||
JS_SetErrorInterceptorCallback(mJSRuntime, &mErrorInterceptor);
|
||||
#endif // MOZ_JS_DEV_ERROR_INTERCEPTOR
|
||||
}
|
||||
|
||||
void
|
||||
CycleCollectedJSRuntime::Shutdown(JSContext* cx)
|
||||
{
|
||||
#ifdef MOZ_JS_DEV_ERROR_INTERCEPTOR
|
||||
mErrorInterceptor.Shutdown(mJSRuntime);
|
||||
#endif // MOZ_JS_DEV_ERROR_INTERCEPTOR
|
||||
JS_RemoveExtraGCRootsTracer(cx, TraceBlackJS, this);
|
||||
JS_RemoveExtraGCRootsTracer(cx, TraceGrayJS, this);
|
||||
#ifdef DEBUG
|
||||
|
@ -1557,3 +1569,113 @@ CycleCollectedJSRuntime::Get()
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_JS_DEV_ERROR_INTERCEPTOR
|
||||
|
||||
namespace js {
|
||||
extern void DumpValue(const JS::Value& val);
|
||||
}
|
||||
|
||||
void
|
||||
CycleCollectedJSRuntime::ErrorInterceptor::Shutdown(JSRuntime* rt)
|
||||
{
|
||||
JS_SetErrorInterceptorCallback(rt, nullptr);
|
||||
mThrownError.reset();
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
CycleCollectedJSRuntime::ErrorInterceptor::interceptError(JSContext* cx, const JS::Value& exn)
|
||||
{
|
||||
if (mThrownError) {
|
||||
// We already have an error, we don't need anything more.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
|
||||
// We are only interested in chrome code.
|
||||
return;
|
||||
}
|
||||
|
||||
const auto type = JS_GetErrorType(exn);
|
||||
if (!type) {
|
||||
// This is not one of the primitive error types.
|
||||
return;
|
||||
}
|
||||
|
||||
switch (*type) {
|
||||
case JSExnType::JSEXN_REFERENCEERR:
|
||||
case JSExnType::JSEXN_SYNTAXERR:
|
||||
case JSExnType::JSEXN_TYPEERR:
|
||||
break;
|
||||
default:
|
||||
// Not one of the errors we are interested in.
|
||||
return;
|
||||
}
|
||||
|
||||
// Now copy the details of the exception locally.
|
||||
// While copying the details of an exception could be expensive, in most runs,
|
||||
// this will be done at most once during the execution of the process, so the
|
||||
// total cost should be reasonable.
|
||||
JS::RootedValue value(cx, exn);
|
||||
|
||||
ErrorDetails details;
|
||||
details.mType = *type;
|
||||
// If `exn` isn't an exception object, `ExtractErrorValues` could end up calling
|
||||
// `toString()`, which could in turn end up throwing an error. While this should
|
||||
// work, we want to avoid that complex use case.
|
||||
// Fortunately, we have already checked above that `exn` is an exception object,
|
||||
// so nothing such should happen.
|
||||
nsContentUtils::ExtractErrorValues(cx, value, details.mFilename, &details.mLine, &details.mColumn, details.mMessage);
|
||||
|
||||
nsAutoCString stack;
|
||||
JS::UniqueChars buf = JS::FormatStackDump(cx, nullptr, /* showArgs = */ false, /* showLocals = */ false, /* showThisProps = */ false);
|
||||
stack.Append(buf.get());
|
||||
CopyUTF8toUTF16(buf.get(), details.mStack);
|
||||
|
||||
mThrownError.emplace(Move(details));
|
||||
}
|
||||
|
||||
void
|
||||
CycleCollectedJSRuntime::ClearRecentDevError()
|
||||
{
|
||||
mErrorInterceptor.mThrownError.reset();
|
||||
}
|
||||
|
||||
bool
|
||||
CycleCollectedJSRuntime::GetRecentDevError(JSContext*cx, JS::MutableHandle<JS::Value> error)
|
||||
{
|
||||
if (!mErrorInterceptor.mThrownError) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create a copy of the exception.
|
||||
JS::RootedObject obj(cx, JS_NewPlainObject(cx));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::RootedValue message(cx);
|
||||
JS::RootedValue filename(cx);
|
||||
JS::RootedValue stack(cx);
|
||||
if (!ToJSValue(cx, mErrorInterceptor.mThrownError->mMessage, &message) ||
|
||||
!ToJSValue(cx, mErrorInterceptor.mThrownError->mFilename, &filename) ||
|
||||
!ToJSValue(cx, mErrorInterceptor.mThrownError->mStack, &stack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build the object.
|
||||
const auto FLAGS = JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT;
|
||||
if (!JS_DefineProperty(cx, obj, "message", message, FLAGS) ||
|
||||
!JS_DefineProperty(cx, obj, "fileName", filename, FLAGS) ||
|
||||
!JS_DefineProperty(cx, obj, "lineNumber", mErrorInterceptor.mThrownError->mLine, FLAGS) ||
|
||||
!JS_DefineProperty(cx, obj, "stack", stack, FLAGS)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pass the result.
|
||||
error.setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
#endif // MOZ_JS_DEV_ERROR_INTERCEPTOR
|
||||
|
||||
#undef MOZ_JS_DEV_ERROR_INTERCEPTOR
|
||||
|
|
|
@ -328,6 +328,11 @@ public:
|
|||
void AddContext(CycleCollectedJSContext* aContext);
|
||||
void RemoveContext(CycleCollectedJSContext* aContext);
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
bool GetRecentDevError(JSContext* aContext, JS::MutableHandle<JS::Value> aError);
|
||||
void ClearRecentDevError();
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
|
||||
private:
|
||||
LinkedList<CycleCollectedJSContext> mContexts;
|
||||
|
||||
|
@ -372,6 +377,37 @@ private:
|
|||
#ifdef DEBUG
|
||||
bool mShutdownCalled;
|
||||
#endif
|
||||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
// Implementation of the error interceptor.
|
||||
// Built on nightly only to avoid any possible performance impact on release
|
||||
|
||||
struct ErrorInterceptor final : public JSErrorInterceptor {
|
||||
virtual void interceptError(JSContext* cx, const JS::Value& val) override;
|
||||
void Shutdown(JSRuntime* rt);
|
||||
|
||||
// Copy of the details of the exception.
|
||||
// We store this rather than the exception itself to avoid dealing with complicated
|
||||
// garbage-collection scenarios, e.g. a JSContext being killed while we still hold
|
||||
// onto an exception thrown from it.
|
||||
struct ErrorDetails {
|
||||
nsString mFilename;
|
||||
nsString mMessage;
|
||||
nsString mStack;
|
||||
JSExnType mType;
|
||||
uint32_t mLine;
|
||||
uint32_t mColumn;
|
||||
};
|
||||
|
||||
// If we have encountered at least one developer error,
|
||||
// the first error we have encountered. Otherwise, or
|
||||
// if we have reset since the latest error, `None`.
|
||||
Maybe<ErrorDetails> mThrownError;
|
||||
};
|
||||
ErrorInterceptor mErrorInterceptor;
|
||||
|
||||
#endif // defined(NIGHTLY_BUILD)
|
||||
|
||||
};
|
||||
|
||||
void TraceScriptHolder(nsISupports* aHolder, JSTracer* aTracer);
|
||||
|
|
Загрузка…
Ссылка в новой задаче