Compare commits

..
Author SHA1 Message Date
Moonchild 510d86ddfb Issue #2730 - Part 2: Add support for reading [u]int64 values from a BigInt.
Provides an inline assembly implementation of `BigInt::toUint64()` resp.
`BigInt::toInt64()`.

Also adds a template class for GC things that have 32-bit length and
32-bit flags stored at the beginning of the GC thing.
This was necessary to follow Mozilla's implementation that builds on
a big rewrite of code depending on this generalization of JSString and
BigInt in the hunt for code-deduping-complexity-increase.
Not ideal since it's only used for BigInt as a result, but
reverse-refactoring of the necessary code referencing JSString would have
been worse.
2025-04-18 16:10:19 +02:00
Moonchild 3527ad788c Issue #2730 - Part 1: Avoid crashes for TypedObjects using bigint properties. 2025-04-18 00:31:01 +02:00
9331 changed files with 535311 additions and 4691562 deletions

No files matched your search

+1 -1
View File
@@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Clobber for libvpx changes
Clobber for NSS update
+8 -17
View File
@@ -6,7 +6,7 @@
#include "Platform.h"
#include "nsIAccessibleEvent.h"
#include "nsIGSettingsService.h"
#include "nsIGConfService.h"
#include "nsIServiceManager.h"
#include "nsMai.h"
#include "AtkSocketAccessible.h"
@@ -360,22 +360,13 @@ dbus_done:
return sShouldEnable;
#endif
// check GSettings
#define GSETINGS_A11Y_INTERFACE "org.gnome.desktop.interface"
#define GSETINGS_A11Y_KEY "toolkit-accessibility"
nsCOMPtr<nsIGSettingsService> gsettings =
do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
nsCOMPtr<nsIGSettingsCollection> a11y_settings;
if (gsettings) {
gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(GSETINGS_A11Y_INTERFACE),
getter_AddRefs(a11y_settings));
if (a11y_settings) {
a11y_settings->GetBoolean(NS_LITERAL_CSTRING(GSETINGS_A11Y_KEY),
&sShouldEnable);
}
}
//check gconf-2 setting
#define GCONF_A11Y_KEY "/desktop/gnome/interface/accessibility"
nsresult rv = NS_OK;
nsCOMPtr<nsIGConfService> gconf =
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv) && gconf)
gconf->GetBool(NS_LITERAL_CSTRING(GCONF_A11Y_KEY), &sShouldEnable);
return sShouldEnable;
}
+3 -3
View File
@@ -60,7 +60,7 @@
#ifdef MOZ_ENABLE_NPAPI
#include "nsPluginFrame.h"
#endif
#include "SVGGeometryFrame.h"
#include "nsSVGPathGeometryFrame.h"
#include "nsTreeBodyFrame.h"
#include "nsTreeColumns.h"
#include "nsTreeUtils.h"
@@ -1165,8 +1165,8 @@ nsAccessibilityService::CreateAccessible(nsINode* aNode,
if (!newAcc) {
if (content->IsSVGElement()) {
SVGGeometryFrame* geometryFrame = do_QueryFrame(frame);
if (geometryFrame) {
nsSVGPathGeometryFrame* pathGeometryFrame = do_QueryFrame(frame);
if (pathGeometryFrame) {
// A graphic elements: rect, circle, ellipse, line, path, polygon,
// polyline and image. A 'use' and 'text' graphic elements require
// special support.
+1 -1
View File
@@ -76,7 +76,7 @@ HyperTextAccessible::NativeState()
{
uint64_t states = AccessibleWrap::NativeState();
if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_READWRITE)) {
if (mContent->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
states |= states::EDITABLE;
} else if (mContent->IsHTMLElement(nsGkAtoms::article)) {
-3
View File
@@ -982,9 +982,6 @@ EOF
k1om:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
loongarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
-3
View File
@@ -375,9 +375,6 @@ def split_triplet(triplet):
elif cpu.startswith('aarch64'):
canonical_cpu = 'aarch64'
endianness = 'little'
elif cpu.startswith('loongarch64'):
canonical_cpu = 'loongarch64'
endianness = 'little'
else:
die('Unknown CPU type: %s' % cpu)
+2 -34
View File
@@ -11,14 +11,9 @@ def moz_jemalloc4(value):
option('--enable-jemalloc', env='MOZ_MEMORY',
help='Replace system memory allocator with jemalloc')
option('--enable-mimalloc',
help='Replace system memory allocator with mimalloc')
@depends('--enable-jemalloc', '--enable-mimalloc', target, build_project,
c_compiler)
def jemalloc(value, mimalloc, target, build_project, c_compiler):
if value and mimalloc:
die('--enable-jemalloc and --enable-mimalloc cannot be used together')
@depends('--enable-jemalloc', target, build_project, c_compiler)
def jemalloc(value, target, build_project, c_compiler):
if value.origin != 'default':
return bool(value) or None
@@ -35,38 +30,11 @@ def jemalloc(value, mimalloc, target, build_project, c_compiler):
if target.kernel == 'Linux':
return True
@depends('--enable-mimalloc', '--enable-jemalloc', target)
def mimalloc(value, jemalloc, target):
if value and jemalloc:
die('--enable-jemalloc and --enable-mimalloc cannot be used together')
if value.origin != 'default':
if not value:
return None
if target.kernel not in ('Darwin', 'WINNT', 'Linux', 'kFreeBSD', 'FreeBSD',
'NetBSD', 'OpenBSD', 'DragonFly'):
die('--enable-mimalloc is not supported on %s', target.kernel)
return True
@depends('--enable-mimalloc', '--enable-jemalloc')
def mimalloc_requires_disable(mimalloc, jemalloc):
if not mimalloc:
return
if jemalloc or jemalloc.origin not in ('command-line', 'mozconfig'):
die('--enable-mimalloc requires --disable-jemalloc to be passed explicitly')
set_config('MOZ_MEMORY', jemalloc)
set_define('MOZ_MEMORY', jemalloc)
add_old_configure_assignment('MOZ_MEMORY', jemalloc)
@depends(mimalloc)
def mimalloc_config(mimalloc):
return True if mimalloc else False
set_config('MOZ_MIMALLOC', mimalloc_config)
set_define('MOZ_MIMALLOC', mimalloc)
add_old_configure_assignment('MOZ_MIMALLOC', mimalloc_config)
# Because --enable-jemalloc doesn't use a default because of the dependency
# on the target, we can't use a js_option for it to propagate to js/src
+4
View File
@@ -127,6 +127,7 @@ def old_configure_options(*options):
'--enable-alsa',
'--enable-appcompat-guid',
'--enable-av1',
'--enable-jxl',
'--enable-b2g-bt',
'--enable-b2g-camera',
'--enable-b2g-ril',
@@ -152,7 +153,10 @@ def old_configure_options(*options):
'--enable-faststripe',
'--enable-feeds',
'--enable-gamepad',
'--enable-gconf',
'--enable-gczeal',
'--enable-gio',
'--enable-gnomeui',
'--enable-gold',
'--enable-hardware-aec-ns',
'--enable-icf',
@@ -88,7 +88,7 @@ var decompressedJQuery = function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(par
for documentation and information on getting the source.
*/
var decompressedDojo = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(V z=="1k"){(B(){if(V D["1o"]=="1k"){D.1o={}}if((!D["1z"])||(!1z["ca"])){D.1z={}}A cn=["rA","rz","1K","ry","rx","9f","rw","rv","ru","rt","rs","rr","rq","ro","rn","rm"];A i=0,24;1s(24=cn[i++]){if(!1z[24]){1z[24]=B(){}}}if(V D["z"]=="1k"){D.z={}}z.1W=D;A d3={im:U,rl:U,rk:"",rj:"",ri:"",rh:K,rg:U};R(A 8z in d3){if(V 1o[8z]=="1k"){1o[8z]=d3[8z]}}A jK=["rf","rd","rc","rb"];A t;1s(t=jK.3a()){z["is"+t]=U}})();z.8h=1o.8h;z.cY={jJ:0,jI:9,jH:0,jG:"",jF:2V("$ra: r9 $".1f(/[0-9]+/)[0]),2i:B(){4G(z.cY){C jJ+"."+jI+"."+jH+jG+" ("+jF+")"}}};z.d1=B(jE,jD,1V){A 2h=1V||z.1W;R(A i=0,p;2h&&(p=jE[i]);i++){2h=(p in 2h?2h[p]:(jD?2h[p]={}:1k))}C 2h};z.88=B(jC,jA,jB){A d2=jC.1A("."),p=d2.8q(),M=z.d1(d2,K,jB);C(M&&p?(M[p]=jA):1k)};z.6q=B(jz,jy,jx){C z.d1(jz.1A("."),jy,jx)};z.r8=B(jw,M){C!!z.6q(jw,U,M)};z["3u"]=B(d0){C z.1W.3u?z.1W.3u(d0):3u(d0)};z.ia=B(jv,cZ,cX){A 8y="r7: "+jv;if(cZ){8y+=" "+cZ}if(cX){8y+=" -- r6 be r5 in cY: "+cX}1z.1K(8y)};z.r4=B(ju,cW){A cV="r3: "+ju+" -- r2 r1 4F r0 qZ qY.";if(cW){cV+=" "+cW}1z.1K(cV)};(B(){A cR={53:{},6p:0,1h:{},8k:{z:{1p:"z",1Z:"."},cU:{1p:"cU",1Z:"../qX/cU"},cT:{1p:"cT",1Z:"cT"}},cN:B(cS){A mp=D.8k;C jp(mp[cS]&&mp[cS].1Z)},jk:B(8x){A mp=D.8k;if(D.cN(8x)){C mp[8x].1Z}C 8x},8v:[],6t:U,56:[],8t:[],8u:U};R(A cQ in cR){z[cQ]=cR[cQ]}})();z.jg=B(8w,cP,cb){A 1g=(((8w.2s(0)=="/"||8w.1f(/^\\w+:/)))?"":D.51)+8w;if(1o.jt&&z.c8){1g+="?"+67(1o.jt).2f(/\\W+/g,"")}1u{C!cP?D.cO(1g,cb):D.jq(1g,cP,cb)}1y(e){1z.1K(e);C U}};z.cO=B(1g,cb){if(D.8v[1g]){C K}A 6u=D.iR(1g,K);if(!6u){C U}D.8v[1g]=K;D.8v.Y(1g);if(cb){6u="("+6u+")"}A jr=z["3u"](6u+"\\r\\n//@ qW="+1g);if(cb){cb(jr)}C K};z.jq=B(1g,jo,cb){A ok=U;1u{ok=D.cO(1g,cb)}1y(e){1z.1K("qV je ",1g," 4G 9f: ",e)}C jp(ok&&D.53[jo])};z.6m=B(){D.8u=K;D.6t=K;A 57=D.56;D.56=[];R(A x=0;x<57.G;x++){57[x]()}D.8u=U;if(z.6t&&z.6p==0&&D.56.G>0){z.8s()}};z.ck=B(){A 57=D.8t;1s(57.G){(57.8q())()}};z.qU=B(M,jn){A d=z;if(P.G==1){d.56.Y(M)}I{if(P.G>1){d.56.Y(B(){M[jn]()})}}if(d.6t&&d.6p==0&&!d.8u){d.8s()}};z.dW=B(M,jm){A d=z;if(P.G==1){d.8t.Y(M)}I{if(P.G>1){d.8t.Y(B(){M[jm]()})}}};z.iM=B(){if(D.6t){C}if(D.6p>0){1z.1K("qT qS in qR!");C}z.8s()};z.8s=B(){if(V 5c=="8b"||(1o["qQ"]&&z.2M)){5c("z.6m();",0)}I{z.6m()}};z.cF=B(jl){A 4v=jl.1A(".");R(A i=4v.G;i>0;i--){A 8r=4v.2w(0,i).22(".");if((i==1)&&!D.cN(8r)){4v[0]="../"+4v[0]}I{A cM=D.jk(8r);if(cM!=8r){4v.3S(0,i,cM);3f}}}C 4v};z.jj=U;z.8m=B(2T,qP,55){55=D.jj||55;A 54=D.53[2T];if(54){C 54}A cL=2T.1A(".");A 3L=D.cF(2T);A jh=((3L[0].2s(0)!="/")&&!3L[0].1f(/^\\w+:/));A ji=3L[3L.G-1];A 3m;if(ji=="*"){2T=cL.2w(0,-1).22(".");3L.8q();3m=3L.22("/")+"/"+(1o["qO"]||"qN")+".js";if(jh&&3m.2s(0)=="/"){3m=3m.2w(1)}}I{3m=3L.22("/")+".js";2T=cL.22(".")}A jf=(!55)?2T:L;A ok=D.jg(3m,jf);if((!ok)&&(!55)){2m S 1O("qM 3O 4E \'"+2T+"\'; 72 qL \'"+3m+"\'")}if((!55)&&(!D["qK"])){54=D.53[2T];if(!54){2m S 1O("qJ \'"+2T+"\' is 3O qI a8 je \'"+3m+"\'")}}C 54};z.8c=z.8m;z.1Q=B(cK){A cJ=cK+"";A 8p=cJ;A 6s=cK.1A(/\\./);if(6s[6s.G-1]=="*"){6s.8q();8p=6s.22(".")}A 8o=z.6q(8p,K);D.53[cJ]=8o;D.53[8p]=8o;C 8o};z.qH=B(8n){A jd=8n["qG"]||[];A cI=jd.3U(8n[z.j4]||8n["aY"]||[]);R(A x=0;x<cI.G;x++){A 8l=cI[x];if(8l.1P==4e){z.8m.14(z,8l)}I{z.8m(8l)}}};z.jb=B(jc,qF){if(jc===K){A cH=[];R(A i=1;i<P.G;i++){cH.Y(P[i])}z.8c.14(z,cH)}};z.qE=z.jb;z.io=B(cG,ja){D.8k[cG]={1p:cG,1Z:ja}};z.qD=B(qC,qB,qA,qz){z.8c("z.j9");z.j9.qy.14(z.qx,P)};(B(){A j7=S 9G("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?$");A j6=S 9G("^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$");z.4r=B(){A n=L;A 1V=P;A 1g=1V[0];R(A i=1;i<1V.G;i++){if(!1V[i]){6c}A 1t=S z.4r(1V[i]+"");A 4u=S z.4r(1g+"");if((1t.28=="")&&(!1t.4t)&&(!1t.3l)&&(!1t.1r)){if(1t.52!=n){4u.52=1t.52}1t=4u}I{if(!1t.4t){1t.4t=4u.4t;if(!1t.3l){1t.3l=4u.3l;if(1t.28.2s(0)!="/"){A j8=4u.28.21(0,4u.28.31("/")+1)+1t.28;A 1X=j8.1A("/");R(A j=0;j<1X.G;j++){if(1X[j]=="."){if(j==1X.G-1){1X[j]=""}I{1X.3S(j,1);j--}}I{if(j>0&&!(j==1&&1X[0]=="")&&1X[j]==".."&&1X[j-1]!=".."){if(j==(1X.G-1)){1X.3S(j,1);1X[j-1]=""}I{1X.3S(j-1,2);j-=2}}}}1t.28=1X.22("/")}}}}1g="";if(1t.4t){1g+=1t.4t+":"}if(1t.3l){1g+="//"+1t.3l}1g+=1t.28;if(1t.1r){1g+="?"+1t.1r}if(1t.52){1g+="#"+1t.52}}D.1g=1g.2i();A r=D.1g.1f(j7);D.4t=r[2]||(r[1]?"":n);D.3l=r[4]||(r[3]?"":n);D.28=r[5];D.1r=r[7]||(r[6]?"":n);D.52=r[9]||(r[8]?"":n);if(D.3l!=n){r=D.3l.1f(j6);D.8X=r[3]||n;D.8W=r[4]||n;D.qw=r[5];D.qv=r[7]||n}};z.4r.1C.2i=B(){C D.1g}})();z.qu=B(j5,2E){A 2B=z.cF(j5).22("/");if(!2B){C L}if(2B.31("/")!=2B.G-1){2B+="/"}A cE=2B.T(":");if(2B.2s(0)!="/"&&(cE==-1||cE>2B.T("/"))){2B=z.51+2B}C S z.4r(2B,2E)};if(V 26!="1k"){z.c8=K;z.j4="qt";(B(){A d=z;if(1q&&1q.4I){A 8j=1q.4I("ak");A j3=/z(\\.qs)?\\.js([\\?\\.]|$)/i;R(A i=0;i<8j.G;i++){A 4X=8j[i].5t("4X");if(!4X){6c}A m=4X.1fLine truncated
var decompressedDojo = function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('if(V z=="1k"){(B(){if(V D["1o"]=="1k"){D.1o={}}if((!D["1z"])||(!1z["ca"])){D.1z={}}A cn=["rA","rz","1K","ry","rx","9f","rw","rv","ru","rt","rs","rr","rq","ro","rn","rm"];A i=0,24;1s(24=cn[i++]){if(!1z[24]){1z[24]=B(){}}}if(V D["z"]=="1k"){D.z={}}z.1W=D;A d3={im:U,rl:U,rk:"",rj:"",ri:"",rh:K,rg:U};R(A 8z in d3){if(V 1o[8z]=="1k"){1o[8z]=d3[8z]}}A jK=["rf","rd","rc","rb"];A t;1s(t=jK.3a()){z["is"+t]=U}})();z.8h=1o.8h;z.cY={jJ:0,jI:9,jH:0,jG:"",jF:2V("$ra: r9 $".1f(/[0-9]+/)[0]),2i:B(){4G(z.cY){C jJ+"."+jI+"."+jH+jG+" ("+jF+")"}}};z.d1=B(jE,jD,1V){A 2h=1V||z.1W;R(A i=0,p;2h&&(p=jE[i]);i++){2h=(p in 2h?2h[p]:(jD?2h[p]={}:1k))}C 2h};z.88=B(jC,jA,jB){A d2=jC.1A("."),p=d2.8q(),M=z.d1(d2,K,jB);C(M&&p?(M[p]=jA):1k)};z.6q=B(jz,jy,jx){C z.d1(jz.1A("."),jy,jx)};z.r8=B(jw,M){C!!z.6q(jw,U,M)};z["3u"]=B(d0){C z.1W.3u?z.1W.3u(d0):3u(d0)};z.ia=B(jv,cZ,cX){A 8y="r7: "+jv;if(cZ){8y+=" "+cZ}if(cX){8y+=" -- r6 be r5 in cY: "+cX}1z.1K(8y)};z.r4=B(ju,cW){A cV="r3: "+ju+" -- r2 r1 4F r0 qZ qY.";if(cW){cV+=" "+cW}1z.1K(cV)};(B(){A cR={53:{},6p:0,1h:{},8k:{z:{1p:"z",1Z:"."},cU:{1p:"cU",1Z:"../qX/cU"},cT:{1p:"cT",1Z:"cT"}},cN:B(cS){A mp=D.8k;C jp(mp[cS]&&mp[cS].1Z)},jk:B(8x){A mp=D.8k;if(D.cN(8x)){C mp[8x].1Z}C 8x},8v:[],6t:U,56:[],8t:[],8u:U};R(A cQ in cR){z[cQ]=cR[cQ]}})();z.jg=B(8w,cP,cb){A 1g=(((8w.2s(0)=="/"||8w.1f(/^\\w+:/)))?"":D.51)+8w;if(1o.jt&&z.c8){1g+="?"+67(1o.jt).2f(/\\W+/g,"")}1u{C!cP?D.cO(1g,cb):D.jq(1g,cP,cb)}1y(e){1z.1K(e);C U}};z.cO=B(1g,cb){if(D.8v[1g]){C K}A 6u=D.iR(1g,K);if(!6u){C U}D.8v[1g]=K;D.8v.Y(1g);if(cb){6u="("+6u+")"}A jr=z["3u"](6u+"\\r\\n//@ qW="+1g);if(cb){cb(jr)}C K};z.jq=B(1g,jo,cb){A ok=U;1u{ok=D.cO(1g,cb)}1y(e){1z.1K("qV je ",1g," 4G 9f: ",e)}C jp(ok&&D.53[jo])};z.6m=B(){D.8u=K;D.6t=K;A 57=D.56;D.56=[];R(A x=0;x<57.G;x++){57[x]()}D.8u=U;if(z.6t&&z.6p==0&&D.56.G>0){z.8s()}};z.ck=B(){A 57=D.8t;1s(57.G){(57.8q())()}};z.qU=B(M,jn){A d=z;if(P.G==1){d.56.Y(M)}I{if(P.G>1){d.56.Y(B(){M[jn]()})}}if(d.6t&&d.6p==0&&!d.8u){d.8s()}};z.dW=B(M,jm){A d=z;if(P.G==1){d.8t.Y(M)}I{if(P.G>1){d.8t.Y(B(){M[jm]()})}}};z.iM=B(){if(D.6t){C}if(D.6p>0){1z.1K("qT qS in qR!");C}z.8s()};z.8s=B(){if(V 5c=="8b"||(1o["qQ"]&&z.2M)){5c("z.6m();",0)}I{z.6m()}};z.cF=B(jl){A 4v=jl.1A(".");R(A i=4v.G;i>0;i--){A 8r=4v.2w(0,i).22(".");if((i==1)&&!D.cN(8r)){4v[0]="../"+4v[0]}I{A cM=D.jk(8r);if(cM!=8r){4v.3S(0,i,cM);3f}}}C 4v};z.jj=U;z.8m=B(2T,qP,55){55=D.jj||55;A 54=D.53[2T];if(54){C 54}A cL=2T.1A(".");A 3L=D.cF(2T);A jh=((3L[0].2s(0)!="/")&&!3L[0].1f(/^\\w+:/));A ji=3L[3L.G-1];A 3m;if(ji=="*"){2T=cL.2w(0,-1).22(".");3L.8q();3m=3L.22("/")+"/"+(1o["qO"]||"qN")+".js";if(jh&&3m.2s(0)=="/"){3m=3m.2w(1)}}I{3m=3L.22("/")+".js";2T=cL.22(".")}A jf=(!55)?2T:L;A ok=D.jg(3m,jf);if((!ok)&&(!55)){2m S 1O("qM 3O 4E \'"+2T+"\'; 72 qL \'"+3m+"\'")}if((!55)&&(!D["qK"])){54=D.53[2T];if(!54){2m S 1O("qJ \'"+2T+"\' is 3O qI a8 je \'"+3m+"\'")}}C 54};z.8c=z.8m;z.1Q=B(cK){A cJ=cK+"";A 8p=cJ;A 6s=cK.1A(/\\./);if(6s[6s.G-1]=="*"){6s.8q();8p=6s.22(".")}A 8o=z.6q(8p,K);D.53[cJ]=8o;D.53[8p]=8o;C 8o};z.qH=B(8n){A jd=8n["qG"]||[];A cI=jd.3U(8n[z.j4]||8n["aY"]||[]);R(A x=0;x<cI.G;x++){A 8l=cI[x];if(8l.1P==4e){z.8m.14(z,8l)}I{z.8m(8l)}}};z.jb=B(jc,qF){if(jc===K){A cH=[];R(A i=1;i<P.G;i++){cH.Y(P[i])}z.8c.14(z,cH)}};z.qE=z.jb;z.io=B(cG,ja){D.8k[cG]={1p:cG,1Z:ja}};z.qD=B(qC,qB,qA,qz){z.8c("z.j9");z.j9.qy.14(z.qx,P)};(B(){A j7=S 9G("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?$");A j6=S 9G("^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$");z.4r=B(){A n=L;A 1V=P;A 1g=1V[0];R(A i=1;i<1V.G;i++){if(!1V[i]){6c}A 1t=S z.4r(1V[i]+"");A 4u=S z.4r(1g+"");if((1t.28=="")&&(!1t.4t)&&(!1t.3l)&&(!1t.1r)){if(1t.52!=n){4u.52=1t.52}1t=4u}I{if(!1t.4t){1t.4t=4u.4t;if(!1t.3l){1t.3l=4u.3l;if(1t.28.2s(0)!="/"){A j8=4u.28.21(0,4u.28.31("/")+1)+1t.28;A 1X=j8.1A("/");R(A j=0;j<1X.G;j++){if(1X[j]=="."){if(j==1X.G-1){1X[j]=""}I{1X.3S(j,1);j--}}I{if(j>0&&!(j==1&&1X[0]=="")&&1X[j]==".."&&1X[j-1]!=".."){if(j==(1X.G-1)){1X.3S(j,1);1X[j-1]=""}I{1X.3S(j-1,2);j-=2}}}}1t.28=1X.22("/")}}}}1g="";if(1t.4t){1g+=1t.4t+":"}if(1t.3l){1g+="//"+1t.3l}1g+=1t.28;if(1t.1r){1g+="?"+1t.1r}if(1t.52){1g+="#"+1t.52}}D.1g=1g.2i();A r=D.1g.1f(j7);D.4t=r[2]||(r[1]?"":n);D.3l=r[4]||(r[3]?"":n);D.28=r[5];D.1r=r[7]||(r[6]?"":n);D.52=r[9]||(r[8]?"":n);if(D.3l!=n){r=D.3l.1f(j6);D.8X=r[3]||n;D.8W=r[4]||n;D.qw=r[5];D.qv=r[7]||n}};z.4r.1C.2i=B(){C D.1g}})();z.qu=B(j5,2E){A 2B=z.cF(j5).22("/");if(!2B){C L}if(2B.31("/")!=2B.G-1){2B+="/"}A cE=2B.T(":");if(2B.2s(0)!="/"&&(cE==-1||cE>2B.T("/"))){2B=z.51+2B}C S z.4r(2B,2E)};if(V 26!="1k"){z.c8=K;z.j4="qt";(B(){A d=z;if(1q&&1q.4I){A 8j=1q.4I("ak");A j3=/z(\\.qs)?\\.js([\\?\\.]|$)/i;R(A i=0;i<8j.G;i++){A 4X=8j[i].5t("4X");if(!4X){6c}A m=4X.1fLine truncated
/*
+1 -2
View File
@@ -343,8 +343,7 @@ OriginAttributes::IsFirstPartyEnabled()
return sFirstPartyIsolation;
}
BasePrincipal::BasePrincipal(PrincipalKind aKind)
: mKind(aKind)
BasePrincipal::BasePrincipal()
{}
BasePrincipal::~BasePrincipal()
+9 -19
View File
@@ -251,14 +251,7 @@ public:
class BasePrincipal : public nsJSPrincipals
{
public:
enum PrincipalKind {
eNullPrincipal,
eCodebasePrincipal,
eExpandedPrincipal,
eSystemPrincipal
};
explicit BasePrincipal(PrincipalKind aKind);
BasePrincipal();
enum DocumentDomainConsideration { DontConsiderDocumentDomain, ConsiderDocumentDomain};
bool Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration);
@@ -308,19 +301,17 @@ public:
uint32_t PrivateBrowsingId() const { return mOriginAttributes.mPrivateBrowsingId; }
bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; }
PrincipalKind Kind() const { return mKind; }
enum PrincipalKind {
eNullPrincipal,
eCodebasePrincipal,
eExpandedPrincipal,
eSystemPrincipal
};
virtual PrincipalKind Kind() = 0;
already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain();
/**
* Returns true if this principal's CSP should override a document's CSP for
* loads that it triggers. Currently true only for expanded principals which
* subsume the document principal.
*/
bool OverridesCSP(nsIPrincipal* aDocumentPrincipal) {
return mKind == eExpandedPrincipal && Subsumes(aDocumentPrincipal, DontConsiderDocumentDomain);
}
protected:
virtual ~BasePrincipal();
@@ -342,7 +333,6 @@ protected:
nsCOMPtr<nsIContentSecurityPolicy> mCSP;
nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
PrincipalOriginAttributes mOriginAttributes;
PrincipalKind mKind;
};
} // namespace mozilla
+3 -3
View File
@@ -36,9 +36,7 @@ public:
// This should only be used by deserialization, and the factory constructor.
// Other consumers should use the Create and CreateWithInheritedAttributes
// methods.
nsNullPrincipal()
: BasePrincipal(eNullPrincipal)
{}
nsNullPrincipal() {}
NS_DECL_NSISERIALIZABLE
@@ -62,6 +60,8 @@ public:
virtual nsresult GetScriptLocation(nsACString &aStr) override;
PrincipalKind Kind() override { return eNullPrincipal; }
protected:
virtual ~nsNullPrincipal() {}
+2 -16
View File
@@ -64,11 +64,10 @@ nsPrincipal::InitializeStatics()
}
nsPrincipal::nsPrincipal()
: BasePrincipal(eCodebasePrincipal)
, mCodebaseImmutable(false)
: mCodebaseImmutable(false)
, mDomainImmutable(false)
, mInitialized(false)
{}
{ }
nsPrincipal::~nsPrincipal()
{
@@ -464,18 +463,6 @@ nsPrincipal::Write(nsIObjectOutputStream* aStream)
rv = aStream->WriteStringZ(suffix.get());
NS_ENSURE_SUCCESS(rv, rv);
// This is an ugly hack to prevent re-entrancy calls into nsPrincipal::Write()
// because of repeat CSP processing.
// We refcount the context and if found 3+ refcounts on the same, skip writing
// the mCSP compound object.
// TODO: figure out exactly why this happens and fix the root cause.
nsCSPContext* CSPContext = static_cast<nsCSPContext*>(mCSP.get());
if(CSPContext) {
auto CSPDepth = CSPContext->AddRef();
CSPContext->Release();
if(CSPDepth > 2) return NS_OK;
}
rv = NS_WriteOptionalCompoundObject(aStream, mCSP,
NS_GET_IID(nsIContentSecurityPolicy),
true);
@@ -527,7 +514,6 @@ struct OriginComparator
nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList,
const PrincipalOriginAttributes& aAttrs)
: BasePrincipal(eExpandedPrincipal)
{
// We force the principals to be sorted by origin so that nsExpandedPrincipal
// origins can have a canonical form.
+4
View File
@@ -46,6 +46,8 @@ public:
*/
static void InitializeStatics();
PrincipalKind Kind() override { return eCodebasePrincipal; }
nsCOMPtr<nsIURI> mDomain;
nsCOMPtr<nsIURI> mCodebase;
// If mCodebaseImmutable is true, mCodebase is non-null and immutable
@@ -80,6 +82,8 @@ public:
virtual nsresult GetScriptLocation(nsACString &aStr) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
PrincipalKind Kind() override { return eExpandedPrincipal; }
protected:
virtual ~nsExpandedPrincipal();
+3 -3
View File
@@ -36,9 +36,7 @@ public:
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
nsSystemPrincipal()
: BasePrincipal(eSystemPrincipal)
{}
nsSystemPrincipal() {}
virtual nsresult GetScriptLocation(nsACString &aStr) override;
@@ -54,6 +52,8 @@ protected:
{
return true;
}
PrincipalKind Kind() override { return eSystemPrincipal; }
};
#endif // nsSystemPrincipal_h__
+1 -20
View File
@@ -18,30 +18,20 @@ sources = [
'/intl/icu/source/common/dictionarydata.cpp',
'/intl/icu/source/common/dtintrv.cpp',
'/intl/icu/source/common/edits.cpp',
'/intl/icu/source/common/emojiprops.cpp',
'/intl/icu/source/common/errorcode.cpp',
'/intl/icu/source/common/filteredbrk.cpp',
'/intl/icu/source/common/filterednormalizer2.cpp',
'/intl/icu/source/common/fixedstring.cpp',
'/intl/icu/source/common/loadednormalizer2impl.cpp',
'/intl/icu/source/common/localebuilder.cpp',
'/intl/icu/source/common/localematcher.cpp',
'/intl/icu/source/common/localeprioritylist.cpp',
'/intl/icu/source/common/locavailable.cpp',
'/intl/icu/source/common/locbased.cpp',
'/intl/icu/source/common/locdispnames.cpp',
'/intl/icu/source/common/locdistance.cpp',
'/intl/icu/source/common/locdspnm.cpp',
'/intl/icu/source/common/locid.cpp',
'/intl/icu/source/common/loclikely.cpp',
'/intl/icu/source/common/loclikelysubtags.cpp',
'/intl/icu/source/common/locmap.cpp',
'/intl/icu/source/common/locresdata.cpp',
'/intl/icu/source/common/locutil.cpp',
'/intl/icu/source/common/lsr.cpp',
'/intl/icu/source/common/lstmbe.cpp',
'/intl/icu/source/common/messagepattern.cpp',
'/intl/icu/source/common/mlbe.cpp',
'/intl/icu/source/common/normalizer2.cpp',
'/intl/icu/source/common/normalizer2impl.cpp',
'/intl/icu/source/common/normlzr.cpp',
@@ -61,7 +51,6 @@ sources = [
'/intl/icu/source/common/rbbitblb.cpp',
'/intl/icu/source/common/resbund.cpp',
'/intl/icu/source/common/resource.cpp',
'/intl/icu/source/common/restrace.cpp',
'/intl/icu/source/common/ruleiter.cpp',
'/intl/icu/source/common/schriter.cpp',
'/intl/icu/source/common/serv.cpp',
@@ -121,8 +110,6 @@ sources = [
'/intl/icu/source/common/uloc.cpp',
'/intl/icu/source/common/uloc_keytype.cpp',
'/intl/icu/source/common/uloc_tag.cpp',
'/intl/icu/source/common/ulocale.cpp',
'/intl/icu/source/common/ulocbuilder.cpp',
'/intl/icu/source/common/umapfile.cpp',
'/intl/icu/source/common/umath.cpp',
'/intl/icu/source/common/umutablecptrie.cpp',
@@ -164,7 +151,6 @@ sources = [
'/intl/icu/source/common/utext.cpp',
'/intl/icu/source/common/utf_impl.cpp',
'/intl/icu/source/common/util.cpp',
'/intl/icu/source/common/util_props.cpp',
'/intl/icu/source/common/utrace.cpp',
'/intl/icu/source/common/utrie.cpp',
'/intl/icu/source/common/utrie2.cpp',
@@ -204,6 +190,7 @@ other_sources = [
'/intl/icu/source/common/usc_impl.cpp',
'/intl/icu/source/common/ushape.cpp',
'/intl/icu/source/common/ustr_wcs.cpp',
'/intl/icu/source/common/util_props.cpp',
]
EXPORTS.unicode += [
'/intl/icu/source/common/unicode/appendable.h',
@@ -225,8 +212,6 @@ EXPORTS.unicode += [
'/intl/icu/source/common/unicode/icudataver.h',
'/intl/icu/source/common/unicode/icuplug.h',
'/intl/icu/source/common/unicode/idna.h',
'/intl/icu/source/common/unicode/localebuilder.h',
'/intl/icu/source/common/unicode/localematcher.h',
'/intl/icu/source/common/unicode/localpointer.h',
'/intl/icu/source/common/unicode/locdspnm.h',
'/intl/icu/source/common/unicode/locid.h',
@@ -274,8 +259,6 @@ EXPORTS.unicode += [
'/intl/icu/source/common/unicode/uiter.h',
'/intl/icu/source/common/unicode/uldnames.h',
'/intl/icu/source/common/unicode/uloc.h',
'/intl/icu/source/common/unicode/ulocale.h',
'/intl/icu/source/common/unicode/ulocbuilder.h',
'/intl/icu/source/common/unicode/umachine.h',
'/intl/icu/source/common/unicode/umisc.h',
'/intl/icu/source/common/unicode/umutablecptrie.h',
@@ -303,8 +286,6 @@ EXPORTS.unicode += [
'/intl/icu/source/common/unicode/utf32.h',
'/intl/icu/source/common/unicode/utf8.h',
'/intl/icu/source/common/unicode/utf_old.h',
'/intl/icu/source/common/unicode/utfiterator.h',
'/intl/icu/source/common/unicode/utfstring.h',
'/intl/icu/source/common/unicode/utrace.h',
'/intl/icu/source/common/unicode/utypes.h',
'/intl/icu/source/common/unicode/uvernum.h',
-22
View File
@@ -3,15 +3,12 @@
# 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/.
# Also see <http://www.icu-project.org/repos/icu/tags/latest/icu4c/readme.html#RecBuild> for the
# recommended build options when compiling ICU.
DEFINES.update(
# Don't use icu namespace automatically in client code.
U_USING_ICU_NAMESPACE = 0,
# Don't include obsolete header files.
U_NO_DEFAULT_INCLUDE_UTF_HEADERS = 1,
U_HIDE_OBSOLETE_UTF_OLD_H = 1,
# Remove chunks of the library that we don't need (yet).
UCONFIG_NO_LEGACY_CONVERSION = True,
@@ -20,13 +17,6 @@ DEFINES.update(
# We don't need to pass data to and from legacy char* APIs.
U_CHARSET_IS_UTF8 = True,
# Add 'explicit' keyword to UnicodeString constructors.
UNISTR_FROM_CHAR_EXPLICIT = 'explicit',
UNISTR_FROM_STRING_EXPLICIT = 'explicit',
# Disable dynamic loading of ICU data as a loadable library.
U_ENABLE_DYLOAD = 0,
)
if not CONFIG['HAVE_LANGINFO_CODESET']:
@@ -48,24 +38,12 @@ ALLOW_COMPILER_WARNINGS = True
# warnings that get triggered for every file.
if CONFIG['CLANG_CL']:
CFLAGS += [
'-Wno-c++20-compat',
'-Wno-comma',
'-Wno-implicit-const-int-float-conversion',
'-Wno-macro-redefined',
'-Wno-microsoft-include',
'-Wno-tautological-unsigned-enum-zero-compare',
'-Wno-unreachable-code-loop-increment',
'-Wno-unreachable-code-return',
]
CXXFLAGS += [
'-Wno-c++20-compat',
'-Wno-comma',
'-Wno-implicit-const-int-float-conversion',
'-Wno-macro-redefined',
'-Wno-microsoft-include',
'-Wno-tautological-unsigned-enum-zero-compare',
'-Wno-unreachable-code-loop-increment',
'-Wno-unreachable-code-return',
]
if CONFIG['_MSC_VER'] and not CONFIG['CLANG_CL']:
+5 -47
View File
@@ -42,14 +42,13 @@ sources = [
'/intl/icu/source/i18n/decContext.cpp',
'/intl/icu/source/i18n/decimfmt.cpp',
'/intl/icu/source/i18n/decNumber.cpp',
'/intl/icu/source/i18n/displayoptions.cpp',
'/intl/icu/source/i18n/double-conversion-bignum-dtoa.cpp',
'/intl/icu/source/i18n/double-conversion-bignum.cpp',
'/intl/icu/source/i18n/double-conversion-cached-powers.cpp',
'/intl/icu/source/i18n/double-conversion-double-to-string.cpp',
'/intl/icu/source/i18n/double-conversion-diy-fp.cpp',
'/intl/icu/source/i18n/double-conversion-fast-dtoa.cpp',
'/intl/icu/source/i18n/double-conversion-string-to-double.cpp',
'/intl/icu/source/i18n/double-conversion-strtod.cpp',
'/intl/icu/source/i18n/double-conversion.cpp',
'/intl/icu/source/i18n/dtfmtsym.cpp',
'/intl/icu/source/i18n/dtitvfmt.cpp',
'/intl/icu/source/i18n/dtitvinf.cpp',
@@ -59,10 +58,6 @@ sources = [
'/intl/icu/source/i18n/ethpccal.cpp',
'/intl/icu/source/i18n/fmtable.cpp',
'/intl/icu/source/i18n/format.cpp',
'/intl/icu/source/i18n/formatted_string_builder.cpp',
'/intl/icu/source/i18n/formattedval_iterimpl.cpp',
'/intl/icu/source/i18n/formattedval_sbimpl.cpp',
'/intl/icu/source/i18n/formattedvalue.cpp',
'/intl/icu/source/i18n/fphdlimp.cpp',
'/intl/icu/source/i18n/fpositer.cpp',
'/intl/icu/source/i18n/gregocal.cpp',
@@ -70,28 +65,16 @@ sources = [
'/intl/icu/source/i18n/hebrwcal.cpp',
'/intl/icu/source/i18n/indiancal.cpp',
'/intl/icu/source/i18n/islamcal.cpp',
'/intl/icu/source/i18n/iso8601cal.cpp',
'/intl/icu/source/i18n/japancal.cpp',
'/intl/icu/source/i18n/listformatter.cpp',
'/intl/icu/source/i18n/measfmt.cpp',
'/intl/icu/source/i18n/measunit.cpp',
'/intl/icu/source/i18n/measunit_extra.cpp',
'/intl/icu/source/i18n/measure.cpp',
'/intl/icu/source/i18n/messageformat2.cpp',
'/intl/icu/source/i18n/messageformat2_arguments.cpp',
'/intl/icu/source/i18n/messageformat2_checker.cpp',
'/intl/icu/source/i18n/messageformat2_data_model.cpp',
'/intl/icu/source/i18n/messageformat2_errors.cpp',
'/intl/icu/source/i18n/messageformat2_evaluation.cpp',
'/intl/icu/source/i18n/messageformat2_formattable.cpp',
'/intl/icu/source/i18n/messageformat2_formatter.cpp',
'/intl/icu/source/i18n/messageformat2_function_registry.cpp',
'/intl/icu/source/i18n/messageformat2_parser.cpp',
'/intl/icu/source/i18n/messageformat2_serializer.cpp',
'/intl/icu/source/i18n/msgfmt.cpp',
'/intl/icu/source/i18n/nfrs.cpp',
'/intl/icu/source/i18n/nfrule.cpp',
'/intl/icu/source/i18n/nfsubs.cpp',
'/intl/icu/source/i18n/nounit.cpp',
'/intl/icu/source/i18n/number_affixutils.cpp',
'/intl/icu/source/i18n/number_asformat.cpp',
'/intl/icu/source/i18n/number_capi.cpp',
@@ -108,16 +91,13 @@ sources = [
'/intl/icu/source/i18n/number_modifiers.cpp',
'/intl/icu/source/i18n/number_multiplier.cpp',
'/intl/icu/source/i18n/number_notation.cpp',
'/intl/icu/source/i18n/number_output.cpp',
'/intl/icu/source/i18n/number_padding.cpp',
'/intl/icu/source/i18n/number_patternmodifier.cpp',
'/intl/icu/source/i18n/number_patternstring.cpp',
'/intl/icu/source/i18n/number_rounding.cpp',
'/intl/icu/source/i18n/number_scientific.cpp',
'/intl/icu/source/i18n/number_simple.cpp',
'/intl/icu/source/i18n/number_skeletons.cpp',
'/intl/icu/source/i18n/number_symbolswrapper.cpp',
'/intl/icu/source/i18n/number_usageprefs.cpp',
'/intl/icu/source/i18n/number_stringbuilder.cpp',
'/intl/icu/source/i18n/number_utils.cpp',
'/intl/icu/source/i18n/numfmt.cpp',
'/intl/icu/source/i18n/numparse_affixes.cpp',
@@ -127,15 +107,14 @@ sources = [
'/intl/icu/source/i18n/numparse_impl.cpp',
'/intl/icu/source/i18n/numparse_parsednumber.cpp',
'/intl/icu/source/i18n/numparse_scientific.cpp',
'/intl/icu/source/i18n/numparse_stringsegment.cpp',
'/intl/icu/source/i18n/numparse_symbols.cpp',
'/intl/icu/source/i18n/numparse_validators.cpp',
'/intl/icu/source/i18n/numrange_capi.cpp',
'/intl/icu/source/i18n/numrange_fluent.cpp',
'/intl/icu/source/i18n/numrange_impl.cpp',
'/intl/icu/source/i18n/numsys.cpp',
'/intl/icu/source/i18n/olsontz.cpp',
'/intl/icu/source/i18n/persncal.cpp',
'/intl/icu/source/i18n/pluralranges.cpp',
'/intl/icu/source/i18n/plurfmt.cpp',
'/intl/icu/source/i18n/plurrule.cpp',
'/intl/icu/source/i18n/quantityformatter.cpp',
@@ -154,7 +133,6 @@ sources = [
'/intl/icu/source/i18n/smpdtfst.cpp',
'/intl/icu/source/i18n/sortkey.cpp',
'/intl/icu/source/i18n/standardplural.cpp',
'/intl/icu/source/i18n/string_segment.cpp',
'/intl/icu/source/i18n/stsearch.cpp',
'/intl/icu/source/i18n/taiwncal.cpp',
'/intl/icu/source/i18n/timezone.cpp',
@@ -179,10 +157,6 @@ sources = [
'/intl/icu/source/i18n/uitercollationiterator.cpp',
'/intl/icu/source/i18n/ulistformatter.cpp',
'/intl/icu/source/i18n/umsg.cpp',
'/intl/icu/source/i18n/units_complexconverter.cpp',
'/intl/icu/source/i18n/units_converter.cpp',
'/intl/icu/source/i18n/units_data.cpp',
'/intl/icu/source/i18n/units_router.cpp',
'/intl/icu/source/i18n/unum.cpp',
'/intl/icu/source/i18n/unumsys.cpp',
'/intl/icu/source/i18n/upluralrules.cpp',
@@ -271,7 +245,6 @@ EXPORTS.unicode += [
'/intl/icu/source/i18n/unicode/datefmt.h',
'/intl/icu/source/i18n/unicode/dcfmtsym.h',
'/intl/icu/source/i18n/unicode/decimfmt.h',
'/intl/icu/source/i18n/unicode/displayoptions.h',
'/intl/icu/source/i18n/unicode/dtfmtsym.h',
'/intl/icu/source/i18n/unicode/dtitvfmt.h',
'/intl/icu/source/i18n/unicode/dtitvinf.h',
@@ -280,8 +253,6 @@ EXPORTS.unicode += [
'/intl/icu/source/i18n/unicode/fieldpos.h',
'/intl/icu/source/i18n/unicode/fmtable.h',
'/intl/icu/source/i18n/unicode/format.h',
'/intl/icu/source/i18n/unicode/formattednumber.h',
'/intl/icu/source/i18n/unicode/formattedvalue.h',
'/intl/icu/source/i18n/unicode/fpositer.h',
'/intl/icu/source/i18n/unicode/gender.h',
'/intl/icu/source/i18n/unicode/gregocal.h',
@@ -289,12 +260,6 @@ EXPORTS.unicode += [
'/intl/icu/source/i18n/unicode/measfmt.h',
'/intl/icu/source/i18n/unicode/measunit.h',
'/intl/icu/source/i18n/unicode/measure.h',
'/intl/icu/source/i18n/unicode/messageformat2.h',
'/intl/icu/source/i18n/unicode/messageformat2_arguments.h',
'/intl/icu/source/i18n/unicode/messageformat2_data_model.h',
'/intl/icu/source/i18n/unicode/messageformat2_data_model_names.h',
'/intl/icu/source/i18n/unicode/messageformat2_formattable.h',
'/intl/icu/source/i18n/unicode/messageformat2_function_registry.h',
'/intl/icu/source/i18n/unicode/msgfmt.h',
'/intl/icu/source/i18n/unicode/nounit.h',
'/intl/icu/source/i18n/unicode/numberformatter.h',
@@ -311,7 +276,6 @@ EXPORTS.unicode += [
'/intl/icu/source/i18n/unicode/scientificnumberformatter.h',
'/intl/icu/source/i18n/unicode/search.h',
'/intl/icu/source/i18n/unicode/selfmt.h',
'/intl/icu/source/i18n/unicode/simplenumberformatter.h',
'/intl/icu/source/i18n/unicode/simpletz.h',
'/intl/icu/source/i18n/unicode/smpdtfmt.h',
'/intl/icu/source/i18n/unicode/sortkey.h',
@@ -333,11 +297,8 @@ EXPORTS.unicode += [
'/intl/icu/source/i18n/unicode/udat.h',
'/intl/icu/source/i18n/unicode/udateintervalformat.h',
'/intl/icu/source/i18n/unicode/udatpg.h',
'/intl/icu/source/i18n/unicode/udisplayoptions.h',
'/intl/icu/source/i18n/unicode/ufieldpositer.h',
'/intl/icu/source/i18n/unicode/uformattable.h',
'/intl/icu/source/i18n/unicode/uformattednumber.h',
'/intl/icu/source/i18n/unicode/uformattedvalue.h',
'/intl/icu/source/i18n/unicode/ugender.h',
'/intl/icu/source/i18n/unicode/ulistformatter.h',
'/intl/icu/source/i18n/unicode/ulocdata.h',
@@ -345,15 +306,12 @@ EXPORTS.unicode += [
'/intl/icu/source/i18n/unicode/unirepl.h',
'/intl/icu/source/i18n/unicode/unum.h',
'/intl/icu/source/i18n/unicode/unumberformatter.h',
'/intl/icu/source/i18n/unicode/unumberoptions.h',
'/intl/icu/source/i18n/unicode/unumberrangeformatter.h',
'/intl/icu/source/i18n/unicode/unumsys.h',
'/intl/icu/source/i18n/unicode/upluralrules.h',
'/intl/icu/source/i18n/unicode/uregex.h',
'/intl/icu/source/i18n/unicode/uregion.h',
'/intl/icu/source/i18n/unicode/ureldatefmt.h',
'/intl/icu/source/i18n/unicode/usearch.h',
'/intl/icu/source/i18n/unicode/usimplenumberformatter.h',
'/intl/icu/source/i18n/unicode/uspoof.h',
'/intl/icu/source/i18n/unicode/utmscale.h',
'/intl/icu/source/i18n/unicode/utrans.h',
+3 -2
View File
@@ -41,11 +41,12 @@ if CONFIG['CPU_ARCH'] == 'arm':
if CONFIG['MOZ_FFVPX']:
external_dirs += ['media/ffvpx']
if CONFIG["MOZ_JXL"]:
external_dirs += ["media/libjxl", "media/highway"]
external_dirs += [
'media/highway',
'media/kiss_fft',
'media/libcubeb',
'media/libjxl',
'media/libnestegg',
'media/libogg',
'media/libopus',
+1 -1
View File
@@ -8,4 +8,4 @@
# Referenced by milestone.py.
#--------------------------------------------------------
6.8.1
6.7.0
+4
View File
@@ -348,7 +348,11 @@ ifdef SHARED_LIBRARY
ifdef IS_COMPONENT
EXTRA_DSO_LDOPTS += -bundle
else
ifdef MOZ_IOS
_LOADER_PATH := @rpath
else
_LOADER_PATH := @executable_path
endif
EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
endif
endif
+6
View File
@@ -424,6 +424,7 @@ fstream
fstream.h
ft2build.h
fts.h
gconf/gconf-client.h
Gdiplus.h
gdk/gdk.h
gdk/gdkkeysyms.h
@@ -1032,6 +1033,9 @@ X11/Xutil.h
zmouse.h
soundtouch/SoundTouch.h
soundtouch/SoundTouchFactory.h
#if MOZ_LIBAV_FFT==1
libavcodec/avfft.h
#endif
#if MOZ_SYSTEM_ZLIB==1
zlib.h
#endif
@@ -1049,7 +1053,9 @@ hunspell.hxx
#if MOZ_SYSTEM_BZ2==1
bzlib.h
#endif
#ifdef MOZ_ENABLE_GIO
gio/gio.h
#endif
sys/event.h
#ifdef MOZ_ENABLE_LIBPROXY
proxy.h
+1516 -2871
View File
File diff suppressed because it is too large. Load diff
+44 -102
View File
@@ -133,7 +133,7 @@ extern "C" {
**
** Since [version 3.6.18] ([dateof:3.6.18]),
** SQLite source code has been stored in the
** <a href="http://fossil-scm.org/">Fossil configuration management
** <a href="http://www.fossil-scm.org/">Fossil configuration management
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
@@ -146,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.50.1"
#define SQLITE_VERSION_NUMBER 3050001
#define SQLITE_SOURCE_ID "2025-06-06 14:52:32 b77dc5e0f596d2140d9ac682b2893ff65d3a4140aa86067a3efebe29dc914c95"
#define SQLITE_VERSION "3.49.1"
#define SQLITE_VERSION_NUMBER 3049001
#define SQLITE_SOURCE_ID "2025-02-18 13:38:58 873d4e274b4988d260ba8354a9718324a1c26187a4ab4c1cc0227c03d0f10e70"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1163,12 +1163,6 @@ struct sqlite3_io_methods {
** the value that M is to be set to. Before returning, the 32-bit signed
** integer is overwritten with the previous value of M.
**
** <li>[[SQLITE_FCNTL_BLOCK_ON_CONNECT]]
** The [SQLITE_FCNTL_BLOCK_ON_CONNECT] opcode is used to configure the
** VFS to block when taking a SHARED lock to connect to a wal mode database.
** This is used to implement the functionality associated with
** SQLITE_SETLK_BLOCK_ON_CONNECT.
**
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
** a database file. The argument is a pointer to a 32-bit unsigned integer.
@@ -1265,7 +1259,6 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
#define SQLITE_FCNTL_NULL_IO 43
#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1996,16 +1989,13 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
** <dd> ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine
** the default size of [lookaside memory] on each [database connection].
** the default size of lookaside memory on each [database connection].
** The first argument is the
** size of each lookaside buffer slot ("sz") and the second is the number of
** slots allocated to each database connection ("cnt").)^
** ^(SQLITE_CONFIG_LOOKASIDE sets the <i>default</i> lookaside size.
** The [SQLITE_DBCONFIG_LOOKASIDE] option to [sqlite3_db_config()] can
** be used to change the lookaside configuration on individual connections.)^
** The [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to change the
** default lookaside configuration at compile-time.
** </dd>
** size of each lookaside buffer slot and the second is the number of
** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE
** sets the <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
** option to [sqlite3_db_config()] can be used to change the lookaside
** configuration on individual connections.)^ </dd>
**
** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is
@@ -2242,50 +2232,31 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> The SQLITE_DBCONFIG_LOOKASIDE option is used to adjust the
** configuration of the [lookaside memory allocator] within a database
** configuration of the lookaside memory allocator within a database
** connection.
** The arguments to the SQLITE_DBCONFIG_LOOKASIDE option are <i>not</i>
** in the [DBCONFIG arguments|usual format].
** The SQLITE_DBCONFIG_LOOKASIDE option takes three arguments, not two,
** so that a call to [sqlite3_db_config()] that uses SQLITE_DBCONFIG_LOOKASIDE
** should have a total of five parameters.
** <ol>
** <li><p>The first argument ("buf") is a
** ^The first argument (the third parameter to [sqlite3_db_config()] is a
** pointer to a memory buffer to use for lookaside memory.
** The first argument may be NULL in which case SQLite will allocate the
** lookaside buffer itself using [sqlite3_malloc()].
** <li><P>The second argument ("sz") is the
** size of each lookaside buffer slot. Lookaside is disabled if "sz"
** is less than 8. The "sz" argument should be a multiple of 8 less than
** 65536. If "sz" does not meet this constraint, it is reduced in size until
** it does.
** <li><p>The third argument ("cnt") is the number of slots. Lookaside is disabled
** if "cnt"is less than 1. The "cnt" value will be reduced, if necessary, so
** that the product of "sz" and "cnt" does not exceed 2,147,418,112. The "cnt"
** parameter is usually chosen so that the product of "sz" and "cnt" is less
** than 1,000,000.
** </ol>
** <p>If the "buf" argument is not NULL, then it must
** point to a memory buffer with a size that is greater than
** or equal to the product of "sz" and "cnt".
** The buffer must be aligned to an 8-byte boundary.
** The lookaside memory
** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
** may be NULL in which case SQLite will allocate the
** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
** size of each lookaside buffer slot. ^The third argument is the number of
** slots. The size of the buffer in the first argument must be greater than
** or equal to the product of the second and third arguments. The buffer
** must be aligned to an 8-byte boundary. ^If the second argument to
** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
** rounded down to the next smaller multiple of 8. ^(The lookaside memory
** configuration for a database connection can only be changed when that
** connection is not currently using lookaside memory, or in other words
** when the value returned by [SQLITE_DBSTATUS_LOOKASIDE_USED] is zero.
** when the "current value" returned by
** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero.
** Any attempt to change the lookaside memory configuration when lookaside
** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].
** If the "buf" argument is NULL and an attempt
** to allocate memory based on "sz" and "cnt" fails, then
** lookaside is silently disabled.
** <p>
** The [SQLITE_CONFIG_LOOKASIDE] configuration option can be used to set the
** default lookaside configuration at initialization. The
** [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to set the default lookaside
** configuration at compile-time. Typical values for lookaside are 1200 for
** "sz" and 40 to 100 for "cnt".
** </dd>
** [SQLITE_BUSY].)^</dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
@@ -3022,44 +2993,6 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
/*
** CAPI3REF: Set the Setlk Timeout
** METHOD: sqlite3
**
** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If
** the VFS supports blocking locks, it sets the timeout in ms used by
** eligible locks taken on wal mode databases by the specified database
** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does
** not support blocking locks, this function is a no-op.
**
** Passing 0 to this function disables blocking locks altogether. Passing
** -1 to this function requests that the VFS blocks for a long time -
** indefinitely if possible. The results of passing any other negative value
** are undefined.
**
** Internally, each SQLite database handle store two timeout values - the
** busy-timeout (used for rollback mode databases, or if the VFS does not
** support blocking locks) and the setlk-timeout (used for blocking locks
** on wal-mode databases). The sqlite3_busy_timeout() method sets both
** values, this function sets only the setlk-timeout value. Therefore,
** to configure separate busy-timeout and setlk-timeout values for a single
** database handle, call sqlite3_busy_timeout() followed by this function.
**
** Whenever the number of connections to a wal mode database falls from
** 1 to 0, the last connection takes an exclusive lock on the database,
** then checkpoints and deletes the wal file. While it is doing this, any
** new connection that tries to read from the database fails with an
** SQLITE_BUSY error. Or, if the SQLITE_SETLK_BLOCK_ON_CONNECT flag is
** passed to this API, the new connection blocks until the exclusive lock
** has been released.
*/
SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags);
/*
** CAPI3REF: Flags for sqlite3_setlk_timeout()
*/
#define SQLITE_SETLK_BLOCK_ON_CONNECT 0x01
/*
** CAPI3REF: Convenience Routines For Running Queries
** METHOD: sqlite3
@@ -5175,7 +5108,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
** sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
@@ -7071,8 +7004,6 @@ SQLITE_API int sqlite3_autovacuum_pages(
**
** ^The second argument is a pointer to the function to invoke when a
** row is updated, inserted or deleted in a rowid table.
** ^The update hook is disabled by invoking sqlite3_update_hook()
** with a NULL pointer as the second parameter.
** ^The first argument to the callback is a copy of the third argument
** to sqlite3_update_hook().
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -11555,10 +11486,9 @@ SQLITE_API void sqlite3session_table_filter(
** is inserted while a session object is enabled, then later deleted while
** the same session object is disabled, no INSERT record will appear in the
** changeset, even though the delete took place while the session was disabled.
** Or, if one field of a row is updated while a session is enabled, and
** then another field of the same row is updated while the session is disabled,
** the resulting changeset will contain an UPDATE change that updates both
** fields.
** Or, if one field of a row is updated while a session is disabled, and
** another field of the same row is updated while the session is enabled, the
** resulting changeset will contain an UPDATE change that updates both fields.
*/
SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
@@ -11630,9 +11560,8 @@ SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession
** database zFrom the contents of the two compatible tables would be
** identical.
**
** Unless the call to this function is a no-op as described above, it is an
** error if database zFrom does not exist or does not contain the required
** compatible table.
** It an error if database zFrom does not exist or does not contain the
** required compatible table.
**
** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
@@ -11767,7 +11696,7 @@ SQLITE_API int sqlite3changeset_start_v2(
** The following flags may passed via the 4th parameter to
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
**
** <dt>SQLITE_CHANGESETSTART_INVERT <dd>
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
** Invert the changeset while iterating through it. This is equivalent to
** inverting a changeset using sqlite3changeset_invert() before applying it.
** It is an error to specify this flag with a patchset.
@@ -12082,6 +12011,19 @@ SQLITE_API int sqlite3changeset_concat(
void **ppOut /* OUT: Buffer containing output changeset */
);
/*
** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
*/
SQLITE_API int sqlite3changeset_upgrade(
sqlite3 *db,
const char *zDb,
int nIn, const void *pIn, /* Input changeset */
int *pnOut, void **ppOut /* OUT: Inverse of input */
);
/*
** CAPI3REF: Changegroup Handle
**
+161 -161
View File
@@ -2397,7 +2397,7 @@ var Debugger =
/***/ function(module, exports, __webpack_require__) {
/* 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,
* 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/. */
var React = __webpack_require__(2);
@@ -30019,166 +30019,166 @@ var Debugger =
/* 266 */
/***/ function(module, exports, __webpack_require__) {
(function(){
var crypt = __webpack_require__(267),
utf8 = __webpack_require__(268).utf8,
isBuffer = __webpack_require__(269),
bin = __webpack_require__(268).bin,
// The core
md5 = function (message, options) {
// Convert to byte array
if (message.constructor == String)
if (options && options.encoding === 'binary')
message = bin.stringToBytes(message);
else
message = utf8.stringToBytes(message);
else if (isBuffer(message))
message = Array.prototype.slice.call(message, 0);
else if (!Array.isArray(message))
message = message.toString();
// else, assume byte array already
var m = crypt.bytesToWords(message),
l = message.length * 8,
a = 1732584193,
b = -271733879,
c = -1732584194,
d = 271733878;
// Swap endian
for (var i = 0; i < m.length; i++) {
m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
}
// Padding
m[l >>> 5] |= 0x80 << (l % 32);
m[(((l + 64) >>> 9) << 4) + 14] = l;
// Method shortcuts
var FF = md5._ff,
GG = md5._gg,
HH = md5._hh,
II = md5._ii;
for (var i = 0; i < m.length; i += 16) {
var aa = a,
bb = b,
cc = c,
dd = d;
a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
c = FF(c, d, a, b, m[i+10], 17, -42063);
b = FF(b, c, d, a, m[i+11], 22, -1990404162);
a = FF(a, b, c, d, m[i+12], 7, 1804603682);
d = FF(d, a, b, c, m[i+13], 12, -40341101);
c = FF(c, d, a, b, m[i+14], 17, -1502002290);
b = FF(b, c, d, a, m[i+15], 22, 1236535329);
a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
c = GG(c, d, a, b, m[i+11], 14, 643717713);
b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
d = GG(d, a, b, c, m[i+10], 9, 38016083);
c = GG(c, d, a, b, m[i+15], 14, -660478335);
b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
d = GG(d, a, b, c, m[i+14], 9, -1019803690);
c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
a = GG(a, b, c, d, m[i+13], 5, -1444681467);
d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
b = GG(b, c, d, a, m[i+12], 20, -1926607734);
a = HH(a, b, c, d, m[i+ 5], 4, -378558);
d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
c = HH(c, d, a, b, m[i+11], 16, 1839030562);
b = HH(b, c, d, a, m[i+14], 23, -35309556);
a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
b = HH(b, c, d, a, m[i+10], 23, -1094730640);
a = HH(a, b, c, d, m[i+13], 4, 681279174);
d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
d = HH(d, a, b, c, m[i+12], 11, -421815835);
c = HH(c, d, a, b, m[i+15], 16, 530742520);
b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
a = II(a, b, c, d, m[i+ 0], 6, -198630844);
d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
c = II(c, d, a, b, m[i+14], 15, -1416354905);
b = II(b, c, d, a, m[i+ 5], 21, -57434055);
a = II(a, b, c, d, m[i+12], 6, 1700485571);
d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
c = II(c, d, a, b, m[i+10], 15, -1051523);
b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
d = II(d, a, b, c, m[i+15], 10, -30611744);
c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
b = II(b, c, d, a, m[i+13], 21, 1309151649);
a = II(a, b, c, d, m[i+ 4], 6, -145523070);
d = II(d, a, b, c, m[i+11], 10, -1120210379);
c = II(c, d, a, b, m[i+ 2], 15, 718787259);
b = II(b, c, d, a, m[i+ 9], 21, -343485551);
a = (a + aa) >>> 0;
b = (b + bb) >>> 0;
c = (c + cc) >>> 0;
d = (d + dd) >>> 0;
}
return crypt.endian([a, b, c, d]);
};
// Auxiliary functions
md5._ff = function (a, b, c, d, x, s, t) {
var n = a + (b & c | ~b & d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._gg = function (a, b, c, d, x, s, t) {
var n = a + (b & d | c & ~d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._hh = function (a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._ii = function (a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
// Package private blocksize
md5._blocksize = 16;
md5._digestsize = 16;
module.exports = function (message, options) {
if (message === undefined || message === null)
throw new Error('Illegal argument ' + message);
var digestbytes = crypt.wordsToBytes(md5(message, options));
return options && options.asBytes ? digestbytes :
options && options.asString ? bin.bytesToString(digestbytes) :
crypt.bytesToHex(digestbytes);
};
})();
(function(){
var crypt = __webpack_require__(267),
utf8 = __webpack_require__(268).utf8,
isBuffer = __webpack_require__(269),
bin = __webpack_require__(268).bin,
// The core
md5 = function (message, options) {
// Convert to byte array
if (message.constructor == String)
if (options && options.encoding === 'binary')
message = bin.stringToBytes(message);
else
message = utf8.stringToBytes(message);
else if (isBuffer(message))
message = Array.prototype.slice.call(message, 0);
else if (!Array.isArray(message))
message = message.toString();
// else, assume byte array already
var m = crypt.bytesToWords(message),
l = message.length * 8,
a = 1732584193,
b = -271733879,
c = -1732584194,
d = 271733878;
// Swap endian
for (var i = 0; i < m.length; i++) {
m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
}
// Padding
m[l >>> 5] |= 0x80 << (l % 32);
m[(((l + 64) >>> 9) << 4) + 14] = l;
// Method shortcuts
var FF = md5._ff,
GG = md5._gg,
HH = md5._hh,
II = md5._ii;
for (var i = 0; i < m.length; i += 16) {
var aa = a,
bb = b,
cc = c,
dd = d;
a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
c = FF(c, d, a, b, m[i+10], 17, -42063);
b = FF(b, c, d, a, m[i+11], 22, -1990404162);
a = FF(a, b, c, d, m[i+12], 7, 1804603682);
d = FF(d, a, b, c, m[i+13], 12, -40341101);
c = FF(c, d, a, b, m[i+14], 17, -1502002290);
b = FF(b, c, d, a, m[i+15], 22, 1236535329);
a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
c = GG(c, d, a, b, m[i+11], 14, 643717713);
b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
d = GG(d, a, b, c, m[i+10], 9, 38016083);
c = GG(c, d, a, b, m[i+15], 14, -660478335);
b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
d = GG(d, a, b, c, m[i+14], 9, -1019803690);
c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
a = GG(a, b, c, d, m[i+13], 5, -1444681467);
d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
b = GG(b, c, d, a, m[i+12], 20, -1926607734);
a = HH(a, b, c, d, m[i+ 5], 4, -378558);
d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
c = HH(c, d, a, b, m[i+11], 16, 1839030562);
b = HH(b, c, d, a, m[i+14], 23, -35309556);
a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
b = HH(b, c, d, a, m[i+10], 23, -1094730640);
a = HH(a, b, c, d, m[i+13], 4, 681279174);
d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
d = HH(d, a, b, c, m[i+12], 11, -421815835);
c = HH(c, d, a, b, m[i+15], 16, 530742520);
b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
a = II(a, b, c, d, m[i+ 0], 6, -198630844);
d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
c = II(c, d, a, b, m[i+14], 15, -1416354905);
b = II(b, c, d, a, m[i+ 5], 21, -57434055);
a = II(a, b, c, d, m[i+12], 6, 1700485571);
d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
c = II(c, d, a, b, m[i+10], 15, -1051523);
b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
d = II(d, a, b, c, m[i+15], 10, -30611744);
c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
b = II(b, c, d, a, m[i+13], 21, 1309151649);
a = II(a, b, c, d, m[i+ 4], 6, -145523070);
d = II(d, a, b, c, m[i+11], 10, -1120210379);
c = II(c, d, a, b, m[i+ 2], 15, 718787259);
b = II(b, c, d, a, m[i+ 9], 21, -343485551);
a = (a + aa) >>> 0;
b = (b + bb) >>> 0;
c = (c + cc) >>> 0;
d = (d + dd) >>> 0;
}
return crypt.endian([a, b, c, d]);
};
// Auxiliary functions
md5._ff = function (a, b, c, d, x, s, t) {
var n = a + (b & c | ~b & d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._gg = function (a, b, c, d, x, s, t) {
var n = a + (b & d | c & ~d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._hh = function (a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._ii = function (a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
// Package private blocksize
md5._blocksize = 16;
md5._digestsize = 16;
module.exports = function (message, options) {
if (message === undefined || message === null)
throw new Error('Illegal argument ' + message);
var digestbytes = crypt.wordsToBytes(md5(message, options));
return options && options.asBytes ? digestbytes :
options && options.asString ? bin.bytesToString(digestbytes) :
crypt.bytesToHex(digestbytes);
};
})();
/***/ },
+14
View File
@@ -612,6 +612,7 @@ menuseparator {
}
.autocomplete .results * {
-moz-user-select: none;
user-select: none;
}
@@ -772,6 +773,7 @@ menuseparator {
}
.tree {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
@@ -818,6 +820,7 @@ html[dir="rtl"] .tree .node > div {
}
.sources-panel * {
-moz-user-select: none;
user-select: none;
}
@@ -831,6 +834,7 @@ html[dir="rtl"] .tree .node > div {
display: flex;
align-items: baseline;
justify-content: space-between;
-moz-user-select: none;
user-select: none;
}
@@ -912,6 +916,7 @@ html[dir="rtl"] .worker svg {
.tree {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
@@ -961,6 +966,7 @@ html[dir="rtl"] .worker svg {
right: 1px;
opacity: 1;
z-index: 100;
-moz-user-select: none;
user-select: none;
}
@@ -973,6 +979,7 @@ html[dir="rtl"] .source-footer .command-bar {
}
.source-footer .command-bar * {
-moz-user-select: none;
user-select: none;
}
@@ -1179,6 +1186,7 @@ html[dir="rtl"] .editor-mount {
background-color: var(--theme-tab-toolbar-background);
font-weight: lighter;
z-index: 100;
-moz-user-select: none;
user-select: none;
}
@@ -1205,6 +1213,7 @@ html[dir="rtl"] .editor-mount {
outline-width: 0;
}
.breakpoints-list * {
-moz-user-select: none;
user-select: none;
}
@@ -1387,6 +1396,7 @@ html .arrow.expanded svg {
*/
.frames ul li * {
-moz-user-select: none;
user-select: none;
}
@@ -1439,6 +1449,7 @@ html .arrow.expanded svg {
width: 100%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
@@ -1464,6 +1475,7 @@ html .arrow.expanded svg {
}
.right-siderbar * {
-moz-user-select: none;
user-select: none;
}
@@ -1538,6 +1550,7 @@ html[dir="rtl"] .command-bar .stepOut {
font-style: italic;
text-align: center;
padding: 0.5em;
-moz-user-select: none;
user-select: none;
}
@@ -1559,6 +1572,7 @@ span.pause-exceptions.all {
}
.source-header * {
-moz-user-select: none;
user-select: none;
}
+1 -1
View File
@@ -2,7 +2,7 @@
* 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/. */
:root{
user-select: none;
-moz-user-select: none;
}
#options-panel-container {
@@ -20,7 +20,7 @@
padding: 5px;
transition: all 0.25s ease;
width: 100%;
user-select: none;
-moz-user-select: none;
}
.accordion ._header:hover {
+5
View File
@@ -37,6 +37,8 @@ const {AutocompletePopup} = require("devtools/client/shared/autocomplete-popup")
const HTML_NS = "http://www.w3.org/1999/xhtml";
const PREF_UA_STYLES = "devtools.inspector.showUserAgentStyles";
const PREF_DEFAULT_COLOR_UNIT = "devtools.defaultColorUnit";
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
"devtools.inspector.mdnDocsTooltip.enabled";
const FILTER_CHANGED_TIMEOUT = 150;
// This is used to parse user input when filtering.
@@ -155,8 +157,11 @@ function CssRuleView(inspector, document, store, pageStyle) {
this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
this._prefObserver.on(PREF_UA_STYLES, this._handlePrefChange);
this._prefObserver.on(PREF_DEFAULT_COLOR_UNIT, this._handlePrefChange);
this._prefObserver.on(PREF_ENABLE_MDN_DOCS_TOOLTIP, this._handlePrefChange);
this.showUserAgentStyles = Services.prefs.getBoolPref(PREF_UA_STYLES);
this.enableMdnDocsTooltip =
Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
// The popup will be attached to the toolbox document.
this.popup = new AutocompletePopup(inspector._toolbox.doc, {
@@ -85,6 +85,9 @@ support-files =
[browser_rules_content_01.js]
[browser_rules_content_02.js]
skip-if = e10s && debug # Bug 1250058 - Docshell leak on debug e10s
[browser_rules_context-menu-show-mdn-docs-01.js]
[browser_rules_context-menu-show-mdn-docs-02.js]
[browser_rules_context-menu-show-mdn-docs-03.js]
[browser_rules_copy_styles.js]
subsuite = clipboard
[browser_rules_cssom.js]
@@ -0,0 +1,138 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests the code that integrates the Style Inspector's rule view
* with the MDN docs tooltip.
*
* If you display the context click on a property name in the rule view, you
* should see a menu item "Show MDN Docs". If you click that item, the MDN
* docs tooltip should be shown, containing docs from MDN for that property.
*
* This file tests that the context menu item is shown when it should be
* shown and hidden when it should be hidden.
*/
"use strict";
/**
* The test document tries to confuse the context menu
* code by having a tag called "padding" and a property
* value called "margin".
*/
const { PrefObserver } = require("devtools/client/shared/prefs");
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
"devtools.inspector.mdnDocsTooltip.enabled";
const TEST_URI = `
<html>
<head>
<style>
padding {font-family: margin;}
</style>
</head>
<body>
<padding>MDN tooltip testing</padding>
</body>
</html>
`;
add_task(function* () {
info("Ensure the pref is true to begin with");
let initial = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
if (initial != true) {
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
}
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_URI));
let {inspector, view} = yield openRuleView();
yield selectNode("padding", inspector);
yield testMdnContextMenuItemVisibility(view);
info("Ensure the pref is reset to its initial value");
let eventual = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
if (eventual != initial) {
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, initial);
}
});
/**
* Set a boolean pref, and wait for the pref observer to
* trigger, so that code listening for the pref change
* has had a chance to update itself.
*
* @param pref {string} Name of the pref to change
* @param state {boolean} Desired value of the pref.
*
* Note that if the pref already has the value in `state`,
* then the prefObserver will not trigger. So you should only
* call this function if you know the pref's current value is
* not `state`.
*/
function* setBooleanPref(pref, state) {
let oncePrefChanged = defer();
let prefObserver = new PrefObserver("devtools.");
prefObserver.on(pref, oncePrefChanged.resolve);
info("Set the pref " + pref + " to: " + state);
Services.prefs.setBoolPref(pref, state);
info("Wait for prefObserver to call back so the UI can update");
yield oncePrefChanged.promise;
prefObserver.off(pref, oncePrefChanged.resolve);
}
/**
* Tests that the MDN context menu item is shown when it should be,
* and hidden when it should be.
* - iterate through every node in the rule view
* - set that node as popupNode (the node that the context menu
* is shown for)
* - update the context menu's state
* - test that the MDN context menu item is hidden, or not,
* depending on popupNode
*/
function* testMdnContextMenuItemVisibility(view) {
info("Test that MDN context menu item is shown only when it should be.");
let root = rootElement(view);
for (let node of iterateNodes(root)) {
info("Setting " + node + " as popupNode");
info("Creating context menu with " + node + " as popupNode");
let allMenuItems = openStyleContextMenuAndGetAllItems(view, node);
let menuitemShowMdnDocs = allMenuItems.find(item => item.label ===
STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"));
let isVisible = menuitemShowMdnDocs.visible;
let shouldBeVisible = isPropertyNameNode(node);
let message = shouldBeVisible ? "shown" : "hidden";
is(isVisible, shouldBeVisible,
"The MDN context menu item is " + message + " ; content : " +
node.textContent + " ; type : " + node.nodeType);
}
}
/**
* Check if a node is a property name.
*/
function isPropertyNameNode(node) {
return node.textContent === "font-family";
}
/**
* A generator that iterates recursively through all child nodes of baseNode.
*/
function* iterateNodes(baseNode) {
yield baseNode;
for (let child of baseNode.childNodes) {
yield* iterateNodes(child);
}
}
/**
* Returns the root element for the rule view.
*/
var rootElement = view => (view.element) ? view.element : view.styleDocument;
@@ -0,0 +1,60 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests the code that integrates the Style Inspector's rule view
* with the MDN docs tooltip.
*
* If you display the context click on a property name in the rule view, you
* should see a menu item "Show MDN Docs". If you click that item, the MDN
* docs tooltip should be shown, containing docs from MDN for that property.
*
* This file tests that:
* - clicking the context menu item shows the tooltip
* - the tooltip content matches the property name for which the context menu was opened
*/
"use strict";
const {setBaseCssDocsUrl} =
require("devtools/client/shared/widgets/MdnDocsWidget");
const PROPERTYNAME = "color";
const TEST_DOC = `
<html>
<body>
<div style="color: red">
Test "Show MDN Docs" context menu option
</div>
</body>
</html>
`;
add_task(function* () {
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_DOC));
let {inspector, view} = yield openRuleView();
yield selectNode("div", inspector);
setBaseCssDocsUrl(URL_ROOT);
info("Setting the popupNode for the MDN docs tooltip");
let {nameSpan} = getRuleViewProperty(view, "element", PROPERTYNAME);
let allMenuItems = openStyleContextMenuAndGetAllItems(view, nameSpan.firstChild);
let menuitemShowMdnDocs = allMenuItems.find(item => item.label ===
STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"));
let cssDocs = view.tooltips.cssDocs;
info("Showing the MDN docs tooltip");
let onShown = cssDocs.tooltip.once("shown");
menuitemShowMdnDocs.click();
yield onShown;
ok(true, "The MDN docs tooltip was shown");
info("Quick check that the tooltip contents are set");
let h1 = cssDocs.tooltip.container.querySelector(".mdn-property-name");
is(h1.textContent, PROPERTYNAME, "The MDN docs tooltip h1 is correct");
});
@@ -0,0 +1,117 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests the "devtools.inspector.mdnDocsTooltip.enabled" preference,
* that we use to enable/disable the MDN tooltip in the Inspector.
*
* The desired behavior is:
* - if the preference is true, show the "Show MDN Docs" context menu item
* - if the preference is false, don't show the item
* - listen for changes to the pref, so we can show/hide the item dynamically
*/
"use strict";
const { PrefObserver } = require("devtools/client/styleeditor/utils");
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
"devtools.inspector.mdnDocsTooltip.enabled";
const PROPERTY_NAME_CLASS = "ruleview-propertyname";
const TEST_DOC = `
<html>
<body>
<div style="color: red">
Test the pref to enable/disable the "Show MDN Docs" context menu option
</div>
</body>
</html>
`;
add_task(function* () {
info("Ensure the pref is true to begin with");
let initial = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
if (initial != true) {
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
}
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_DOC));
let {inspector, view} = yield openRuleView();
yield selectNode("div", inspector);
yield testMdnContextMenuItemVisibility(view, true);
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, false);
yield testMdnContextMenuItemVisibility(view, false);
info("Close the Inspector");
let target = TargetFactory.forTab(gBrowser.selectedTab);
yield gDevTools.closeToolbox(target);
({inspector, view} = yield openRuleView());
yield selectNode("div", inspector);
yield testMdnContextMenuItemVisibility(view, false);
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
yield testMdnContextMenuItemVisibility(view, true);
info("Ensure the pref is reset to its initial value");
let eventual = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
if (eventual != initial) {
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, initial);
}
});
/**
* Set a boolean pref, and wait for the pref observer to
* trigger, so that code listening for the pref change
* has had a chance to update itself.
*
* @param pref {string} Name of the pref to change
* @param state {boolean} Desired value of the pref.
*
* Note that if the pref already has the value in `state`,
* then the prefObserver will not trigger. So you should only
* call this function if you know the pref's current value is
* not `state`.
*/
function* setBooleanPref(pref, state) {
let oncePrefChanged = defer();
let prefObserver = new PrefObserver("devtools.");
prefObserver.on(pref, oncePrefChanged.resolve);
info("Set the pref " + pref + " to: " + state);
Services.prefs.setBoolPref(pref, state);
info("Wait for prefObserver to call back so the UI can update");
yield oncePrefChanged.promise;
prefObserver.off(pref, oncePrefChanged.resolve);
}
/**
* Test whether the MDN tooltip context menu item is visible when it should be.
*
* @param view The rule view
* @param shouldBeVisible {boolean} Whether we expect the context
* menu item to be visible or not.
*/
function* testMdnContextMenuItemVisibility(view, shouldBeVisible) {
let message = shouldBeVisible ? "shown" : "hidden";
info("Test that MDN context menu item is " + message);
info("Set a CSS property name as popupNode");
let root = rootElement(view);
let node = root.querySelector("." + PROPERTY_NAME_CLASS).firstChild;
let allMenuItems = openStyleContextMenuAndGetAllItems(view, node);
let menuitemShowMdnDocs = allMenuItems.find(item => item.label ===
STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"));
let isVisible = menuitemShowMdnDocs.visible;
is(isVisible, shouldBeVisible,
"The MDN context menu item is " + message);
}
/**
* Returns the root element for the rule view.
*/
var rootElement = view => (view.element) ? view.element : view.styleDocument;
@@ -25,6 +25,9 @@ const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.prope
const {LocalizationHelper} = require("devtools/shared/l10n");
const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
"devtools.inspector.mdnDocsTooltip.enabled";
/**
* Style inspector context menu
*
@@ -53,6 +56,7 @@ function StyleInspectorMenu(view, options) {
this._onCopySelector = this._onCopySelector.bind(this);
this._onCopyUrl = this._onCopyUrl.bind(this);
this._onSelectAll = this._onSelectAll.bind(this);
this._onShowMdnDocs = this._onShowMdnDocs.bind(this);
this._onToggleOrigSources = this._onToggleOrigSources.bind(this);
}
@@ -225,6 +229,19 @@ StyleInspectorMenu.prototype = {
});
menu.append(menuitemAddRule);
// Show MDN Docs
let mdnDocsAccessKey = "styleinspector.contextmenu.showMdnDocs.accessKey";
let menuitemShowMdnDocs = new MenuItem({
label: STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"),
accesskey: STYLE_INSPECTOR_L10N.getStr(mdnDocsAccessKey),
click: () => {
this._onShowMdnDocs();
},
visible: (Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP) &&
this._isPropertyName()),
});
menu.append(menuitemShowMdnDocs);
// Show Original Sources
let sourcesAccessKey = "styleinspector.contextmenu.toggleOrigSources.accessKey";
let menuitemSources = new MenuItem({
@@ -390,6 +407,16 @@ StyleInspectorMenu.prototype = {
clipboardHelper.copyString(message);
}),
/**
* Show docs from MDN for a CSS property.
*/
_onShowMdnDocs: function () {
let cssPropertyName = this.styleDocument.popupNode.textContent;
let anchor = this.styleDocument.popupNode.parentNode;
let cssDocsTooltip = this.view.tooltips.cssDocs;
cssDocsTooltip.show(anchor, cssPropertyName);
},
/**
* Add a new rule to the current element.
*/
@@ -18,6 +18,7 @@ const {
} = require("devtools/client/inspector/shared/node-types");
const { getColor } = require("devtools/client/shared/theme");
const { getCssProperties } = require("devtools/shared/fronts/css-properties");
const CssDocsTooltip = require("devtools/client/shared/widgets/tooltip/CssDocsTooltip");
const { HTMLTooltip } = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
const {
getImageDimensions,
@@ -81,6 +82,9 @@ TooltipsOverlay.prototype = {
this.previewTooltip.startTogglingOnHover(this.view.element,
this._onPreviewTooltipTargetHover.bind(this));
// MDN CSS help tooltip
this.cssDocs = new CssDocsTooltip(toolbox.doc);
if (this.isRuleView) {
// Color picker tooltip
this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc,
@@ -116,6 +120,10 @@ TooltipsOverlay.prototype = {
this.cubicBezier.destroy();
}
if (this.cssDocs) {
this.cssDocs.destroy();
}
if (this.filterEditor) {
this.filterEditor.destroy();
}
@@ -143,7 +151,7 @@ TooltipsOverlay.prototype = {
// Font preview tooltip
if (type === VIEW_NODE_VALUE_TYPE && prop.property === "font-family") {
let value = prop.value.toLowerCase();
if (value !== "inherit" && value !== "unset" && value !== "initial" && value !== "revert") {
if (value !== "inherit" && value !== "unset" && value !== "initial") {
tooltipType = TOOLTIP_FONTFAMILY_TYPE;
}
}
@@ -183,6 +191,10 @@ TooltipsOverlay.prototype = {
this.cubicBezier.hide();
}
if (this.isRuleView && this.cssDocs.tooltip.isVisible()) {
this.cssDocs.hide();
}
if (this.isRuleView && this.filterEditor.tooltip.isVisible()) {
this.filterEditor.revert();
this.filterEdtior.hide();
@@ -283,6 +295,10 @@ TooltipsOverlay.prototype = {
this.cubicBezier.hide();
}
if (this.cssDocs) {
this.cssDocs.hide();
}
if (this.filterEditor) {
this.filterEditor.hide();
}
+1
View File
@@ -117,6 +117,7 @@ devtools.jar:
content/framework/connect/connect.js (framework/connect/connect.js)
content/shared/widgets/graphs-frame.xhtml (shared/widgets/graphs-frame.xhtml)
content/shared/widgets/cubic-bezier.css (shared/widgets/cubic-bezier.css)
content/shared/widgets/mdn-docs.css (shared/widgets/mdn-docs.css)
content/shared/widgets/filter-widget.css (shared/widgets/filter-widget.css)
content/shared/widgets/spectrum.css (shared/widgets/spectrum.css)
content/aboutdebugging/aboutdebugging.xhtml (aboutdebugging/aboutdebugging.xhtml)
@@ -29,7 +29,7 @@
padding-top: 8px;
padding-bottom: 4px;
font-weight: bold;
user-select: none;
-moz-user-select: none;
}
.headersPanelBox .netInfoParamValue {
+1 -1
View File
@@ -22,7 +22,7 @@
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
user-select: none;
-moz-user-select: none;
padding: 0 2px;
border-radius: 2px;
}
@@ -48,6 +48,14 @@ eyedropper.disabled.title=Unavailable in non-HTML documents
#LOCALIZATION NOTE: Used in the image preview tooltip when the image could not be loaded
eventsTooltip.openInDebugger=Open in Debugger
# LOCALIZATION NOTE (docsTooltip.visitMDN): Shown in the tooltip that displays
# help from MDN. This is a link to the complete MDN documentation page.
docsTooltip.visitMDN=Visit MDN page
# LOCALIZATION NOTE (docsTooltip.visitMDN): Shown in the docs tooltip when the MDN page
# could not be loaded (for example, because of a connectivity problem).
docsTooltip.loadDocsError=Could not load docs page.
# LOCALIZATION NOTE (inspector.collapsePane): This is the tooltip for the button
# that collapses the right panel (rules, computed, box-model, etc...) in the
# inspector UI.
+2
View File
@@ -47,6 +47,8 @@ pref("devtools.inspector.imagePreviewTooltipSize", 300);
pref("devtools.inspector.showUserAgentStyles", false);
// Show all native anonymous content (like controls in <video> tags)
pref("devtools.inspector.showAllAnonymousContent", false);
// Enable the MDN docs tooltip
pref("devtools.inspector.mdnDocsTooltip.enabled", false);
// Enable the Font Inspector
pref("devtools.fontinspector.enabled", true);
+5 -5
View File
@@ -78,7 +78,7 @@ html, body {
}
select {
appearance: none;
-moz-appearance: none;
background-color: var(--theme-toolbar-background);
background-image: var(--viewport-selection-arrow);
background-position: 100% 50%;
@@ -140,7 +140,7 @@ select > option.divider {
margin: 0 0 15px 0;
padding: 4px 5px;
display: inline-flex;
user-select: none;
-moz-user-select: none;
}
#global-toolbar > .title {
@@ -196,7 +196,7 @@ select > option.divider {
#global-dpr-selector {
margin: 0 8px;
user-select: none;
-moz-user-select: none;
color: var(--viewport-color);
font-size: 11px;
height: 15px;
@@ -295,7 +295,7 @@ select > option.divider {
.browser {
display: block;
border: 0;
user-select: none;
-moz-user-select: none;
}
.browser:-moz-focusring {
@@ -383,7 +383,7 @@ select > option.divider {
}
.viewport-dimension-separator {
user-select: none;
-moz-user-select: none;
}
/**
@@ -85,7 +85,7 @@
.treeTable .treeHeaderCell {
cursor: pointer;
user-select: none;
-moz-user-select: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
padding: 0 !important;
background: linear-gradient(
+1 -2
View File
@@ -9,8 +9,7 @@ const {CSS_ANGLEUNIT} = require("devtools/shared/css/properties-db");
const SPECIALVALUES = new Set([
"initial",
"inherit",
"unset",
"revert"
"unset"
]);
const {getCSSLexer} = require("devtools/shared/css/lexer");
+62 -65
View File
@@ -8,7 +8,7 @@
* Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
* Copyright (C) 2011 Google Inc. All rights reserved.
* Copyright (C) 2009 Mozilla Foundation. All rights reserved.
* Copyright (C) 2022, 2023, 2025 Moonchild Productions. All rights reserved.
* Copyright (C) 2022, 2023 Moonchild Productions. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -60,11 +60,17 @@ const Curl = {
generateCommand: function (data) {
const utils = CurlUtils;
let commandParts = [];
let command = ["curl"];
// Make sure to use the following helpers to sanitize arguments before execution.
const escapeStringifNeeded = value => {
return /^[a-zA-Z-]+$/.test(value) ? value : escapeString(value);
const addParam = value => {
const safe = /^[a-zA-Z-]+$/.test(value) ? value : escapeString(value);
command.push(safe);
};
const addPostData = value => {
const safe = /^[a-zA-Z-]+$/.test(value) ? value : escapeString(value);
postData.push(safe);
};
let ignoredHeaders = new Set();
@@ -75,13 +81,7 @@ const Curl = {
utils.escapeStringWin : utils.escapeStringPosix;
// Add URL.
commandParts.push(data.url);
// Disable globbing if the URL contains brackets.
// cURL also globs braces but they are already percent-encoded.
if (data.url.includes("[") || data.url.includes("]")) {
commandParts.push("--globoff");
}
addParam(data.url);
let postDataText = null;
let multipartRequest = utils.isMultipartRequest(data);
@@ -91,16 +91,15 @@ const Curl = {
if (utils.isUrlEncodedRequest(data) ||
["PUT", "POST", "PATCH"].includes(data.method)) {
postDataText = data.postDataText;
postData.push("--data-raw");
let text =utils.writePostDataTextParams(postDataText);
postData.push(escapeStringifNeeded(text));
addPostData("--data-raw");
addPostData(utils.writePostDataTextParams(postDataText));
ignoredHeaders.add("content-length");
} else if (multipartRequest) {
postDataText = data.postDataText;
postData.push("--data-binary");
addPostData("--data-binary");
let boundary = utils.getMultipartBoundary(data);
let text = utils.removeBinaryDataFromMultipartText(postDataText, boundary);
postData.push(escapeStringifNeeded(text));
addPostData(text);
ignoredHeaders.add("content-length");
}
@@ -108,15 +107,15 @@ const Curl = {
// For GET and POST requests this is not necessary as GET is the
// default. If --data or --binary is added POST is the default.
if (!(data.method == "GET" || data.method == "POST")) {
commandParts.push("-X");
commandParts.push(data.method);
addParam("-X");
addParam(data.method);
}
// Add -I (HEAD)
// For servers that supports HEAD.
// This will fetch the header of a document only.
if (data.method == "HEAD") {
commandParts.push("-I");
addParam("-I");
}
// Add http version.
@@ -127,7 +126,7 @@ const Curl = {
// data.httpVersion are HTTP/1.0, HTTP/1.1 and HTTP/2.0
// So in case of HTTP/2.0 (which should ideally be HTTP/2) we are using
// only major version, and full version in other cases
commandParts.push("--http" + (version == "2.0" ? version.split(".")[0] : version));
addParam("--http" + (version == "2.0" ? version.split(".")[0] : version));
}
// Add request headers.
@@ -146,26 +145,14 @@ const Curl = {
if (ignoredHeaders.has(header.name.toLowerCase())) {
continue;
}
commandParts.push("-H");
let text = header.name + ": " + header.value;
commandParts.push(escapeStringifNeeded(text));
addParam("-H");
addParam(header.name + ": " + header.value);
}
// Add post data.
commandParts = commandParts.concat(postData);
command = command.concat(postData);
// Format with line breaks if the command has more than 2 parts
// e.g
// Command with 2 parts - curl https://foo.com
// Commands with more than 2 parts -
// curl https://foo.com
// -X POST
// -H "Accept : */*"
// -H "accept-language: en-US"
const joinStr = Services.appinfo.OS == "WINNT" ? " ^\n " : " \\\n ";
return (
"curl " + commandParts.join(commandParts.length >= 3 ? joinStr : " ")
);
return command.join(" ");
}
};
@@ -413,43 +400,53 @@ const CurlUtils = {
* Escape util function for Windows systems.
*/
escapeStringWin: function (str) {
/*
Because the cmd.exe parser and the MS Crt arguments parsers use some
of the same escape characters, they can interact with each other in
terrible ways, meaning the order of operations is critical here.
1. Replace \ with \\ first, because it is an escape character for
certain conditions in both parsers.
2. Replace double quote chars with two double quotes (not by escaping
with \") because it is recognized by both the cmd.exe and MS Crt
arguments parsers.
3. Escape ` and $ so commands do not get executed, e.g $(calc.exe) or
`\$(calc.exe)
4. Escape all characters we are not sure about with ^, to ensure it
gets to the MS Crt arguments parser safely.
5. The % character is special because the MS Crt arguments parser will
try and look for environment variables and fill them in, in-place. We
cannot escape them with % and cannot escape them with ^ (because it's
cmd.exe's escape, not the MS Crt arguments parser). So, we can get the
cmd.exe parser to escape the character after it, if it is followed by
a valid starting character of an environment variable.
This ensures we do not try and double-escape another ^ if it was placed
by the previous replace.
6. We replace \r and \r\n with \n; this allows us to consistently
escape all new lines in the next replace.
7. Lastly, we replace new lines with ^ and TWO new lines, because the
first new line is there to enact the escape command, and the second is
the character to escape (in this case new line).
The extra " enables escaping new lines with ^ within quotes in cmd.exe.
*/
const encapsChars = '"';
return (
encapsChars +
str
// Replace \ with \\ first because it is an escape character for certain
// conditions in both parsers.
.replace(/\\/g, "\\\\")
// Replace double quote chars with two double quotes (not by escaping with \")
// because it is recognized by both cmd.exe and MS CRT arguments parser.
.replace(/"/g, '""')
// Escape ` and $ so commands do not get executed e.g $(calc.exe) or `\$(calc.exe)
.replace(/[`$]/g, "\\$&")
// Then escape all characters we are not sure about with ^ to ensure it
// gets to the MS CRT parser safely.
// Note: Do not escape unicode control non-printable characters (0000-001f + 007f-009f)
.replace(/[^a-zA-Z0-9\s_\-:=+~\/.',?;()*\$&\\{}\"`\u0000-\u001f\u007f-\u009f]/g, "^$&")
// The % character is special because MS CRT parser will try and look for
// ENV variables and fill them in its place. We cannot escape them with %
// and cannot escape them with ^ (because it's cmd.exe's escape not MS CRT
// parser); So we can get cmd.exe parser to escape the character after it,
// if it is followed by a valid beginning character of an ENV variable.
// This ensures we do not try and double escape another ^ if it was placed
// by the previous replace.
.replace(/[^a-zA-Z0-9\s_\-:=+~\/.',?;()*\$&\\{}\"`]/g, "^$&")
.replace(/%(?=[a-zA-Z0-9_])/g, "%^")
// All other whitespace characters are replaced with a single space, as there
// is no way to enter their literal values in a command line, and they do break
// the command sequence, allowing for injection.
// Since want to keep line breaks, we need to exclude them in the regex (`[^\r\n]`),
// and use double negations to get the other whitespace chars (`[^\S]` translates
// to "not not whitespace")
.replace(/[^\S\r\n]/g, " ")
// Lastly we replace new lines with ^ and TWO new lines because the first
// new line is there to enact the escape command the second is the character
// to escape (in this case new line).
.replace(/\r?\n|\r/g, "^\n\n")
+ encapsChars
);
.replace(/\r\n?/g, "\n")
.replace(/\n/g, '"^\r\n\r\n"')
+ encapsChars);
}
};
+8
View File
@@ -13,6 +13,11 @@ support-files =
helper_color_data.js
helper_html_tooltip.js
helper_inplace_editor.js
html-mdn-css-basic-testing.html
html-mdn-css-no-summary.html
html-mdn-css-no-summary-or-syntax.html
html-mdn-css-no-syntax.html
html-mdn-css-syntax-old-style.html
leakhunt.js
test-actor.js
test-actor-registry.js
@@ -135,6 +140,9 @@ skip-if = e10s # Bug 1221911, bug 1222289, frequent e10s timeouts
skip-if = e10s # Layouthelpers test should not run in a content page.
[browser_layoutHelpers-getBoxQuads.js]
skip-if = e10s # Layouthelpers test should not run in a content page.
[browser_mdn-docs-01.js]
[browser_mdn-docs-02.js]
[browser_mdn-docs-03.js]
[browser_num-l10n.js]
[browser_options-view-01.js]
[browser_outputparser.js]
@@ -0,0 +1,167 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests the MdnDocsWidget object, and specifically its
* loadCssDocs() function.
*
* The MdnDocsWidget is initialized with a document which has a specific
* structure. You then call loadCssDocs(), passing in a CSS property name.
* MdnDocsWidget then fetches docs for that property by making an XHR to
* a docs page, and loads the results into the document. While the XHR is
* still not resolved the document is put into an "initializing" state in
* which the devtools throbber is displayed.
*
* In this file we test:
* - the initial state of the document before the docs have loaded
* - the state of the document after the docs have loaded
*/
"use strict";
const {setBaseCssDocsUrl, MdnDocsWidget} = require("devtools/client/shared/widgets/MdnDocsWidget");
/**
* Test properties
*
* In the real tooltip, a CSS property name is used to look up an MDN page
* for that property.
* In the test code, the names defined here is used to look up a page
* served by the test server.
*/
const BASIC_TESTING_PROPERTY = "html-mdn-css-basic-testing.html";
const BASIC_EXPECTED_SUMMARY = "A summary of the property.";
const BASIC_EXPECTED_SYNTAX = [{type: "comment", text: "/* The part we want */"},
{type: "text", text: "\n"},
{type: "property-name", text: "this"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "is-the-part-we-want"},
{type: "text", text: ";"}];
const URI_PARAMS =
"?utm_source=mozilla&utm_medium=firefox-inspector&utm_campaign=default";
add_task(function* () {
setBaseCssDocsUrl(TEST_URI_ROOT);
yield addTab("about:blank");
let [host, win] = yield createHost("bottom", "data:text/html," +
"<div class='mdn-container'></div>");
let widget = new MdnDocsWidget(win.document.querySelector("div"));
yield testTheBasics(widget);
host.destroy();
gBrowser.removeCurrentTab();
});
/**
* Test all the basics
* - initial content, before docs have loaded, is as expected
* - throbber is set before docs have loaded
* - contents are as expected after docs have loaded
* - throbber is gone after docs have loaded
* - mdn link text is correct and onclick behavior is correct
*/
function* testTheBasics(widget) {
info("Test all the basic functionality in the widget");
info("Get the widget state before docs have loaded");
let promise = widget.loadCssDocs(BASIC_TESTING_PROPERTY);
info("Check initial contents before docs have loaded");
checkTooltipContents(widget.elements, {
propertyName: BASIC_TESTING_PROPERTY,
summary: "",
syntax: ""
});
// throbber is set
ok(widget.elements.info.classList.contains("devtools-throbber"),
"Throbber is set");
info("Now let the widget finish loading");
yield promise;
info("Check contents after docs have loaded");
checkTooltipContents(widget.elements, {
propertyName: BASIC_TESTING_PROPERTY,
summary: BASIC_EXPECTED_SUMMARY,
syntax: BASIC_EXPECTED_SYNTAX
});
// throbber is gone
ok(!widget.elements.info.classList.contains("devtools-throbber"),
"Throbber is not set");
info("Check that MDN link text is correct and onclick behavior is correct");
let mdnLink = widget.elements.linkToMdn;
let expectedHref = TEST_URI_ROOT + BASIC_TESTING_PROPERTY + URI_PARAMS;
is(mdnLink.href, expectedHref, "MDN link href is correct");
let uri = yield checkLinkClick(mdnLink);
is(uri, expectedHref, "New tab opened with the expected URI");
}
/**
* Clicking the "Visit MDN Page" in the tooltip panel
* should open a new browser tab with the page loaded.
*
* To test this we'll listen for a new tab opening, and
* when it does, add a listener to that new tab to tell
* us when it has loaded.
*
* Then we click the link.
*
* In the tab's load listener, we'll resolve the promise
* with the URI, which is expected to match the href
* in the orginal link.
*
* One complexity is that when you open a new tab,
* "about:blank" is first loaded into the tab before the
* actual page. So we ignore that first load event, and keep
* listening until "load" is triggered for a different URI.
*/
function checkLinkClick(link) {
function loadListener(tab) {
let browser = getBrowser().getBrowserForTab(tab);
let uri = browser.currentURI.spec;
info("New browser tab has loaded");
gBrowser.removeTab(tab);
info("Resolve promise with new tab URI");
deferred.resolve(uri);
}
function newTabListener(e) {
gBrowser.tabContainer.removeEventListener("TabOpen", newTabListener);
let tab = e.target;
BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, url => url != "about:blank")
.then(url => loadListener(tab));
}
let deferred = defer();
info("Check that clicking the link opens a new tab with the correct URI");
gBrowser.tabContainer.addEventListener("TabOpen", newTabListener, false);
info("Click the link to MDN");
link.click();
return deferred.promise;
}
/**
* Utility function to check content of the tooltip.
*/
function checkTooltipContents(doc, expected) {
is(doc.heading.textContent,
expected.propertyName,
"Property name is correct");
is(doc.summary.textContent,
expected.summary,
"Summary is correct");
checkCssSyntaxHighlighterOutput(expected.syntax, doc.syntax);
}
@@ -0,0 +1,127 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests the MdnDocsWidget object, and specifically its
* loadCssDocs() function.
*
* The MdnDocsWidget is initialized with a document which has a specific
* structure. You then call loadCssDocs(), passing in a CSS property name.
* MdnDocsWidget then fetches docs for that property by making an XHR to
* a docs page, and loads the results into the document.
*
* In this file we test that the tooltip can properly handle the different
* structures that the docs page might have, including variant structures and
* error conditions like parts of the document being missing.
*
* We also test that the tooltip properly handles the case where the page
* doesn't exist at all.
*/
"use strict";
const {
setBaseCssDocsUrl,
MdnDocsWidget
} = require("devtools/client/shared/widgets/MdnDocsWidget");
const BASIC_EXPECTED_SUMMARY = "A summary of the property.";
const BASIC_EXPECTED_SYNTAX = [{type: "comment", text: "/* The part we want */"},
{type: "text", text: "\n"},
{type: "property-name", text: "this"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "is-the-part-we-want"},
{type: "text", text: ";"}];
const ERROR_MESSAGE = "Could not load docs page.";
/**
* Test properties
*
* In the real tooltip, a CSS property name is used to look up an MDN page
* for that property.
* In the test code, the names defined here are used to look up a page
* served by the test server. We have different properties to test
* different ways that the docs pages might be constructed, including errors
* like pages that don't include docs where we expect.
*/
const SYNTAX_OLD_STYLE = "html-mdn-css-syntax-old-style.html";
const NO_SUMMARY = "html-mdn-css-no-summary.html";
const NO_SYNTAX = "html-mdn-css-no-syntax.html";
const NO_SUMMARY_OR_SYNTAX = "html-mdn-css-no-summary-or-syntax.html";
const TEST_DATA = [{
desc: "Test a property for which we don't have a page",
docsPageUrl: "i-dont-exist.html",
expectedContents: {
propertyName: "i-dont-exist.html",
summary: ERROR_MESSAGE,
syntax: []
}
}, {
desc: "Test a property whose syntax section is specified using an old-style page",
docsPageUrl: SYNTAX_OLD_STYLE,
expectedContents: {
propertyName: SYNTAX_OLD_STYLE,
summary: BASIC_EXPECTED_SUMMARY,
syntax: BASIC_EXPECTED_SYNTAX
}
}, {
desc: "Test a property whose page doesn't have a summary",
docsPageUrl: NO_SUMMARY,
expectedContents: {
propertyName: NO_SUMMARY,
summary: "",
syntax: BASIC_EXPECTED_SYNTAX
}
}, {
desc: "Test a property whose page doesn't have a syntax",
docsPageUrl: NO_SYNTAX,
expectedContents: {
propertyName: NO_SYNTAX,
summary: BASIC_EXPECTED_SUMMARY,
syntax: []
}
}, {
desc: "Test a property whose page doesn't have a summary or a syntax",
docsPageUrl: NO_SUMMARY_OR_SYNTAX,
expectedContents: {
propertyName: NO_SUMMARY_OR_SYNTAX,
summary: ERROR_MESSAGE,
syntax: []
}
}
];
add_task(function* () {
setBaseCssDocsUrl(TEST_URI_ROOT);
yield addTab("about:blank");
let [host, win] = yield createHost("bottom", "data:text/html," +
"<div class='mdn-container'></div>");
let widget = new MdnDocsWidget(win.document.querySelector("div"));
for (let {desc, docsPageUrl, expectedContents} of TEST_DATA) {
info(desc);
yield widget.loadCssDocs(docsPageUrl);
checkTooltipContents(widget.elements, expectedContents);
}
host.destroy();
gBrowser.removeCurrentTab();
});
/*
* Utility function to check content of the tooltip.
*/
function checkTooltipContents(doc, expected) {
is(doc.heading.textContent,
expected.propertyName,
"Property name is correct");
is(doc.summary.textContent,
expected.summary,
"Summary is correct");
checkCssSyntaxHighlighterOutput(expected.syntax, doc.syntax);
}
@@ -0,0 +1,276 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This file tests the CSS syntax highlighter in the MdnDocsWidget object.
*
* The CSS syntax highlighter accepts:
* - a string containing CSS
* - a DOM node
*
* It parses the string and creates a collection of DOM nodes for different
* CSS token types. These DOM nodes have CSS classes applied to them,
* to apply the right style for that particular token type. The DOM nodes
* are returned as children of the node that was passed to the function.
*
* This test code defines a number of different strings containing valid and
* invalid CSS in various forms. For each string it defines the DOM nodes
* that it expects to get from the syntax highlighter.
*
* It then calls the syntax highlighter, and checks that the resulting
* collection of DOM nodes is what we expected.
*/
"use strict";
const {appendSyntaxHighlightedCSS} = require("devtools/client/shared/widgets/MdnDocsWidget");
/**
* An array containing the actual test cases.
*
* The test code tests every case in the array. If you want to add more
* test cases, just add more items to the array.
*
* Each test case consists of:
* - description: string describing the salient features of this test case
* - example: the string to test
* - expected: an array of objects, one for each DOM node we expect, that
* captures the information about the node that we expect to test.
*/
const TEST_DATA = [{
description: "Valid syntax, string value.",
example: "name: stringValue;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, numeric value.",
example: "name: 1;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "1"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, url value.",
example: "name: url(./name);",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "url(./name)"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, space before ':'.",
example: "name : stringValue;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: " "},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, space before ';'.",
example: "name: stringValue ;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: " "},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, trailing space.",
example: "name: stringValue; ",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"},
{type: "text", text: " "}
]}, {
description: "Valid syntax, leading space.",
example: " name: stringValue;",
expected: [{type: "text", text: " "},
{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, two spaces.",
example: "name: stringValue;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, no spaces.",
example: "name:stringValue;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, two-part value.",
example: "name: stringValue 1;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: " "},
{type: "property-value", text: "1"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, two declarations.",
example: "name: stringValue;\n" +
"name: 1;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"},
{type: "text", text: "\n"},
{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "1"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, commented, numeric value.",
example: "/* comment */\n" +
"name: 1;",
expected: [{type: "comment", text: "/* comment */"},
{type: "text", text: "\n"},
{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "1"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, multiline commented, string value.",
example: "/* multiline \n" +
"comment */\n" +
"name: stringValue;",
expected: [{type: "comment", text: "/* multiline \ncomment */"},
{type: "text", text: "\n"},
{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, commented, two declarations.",
example: "/* comment 1 */\n" +
"name: 1;\n" +
"/* comment 2 */\n" +
"name: stringValue;",
expected: [{type: "comment", text: "/* comment 1 */"},
{type: "text", text: "\n"},
{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "1"},
{type: "text", text: ";"},
{type: "text", text: "\n"},
{type: "comment", text: "/* comment 2 */"},
{type: "text", text: "\n"},
{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, multiline.",
example: "name: \n" +
"stringValue;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " \n"},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Valid syntax, multiline, two declarations.",
example: "name: \n" +
"stringValue \n" +
"stringValue2;",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " \n"},
{type: "property-value", text: "stringValue"},
{type: "text", text: " \n"},
{type: "property-value", text: "stringValue2"},
{type: "text", text: ";"}
]}, {
description: "Invalid: not CSS at all.",
example: "not CSS at all",
expected: [{type: "property-name", text: "not"},
{type: "text", text: " "},
{type: "property-name", text: "CSS"},
{type: "text", text: " "},
{type: "property-name", text: "at"},
{type: "text", text: " "},
{type: "property-name", text: "all"}
]}, {
description: "Invalid: switched ':' and ';'.",
example: "name; stringValue:",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ";"},
{type: "text", text: " "},
{type: "property-name", text: "stringValue"},
{type: "text", text: ":"}
]}, {
description: "Invalid: unterminated comment.",
example: "/* unterminated comment\n" +
"name: stringValue;",
expected: [{type: "comment", text: "/* unterminated comment\nname: stringValue;"}
]}, {
description: "Invalid: bad comment syntax.",
example: "// invalid comment\n" +
"name: stringValue;",
expected: [{type: "text", text: "/"},
{type: "text", text: "/"},
{type: "text", text: " "},
{type: "property-name", text: "invalid"},
{type: "text", text: " "},
{type: "property-name", text: "comment"},
{type: "text", text: "\n"},
{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: ";"}
]}, {
description: "Invalid: no trailing ';'.",
example: "name: stringValue\n" +
"name: stringValue2",
expected: [{type: "property-name", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue"},
{type: "text", text: "\n"},
{type: "property-value", text: "name"},
{type: "text", text: ":"},
{type: "text", text: " "},
{type: "property-value", text: "stringValue2"},
]}
];
/**
* Iterate through every test case, calling the syntax highlighter,
* then calling a helper function to check the output.
*/
add_task(function* () {
let doc = gBrowser.selectedTab.ownerDocument;
let parent = doc.createElement("div");
info("Testing all CSS syntax highlighter test cases");
for (let {description, example, expected} of TEST_DATA) {
info("Testing: " + description);
appendSyntaxHighlightedCSS(example, parent);
checkCssSyntaxHighlighterOutput(expected, parent);
while (parent.firstChild) {
parent.firstChild.remove();
}
}
});
+102
View File
@@ -242,3 +242,105 @@ Task.async(function* (widget, name, value) {
yield onRender;
});
/**
* Utility function for testing CSS code samples that have been
* syntax-highlighted.
*
* The CSS syntax highlighter emits a collection of DOM nodes that have
* CSS classes applied to them. This function checks that those nodes
* are what we expect.
*
* @param {array} expectedNodes
* A representation of the nodes we expect to see.
* Each node is an object containing two properties:
* - type: a string which can be one of:
* - text, comment, property-name, property-value
* - text: the textContent of the node
*
* For example, given a string like this:
* "<comment> The part we want </comment>\n this: is-the-part-we-want;"
*
* we would represent the expected output like this:
* [{type: "comment", text: "<comment> The part we want </comment>"},
* {type: "text", text: "\n"},
* {type: "property-name", text: "this"},
* {type: "text", text: ":"},
* {type: "text", text: " "},
* {type: "property-value", text: "is-the-part-we-want"},
* {type: "text", text: ";"}];
*
* @param {Node} parent
* The DOM node whose children are the output of the syntax highlighter.
*/
function checkCssSyntaxHighlighterOutput(expectedNodes, parent) {
/**
* The classes applied to the output nodes by the syntax highlighter.
* These must be same as the definitions in MdnDocsWidget.js.
*/
const PROPERTY_NAME_COLOR = "theme-fg-color5";
const PROPERTY_VALUE_COLOR = "theme-fg-color1";
const COMMENT_COLOR = "theme-comment";
/**
* Check the type and content of a single node.
*/
function checkNode(expected, actual) {
ok(actual.textContent == expected.text,
"Check that node has the expected textContent");
info("Expected text content: [" + expected.text + "]");
info("Actual text content: [" + actual.textContent + "]");
info("Check that node has the expected type");
if (expected.type == "text") {
ok(actual.nodeType == 3, "Check that node is a text node");
} else {
ok(actual.tagName.toUpperCase() == "SPAN", "Check that node is a SPAN");
}
info("Check that node has the expected className");
let expectedClassName = null;
let actualClassName = null;
switch (expected.type) {
case "property-name":
expectedClassName = PROPERTY_NAME_COLOR;
break;
case "property-value":
expectedClassName = PROPERTY_VALUE_COLOR;
break;
case "comment":
expectedClassName = COMMENT_COLOR;
break;
default:
ok(!actual.classList, "No className expected");
return;
}
ok(actual.classList.length == 1, "One className expected");
actualClassName = actual.classList[0];
ok(expectedClassName == actualClassName, "Check className value");
info("Expected className: " + expectedClassName);
info("Actual className: " + actualClassName);
}
info("Logging the actual nodes we have:");
for (let j = 0; j < parent.childNodes.length; j++) {
let n = parent.childNodes[j];
info(j + " / " +
"nodeType: " + n.nodeType + " / " +
"textContent: " + n.textContent);
}
ok(parent.childNodes.length == parent.childNodes.length,
"Check we have the expected number of nodes");
info("Expected node count " + expectedNodes.length);
info("Actual node count " + expectedNodes.length);
for (let i = 0; i < expectedNodes.length; i++) {
info("Check node " + i);
checkNode(expectedNodes[i], parent.childNodes[i]);
}
}
@@ -0,0 +1,21 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h2 id="Summary">Summary</h2>
<p>A summary of the property.</p>
<h2 id="Syntax">Syntax</h2>
<pre>/* The part we want */
this: is-the-part-we-want;</pre>
</body>
</html>
@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<p>This is not the summary or the syntax.</p>
</body>
</html>
@@ -0,0 +1,21 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<p>This is not the summary.</p>
<h2 id="Syntax">Syntax</h2>
<pre>To be ignored.</pre>
<pre>/* The part we want */
this: is-the-part-we-want;</pre>
</body>
</html>
@@ -0,0 +1,17 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h2 id="Summary">Summary</h2>
<p>A summary of the property.</p>
<p>This is not the syntax.</p>
</body>
</html>
@@ -0,0 +1,23 @@
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h2 id="Summary">Summary</h2>
<p>A summary of the property.</p>
<h2 id="Syntax">Syntax</h2>
<pre>The part we should ignore</pre>
<pre>/* The part we want */
this: is-the-part-we-want;</pre>
</body>
</html>
@@ -99,7 +99,7 @@ const filterList = [
];
// Valid values that shouldn't be parsed for filters.
const SPECIAL_VALUES = new Set(["none", "unset", "initial", "inherit", "revert"]);
const SPECIAL_VALUES = new Set(["none", "unset", "initial", "inherit"]);
/**
* A CSS Filter editor widget used to add/remove/modify
@@ -0,0 +1,510 @@
/* 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/. */
/**
* This file contains functions to retrieve docs content from
* MDN (developer.mozilla.org) for particular items, and to display
* the content in a tooltip.
*
* At the moment it only supports fetching content for CSS properties,
* but it might support other types of content in the future
* (Web APIs, for example).
*
* It's split into two parts:
*
* - functions like getCssDocs that just fetch content from MDN,
* without any constraints on what to do with the content. If you
* want to embed the content in some custom way, use this.
*
* - the MdnDocsWidget class, that manages and updates a tooltip
* document whose content is taken from MDN. If you want to embed
* the content in a tooltip, use this in conjunction with Tooltip.js.
*/
"use strict";
const Services = require("Services");
const defer = require("devtools/shared/defer");
const {getCSSLexer} = require("devtools/shared/css/lexer");
const EventEmitter = require("devtools/shared/event-emitter");
const {gDevTools} = require("devtools/client/framework/devtools");
const {LocalizationHelper} = require("devtools/shared/l10n");
const L10N = new LocalizationHelper("devtools/client/locales/inspector.properties");
const XHTML_NS = "http://www.w3.org/1999/xhtml";
// Parameters for the XHR request
// see https://developer.mozilla.org/en-US/docs/MDN/Kuma/API#Document_parameters
const XHR_PARAMS = "?raw&macros";
// URL for the XHR request
var XHR_CSS_URL = "https://developer.mozilla.org/en-US/docs/Web/CSS/";
// Parameters for the link to MDN in the tooltip, so
// so we know which MDN visits come from this feature
const PAGE_LINK_PARAMS =
"?utm_source=mozilla&utm_medium=firefox-inspector&utm_campaign=default";
// URL for the page link omits locale, so a locale-specific page will be loaded
var PAGE_LINK_URL = "https://developer.mozilla.org/docs/Web/CSS/";
exports.PAGE_LINK_URL = PAGE_LINK_URL;
const PROPERTY_NAME_COLOR = "theme-fg-color5";
const PROPERTY_VALUE_COLOR = "theme-fg-color1";
const COMMENT_COLOR = "theme-comment";
/**
* Turns a string containing a series of CSS declarations into
* a series of DOM nodes, with classes applied to provide syntax
* highlighting.
*
* It uses the CSS tokenizer to generate a stream of CSS tokens.
* https://dxr.mozilla.org/mozilla-central/source/dom/webidl/CSSLexer.webidl
* lists all the token types.
*
* - "whitespace", "comment", and "symbol" tokens are appended as TEXT nodes,
* and will inherit the default style for text.
*
* - "ident" tokens that we think are property names are considered to be
* a property name, and are appended as SPAN nodes with a distinct color class.
*
* - "ident" nodes which we do not think are property names, and nodes
* of all other types ("number", "url", "percentage", ...) are considered
* to be part of a property value, and are appended as SPAN nodes with
* a different color class.
*
* @param {Document} doc
* Used to create nodes.
*
* @param {String} syntaxText
* The CSS input. This is assumed to consist of a series of
* CSS declarations, with trailing semicolons.
*
* @param {DOM node} syntaxSection
* This is the parent for the output nodes. Generated nodes
* are appended to this as children.
*/
function appendSyntaxHighlightedCSS(cssText, parentElement) {
let doc = parentElement.ownerDocument;
let identClass = PROPERTY_NAME_COLOR;
let lexer = getCSSLexer(cssText);
/**
* Create a SPAN node with the given text content and class.
*/
function createStyledNode(textContent, className) {
let newNode = doc.createElementNS(XHTML_NS, "span");
newNode.classList.add(className);
newNode.textContent = textContent;
return newNode;
}
/**
* If the symbol is ":", we will expect the next
* "ident" token to be part of a property value.
*
* If the symbol is ";", we will expect the next
* "ident" token to be a property name.
*/
function updateIdentClass(tokenText) {
if (tokenText === ":") {
identClass = PROPERTY_VALUE_COLOR;
} else if (tokenText === ";") {
identClass = PROPERTY_NAME_COLOR;
}
}
/**
* Create the appropriate node for this token type.
*
* If this token is a symbol, also update our expectations
* for what the next "ident" token represents.
*/
function tokenToNode(token, tokenText) {
switch (token.tokenType) {
case "ident":
return createStyledNode(tokenText, identClass);
case "symbol":
updateIdentClass(tokenText);
return doc.createTextNode(tokenText);
case "whitespace":
return doc.createTextNode(tokenText);
case "comment":
return createStyledNode(tokenText, COMMENT_COLOR);
default:
return createStyledNode(tokenText, PROPERTY_VALUE_COLOR);
}
}
let token = lexer.nextToken();
while (token) {
let tokenText = cssText.slice(token.startOffset, token.endOffset);
let newNode = tokenToNode(token, tokenText);
parentElement.appendChild(newNode);
token = lexer.nextToken();
}
}
exports.appendSyntaxHighlightedCSS = appendSyntaxHighlightedCSS;
/**
* Fetch an MDN page.
*
* @param {string} pageUrl
* URL of the page to fetch.
*
* @return {promise}
* The promise is resolved with the page as an XML document.
*
* The promise is rejected with an error message if
* we could not load the page.
*/
function getMdnPage(pageUrl) {
let deferred = defer();
let xhr = new XMLHttpRequest();
xhr.addEventListener("load", onLoaded, false);
xhr.addEventListener("error", onError, false);
xhr.open("GET", pageUrl);
xhr.responseType = "document";
xhr.send();
function onLoaded(e) {
if (xhr.status != 200) {
deferred.reject({page: pageUrl, status: xhr.status});
} else {
deferred.resolve(xhr.responseXML);
}
}
function onError(e) {
deferred.reject({page: pageUrl, status: xhr.status});
}
return deferred.promise;
}
/**
* Gets some docs for the given CSS property.
* Loads an MDN page for the property and gets some
* information about the property.
*
* @param {string} cssProperty
* The property for which we want docs.
*
* @return {promise}
* The promise is resolved with an object containing:
* - summary: a short summary of the property
* - syntax: some example syntax
*
* The promise is rejected with an error message if
* we could not load the page.
*/
function getCssDocs(cssProperty) {
let deferred = defer();
let pageUrl = XHR_CSS_URL + cssProperty + XHR_PARAMS;
getMdnPage(pageUrl).then(parseDocsFromResponse, handleRejection);
function parseDocsFromResponse(responseDocument) {
let theDocs = {};
theDocs.summary = getSummary(responseDocument);
theDocs.syntax = getSyntax(responseDocument);
if (theDocs.summary || theDocs.syntax) {
deferred.resolve(theDocs);
} else {
deferred.reject("Couldn't find the docs in the page.");
}
}
function handleRejection(e) {
deferred.reject(e.status);
}
return deferred.promise;
}
exports.getCssDocs = getCssDocs;
/**
* The MdnDocsWidget is used by tooltip code that needs to display docs
* from MDN in a tooltip.
*
* In the constructor, the widget does some general setup that's not
* dependent on the particular item we need docs for.
*
* After that, when the tooltip code needs to display docs for an item, it
* asks the widget to retrieve the docs and update the document with them.
*
* @param {Element} tooltipContainer
* A DOM element where the MdnDocs widget markup should be created.
*/
function MdnDocsWidget(tooltipContainer) {
EventEmitter.decorate(this);
tooltipContainer.innerHTML =
`<header>
<h1 class="mdn-property-name theme-fg-color5"></h1>
</header>
<div class="mdn-property-info">
<div class="mdn-summary"></div>
<pre class="mdn-syntax devtools-monospace"></pre>
</div>
<footer>
<a class="mdn-visit-page theme-link" href="#">Visit MDN (placeholder)</a>
</footer>`;
// fetch all the bits of the document that we will manipulate later
this.elements = {
heading: tooltipContainer.querySelector(".mdn-property-name"),
summary: tooltipContainer.querySelector(".mdn-summary"),
syntax: tooltipContainer.querySelector(".mdn-syntax"),
info: tooltipContainer.querySelector(".mdn-property-info"),
linkToMdn: tooltipContainer.querySelector(".mdn-visit-page")
};
// get the localized string for the link text
this.elements.linkToMdn.textContent = L10N.getStr("docsTooltip.visitMDN");
// listen for clicks and open in the browser window instead
let mainWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
this.elements.linkToMdn.addEventListener("click", (e) => {
e.stopPropagation();
e.preventDefault();
mainWindow.openUILinkIn(e.target.href, "tab");
this.emit("visitlink");
});
}
exports.MdnDocsWidget = MdnDocsWidget;
MdnDocsWidget.prototype = {
/**
* This is called just before the tooltip is displayed, and is
* passed the CSS property for which we want to display help.
*
* Its job is to make sure the document contains the docs
* content for that CSS property.
*
* First, it initializes the document, setting the things it can
* set synchronously, resetting the things it needs to get
* asynchronously, and making sure the throbber is throbbing.
*
* Then it tries to get the content asynchronously, updating
* the document with the content or with an error message.
*
* It returns immediately, so the caller can display the tooltip
* without waiting for the asynch operation to complete.
*
* @param {string} propertyName
* The name of the CSS property for which we need to display help.
*/
loadCssDocs: function (propertyName) {
/**
* Do all the setup we can do synchronously, and get the document in
* a state where it can be displayed while we are waiting for the
* MDN docs content to be retrieved.
*/
function initializeDocument(propName) {
// set property name heading
elements.heading.textContent = propName;
// set link target
elements.linkToMdn.setAttribute("href",
PAGE_LINK_URL + propName + PAGE_LINK_PARAMS);
// clear docs summary and syntax
elements.summary.textContent = "";
while (elements.syntax.firstChild) {
elements.syntax.firstChild.remove();
}
// reset the scroll position
elements.info.scrollTop = 0;
elements.info.scrollLeft = 0;
// show the throbber
elements.info.classList.add("devtools-throbber");
}
/**
* This is called if we successfully got the docs content.
* Finishes setting up the tooltip content, and disables the throbber.
*/
function finalizeDocument({summary, syntax}) {
// set docs summary and syntax
elements.summary.textContent = summary;
appendSyntaxHighlightedCSS(syntax, elements.syntax);
// hide the throbber
elements.info.classList.remove("devtools-throbber");
deferred.resolve(this);
}
/**
* This is called if we failed to get the docs content.
* Sets the content to contain an error message, and disables the throbber.
*/
function gotError(error) {
// show error message
elements.summary.textContent = L10N.getStr("docsTooltip.loadDocsError");
// hide the throbber
elements.info.classList.remove("devtools-throbber");
// although gotError is called when there's an error, we have handled
// the error, so call resolve not reject.
deferred.resolve(this);
}
let deferred = defer();
let elements = this.elements;
initializeDocument(propertyName);
getCssDocs(propertyName).then(finalizeDocument, gotError);
return deferred.promise;
},
destroy: function () {
this.elements = null;
}
};
/**
* Test whether a node is all whitespace.
*
* @return {boolean}
* True if the node all whitespace, otherwise false.
*/
function isAllWhitespace(node) {
return !(/[^\t\n\r ]/.test(node.textContent));
}
/**
* Test whether a node is a comment or whitespace node.
*
* @return {boolean}
* True if the node is a comment node or is all whitespace, otherwise false.
*/
function isIgnorable(node) {
// Comment nodes (8), text nodes (3) or whitespace
return (node.nodeType == 8) ||
((node.nodeType == 3) && isAllWhitespace(node));
}
/**
* Get the next node, skipping comments and whitespace.
*
* @return {node}
* The next sibling node that is not a comment or whitespace, or null if
* there isn't one.
*/
function nodeAfter(sib) {
while ((sib = sib.nextSibling)) {
if (!isIgnorable(sib)) {
return sib;
}
}
return null;
}
/**
* Test whether the argument `node` is a node whose tag is `tagName`.
*
* @param {node} node
* The code to test. May be null.
*
* @param {string} tagName
* The tag name to test against.
*
* @return {boolean}
* True if the node is not null and has the tag name `tagName`,
* otherwise false.
*/
function hasTagName(node, tagName) {
return node && node.tagName &&
node.tagName.toLowerCase() == tagName.toLowerCase();
}
/**
* Given an MDN page, get the "summary" portion.
*
* This is the textContent of the first non-whitespace
* element in the #Summary section of the document.
*
* It's expected to be a <P> element.
*
* @param {Document} mdnDocument
* The document in which to look for the "summary" section.
*
* @return {string}
* The summary section as a string, or null if it could not be found.
*/
function getSummary(mdnDocument) {
let summary = mdnDocument.getElementById("Summary");
if (!hasTagName(summary, "H2")) {
return null;
}
let firstParagraph = nodeAfter(summary);
if (!hasTagName(firstParagraph, "P")) {
return null;
}
return firstParagraph.textContent;
}
/**
* Given an MDN page, get the "syntax" portion.
*
* First we get the #Syntax section of the document. The syntax
* section we want is somewhere inside there.
*
* If the page is in the old structure, then the *first two*
* non-whitespace elements in the #Syntax section will be <PRE>
* nodes, and the second of these will be the syntax section.
*
* If the page is in the new structure, then the only the *first*
* non-whitespace element in the #Syntax section will be a <PRE>
* node, and it will be the syntax section.
*
* @param {Document} mdnDocument
* The document in which to look for the "syntax" section.
*
* @return {string}
* The syntax section as a string, or null if it could not be found.
*/
function getSyntax(mdnDocument) {
let syntax = mdnDocument.getElementById("Syntax");
if (!hasTagName(syntax, "H2")) {
return null;
}
let firstParagraph = nodeAfter(syntax);
if (!hasTagName(firstParagraph, "PRE")) {
return null;
}
let secondParagraph = nodeAfter(firstParagraph);
if (hasTagName(secondParagraph, "PRE")) {
return secondParagraph.textContent;
}
return firstParagraph.textContent;
}
/**
* Use a different URL for CSS docs pages. Used only for testing.
*
* @param {string} baseUrl
* The baseURL to use.
*/
function setBaseCssDocsUrl(baseUrl) {
PAGE_LINK_URL = baseUrl;
XHR_CSS_URL = baseUrl;
}
exports.setBaseCssDocsUrl = setBaseCssDocsUrl;
@@ -63,7 +63,7 @@
background-size: 100% 100%, 100% 100%;
background-position: -2px 5px, -2px 5px;
user-select: none;
-moz-user-select: none;
}
canvas.curve {
@@ -16,7 +16,7 @@
}
#filter-container.dragging {
user-select: none;
-moz-user-select: none;
}
.filters-list,
@@ -96,7 +96,7 @@
}
.filter-name label {
user-select: none;
-moz-user-select: none;
flex-grow: 1;
}
@@ -0,0 +1,39 @@
/* 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/. */
.mdn-container {
height: 300px;
margin: 4px;
overflow: auto;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.mdn-container header,
.mdn-container footer {
flex: 1;
padding: 0 1em;
}
.mdn-property-info {
flex: 10;
padding: 0 1em;
overflow: auto;
transition: opacity 400ms ease-in;
}
.mdn-syntax {
margin-top: 1em;
}
.devtools-throbber {
align-self: center;
opacity: 0;
}
.mdn-visit-page {
display: inline-block;
padding: 1em 0;
}
+1
View File
@@ -20,6 +20,7 @@ DevToolsModules(
'Graphs.js',
'GraphsWorker.js',
'LineGraphWidget.js',
'MdnDocsWidget.js',
'MountainGraphWidget.js',
'SideMenuWidget.jsm',
'SimpleListWidget.jsm',
+1 -1
View File
@@ -101,7 +101,7 @@ http://www.briangrinstead.com/blog/keep-aspect-ratio-with-html-and-css */
}
.spectrum-dragger, .spectrum-slider {
user-select: none;
-moz-user-select: none;
}
.spectrum-alpha {
@@ -0,0 +1,93 @@
/* 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";
const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
const {MdnDocsWidget} = require("devtools/client/shared/widgets/MdnDocsWidget");
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const TOOLTIP_WIDTH = 418;
const TOOLTIP_HEIGHT = 308;
/**
* Tooltip for displaying docs for CSS properties from MDN.
*
* @param {Document} toolboxDoc
* The toolbox document to attach the CSS docs tooltip.
*/
function CssDocsTooltip(toolboxDoc) {
this.tooltip = new HTMLTooltip(toolboxDoc, {
type: "arrow",
consumeOutsideClicks: true,
autofocus: true,
useXulWrapper: true,
stylesheet: "chrome://devtools/content/shared/widgets/mdn-docs.css",
});
this.widget = this.setMdnDocsContent();
this._onVisitLink = this._onVisitLink.bind(this);
this.widget.on("visitlink", this._onVisitLink);
// Initialize keyboard shortcuts
this.shortcuts = new KeyShortcuts({ window: this.tooltip.topWindow });
this._onShortcut = this._onShortcut.bind(this);
this.shortcuts.on("Escape", this._onShortcut);
}
CssDocsTooltip.prototype = {
/**
* Load CSS docs for the given property,
* then display the tooltip.
*/
show: function (anchor, propertyName) {
this.tooltip.once("shown", () => {
this.widget.loadCssDocs(propertyName);
});
this.tooltip.show(anchor);
},
hide: function () {
this.tooltip.hide();
},
_onShortcut: function (shortcut, event) {
if (!this.tooltip.isVisible()) {
return;
}
event.stopPropagation();
event.preventDefault();
this.hide();
},
_onVisitLink: function () {
this.hide();
},
/**
* Set the content of this tooltip to the MDN docs widget. This is called when the
* tooltip is first constructed.
* The caller can use the MdnDocsWidget to update the tooltip's UI with new content
* each time the tooltip is shown.
*
* @return {MdnDocsWidget} the created MdnDocsWidget instance.
*/
setMdnDocsContent: function () {
let container = this.tooltip.doc.createElementNS(XHTML_NS, "div");
container.setAttribute("class", "mdn-container theme-body");
this.tooltip.setContent(container, {width: TOOLTIP_WIDTH, height: TOOLTIP_HEIGHT});
return new MdnDocsWidget(container);
},
destroy: function () {
this.widget.off("visitlink", this._onVisitLink);
this.widget.destroy();
this.shortcuts.destroy();
this.tooltip.destroy();
}
};
module.exports = CssDocsTooltip;
@@ -4,6 +4,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'CssDocsTooltip.js',
'EventTooltipHelper.js',
'HTMLTooltip.js',
'ImageTooltipHelper.js',
@@ -228,6 +228,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@@ -2096,6 +2096,7 @@ textarea.input-lg, .input-group-lg > textarea.form-control, .input-group-lg > te
line-height: 1.42857;
border-radius: 4px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; }
.btn:focus, .btn:active:focus, .btn.active:focus {
@@ -188,7 +188,7 @@ body {
}
#timeline-rate select.devtools-button {
appearance: none;
-moz-appearance: none;
text-align: center;
font-family: inherit;
color: var(--theme-body-color);
@@ -275,7 +275,7 @@ body {
.animation-timeline .time-header {
min-height: var(--timeline-animation-height);
cursor: col-resize;
user-select: none;
-moz-user-select: none;
}
.animation-timeline .time-header .header-item {
@@ -300,7 +300,7 @@ body {
}
.animation-timeline .time-body .time-tick {
user-select: none;
-moz-user-select: none;
position: absolute;
width: 0;
/* When scroll bar is shown, make it covers entire time-body */
+1 -1
View File
@@ -228,7 +228,7 @@
.boxmodel-editable {
border: 1px dashed transparent;
user-select: text;
-moz-user-select: text;
}
.boxmodel-editable:hover {
+4 -4
View File
@@ -34,7 +34,7 @@
}
#developer-toolbar {
appearance: none;
-moz-appearance: none;
padding: 0;
min-height: 32px;
background-color: var(--gcli-background-color);
@@ -42,7 +42,7 @@
}
#developer-toolbar > toolbarbutton {
appearance: none;
-moz-appearance: none;
border: none;
background-color: transparent;
margin: 0;
@@ -122,7 +122,7 @@ html|*#gcli-output-frame {
#gcli-tooltip {
border-width: 0;
background-color: transparent;
appearance: none;
-moz-appearance: none;
}
.gclitoolbar-input-node,
@@ -140,7 +140,7 @@ html|*#gcli-output-frame {
}
.gclitoolbar-input-node {
appearance: none;
-moz-appearance: none;
color: var(--gcli-input-color);
background-color: var(--gcli-input-background);
background-repeat: no-repeat;
+7 -7
View File
@@ -70,7 +70,7 @@ html|button, html|select {
}
.devtools-autocomplete-listbox {
appearance: none !important;
-moz-appearance: none !important;
background-color: transparent;
border-width: 0px !important;
margin: 0;
@@ -243,7 +243,7 @@ checkbox:-moz-focusring {
.devtools-menulist,
.devtools-toolbarbutton,
.devtools-button {
appearance: none;
-moz-appearance: none;
background: transparent;
min-height: 18px;
text-shadow: none;
@@ -334,7 +334,7 @@ checkbox:-moz-focusring {
/* Menu button styles (eg. web console filters) */
.devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-button {
appearance: none;
-moz-appearance: none;
color: inherit;
border-width: 0;
-moz-box-orient: horizontal;
@@ -351,7 +351,7 @@ checkbox:-moz-focusring {
}
.devtools-menulist > .menulist-dropmarker {
appearance: none;
-moz-appearance: none;
display: -moz-box;
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
-moz-box-align: center;
@@ -360,7 +360,7 @@ checkbox:-moz-focusring {
.devtools-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
.devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
appearance: none !important;
-moz-appearance: none !important;
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
-moz-box-align: center;
padding: 0 3px;
@@ -491,7 +491,7 @@ checkbox:-moz-focusring {
* @TODO : Fix when https://bugzilla.mozilla.org/show_bug.cgi?id=1255116 lands
*/
.menu-filter-button {
appearance: none;
-moz-appearance: none;
background: rgba(128,128,128,0.1);
border: none;
border-radius: 2px;
@@ -519,7 +519,7 @@ checkbox:-moz-focusring {
.devtools-textinput,
.devtools-searchinput,
.devtools-filterinput {
appearance: none;
-moz-appearance: none;
margin: 1px 3px;
border: 1px solid;
border-radius: 2px;
+1 -1
View File
@@ -44,7 +44,7 @@
}
#propertyContainer {
user-select: text;
-moz-user-select: text;
overflow-y: auto;
overflow-x: hidden;
flex: auto;
+2 -2
View File
@@ -61,7 +61,7 @@
/* Firebug theme uses breakpoint icon istead of a checkbox */
.theme-firebug #sources-pane .dbg-breakpoint-checkbox .checkbox-check {
appearance: none;
-moz-appearance: none;
border: none;
background: url(chrome://devtools/skin/images/firebug/breakpoint.svg) no-repeat 50% 50%;
}
@@ -326,7 +326,7 @@
}
.dbg-expression-button {
appearance: none;
-moz-appearance: none;
border: none;
background: none;
text-decoration: underline;
+1 -1
View File
@@ -18,7 +18,7 @@
.devtools-eyedropper-panel {
pointer-events: none;
appearance: none;
-moz-appearance: none;
width: 156px;
height: 120px;
background-color: transparent;
@@ -7,7 +7,7 @@
well as any overflow: scroll elements within the page, while excluding
<select>. */
*|*:not(html|select) > scrollbar {
appearance: none !important;
-moz-appearance: none !important;
position: relative;
background-color: transparent;
background-image: none;
@@ -37,14 +37,14 @@
*|*:not(html|select) > scrollbar thumb {
background-color: rgba(170, 170, 170, .2) !important; /* --toolbar-tab-hover */
appearance: none !important;
-moz-appearance: none !important;
border-width: 0px !important;
border-radius: 3px !important;
}
*|*:root[platform="mac"] > scrollbar slider,
*|*:root[platform="mac"] *|*:not(html|select) > scrollbar slider {
appearance: none !important;
-moz-appearance: none !important;
}
*|*:root[platform="win"] > scrollbar scrollbarbutton,
@@ -7,7 +7,7 @@
well as any overflow: scroll elements within the page, while excluding
<select>. */
*|*:not(html|select) > scrollbar {
appearance: none !important;
-moz-appearance: none !important;
position: relative;
background-color: transparent;
background-image: none;
@@ -31,11 +31,11 @@
}
*|*:not(html|select) > scrollbar slider {
appearance: none !important;
-moz-appearance: none !important;
}
*|*:not(html|select) > scrollbar thumb {
appearance: none !important;
-moz-appearance: none !important;
background-color: rgba(0,0,0,0.2);
border-width: 0px !important;
border-radius: 3px !important;
+2 -2
View File
@@ -20,7 +20,7 @@
}
body {
user-select: none;
-moz-user-select: none;
}
/* Force height and width (possibly overflowing) from inline elements.
@@ -359,7 +359,7 @@ ul.children + .tag-line::before {
border-radius: 3px;
padding: 0px 2px;
margin-inline-start: 5px;
user-select: none;
-moz-user-select: none;
}
.markupview-events {
+2 -2
View File
@@ -148,7 +148,7 @@
}
.requests-menu-header-button {
appearance: none;
-moz-appearance: none;
background-color: transparent;
border-image: linear-gradient(transparent 15%,
var(--theme-splitter-color) 15%,
@@ -322,7 +322,7 @@
padding: 0 2px;
margin: 0;
margin-inline-end: 3px;
user-select: none;
-moz-user-select: none;
}
.requests-menu-transferred {
+1 -1
View File
@@ -366,7 +366,7 @@
.call-tree-item .call-tree-cell,
.call-tree-item .call-tree-cell[type=function] description {
user-select: text;
-moz-user-select: text;
/* so that optimizations view doesn't break the lines in call tree */
white-space: nowrap;
}
@@ -11,13 +11,13 @@
}
.arrow {
appearance: treetwisty;
-moz-appearance: treetwisty;
width: 20px;
height: 20px;
}
.arrow[open] {
appearance: treetwistyopen;
-moz-appearance: treetwistyopen;
}
.arrow[invisible] {
+11 -11
View File
@@ -16,7 +16,7 @@
}
.devtools-responsiveui-toolbar {
appearance: none;
-moz-appearance: none;
background: transparent;
/* text color is textColor from dark theme, since no theme is applied to
* the responsive toolbar.
@@ -29,7 +29,7 @@
}
.devtools-responsiveui-textinput {
appearance: none;
-moz-appearance: none;
background: #333;
color: #fff;
border: 1px solid #111;
@@ -46,7 +46,7 @@
.devtools-responsiveui-menulist,
.devtools-responsiveui-toolbarbutton {
appearance: none;
-moz-appearance: none;
-moz-box-align: center;
min-width: 32px;
min-height: 22px;
@@ -60,12 +60,12 @@
}
.devtools-responsiveui-menulist .menulist-editable-box {
appearance: none;
-moz-appearance: none;
background-color: transparent;
}
.devtools-responsiveui-menulist html|*.menulist-editable-input {
appearance: none;
-moz-appearance: none;
color: inherit;
text-align: center;
}
@@ -124,7 +124,7 @@
}
.devtools-responsiveui-menulist > .menulist-dropmarker {
appearance: none;
-moz-appearance: none;
display: -moz-box;
background-color: transparent;
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
@@ -134,7 +134,7 @@
}
.devtools-responsiveui-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-button {
appearance: none;
-moz-appearance: none;
color: inherit;
border-width: 0;
border-inline-end: 1px solid hsla(210,8%,5%,.45);
@@ -152,7 +152,7 @@
.devtools-responsiveui-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
.devtools-responsiveui-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
appearance: none !important;
-moz-appearance: none !important;
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
-moz-box-align: center;
padding: 0 3px;
@@ -266,7 +266,7 @@
}
.devtools-responsiveui-hardware-buttons {
appearance: none;
-moz-appearance: none;
padding: 20px;
border: 1px solid #FFFFFF;
@@ -288,7 +288,7 @@
.devtools-responsiveui-sleep-button {
-moz-user-focus: ignore;
appearance: none;
-moz-appearance: none;
/* compensate browserStack top padding */
margin-top: -67px;
margin-right: 10px;
@@ -316,7 +316,7 @@
.devtools-responsiveui-volume-up-button,
.devtools-responsiveui-volume-down-button {
-moz-user-focus: ignore;
appearance: none;
-moz-appearance: none;
border: 1px solid red;
min-width: 8px;
height: 40px;
+4 -4
View File
@@ -67,7 +67,7 @@
}
#pseudo-class-panel > label {
user-select: none;
-moz-user-select: none;
flex-grow: 1;
display: flex;
align-items: center;
@@ -76,7 +76,7 @@
/* Rule View Container */
#ruleview-container {
user-select: text;
-moz-user-select: text;
overflow: auto;
flex: auto;
height: 100%;
@@ -148,7 +148,7 @@
overflow: hidden;
text-overflow: ellipsis;
user-select: none;
-moz-user-select: none;
margin-bottom: 2px;
}
@@ -184,7 +184,7 @@
border-top-style: solid;
border-bottom-style: solid;
padding: 1px 4px;
user-select: none;
-moz-user-select: none;
word-wrap: break-word;
vertical-align: middle;
min-height: 1.5em;
+2 -2
View File
@@ -28,7 +28,7 @@
}
.side-menu-widget-item-checkbox {
appearance: none;
-moz-appearance: none;
opacity: 0;
transition: opacity .15s ease-out 0s;
}
@@ -43,7 +43,7 @@
}
.side-menu-widget-item-checkbox .checkbox-check {
appearance: none;
-moz-appearance: none;
background-image: url(images/item-toggle.svg);
background-color: transparent;
width: 16px;
+1 -1
View File
@@ -32,7 +32,7 @@
.devtools-horizontal-splitter,
.devtools-side-splitter {
appearance: none;
-moz-appearance: none;
background-image: none;
border: 0;
border-style: solid;
+1 -1
View File
@@ -322,7 +322,7 @@ h3 {
margin: 20px auto;
-moz-column-width: 300px;
font-size: 13px;
user-select: text;
-moz-user-select: text;
}
.csscoverage-report-summary,
+5 -5
View File
@@ -45,7 +45,7 @@
/* Toolbars */
.devtools-toolbar,
.devtools-sidebar-tabs tabs {
appearance: none;
-moz-appearance: none;
padding: 0;
border-width: 0;
border-bottom-width: 1px;
@@ -91,13 +91,13 @@
/* In-tools sidebar */
.devtools-sidebar-tabs {
appearance: none;
-moz-appearance: none;
margin: 0;
height: 100%;
}
.devtools-sidebar-tabs > tabpanels {
appearance: none;
-moz-appearance: none;
background: transparent;
padding: 0;
border: 0;
@@ -116,7 +116,7 @@
}
.devtools-sidebar-alltabs {
appearance: none;
-moz-appearance: none;
height: 24px;
line-height: 24px;
padding: 0 4px;
@@ -136,7 +136,7 @@
}
.devtools-sidebar-tabs tabs > tab {
appearance: none;
-moz-appearance: none;
/* We want to match the height of a toolbar with a toolbarbutton
* First, we need to replicated the padding of toolbar (4px),
* then we need to take the border of the buttons into account (1px).
+3 -3
View File
@@ -41,7 +41,7 @@
/* Toolbox tabbar */
.devtools-tabbar {
appearance: none;
-moz-appearance: none;
min-height: 24px;
border: 0px solid;
border-bottom-width: 1px;
@@ -67,7 +67,7 @@
/* Toolbox tabs */
.devtools-tab {
appearance: none;
-moz-appearance: none;
-moz-binding: url("chrome://global/content/bindings/general.xml#control-item");
-moz-box-align: center;
min-width: 32px;
@@ -224,7 +224,7 @@
#toolbox-controls > button,
#toolbox-dock-buttons > button {
appearance: none;
-moz-appearance: none;
border: none;
margin: 0 4px;
min-width: 16px;
+1 -1
View File
@@ -108,7 +108,7 @@
}
.tooltip-xul-wrapper {
appearance: none;
-moz-appearance: none;
background: transparent;
overflow: visible;
border-style: none;
+1 -1
View File
@@ -125,7 +125,7 @@ text {
.web-audio-inspector .error {
background-image: url(images/alerticon-warning.png);
background-size: 13px 12px;
appearance: none;
-moz-appearance: none;
opacity: 0;
transition: opacity .5s ease-out 0s;
}
+3 -3
View File
@@ -94,7 +94,7 @@ a {
/* The red bubble that shows the number of times a message is repeated */
.message-repeats {
user-select: none;
-moz-user-select: none;
flex: none;
margin: 2px 6px;
padding: 0 6px;
@@ -161,7 +161,7 @@ a {
#output-wrapper {
direction: ltr;
overflow: auto;
user-select: text;
-moz-user-select: text;
position: relative;
}
@@ -424,7 +424,7 @@ a {
padding: 0;
padding-inline-start: 20px;
margin: 0;
appearance: none;
-moz-appearance: none;
background-color: transparent;
}
+3 -3
View File
@@ -122,7 +122,7 @@
.scrollbutton-up,
.scrollbutton-down {
appearance: none;
-moz-appearance: none;
background: transparent;
box-shadow: none;
border: none;
@@ -133,7 +133,7 @@
.scrollbutton-up > .toolbarbutton-icon,
.scrollbutton-down > .toolbarbutton-icon {
appearance: none;
-moz-appearance: none;
width: 7px;
height: 16px;
background-size: 14px 16px;
@@ -190,7 +190,7 @@
.breadcrumbs-widget-item {
background-color: transparent;
appearance: none;
-moz-appearance: none;
min-height: 24px;
min-width: 65px;
margin: 0;
@@ -21,7 +21,7 @@
.netInfoBody .netInfoGroupTitle {
cursor: pointer;
font-weight: bold;
user-select: none;
-moz-user-select: none;
cursor: pointer;
padding-left: 3px;
}
+2 -2
View File
@@ -265,7 +265,7 @@
/* The geometry editor can be interacted with, so it needs to react to
pointer events */
pointer-events: auto;
user-select: none;
-moz-user-select: none;
}
:-moz-native-anonymous .geometry-editor-offset-parent {
@@ -408,7 +408,7 @@
font: message-box;
font-size: 10px;
pointer-events: none;
user-select: none;
-moz-user-select: none;
box-sizing: border-box;
}
-2
View File
@@ -118,8 +118,6 @@ const PSEUDO_SELECTORS = [
[":target", 0],
[":enabled", 0],
[":disabled", 0],
[":read-only", 1],
[":read-write", 1],
[":checked", 1],
["::selection", 0]
];
+1 -2
View File
@@ -19,8 +19,7 @@ const SPECIALVALUES = new Set([
"initial",
"inherit",
"transparent",
"unset",
"revert"
"unset"
]);
/**
File diff suppressed because it is too large. Load diff
+1
View File
@@ -65,6 +65,7 @@ exports.devtoolsModules = [
"devtools/shared/gcli/commands/inject",
"devtools/shared/gcli/commands/jsb",
"devtools/shared/gcli/commands/listen",
"devtools/shared/gcli/commands/mdn",
"devtools/shared/gcli/commands/measure",
"devtools/shared/gcli/commands/media",
"devtools/shared/gcli/commands/pagemod",
+83
View File
@@ -0,0 +1,83 @@
/* 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";
const l10n = require("gcli/l10n");
var MdnDocsWidget;
try {
MdnDocsWidget = require("devtools/client/shared/widgets/MdnDocsWidget");
} catch (e) {
// DevTools MdnDocsWidget only available in Firefox Desktop
}
exports.items = [{
name: "mdn",
description: l10n.lookup("mdnDesc")
}, {
item: "command",
runAt: "client",
name: "mdn css",
description: l10n.lookup("mdnCssDesc"),
returnType: "cssPropertyOutput",
params: [{
name: "property",
type: { name: "string" },
defaultValue: null,
description: l10n.lookup("mdnCssProp")
}],
exec: function(args) {
if (!MdnDocsWidget) {
return null;
}
return MdnDocsWidget.getCssDocs(args.property).then(result => {
return {
data: result,
url: MdnDocsWidget.PAGE_LINK_URL + args.property,
property: args.property
};
}, error => {
return { error, property: args.property };
});
}
}, {
item: "converter",
from: "cssPropertyOutput",
to: "dom",
exec: function(result, context) {
let propertyName = result.property;
let document = context.document;
let root = document.createElement("div");
if (result.error) {
// The css property specified doesn't exist.
root.appendChild(document.createTextNode(
l10n.lookupFormat("mdnCssPropertyNotFound", [ propertyName ]) +
" (" + result.error + ")"));
} else {
let title = document.createElement("h2");
title.textContent = propertyName;
root.appendChild(title);
let link = document.createElement("p");
link.classList.add("gcli-mdn-url");
link.textContent = l10n.lookup("mdnCssVisitPage");
root.appendChild(link);
link.addEventListener("click", () => {
let mainWindow = context.environment.chromeWindow;
mainWindow.openUILinkIn(result.url, "tab");
});
let summary = document.createElement("p");
summary.textContent = result.data.summary;
root.appendChild(summary);
}
return root;
}
}];
+1
View File
@@ -16,6 +16,7 @@ DevToolsModules(
'inject.js',
'jsb.js',
'listen.js',
'mdn.js',
'measure.js',
'media.js',
'pagemod.js',
@@ -1457,6 +1457,24 @@ folderInvalidPath=Please enter a valid path
# The argument (%1$S) is the folder path.
folderOpenDirResult=Opened %1$S
# LOCALIZATION NOTE (mdnDesc) A very short string used to describe the
# use of 'mdn' command.
mdnDesc=Retrieve documentation from MDN
# LOCALIZATION NOTE (mdnCssDesc) A very short string used to describe the
# result of the 'mdn css' command.
mdnCssDesc=Retrieve documentation about a given CSS property name from MDN
# LOCALIZATION NOTE (mdnCssProp) String used to describe the 'property name'
# parameter used in the 'mdn css' command.
mdnCssProp=Property name
# LOCALIZATION NOTE (mdnCssPropertyNotFound) String used to display an error in
# the result of the 'mdn css' command. Errors occur when a given CSS property
# wasn't found on MDN. The %1$S parameter will be replaced with the name of the
# CSS property.
mdnCssPropertyNotFound=MDN documentation for the CSS property ‘%1$S’ was not found.
# LOCALIZATION NOTE (mdnCssVisitPage) String used as the label of a link to the
# MDN page for a given CSS property.
mdnCssVisitPage=Visit MDN page
# LOCALIZATION NOTE (security)
securityPrivacyDesc=Display supported security and privacy features
securityManual=Commands to list and get suggestions about security features for the current domain.
Loaded 100 of 9331 files, more files were not shown because too many files have changed in this diff. Show more