mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- missing bit of 989499 and some other files (23b0597ba6) - Bug 1233666 - Remove hacks for getting frame pointer for x86/x64 gcc. r=glandium (bfe8f59916) - Bug 1176266: In TimeStamp_posix.cpp, check for XP_LINUX instead of LINUX, and add missing #include, to allow strrchr usage. r=BenWa (56c725cffa) - Bug 1167230 - Don't pack ProfileEntry on ARM. r=shu (89f880e0cb) - Bug 1209779 - Ensure that all null elements are written when streaming profiler JSON; r=shu (2bae5addc6) - missing bit of Bug 1141712 - Make LUL (55f1276545) - Bug 1061800 - Add breakpad ids to profiler in Linux. r=BenWa (994fd1a941) - Bug 829621 - Compute the breakpad-id for OS X. r=BenWa. (e129580174) - missing of Bug 938157 - Lightweight CFI/EXIDX (b355dc3140) - Bug 1193838 - Allow ProfileGatherer to gather profiles from exiting processes. r=BenWa (5ab1a6a3c9) - align some missing stuff (5ebecd2364) - align some missing stuff (b8ff7aa361) - Bug 1164315 - Update key fingerprint for bitbucket.org; r=me (c1a3fbd930) - Bug 1178955 - Refactor config path selection; r=smacleod (89552bb0ac) - Bug 1195445 - Update host key fingerprint for bugzilla.mozilla.org (3783541088) - Bug 1218903 - Update bmo fingerprint. r=fubar, a=Tomcat (5b836fc585) - Bug 1178955 - Print config path on failure; r=smacleod (f5499f3771) - Bug 1185113 - Support setting more secure file permissions; r=smacleod (7dbf6b22fd) - Bug 1184229 - Detect multiple version-control-tools repos in Mercurial config; r=smacleod (16c24072a9) - Bug 978514 - mach mercurial-setup: Use mqext from the version-control-tools repo (1fa5765e8a) - Bug 1178955 - Don't pass config paths to updater; r=smacleod (80fcb05121) - Bug 1197527 - Don't unnecessarily attempt to create extensions directory in MercurialUpdater; r=gps (9b049c3ff8) - Bug 1164812 - mach mercurial-setup: Always mark the v-c-t repo as needing update (bd631208bd) - Bug 1197527 - Always clone version-control-tools in MercurialSetupWizard; r=gps (6990e8f589) - Bug 1197527 - Consolidate obtaining hg path into mozversioncontrol.get_hg_path; r=gps (e0b029a8e9) - Bug 1200458 - Skip permission check for .hgrc on Windows in hgsetup wizard. r=gps DONTBUILD (cc5b0d6daf) - Bug 1168466 - Bump minimum Mercurial version; r=smacleod (7fde47cfbe) - Bug 1185113 - Clarify language around Bugzilla credentials; r=smacleod (9166fdfbf9) - Bug 1185112 - Don't prompt for Bugzilla username/password if cookies defined; r=smacleod (cd87c96823) - Bug 1188931 - Fix hgsetup wizard. r=gps (68a6b46be4) - Bug 1200461 - Prompt for Bugzilla API Key instead of password; r=smacleod (780fb5d85d) - Bug 1228580 - ./mach mercurial-setup should use ~ to set up extension paths, not my literal home directory. r=gps (7a0c839880) - Bug 1231192 - Mark Mercurial 3.5.2 as oldest non-legacy version; r=smacleod (8f69483333) - Bug 1231192 - Bump some minimum Mercurial version; r=smacleod (916c56a852) - Bug 1162093 - Add "push-to-try" from version-control-tools to the mercurial setup wizard prompt.;r=gps (d29c7cf63a) - Bug 1168466 - Prompt to install bundleclone extension; r=smacleod (780ce90a08) - Bug 1185557 - Print relevant config options; r=smacleod (2f3f7e0161) - Bug 1231192 - Support clonebundles feature; r=smacleod (dcba1ccd34) - Bug 1231192 - Offer to install hg wip; r=smacleod (c42ebce5c8) - Bug 1231192 - Only install host fingerprints if not running secure Python+hg; r=smacleod (3154a2497b) - Bug 1178955 - Error when semicolon comments are seen; r=smacleod (e1f7081bb6) - Bug 1231989 - Prompt to install hgwatchman extension; r=ahal (0eddf0c1c8) - Bug 1178955 - Print line number for parse errors; r=smacleod (5369468cf1) - Bug 1185557 - Only prompt to install progress on Mercurial <3.5; r=smacleod (401f362265) - Bug 1232747 - Check for ssl.SSLContext existence; r=dminor (d505b07c5c) - Bug 1144629 - UnicodeDecodeError in ./mach mercurial-setup. r=gps, r=glandium (611d3ec83e) - Bug 1216970 - Make the copying more obvious in ProfilerImpl::GetStacktrace. r=froydnj (085625e113) - Bug 1190466 - tools/rb/find-leakers.pl re-written in Python r=mccr8 (4bfdcad13e) - Bug 1116478 - Open web content handlers in the proper tab in e10s. r=billm (ff8e11f45e) - Bug 1213437 - Less data copying when handling structured clones in MessageManager, r=baku (c4e2a13253) - const-var (69d17f312d) - Bug 1203090 - Ensure we always use '/' as the starting path separator for the DOM path of the Directorys initially returned by HTMLInputElement.getFilesAndDirectories. r=baku (1325bbc40c) - Bug 1209975 - Stop using dom::Promise::MaybeRejectBrokenly() in GetDirectoryListingTask. r=baku (2106790950) - Bug 1209924 - Implement a general filtering mechanism for Directory::GetFilesAndDirectories, and add filtering of sensitive files/directories. r=baku (27b4a26262) - Force a repaint after DXGI device resets. (bug 1188019, r=bas) (09c999e6e5) - Bug 1163911 - Make responsive images block the document load event while the load task is queued. r=jst (0ee0e3db79) - Bug 1166138 - Make img srcset react to resize/viewport changes, r=jdm (91674519e6) - Bug 1194893 - Pref for default file upload directory. r=smaug (ec6d33d983) - bug 1116409: switch update server to sha2 cert; update in-tree pinning. r=rstrong,snorp,mfinkle,dkeeler (7c8f631f27) - bug 1116409: fix cert pinning on backup cert for aus5.mozilla.org. r=typofix (3c690cbc6d) - Bug 1167048 - Change default font for Thai script from serif to sans-serif. r=smontagu (15dc86c389) - Bug 1205570 - fix up font prefs for x-math lang group. r=heycam (03f1820752) - Bug 1071769: Use DrawTargetTiled on B2G. r=Bas (b80ce768f1) - fix misspatch of 1149343 (541dd7aac8) - Bug 1199766 - Disable ICE TCP SO gathering via user pref. r=bwc (80cdc9c662) - Bug 1187472 - only log UDP and TCP candidate gathering failures. r=bwc (bc3dcb02d0) - Bug 1190615 - Skip non-UDP STUN servers for UDP sockets. r=bwc (a2d1d914b5) - Bug 1187775 - skip host and reflexive ICE candidates if relay-only. r=bwc (7e2cba1685) - Bug 1185198 - use port 9 for TCP active candidates. r=bwc (0a89cb199d) - Bug 1177921 - Fix typo in STUN server name. r=drno (1ad43ced6b) - Bug 1178349 - Enable ice_unittests on desktop linux on CI. r=bwc (ce5ece8264) - Bug 1189041 - Add option to only gather addresses for default route. r=bwc (3651f2ff06) - Bug 1189040: add a whitelist for network interfaces to use with ICE/webrtc r=ekr (6f693af72c) - Bug 1189198 - don't start STUN transactions with a protocol mis-match. r=mtseng (a3b410e2a8) - Bug 1208096 - Handle various failure cases for TURN gathering better. r=drno (1d8e173448) - Bug 1211389 - Make absolutely sure the relay->srflx pointer doesn't dangle. r=drno (d59b0bf08d) - Bug 1215616: use base address for server rflx ICE candidates r=bwc (89d07331ac) - Bug 1207451 - removed framing from multi_tcp API. r=bwc (317f40f490) - Bug 1186590 - Part 1 - Enable interface prioritizer on all platforms. r=drno (036a69fdb3) - Bug 1194019 - New defaults for gather tests. r=bwc (8343ceab56) - Bug 1144933: Only check that remote candidate is loopback in TestLoopbackOnlySortOf. r=drno (1f53d824e4) - Bug 1186590 - Part 2 - Move hard-coded interface priority list into nrinterfaceprioritizer, and simplify some functions. r=drno (9f20fad21b) - Bug 1152137 - Part 1: Test case. r=ekr (6b50f06d90) - Bug 1152137 - Part 2: Remove attributes that could not be initted properly instead of just freeing them. r=ekr (ccdf81294a) - Bug 1200763 - Remove hard-coded STUN IP address from ice_unittest, and do a DNS lookup instead. r=drno (ae54a83363) - Bug 1208176 - Part 1: Add a couple of interface names. r=drno (b7ead0b476) - Bug 1208176 - Part 2: Add a one-sided trickle test case to ice_unittest. r=drno (ad6afedb1c) - Bug 1037618 - Relax candidate verification for TCP. r=bwc (0cad14c89e) - Bug 1208176 - Part 3: Be forgiving when we see prflx instead of host candidates in ice_unittest. r=drno (50bdec2ba3) - Bug 1035428: Re-register writeable callback after partially servicing the send queue. r=drno (2fdb7880fa) - Bug 1135753 - Mark some overridden virtual functions in WebRTC as MOZ_OVERRIDE; r=mt (97f451c97d) - Bug 950660: Part 4: Bridge TCPSocketChild to nr_socket r=bwc,jdm (654587b321) - Bug 971357: Log STUN responses at INFO instead of DEBUG. r=ekr (81b500df17) - Bug 1006809 - update triggered check behavior to RFC 5245. r+bwc r=mjf (31b718b5e5) - Bug 1208278 - improved STUN request timeout handling. r=bwc (cf470fb12f) - Bug 1142964 - Fix ICE tiebreaker on Windows. r=bwc (0d2fd78252) - Bug 1219557 - don't pair candidates from different reserved networks. r=mt r=bwc (24d3e5106c) - Bug 1220441 - Improve gather trickle ice unit tests. r=bwc r=mjf (96f76c6c8c) - Bug 1205421 - fix DNS resolution of STUN server in ice_unittest. r=bwc (5d5b153358) - Bug 1206465 - removed ice_ctx from TestStunTcpServer. r=bwc (9a0df03894) - ug 1008792 - Check for valid pointer before using. r=bwc (7660fd0a71) - Bug 1233101 - Use MOZ_LIKELY in js_new etc to help branch prediction; r=terrence (31fb244734) - Bug 1225565 - Fix module import cycle detection r=shu (370dc26ee8) - Bug 1225558 - Improve module error messages r=shu (83b6038bb3) - Bug 1225561 - Don't allow a module to export non-existent local bindings r=shu (41f065891a) - Bug 1233124 - Remove mis-named duplicate typedefs for rooted import and export entries r=terrence (17a60bdb39) - Bug 1208464 - Implement proposed ES7 functions Object.values and Object.entries. r=evilpie (615193d0fb) - Bug 1226549 - added assert check for matches pointer in for prevent null dereference. r=hv1989 (d321ad0385) - Bug 1232113 - "Make the format specifiers in JS_snprintf() invocations more portable". r=jcoppeard (7c58b79a53) - Bug 1232446 - Re-enable method calls in SelfHosted code using new anti-content checks. (r=till) (ba7dc22ff8) - Bug 1232159 - Stop using pseudo-Uint32Array in SelfHosted code. (r=till) (c325f8ff58) - Bug 1226235 - Print file and line info for failing assert in self-hosted code. r=efaust (4a8d54d38b) - fix misspatch (fca2efc1f1) - Bug 1186003 - Switch automated builds to Gtk+3. r=mshal (658ad843b7) - Bug 1181342 - tooltool manifests and build-clang config for clang 3.6 r=rail (6264b4df68) - Bug 1181342 - Follow up to use the unpack feature of tooltool instead of setup.sh r=glandium (96bb3b2062) - Bug 1181255 - Mozconfigs for tsan builds. r=glandium (19250f4cc1) - Bug 1181255 - Get tsan builds on gtk3. r=glandium (e5ffd1c02f) - Bug 1187664 - Create a fontconfig cache so that Firefox doesn't have to do it itself when run on build automation. r=mshal (8ce567bd4c) - Bug 1188780 - Include debug symbols in gtk3 tooltool package. r=mshal (a5b573aa58) - Bug 1188780: remove setup.sh invocations, as they fail outside the mock environment; r=glandium a=RyanVM (058e306cac) - Bug 1178513 - Fix non-unified bustage. r=wchen (543d1e5497) - Bug 1162789 - Add a comment explaining why mForm is not set to null during unlink (eaa2a82048) - Bug 1189655 - Define MOZ_HAVE_CXX11_CONSTEXPR on VS2015 or later. r=Waldo (2d134e3b41) - Bug 1231758 - Fix bogus assertion in BCE for Annex B function assignment. (r=jorendorff) (701b2530b9) - Bug 1233100 - Ensure that derived constructor bad return value errors are thrown before leaving the containing block. (r=shu) (52f5bcf0a5) - Bug 1232022, 1232449 - Address forgotten review nits and fix bogus error message. (rs=Waldo) (dfd9d5e388) - Bug 1233121 - Refactor ObjectBox tracing r=terrence (876a140535) - Bug 1231647 - Check for duplicate exported let and const in modules r=shu (99f53ad443)
This commit is contained in:
+1
-1
@@ -562,7 +562,7 @@ pref("app.update.incompatible.mode", 0);
|
||||
pref("app.update.staging.enabled", true);
|
||||
pref("app.update.service.enabled", true);
|
||||
|
||||
pref("app.update.url", "https://aus4.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%PRODUCT_DEVICE%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
|
||||
pref("app.update.url", "https://aus5.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%PRODUCT_DEVICE%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
|
||||
pref("app.update.channel", "@MOZ_UPDATE_CHANNEL@");
|
||||
|
||||
// Interval at which update manifest is fetched. In units of seconds.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
ac_add_options --with-google-oauth-api-keyfile=/builds/google-oauth-api.key
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.tsan
|
||||
|
||||
export PKG_CONFIG_LIBDIR=/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
. $topsrcdir/build/unix/mozconfig.gtk
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=tsan
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
@@ -7,6 +7,13 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 11179576,
|
||||
"digest": "91567ce8e2bb8ab0ebc60c31e90731d88a1ea889fb71bcf55c735746a60fa7610b7e040ea3d8f727b6f692ae3ee703d6f3b30cdbd76fdf5617f77d9c38aa20ed",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 167175,
|
||||
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
|
||||
"algorithm": "sha512",
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12057960,
|
||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 167175,
|
||||
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
|
||||
"algorithm": "sha512",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
[
|
||||
{
|
||||
"clang_version": "r241773"
|
||||
},
|
||||
{
|
||||
"size": 89690541,
|
||||
"digest": "470d258d9785a120fcba65eee90daa632a42affa0f97f57d70fc8285bd76bcc27d4d0d70b6c37577ab271a04c843b6269425391a8d6df1967718dba26dd3a73d",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12057960,
|
||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"llvm_revision": "241773",
|
||||
"llvm_repo": "http://llvm.org/svn/llvm-project/llvm/branches/release_36",
|
||||
"clang_repo": "http://llvm.org/svn/llvm-project/cfe/branches/release_36",
|
||||
"compiler_repo": "http://llvm.org/svn/llvm-project/compiler-rt/branches/release_36",
|
||||
"patches": {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Use "build-gtk.sh" or "build-gtk.sh 64" to build a 64-bits tarball for tooltool.
|
||||
# Use "build-gtk.sh 32" to build a 32-bits tarball for tooltool.
|
||||
|
||||
# Mock environments used:
|
||||
# - 64-bits:
|
||||
# https://s3.amazonaws.com/mozilla-releng-mock-archive/67b65e51eb091fba7941a04d249343924a3ee653
|
||||
# + libxml2-devel.x86_64 gettext.x86_64 libjpeg-devel.x86_64
|
||||
# - 32-bits:
|
||||
# https://s3.amazonaws.com/mozilla-releng-mock-archive/58d76c6acca148a1aedcbec7fc1b8212e12807b4
|
||||
# + libxml2-devel.i686 gettext.i686 libjpeg-devel.i686
|
||||
|
||||
set -e
|
||||
|
||||
pkg_config_version=0.28
|
||||
fontconfig_version=2.8.0
|
||||
libffi_version=3.0.13
|
||||
glib_version=2.34.3
|
||||
gdk_pixbuf_version=2.26.5
|
||||
pixman_version=0.20.2
|
||||
cairo_version=1.10.2
|
||||
pango_version=1.30.1
|
||||
atk_version=2.2.0
|
||||
gtk__version=3.4.4
|
||||
|
||||
pkg_config_url=http://pkgconfig.freedesktop.org/releases/pkg-config-${pkg_config_version}.tar.gz
|
||||
fontconfig_url=http://www.freedesktop.org/software/fontconfig/release/fontconfig-${fontconfig_version}.tar.gz
|
||||
libffi_url=ftp://sourceware.org/pub/libffi/libffi-${libffi_version}.tar.gz
|
||||
glib_url=http://ftp.gnome.org/pub/gnome/sources/glib/${glib_version%.*}/glib-${glib_version}.tar.xz
|
||||
gdk_pixbuf_url=http://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/${gdk_pixbuf_version%.*}/gdk-pixbuf-${gdk_pixbuf_version}.tar.xz
|
||||
pixman_url=http://cairographics.org/releases/pixman-${pixman_version}.tar.gz
|
||||
cairo_url=http://cairographics.org/releases/cairo-${cairo_version}.tar.gz
|
||||
pango_url=http://ftp.gnome.org/pub/GNOME/sources/pango/${pango_version%.*}/pango-${pango_version}.tar.xz
|
||||
atk_url=http://ftp.gnome.org/pub/GNOME/sources/atk/${atk_version%.*}/atk-${atk_version}.tar.xz
|
||||
gtk__url=http://ftp.gnome.org/pub/gnome/sources/gtk+/${gtk__version%.*}/gtk+-${gtk__version}.tar.xz
|
||||
|
||||
cwd=$(pwd)
|
||||
root_dir=$(mktemp -d)
|
||||
cd $root_dir
|
||||
|
||||
if test -z $TMPDIR; then
|
||||
TMPDIR=/tmp/
|
||||
fi
|
||||
|
||||
make_flags=-j12
|
||||
|
||||
build() {
|
||||
name=$1
|
||||
shift
|
||||
pkg=$(echo $name | tr '+-' '__')
|
||||
version=$(eval echo \$${pkg}_version)
|
||||
url=$(eval echo \$${pkg}_url)
|
||||
wget -c -P $TMPDIR $url
|
||||
tar -axf $TMPDIR/$name-$version.tar.*
|
||||
mkdir -p build/$name
|
||||
cd build/$name
|
||||
eval ../../$name-$version/configure --disable-static $* $configure_args
|
||||
make $make_flags
|
||||
make install DESTDIR=$root_dir/gtk3
|
||||
find $root_dir/gtk3 -name \*.la -delete
|
||||
cd ../..
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
32)
|
||||
configure_args='--host=i686-pc-linux --build=i686-pc-linux CC="gcc -m32" CXX="g++ -m32"'
|
||||
lib=lib
|
||||
;;
|
||||
*)
|
||||
configure_args=
|
||||
lib=lib64
|
||||
;;
|
||||
esac
|
||||
|
||||
export PKG_CONFIG_LIBDIR=/usr/$lib/pkgconfig:/usr/share/pkgconfig
|
||||
|
||||
# The pkg-config version in the mock images is buggy is how it handles
|
||||
# PKG_CONFIG_SYSROOT_DIR. So we need our own.
|
||||
build pkg-config
|
||||
|
||||
ln -sf /usr/include $root_dir/gtk3/usr/
|
||||
ln -sf /usr/$lib $root_dir/gtk3/usr/
|
||||
if [ "$lib" = lib64 ]; then
|
||||
ln -s lib $root_dir/gtk3/usr/local/lib64
|
||||
fi
|
||||
export PKG_CONFIG_PATH=$root_dir/gtk3/usr/local/lib/pkgconfig
|
||||
export PKG_CONFIG_SYSROOT_DIR=$root_dir/gtk3
|
||||
export LD_LIBRARY_PATH=$root_dir/gtk3/usr/local/lib
|
||||
export PATH=$root_dir/gtk3/usr/local/bin:${PATH}
|
||||
|
||||
build fontconfig
|
||||
build libffi
|
||||
build glib
|
||||
build gdk-pixbuf --without-libtiff
|
||||
build pixman --disable-gtk
|
||||
build cairo --enable-tee
|
||||
build pango
|
||||
build atk
|
||||
make_flags="$make_flags GLIB_COMPILE_SCHEMAS=glib-compile-schemas"
|
||||
build gtk+
|
||||
|
||||
rm -rf $root_dir/gtk3/usr/local/share/gtk-doc
|
||||
rm -rf $root_dir/gtk3/usr/local/share/locale
|
||||
|
||||
# mock build environment doesn't have fonts in /usr/share/fonts, but
|
||||
# has some in /usr/share/X11/fonts. Add this directory to the
|
||||
# fontconfig configuration without changing the gtk3 tooltool package.
|
||||
cat << EOF > $root_dir/gtk3/usr/local/etc/fonts/local.conf
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||
<fontconfig>
|
||||
<dir>/usr/share/X11/fonts</dir>
|
||||
</fontconfig>
|
||||
EOF
|
||||
|
||||
cat <<EOF > $root_dir/gtk3/setup.sh
|
||||
#!/bin/sh
|
||||
|
||||
cd \$(dirname \$0)
|
||||
|
||||
# pango expects absolute paths in pango.modules, and TOOLTOOL_DIR may vary...
|
||||
LD_LIBRARY_PATH=./usr/local/lib \
|
||||
PANGO_SYSCONFDIR=./usr/local/etc \
|
||||
PANGO_LIBDIR=./usr/local/lib \
|
||||
./usr/local/bin/pango-querymodules > ./usr/local/etc/pango/pango.modules
|
||||
|
||||
# same with gdb-pixbuf and loaders.cache
|
||||
LD_LIBRARY_PATH=./usr/local/lib \
|
||||
GDK_PIXBUF_MODULE_FILE=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
|
||||
GDK_PIXBUF_MODULEDIR=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
|
||||
./usr/local/bin/gdk-pixbuf-query-loaders > ./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
|
||||
|
||||
# The fontconfig version in the tooltool package has known uses of
|
||||
# uninitialized memory when creating its cache, and while most users
|
||||
# will already have an existing cache, running Firefox on automation
|
||||
# will create it. Combined with valgrind, this generates irrelevant
|
||||
# errors.
|
||||
# So create the fontconfig cache beforehand.
|
||||
./usr/local/bin/fc-cache
|
||||
EOF
|
||||
|
||||
chmod +x $root_dir/gtk3/setup.sh
|
||||
|
||||
cd $cwd
|
||||
tar -C $root_dir -Jcf gtk3.tar.xz gtk3
|
||||
@@ -0,0 +1,34 @@
|
||||
MOZ_AUTOMATION_L10N_CHECK=0
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common"
|
||||
|
||||
# Use Clang as specified in manifest
|
||||
export CC="$topsrcdir/clang/bin/clang"
|
||||
export CXX="$topsrcdir/clang/bin/clang++"
|
||||
export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
|
||||
|
||||
# Mandatory flag for TSan
|
||||
export CFLAGS="-fsanitize=thread"
|
||||
export CXXFLAGS="-fsanitize=thread"
|
||||
export LDFLAGS="-fsanitize=thread"
|
||||
|
||||
# Enable TSan specific code and build workarounds
|
||||
ac_add_options --enable-thread-sanitizer
|
||||
|
||||
# The ThreadSanitizer is not compatible with sanboxing
|
||||
# (see bug 1182565)
|
||||
ac_add_options --disable-sandbox
|
||||
|
||||
# These are required by TSan
|
||||
ac_add_options --disable-jemalloc
|
||||
ac_add_options --disable-crashreporter
|
||||
ac_add_options --disable-elf-hack
|
||||
ac_add_options --enable-pie
|
||||
|
||||
# Keep symbols to symbolize TSan traces
|
||||
ac_add_options --disable-install-strip
|
||||
# -gline-tables-only results in significantly smaller binaries.
|
||||
ac_add_options --enable-debug-symbols="-gline-tables-only"
|
||||
|
||||
# Avoid dependency on libstdc++ 4.7
|
||||
ac_add_options --enable-stdcxx-compat
|
||||
@@ -25,6 +25,7 @@ XPIDL_SOURCES += [
|
||||
'nsIImageLoadingContent.idl',
|
||||
'nsIMessageManager.idl',
|
||||
'nsIObjectLoadingContent.idl',
|
||||
'nsIRemoteWindowContext.idl',
|
||||
'nsIScriptChannel.idl',
|
||||
'nsIScriptLoaderObserver.idl',
|
||||
'nsISelection.idl',
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
|
||||
[scriptable, builtinclass, uuid(94f4a92b-752e-4fd9-8345-11b069ca19f3)]
|
||||
interface nsIRemoteWindowContext : nsISupports
|
||||
{
|
||||
void openURI(in nsIURI aURI, in uint32_t aFlags);
|
||||
};
|
||||
@@ -930,7 +930,9 @@ DataTransfer::GetFilesAndDirectories(ErrorResult& aRv)
|
||||
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
|
||||
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);
|
||||
fs = MakeOrReuseFileSystem(dirname, fs, window);
|
||||
filesAndDirsSeq[i].SetAsDirectory() = new Directory(fs, basename);
|
||||
RefPtr<Directory> directory = new Directory(fs, basename);
|
||||
directory->SetContentFilters(NS_LITERAL_STRING("filter-out-sensitive"));
|
||||
filesAndDirsSeq[i].SetAsDirectory() = directory;
|
||||
} else {
|
||||
filesAndDirsSeq[i].SetAsFile() = mFiles->Item(i);
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ Directory::GetFilesAndDirectories()
|
||||
nsString realPath;
|
||||
ErrorResult rv;
|
||||
RefPtr<GetDirectoryListingTask> task =
|
||||
new GetDirectoryListingTask(mFileSystem, mPath, rv);
|
||||
new GetDirectoryListingTask(mFileSystem, mPath, mFilters, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -251,6 +251,12 @@ Directory::GetFilesAndDirectories()
|
||||
return task->GetPromise();
|
||||
}
|
||||
|
||||
void
|
||||
Directory::SetContentFilters(const nsAString& aFilters)
|
||||
{
|
||||
mFilters = aFilters;
|
||||
}
|
||||
|
||||
FileSystemBase*
|
||||
Directory::GetFileSystem() const
|
||||
{
|
||||
|
||||
@@ -87,6 +87,31 @@ public:
|
||||
|
||||
// =========== End WebIDL bindings.============
|
||||
|
||||
/**
|
||||
* Sets a semi-colon separated list of filters to filter-in or filter-out
|
||||
* certain types of files when the contents of this directory are requested
|
||||
* via a GetFilesAndDirectories() call.
|
||||
*
|
||||
* Currently supported keywords:
|
||||
*
|
||||
* * filter-out-sensitive
|
||||
* This keyword filters out files or directories that we don't wish to
|
||||
* make available to Web content because we are concerned that there is
|
||||
* a risk that users may unwittingly give Web content access to them
|
||||
* and suffer undesirable consequences. The details of what is
|
||||
* filtered out can be found in GetDirectoryListingTask::Work.
|
||||
*
|
||||
* In future, we will likely support filtering based on filename extensions
|
||||
* (for example, aFilters could be "*.jpg; *.jpeg; *.gif"), but that isn't
|
||||
* supported yet. Once supported, files that don't match a specified
|
||||
* extension (if any are specified) would be filtered out. This
|
||||
* functionality would allow us to apply the 'accept' attribute from
|
||||
* <input type=file directory accept="..."> to the results of a directory
|
||||
* picker operation.
|
||||
*/
|
||||
void
|
||||
SetContentFilters(const nsAString& aFilters);
|
||||
|
||||
FileSystemBase*
|
||||
GetFileSystem() const;
|
||||
private:
|
||||
@@ -108,6 +133,7 @@ private:
|
||||
|
||||
RefPtr<FileSystemBase> mFileSystem;
|
||||
nsString mPath;
|
||||
nsString mFilters;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
#include "GetDirectoryListingTask.h"
|
||||
|
||||
#include "HTMLSplitOnSpacesTokenizer.h"
|
||||
#include "js/Value.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileSystemBase.h"
|
||||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
@@ -23,9 +23,11 @@ namespace dom {
|
||||
|
||||
GetDirectoryListingTask::GetDirectoryListingTask(FileSystemBase* aFileSystem,
|
||||
const nsAString& aTargetPath,
|
||||
const nsAString& aFilters,
|
||||
ErrorResult& aRv)
|
||||
: FileSystemTaskBase(aFileSystem)
|
||||
, mTargetRealPath(aTargetPath)
|
||||
, mFilters(aFilters)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
@@ -41,12 +43,13 @@ GetDirectoryListingTask::GetDirectoryListingTask(FileSystemBase* aFileSystem,
|
||||
const FileSystemGetDirectoryListingParams& aParam,
|
||||
FileSystemRequestParent* aParent)
|
||||
: FileSystemTaskBase(aFileSystem, aParam, aParent)
|
||||
, mTargetRealPath(aParam.realPath())
|
||||
, mFilters(aParam.filters())
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Only call from parent process!");
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
mTargetRealPath = aParam.realPath();
|
||||
}
|
||||
|
||||
GetDirectoryListingTask::~GetDirectoryListingTask()
|
||||
@@ -66,7 +69,8 @@ FileSystemParams
|
||||
GetDirectoryListingTask::GetRequestParams(const nsString& aFileSystem) const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
return FileSystemGetDirectoryListingParams(aFileSystem, mTargetRealPath);
|
||||
return FileSystemGetDirectoryListingParams(aFileSystem, mTargetRealPath,
|
||||
mFilters);
|
||||
}
|
||||
|
||||
FileSystemResponseValue
|
||||
@@ -156,6 +160,20 @@ GetDirectoryListingTask::Work()
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool filterOutSensitive = false;
|
||||
{
|
||||
HTMLSplitOnSpacesTokenizer tokenizer(mFilters, ';');
|
||||
nsAutoString token;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
token = tokenizer.nextToken();
|
||||
if (token.EqualsLiteral("filter-out-sensitive")) {
|
||||
filterOutSensitive = true;
|
||||
} else {
|
||||
MOZ_CRASH("Unrecognized filter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
bool hasMore = false;
|
||||
if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
|
||||
@@ -180,6 +198,21 @@ GetDirectoryListingTask::Work()
|
||||
!(isFile || isDir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filterOutSensitive) {
|
||||
bool isHidden;
|
||||
if (NS_WARN_IF(NS_FAILED(currFile->IsHidden(&isHidden))) || isHidden) {
|
||||
continue;
|
||||
}
|
||||
nsAutoString leafName;
|
||||
if (NS_WARN_IF(NS_FAILED(currFile->GetLeafName(leafName)))) {
|
||||
continue;
|
||||
}
|
||||
if (leafName[0] == char16_t('.')) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
BlobImplFile* impl = new BlobImplFile(currFile);
|
||||
impl->LookupAndCacheIsDirectory();
|
||||
mTargetBlobImpls.AppendElement(impl);
|
||||
@@ -197,9 +230,7 @@ GetDirectoryListingTask::HandlerCallback()
|
||||
}
|
||||
|
||||
if (HasError()) {
|
||||
RefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
|
||||
mErrorValue);
|
||||
mPromise->MaybeRejectBrokenly(domError);
|
||||
mPromise->MaybeReject(mErrorValue);
|
||||
mPromise = nullptr;
|
||||
return;
|
||||
}
|
||||
@@ -229,7 +260,10 @@ GetDirectoryListingTask::HandlerCallback()
|
||||
MOZ_ASSERT(exist);
|
||||
}
|
||||
#endif
|
||||
listing[i].SetAsDirectory() = new Directory(mFileSystem, path);
|
||||
RefPtr<Directory> directory = new Directory(mFileSystem, path);
|
||||
// Propogate mFilter onto sub-Directory object:
|
||||
directory->SetContentFilters(mFilters);
|
||||
listing[i].SetAsDirectory() = directory;
|
||||
} else {
|
||||
listing[i].SetAsFile() = File::Create(mFileSystem->GetWindow(), mTargetBlobImpls[i]);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
// If aDirectoryOnly is set, we should ensure that the target is a directory.
|
||||
GetDirectoryListingTask(FileSystemBase* aFileSystem,
|
||||
const nsAString& aTargetPath,
|
||||
const nsAString& aFilters,
|
||||
ErrorResult& aRv);
|
||||
GetDirectoryListingTask(FileSystemBase* aFileSystem,
|
||||
const FileSystemGetDirectoryListingParams& aParam,
|
||||
@@ -55,6 +56,7 @@ protected:
|
||||
private:
|
||||
RefPtr<Promise> mPromise;
|
||||
nsString mTargetRealPath;
|
||||
nsString mFilters;
|
||||
|
||||
// We cannot store File or Directory objects bacause this object is created
|
||||
// on a different thread and File and Directory are not thread-safe.
|
||||
|
||||
@@ -27,7 +27,7 @@ NS_NewHTMLExtAppElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
already_AddRefed<mozilla::dom::NodeInfo> aarni = ni.forget();
|
||||
|
||||
if (!permissionManager) {
|
||||
return new HTMLUnknownElement(aarni);
|
||||
return new mozilla::dom::HTMLUnknownElement(aarni);
|
||||
}
|
||||
|
||||
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
|
||||
@@ -35,10 +35,10 @@ NS_NewHTMLExtAppElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
"external-app",
|
||||
&perm);
|
||||
if (perm != nsIPermissionManager::ALLOW_ACTION) {
|
||||
return new HTMLUnknownElement(aarni);
|
||||
return new mozilla::dom::HTMLUnknownElement(aarni);
|
||||
}
|
||||
|
||||
return new HTMLExtAppElement(aarni);
|
||||
return new mozilla::dom::HTMLExtAppElement(aarni);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -121,6 +121,9 @@ HTMLFormControlsCollection::FlushPendingNotifications()
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLFormControlsCollection)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLFormControlsCollection)
|
||||
// Note: We intentionally don't set tmp->mForm to nullptr here, since doing
|
||||
// so may result in crashes because of inconsistent null-checking after the
|
||||
// object gets unlinked.
|
||||
tmp->Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
@@ -80,27 +80,35 @@ namespace dom {
|
||||
class ImageLoadTask : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit ImageLoadTask(HTMLImageElement *aElement) :
|
||||
mElement(aElement)
|
||||
{}
|
||||
ImageLoadTask(HTMLImageElement *aElement, bool aAlwaysLoad)
|
||||
: mElement(aElement)
|
||||
, mAlwaysLoad(aAlwaysLoad)
|
||||
{
|
||||
mDocument = aElement->OwnerDoc();
|
||||
mDocument->BlockOnload();
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (mElement->mPendingImageLoadTask == this) {
|
||||
mElement->mPendingImageLoadTask = nullptr;
|
||||
mElement->LoadSelectedImage(true, true);
|
||||
mElement->LoadSelectedImage(true, true, mAlwaysLoad);
|
||||
}
|
||||
mDocument->UnblockOnload(false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
~ImageLoadTask() {}
|
||||
RefPtr<HTMLImageElement> mElement;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
bool mAlwaysLoad;
|
||||
};
|
||||
|
||||
HTMLImageElement::HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
, mForm(nullptr)
|
||||
, mInDocResponsiveContent(false)
|
||||
{
|
||||
// We start out broken
|
||||
AddStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
@@ -422,7 +430,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
mResponsiveSelector->Content() == this) {
|
||||
mResponsiveSelector->SetDefaultSource(NullString());
|
||||
}
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
} else {
|
||||
// Bug 1076583 - We still behave synchronously in the non-responsive case
|
||||
CancelImageRequests(aNotify);
|
||||
@@ -442,7 +450,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
if (InResponsiveMode()) {
|
||||
// per spec, full selection runs when this changes, even though
|
||||
// it doesn't directly affect the source selection
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
} else {
|
||||
// Bug 1076583 - We still use the older synchronous algorithm in
|
||||
// non-responsive mode. Force a new load of the image with the
|
||||
@@ -542,7 +550,7 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
mResponsiveSelector->Content() == this) {
|
||||
mResponsiveSelector->SetDefaultSource(aValue);
|
||||
}
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
} else if (aNotify) {
|
||||
// If aNotify is false, we are coming from the parser or some such place;
|
||||
// we'll get bound after all the attributes have been set, so we'll do the
|
||||
@@ -585,13 +593,15 @@ HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
UpdateFormOwner();
|
||||
}
|
||||
|
||||
bool addedToPicture = aParent && aParent->IsHTMLElement(nsGkAtoms::picture) &&
|
||||
HTMLPictureElement::IsPictureEnabled();
|
||||
if (addedToPicture) {
|
||||
if (aDocument) {
|
||||
if (HaveSrcsetOrInPicture()) {
|
||||
if (aDocument && !mInDocResponsiveContent) {
|
||||
aDocument->AddResponsiveContent(this);
|
||||
mInDocResponsiveContent = true;
|
||||
}
|
||||
QueueImageLoadTask();
|
||||
|
||||
bool forceLoadEvent = HTMLPictureElement::IsPictureEnabled() &&
|
||||
aParent && aParent->IsHTMLElement(nsGkAtoms::picture);
|
||||
QueueImageLoadTask(forceLoadEvent);
|
||||
} else if (!InResponsiveMode() &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
||||
// We skip loading when our attributes were set from parser land,
|
||||
@@ -632,17 +642,22 @@ HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
}
|
||||
}
|
||||
|
||||
if (mInDocResponsiveContent) {
|
||||
nsIDocument* doc = GetOurOwnerDoc();
|
||||
MOZ_ASSERT(doc);
|
||||
if (doc) {
|
||||
doc->RemoveResponsiveContent(this);
|
||||
mInDocResponsiveContent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetParent() &&
|
||||
GetParent()->IsHTMLElement(nsGkAtoms::picture) &&
|
||||
HTMLPictureElement::IsPictureEnabled()) {
|
||||
nsIDocument* doc = GetOurOwnerDoc();
|
||||
if (doc) {
|
||||
doc->RemoveResponsiveContent(this);
|
||||
}
|
||||
// Being removed from picture re-triggers selection, even if we
|
||||
// weren't using a <source> peer
|
||||
if (aNullParent) {
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,7 +701,7 @@ HTMLImageElement::MaybeLoadImage()
|
||||
|
||||
// Note, check LoadingEnabled() after LoadImage call.
|
||||
|
||||
LoadSelectedImage(false, true);
|
||||
LoadSelectedImage(false, true, false);
|
||||
|
||||
if (!LoadingEnabled()) {
|
||||
CancelImageRequests(true);
|
||||
@@ -886,7 +901,7 @@ HTMLImageElement::ClearForm(bool aRemoveFromForm)
|
||||
}
|
||||
|
||||
void
|
||||
HTMLImageElement::QueueImageLoadTask()
|
||||
HTMLImageElement::QueueImageLoadTask(bool aAlwaysLoad)
|
||||
{
|
||||
// If loading is temporarily disabled, we don't want to queue tasks
|
||||
// that may then run when loading is re-enabled.
|
||||
@@ -894,7 +909,7 @@ HTMLImageElement::QueueImageLoadTask()
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this);
|
||||
nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this, aAlwaysLoad);
|
||||
// The task checks this to determine if it was the last
|
||||
// queued event, and so earlier tasks are implicitly canceled.
|
||||
mPendingImageLoadTask = task;
|
||||
@@ -928,7 +943,7 @@ HTMLImageElement::InResponsiveMode()
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify)
|
||||
HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
@@ -936,7 +951,9 @@ HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify)
|
||||
// In responsive mode we generally want to re-run the full
|
||||
// selection algorithm whenever starting a new load, per
|
||||
// spec. This also causes us to re-resolve the URI as appropriate.
|
||||
UpdateResponsiveSource();
|
||||
if (!UpdateResponsiveSource() && !aAlwaysLoad) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (mResponsiveSelector) {
|
||||
@@ -989,9 +1006,17 @@ HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode,
|
||||
mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue);
|
||||
}
|
||||
|
||||
if (!mInDocResponsiveContent) {
|
||||
nsIDocument* doc = GetOurOwnerDoc();
|
||||
if (doc) {
|
||||
doc->AddResponsiveContent(this);
|
||||
mInDocResponsiveContent = true;
|
||||
}
|
||||
}
|
||||
|
||||
// This always triggers the image update steps per the spec, even if
|
||||
// we are not using this source.
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1018,7 +1043,7 @@ HTMLImageElement::PictureSourceSizesChanged(nsIContent *aSourceNode,
|
||||
|
||||
// This always triggers the image update steps per the spec, even if
|
||||
// we are not using this source.
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1034,7 +1059,7 @@ HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode,
|
||||
|
||||
// This always triggers the image update steps per the spec, even if
|
||||
// we are not switching to/from this source
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1044,7 +1069,7 @@ HTMLImageElement::PictureSourceAdded(nsIContent *aSourceNode)
|
||||
return;
|
||||
}
|
||||
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1054,15 +1079,17 @@ HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode)
|
||||
return;
|
||||
}
|
||||
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(true);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
HTMLImageElement::UpdateResponsiveSource()
|
||||
{
|
||||
bool hadSelector = !!mResponsiveSelector;
|
||||
|
||||
if (!IsSrcsetEnabled()) {
|
||||
mResponsiveSelector = nullptr;
|
||||
return;
|
||||
return hadSelector;
|
||||
}
|
||||
|
||||
nsIContent *currentSource =
|
||||
@@ -1082,7 +1109,7 @@ HTMLImageElement::UpdateResponsiveSource()
|
||||
if (candidateSource == currentSource) {
|
||||
// found no better source before current, re-run selection on
|
||||
// that and keep it if it's still usable.
|
||||
mResponsiveSelector->SelectImage(true);
|
||||
bool changed = mResponsiveSelector->SelectImage(true);
|
||||
if (mResponsiveSelector->NumCandidates()) {
|
||||
bool isUsableCandidate = true;
|
||||
|
||||
@@ -1094,7 +1121,7 @@ HTMLImageElement::UpdateResponsiveSource()
|
||||
}
|
||||
|
||||
if (isUsableCandidate) {
|
||||
break;
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1123,6 +1150,8 @@ HTMLImageElement::UpdateResponsiveSource()
|
||||
// Ran out of siblings without finding ourself, e.g. XBL magic.
|
||||
mResponsiveSelector = nullptr;
|
||||
}
|
||||
|
||||
return !hadSelector || mResponsiveSelector;
|
||||
}
|
||||
|
||||
/*static */ bool
|
||||
@@ -1295,7 +1324,7 @@ HTMLImageElement::DestroyContent()
|
||||
void
|
||||
HTMLImageElement::MediaFeatureValuesChanged()
|
||||
{
|
||||
QueueImageLoadTask();
|
||||
QueueImageLoadTask(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -280,7 +280,7 @@ protected:
|
||||
// algorithm (InResponsiveMode()) -- synchronous actions when just
|
||||
// using img.src will bypass this, and update source and kick off
|
||||
// image load synchronously.
|
||||
void QueueImageLoadTask();
|
||||
void QueueImageLoadTask(bool aAlwaysLoad);
|
||||
|
||||
// True if we have a srcset attribute or a <picture> parent, regardless of if
|
||||
// any valid responsive sources were parsed from either.
|
||||
@@ -292,7 +292,7 @@ protected:
|
||||
|
||||
// Resolve and load the current mResponsiveSelector (responsive mode) or src
|
||||
// attr image.
|
||||
nsresult LoadSelectedImage(bool aForce, bool aNotify);
|
||||
nsresult LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad);
|
||||
|
||||
// True if this string represents a type we would support on <source type>
|
||||
static bool SupportedPictureSourceType(const nsAString& aType);
|
||||
@@ -321,7 +321,9 @@ protected:
|
||||
// the existing mResponsiveSelector, meaning you need to update its
|
||||
// parameters as appropriate before calling (or null it out to force
|
||||
// recreation)
|
||||
void UpdateResponsiveSource();
|
||||
//
|
||||
// Returns true if the source has changed, and false otherwise.
|
||||
bool UpdateResponsiveSource();
|
||||
|
||||
// Given a <source> node that is a previous sibling *or* ourselves, try to
|
||||
// create a ResponsiveSelector.
|
||||
@@ -362,6 +364,7 @@ private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData);
|
||||
|
||||
bool mInDocResponsiveContent;
|
||||
nsCOMPtr<nsIRunnable> mPendingImageLoadTask;
|
||||
};
|
||||
|
||||
|
||||
@@ -295,20 +295,25 @@ NS_IMPL_ISUPPORTS(UploadLastDir::ContentPrefCallback, nsIContentPrefCallback2)
|
||||
NS_IMETHODIMP
|
||||
UploadLastDir::ContentPrefCallback::HandleCompletion(uint16_t aReason)
|
||||
{
|
||||
nsCOMPtr<nsIFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
NS_ENSURE_STATE(localFile);
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
nsAutoString prefStr;
|
||||
|
||||
if (aReason == nsIContentPrefCallback2::COMPLETE_ERROR ||
|
||||
!mResult) {
|
||||
// Default to "desktop" directory for each platform
|
||||
nsCOMPtr<nsIFile> homeDir;
|
||||
NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(homeDir));
|
||||
localFile = do_QueryInterface(homeDir);
|
||||
} else {
|
||||
nsAutoString prefStr;
|
||||
nsCOMPtr<nsIVariant> pref;
|
||||
mResult->GetValue(getter_AddRefs(pref));
|
||||
pref->GetAsAString(prefStr);
|
||||
if (aReason == nsIContentPrefCallback2::COMPLETE_ERROR || !mResult) {
|
||||
prefStr = Preferences::GetString("dom.input.fallbackUploadDir");
|
||||
if (prefStr.IsEmpty()) {
|
||||
// If no custom directory was set through the pref, default to
|
||||
// "desktop" directory for each platform.
|
||||
NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(localFile));
|
||||
}
|
||||
}
|
||||
|
||||
if (!localFile) {
|
||||
if (prefStr.IsEmpty() && mResult) {
|
||||
nsCOMPtr<nsIVariant> pref;
|
||||
mResult->GetValue(getter_AddRefs(pref));
|
||||
pref->GetAsAString(prefStr);
|
||||
}
|
||||
localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
localFile->InitWithPath(prefStr);
|
||||
}
|
||||
|
||||
@@ -4899,10 +4904,17 @@ HTMLInputElement::GetFilesAndDirectories(ErrorResult& aRv)
|
||||
}
|
||||
int32_t leafSeparatorIndex = path.RFind(FILE_PATH_SEPARATOR);
|
||||
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
|
||||
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);
|
||||
fs = MakeOrReuseFileSystem(dirname, fs, window);
|
||||
filesAndDirsSeq[i].SetAsDirectory() = new Directory(fs, basename);
|
||||
nsAutoString dompath(NS_LITERAL_STRING(FILESYSTEM_DOM_PATH_SEPARATOR));
|
||||
dompath.Append(Substring(path, leafSeparatorIndex + 1));
|
||||
RefPtr<Directory> directory = new Directory(fs, dompath);
|
||||
// In future we could refactor SetFilePickerFiltersFromAccept to return a
|
||||
// semicolon separated list of file extensions and include that in the
|
||||
// filter string passed here.
|
||||
directory->SetContentFilters(NS_LITERAL_STRING("filter-out-sensitive"));
|
||||
filesAndDirsSeq[i].SetAsDirectory() = directory;
|
||||
} else {
|
||||
// This file was directly selected by the user, so don't filter it.
|
||||
filesAndDirsSeq[i].SetAsFile() = filesAndDirs[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ static MOZ_CONSTEXPR nsAttrValue::EnumTable kKindTable[] = {
|
||||
};
|
||||
|
||||
// The default value for kKindTable is "subtitles"
|
||||
static MOZ_CONSTEXPR const char* kKindTableDefaultString = kKindTable->tag;
|
||||
static MOZ_CONSTEXPR const char* kKindTableDefaultString = kKindTable[0].tag;
|
||||
|
||||
/** HTMLTrackElement */
|
||||
HTMLTrackElement::HTMLTrackElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 91 B |
Binary file not shown.
|
After Width: | Height: | Size: 100 B |
Binary file not shown.
|
After Width: | Height: | Size: 85 B |
+24
-26
@@ -197,6 +197,9 @@ support-files =
|
||||
file_ignoreuserfocus.html
|
||||
simpleFileOpener.js
|
||||
file_mozaudiochannel.html
|
||||
file_bug1166138_1x.png
|
||||
file_bug1166138_2x.png
|
||||
file_bug1166138_def.png
|
||||
|
||||
[test_a_text.html]
|
||||
[test_anchor_href_cache_invalidation.html]
|
||||
@@ -289,7 +292,7 @@ skip-if = toolkit == 'android'
|
||||
[test_bug518122.html]
|
||||
[test_bug519987.html]
|
||||
[test_bug523771.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(onload of iframe not firing, because submit not working?) b2g-debug(onload of iframe not firing, because submit not working?) b2g-desktop(onload of iframe not firing, because submit not working?)
|
||||
skip-if = buildapp == 'b2g' # b2g(onload of iframe not firing, because submit not working?) b2g-debug(onload of iframe not firing, because submit not working?) b2g-desktop(onload of iframe not firing, because submit not working?)
|
||||
[test_bug529819.html]
|
||||
[test_bug529859.html]
|
||||
[test_bug535043.html]
|
||||
@@ -313,7 +316,7 @@ skip-if = toolkit == 'android' #TIMED_OUT
|
||||
[test_bug560112.html]
|
||||
[test_bug561634.html]
|
||||
[test_bug561636.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(observerservice not working) b2g-debug(observerservice not working) b2g-desktop(observerservice not working)
|
||||
skip-if = buildapp == 'b2g' # b2g(observerservice not working) b2g-debug(observerservice not working) b2g-desktop(observerservice not working)
|
||||
[test_bug561640.html]
|
||||
[test_bug564001.html]
|
||||
[test_bug566046.html]
|
||||
@@ -338,10 +341,9 @@ skip-if = buildapp == 'b2g' || e10s # b2g(observerservice not working) b2g-debug
|
||||
[test_bug592802.html]
|
||||
[test_bug593689.html]
|
||||
[test_bug595429.html]
|
||||
skip-if = e10s
|
||||
[test_bug595447.html]
|
||||
[test_bug595449.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_bug596350.html]
|
||||
[test_bug596511.html]
|
||||
[test_bug598643.html]
|
||||
@@ -362,7 +364,7 @@ skip-if = buildapp == 'mulet' # TC: Bug 1144079 - Re-enable Mulet mochitests and
|
||||
[test_bug612730.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-debug(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-desktop(form control not selected/checked with synthesizeMouse, also fails on Android)
|
||||
[test_bug613113.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
[test_bug613722.html]
|
||||
[test_bug613979.html]
|
||||
[test_bug615595.html]
|
||||
@@ -370,29 +372,22 @@ skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-debug(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-desktop(form control not selected/checked with synthesizeMouse, also fails on Android)
|
||||
[test_bug617528.html]
|
||||
[test_bug618948.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
[test_bug619278.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
[test_bug622558.html]
|
||||
skip-if = e10s
|
||||
[test_bug622597.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
|
||||
[test_bug623291.html]
|
||||
skip-if = e10s
|
||||
[test_bug6296.html]
|
||||
skip-if = e10s
|
||||
[test_bug629801.html]
|
||||
skip-if = e10s
|
||||
[test_bug633058.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug636336.html]
|
||||
skip-if = e10s
|
||||
[test_bug641219.html]
|
||||
skip-if = e10s
|
||||
[test_bug643051.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug646157.html]
|
||||
skip-if = e10s
|
||||
[test_bug649134.html]
|
||||
# This extra subdirectory is needed due to the nature of this test.
|
||||
# With the bug, the test loads the base URL of the bug649134/file_*.sjs
|
||||
@@ -444,7 +439,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||
[test_bug839913.html]
|
||||
[test_bug840877.html]
|
||||
[test_bug841466.html]
|
||||
skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
|
||||
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
|
||||
[test_bug845057.html]
|
||||
[test_bug869040.html]
|
||||
[test_bug870787.html]
|
||||
@@ -486,11 +481,11 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #time out on b2g desktop spec
|
||||
[test_iframe_sandbox_navigation2.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #time out on b2g desktop specific
|
||||
[test_iframe_sandbox_plugins.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
|
||||
[test_iframe_sandbox_popups.html]
|
||||
skip-if = buildapp == 'b2g' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
[test_iframe_sandbox_popups_inheritance.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage) android(bug 939642)
|
||||
[test_iframe_sandbox_redirect.html]
|
||||
[test_iframe_sandbox_refresh.html]
|
||||
[test_iframe_sandbox_same_origin.html]
|
||||
@@ -511,12 +506,12 @@ skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
|
||||
[test_meta_attributes_reflection.html]
|
||||
[test_mod_attributes_reflection.html]
|
||||
[test_mozaudiochannel.html]
|
||||
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Perma-orange on debug emulator) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Perma-orange on debug emulator) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||
[test_named_options.html]
|
||||
[test_nested_invalid_fieldsets.html]
|
||||
[test_object_attributes_reflection.html]
|
||||
[test_object_plugin_nav.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
|
||||
[test_ol_attributes_reflection.html]
|
||||
[test_option_defaultSelected.html]
|
||||
[test_option_selected_state.html]
|
||||
@@ -541,9 +536,9 @@ skip-if = (toolkit == 'gonk' && debug)
|
||||
[test_bug1823.html]
|
||||
[test_bug57600.html]
|
||||
[test_bug196523.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug199692.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' || e10s #bug 811644 #Bug 931116, b2g desktop specific, initial triage
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #bug 811644 #Bug 931116, b2g desktop specific, initial triage
|
||||
[test_bug172261.html]
|
||||
[test_bug255820.html]
|
||||
[test_bug259332.html]
|
||||
@@ -592,7 +587,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
|
||||
skip-if = buildapp == 'b2g' || e10s
|
||||
[test_bug765780.html]
|
||||
[test_bug871161.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
|
||||
support-files = file_bug871161-1.html file_bug871161-2.html
|
||||
[test_bug1013316.html]
|
||||
[test_hash_encoded.html]
|
||||
@@ -600,7 +595,10 @@ support-files = file_bug871161-1.html file_bug871161-2.html
|
||||
[test_window_open_close.html]
|
||||
skip-if = buildapp == 'b2g' # bug 1129014
|
||||
[test_img_complete.html]
|
||||
[test_extapp.html]
|
||||
[test_viewport_resize.html]
|
||||
[test_extapp.html]
|
||||
[test_image_clone_load.html]
|
||||
[test_bug1203668.html]
|
||||
[test_bug1166138.html]
|
||||
[test_filepicker_default_directory.html]
|
||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1166138
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1166138</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1166138">Mozilla Bug 1166138</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
||||
<img srcset="file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x"
|
||||
src="file_bug1166138_def.png"
|
||||
onload="onLoad()">
|
||||
|
||||
<script type="application/javascript">
|
||||
var img1x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_1x.png";
|
||||
var img2x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_2x.png";
|
||||
var imgdef = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_def.png";
|
||||
var onLoadCallback = null;
|
||||
var done = false;
|
||||
|
||||
var startPromise = new Promise((a) => {
|
||||
onLoadCallback = () => {
|
||||
var image = document.querySelector('img');
|
||||
// If we aren't starting at 2x scale, resize to 2x scale, and wait for a load
|
||||
if (image.currentSrc != img2x) {
|
||||
onLoadCallback = a;
|
||||
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
|
||||
} else {
|
||||
a();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// if aLoad is true, waits for a load event. Otherwise, spins the event loop twice to
|
||||
// ensure that no events were queued to be fired.
|
||||
function spin(aLoad) {
|
||||
if (aLoad) {
|
||||
return new Promise((a) => {
|
||||
ok(!onLoadCallback, "Shouldn't be an existing callback");
|
||||
onLoadCallback = a;
|
||||
});
|
||||
} else {
|
||||
return new Promise((a) => SimpleTest.executeSoon(() => SimpleTest.executeSoon(a)));
|
||||
}
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
if (done) return;
|
||||
ok(onLoadCallback, "Expected a load event");
|
||||
if (onLoadCallback) {
|
||||
var cb = onLoadCallback;
|
||||
onLoadCallback = null;
|
||||
cb();
|
||||
}
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
yield startPromise;
|
||||
var image = document.querySelector('img');
|
||||
is(image.currentSrc, img2x, "initial scale must be 2x");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
|
||||
yield spin(true);
|
||||
is(image.currentSrc, img1x, "pre-existing img tag to 1x");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
|
||||
yield spin(true);
|
||||
is(image.currentSrc, img2x, "pre-existing img tag to 2x");
|
||||
|
||||
// Try removing & re-adding the image
|
||||
document.body.removeChild(image);
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
|
||||
yield spin(false); // No load should occur because the element is unbound
|
||||
|
||||
document.body.appendChild(image);
|
||||
yield spin(true);
|
||||
is(image.currentSrc, img1x, "remove and re-add tag after changing to 1x");
|
||||
|
||||
document.body.removeChild(image);
|
||||
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
|
||||
yield spin(false); // No load should occur because the element is unbound
|
||||
|
||||
document.body.appendChild(image);
|
||||
yield spin(true);
|
||||
is(image.currentSrc, img2x, "remove and re-add tag after changing to 2x");
|
||||
|
||||
// get rid of the srcset attribute! It should become the default
|
||||
image.removeAttribute('srcset');
|
||||
yield spin(true);
|
||||
is(image.currentSrc, imgdef, "remove srcset attribute");
|
||||
|
||||
// Setting srcset again should return it to the correct value
|
||||
image.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x");
|
||||
yield spin(true);
|
||||
is(image.currentSrc, img2x, "restore srcset attribute");
|
||||
|
||||
// Create a new image
|
||||
var newImage = document.createElement('img');
|
||||
// Switch load listening over to newImage
|
||||
newImage.addEventListener('load', onLoad);
|
||||
image.removeEventListener('load', onLoad);
|
||||
|
||||
document.body.appendChild(newImage);
|
||||
yield spin(false); // no load event should fire - as the image has no attributes
|
||||
is(newImage.currentSrc, "", "New element with no attributes");
|
||||
newImage.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x");
|
||||
yield spin(true);
|
||||
is(newImage.currentSrc, img2x, "Adding srcset attribute");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
|
||||
yield spin(true);
|
||||
is(newImage.currentSrc, img1x, "new image after switching to 1x");
|
||||
is(image.currentSrc, img1x, "old image after switching to 1x");
|
||||
|
||||
// Clear the listener
|
||||
done = true;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,83 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1194893
|
||||
-->
|
||||
<head>
|
||||
<title>Test for filepicker default directory</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1194893">Mozilla Bug 1194893</a>
|
||||
<div id="content">
|
||||
<input type="file" id="f">
|
||||
</div>
|
||||
<pre id="text">
|
||||
<script class="testbody" type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
const { Cc: Cc, Ci: Ci } = SpecialPowers;
|
||||
|
||||
// Platform-independent directory names are #define'd in xpcom/io/nsDirectoryServiceDefs.h
|
||||
var defaultUploadDirectory = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIDirectoryService)
|
||||
.QueryInterface(Ci.nsIProperties)
|
||||
.get("Desk", Ci.nsIFile);
|
||||
|
||||
// When we want to test an upload directory other than the default, we need to
|
||||
// get a valid directory in a platform-independent way. Since NS_OS_DESKTOP_DIR
|
||||
// may fallback to NS_OS_HOME_DIR, let's use NS_OS_TMP_DIR.
|
||||
var customUploadDirectory = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIDirectoryService)
|
||||
.QueryInterface(Ci.nsIProperties)
|
||||
.get("TmpD", Ci.nsIFile);
|
||||
|
||||
// Useful for debugging
|
||||
//info("defaultUploadDirectory" + defaultUploadDirectory.path);
|
||||
//info("customUploadDirectory" + customUploadDirectory.path);
|
||||
|
||||
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(window);
|
||||
|
||||
// need to show the MockFilePicker so .displayDirectory gets set
|
||||
var f = document.getElementById("f");
|
||||
f.focus();
|
||||
|
||||
var testIndex = 0;
|
||||
var tests = [
|
||||
["", defaultUploadDirectory.path],
|
||||
[customUploadDirectory.path, customUploadDirectory.path]
|
||||
]
|
||||
|
||||
MockFilePicker.showCallback = function(filepicker) {
|
||||
info(SpecialPowers.wrap(MockFilePicker).displayDirectory.path);
|
||||
|
||||
is(SpecialPowers.wrap(MockFilePicker).displayDirectory.path,
|
||||
tests[testIndex][1]);
|
||||
|
||||
if (++testIndex == tests.length) {
|
||||
MockFilePicker.cleanup();
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
launchNextTest();
|
||||
}
|
||||
}
|
||||
|
||||
function launchNextTest() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ 'set': [
|
||||
['dom.input.fallbackUploadDir', tests[testIndex][0]],
|
||||
]},
|
||||
function () {
|
||||
f.click();
|
||||
});
|
||||
}
|
||||
|
||||
launchNextTest();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2963,6 +2963,15 @@ ContentChild::RecvShutdown()
|
||||
|
||||
GetIPCChannel()->SetAbortOnError(false);
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
if (profiler_is_active()) {
|
||||
// We're shutting down while we were profiling. Send the
|
||||
// profile up to the parent so that we don't lose this
|
||||
// information.
|
||||
Unused << RecvGatherProfile();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ignore errors here. If this fails, the parent will kill us after a
|
||||
// timeout.
|
||||
Unused << SendFinishShutdown();
|
||||
|
||||
@@ -134,6 +134,7 @@
|
||||
#include "nsIMutable.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIRemoteWindowContext.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISiteSecurityService.h"
|
||||
@@ -1686,6 +1687,47 @@ StaticAutoPtr<LinkedList<SystemMessageHandledListener> >
|
||||
NS_IMPL_ISUPPORTS(SystemMessageHandledListener,
|
||||
nsITimerCallback)
|
||||
|
||||
|
||||
class RemoteWindowContext final : public nsIRemoteWindowContext
|
||||
, public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
explicit RemoteWindowContext(TabParent* aTabParent)
|
||||
: mTabParent(aTabParent)
|
||||
{
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIREMOTEWINDOWCONTEXT
|
||||
|
||||
private:
|
||||
~RemoteWindowContext();
|
||||
RefPtr<TabParent> mTabParent;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RemoteWindowContext, nsIRemoteWindowContext, nsIInterfaceRequestor)
|
||||
|
||||
RemoteWindowContext::~RemoteWindowContext()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RemoteWindowContext::GetInterface(const nsIID& aIID, void** aSink)
|
||||
{
|
||||
return QueryInterface(aIID, aSink);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RemoteWindowContext::OpenURI(nsIURI* aURI, uint32_t aFlags)
|
||||
{
|
||||
URIParams uri;
|
||||
SerializeURI(aURI, uri);
|
||||
|
||||
Unused << mTabParent->SendOpenURI(uri, aFlags);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
@@ -2089,6 +2131,12 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
|
||||
mConsoleService = nullptr;
|
||||
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
if (mGatherer && !mProfile.IsEmpty()) {
|
||||
mGatherer->OOPExitProfile(mProfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (obs) {
|
||||
RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
|
||||
|
||||
@@ -4314,7 +4362,8 @@ ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool&
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvLoadURIExternal(const URIParams& uri)
|
||||
ContentParent::RecvLoadURIExternal(const URIParams& uri,
|
||||
PBrowserParent* windowContext)
|
||||
{
|
||||
nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
||||
if (!extProtService) {
|
||||
@@ -4324,7 +4373,10 @@ ContentParent::RecvLoadURIExternal(const URIParams& uri)
|
||||
if (!ourURI) {
|
||||
return false;
|
||||
}
|
||||
extProtService->LoadURI(ourURI, nullptr);
|
||||
|
||||
RefPtr<RemoteWindowContext> context =
|
||||
new RemoteWindowContext(static_cast<TabParent*>(windowContext));
|
||||
extProtService->LoadURI(ourURI, context);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -795,7 +795,8 @@ private:
|
||||
|
||||
virtual bool RecvOpenNotificationSettings(const IPC::Principal& aPrincipal) override;
|
||||
|
||||
virtual bool RecvLoadURIExternal(const URIParams& uri) override;
|
||||
virtual bool RecvLoadURIExternal(const URIParams& uri,
|
||||
PBrowserParent* windowContext) override;
|
||||
|
||||
virtual bool RecvSyncMessage(const nsString& aMsg,
|
||||
const ClonedMessageData& aData,
|
||||
|
||||
@@ -554,6 +554,8 @@ child:
|
||||
|
||||
LoadURL(nsCString uri, BrowserConfiguration config, ShowInfo info);
|
||||
|
||||
OpenURI(URIParams uri, uint32_t flags);
|
||||
|
||||
CacheFileDescriptor(nsString path, FileDescriptor fd);
|
||||
|
||||
UpdateDimensions(CSSRect rect, CSSSize size, nsSizeMode sizeMode,
|
||||
|
||||
+11
-1
@@ -278,6 +278,16 @@ struct FileSystemGetDirectoryListingParams
|
||||
{
|
||||
nsString filesystem;
|
||||
nsString realPath;
|
||||
// 'filters' could be an array rather than a semicolon separated string
|
||||
// (we'd then use InfallibleTArray<nsString> internally), but that is
|
||||
// wasteful. E10s requires us to pass the filters over as a string anyway,
|
||||
// so avoiding using an array avoids serialization on the side passing the
|
||||
// filters. Since an nsString can share its buffer when copied,
|
||||
// using that instead of InfallibleTArray<nsString> makes copying the filters
|
||||
// around in any given process a bit more efficient too, since copying a
|
||||
// single nsString is cheaper than copying InfallibleTArray member data and
|
||||
// each nsString that it contains.
|
||||
nsString filters;
|
||||
};
|
||||
|
||||
struct FileSystemGetFileOrDirectoryParams
|
||||
@@ -836,7 +846,7 @@ parent:
|
||||
async VisitURI(URIParams uri, OptionalURIParams referrer, uint32_t flags);
|
||||
async SetURITitle(URIParams uri, nsString title);
|
||||
|
||||
async LoadURIExternal(URIParams uri);
|
||||
async LoadURIExternal(URIParams uri, PBrowser windowContext);
|
||||
|
||||
// PrefService message
|
||||
sync ReadPrefsArray() returns (PrefSetting[] prefs);
|
||||
|
||||
@@ -28,21 +28,19 @@ namespace ipc {
|
||||
bool
|
||||
StructuredCloneData::Copy(const StructuredCloneData& aData)
|
||||
{
|
||||
if (!aData.mData) {
|
||||
if (!aData.Data()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t* data = static_cast<uint64_t*>(js_malloc(aData.mDataLength));
|
||||
if (!data) {
|
||||
return false;
|
||||
if (aData.SharedData()) {
|
||||
mSharedData = aData.SharedData();
|
||||
} else {
|
||||
mSharedData =
|
||||
SharedJSAllocatedData::CreateFromExternalData(aData.Data(),
|
||||
aData.DataLength());
|
||||
NS_ENSURE_TRUE(mSharedData, false);
|
||||
}
|
||||
|
||||
memcpy(data, aData.mData, aData.mDataLength);
|
||||
|
||||
mData = data;
|
||||
mDataLength = aData.mDataLength;
|
||||
mDataOwned = eJSAllocated;
|
||||
|
||||
MOZ_ASSERT(BlobImpls().IsEmpty());
|
||||
BlobImpls().AppendElements(aData.BlobImpls());
|
||||
|
||||
@@ -56,12 +54,12 @@ StructuredCloneData::Read(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue,
|
||||
ErrorResult &aRv)
|
||||
{
|
||||
MOZ_ASSERT(mData);
|
||||
MOZ_ASSERT(Data());
|
||||
|
||||
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
|
||||
MOZ_ASSERT(global);
|
||||
|
||||
ReadFromBuffer(global, aCx, mData, mDataLength, aValue, aRv);
|
||||
ReadFromBuffer(global, aCx, Data(), DataLength(), aValue, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -69,26 +67,28 @@ StructuredCloneData::Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
ErrorResult &aRv)
|
||||
{
|
||||
MOZ_ASSERT(!mData);
|
||||
MOZ_ASSERT(!Data());
|
||||
|
||||
StructuredCloneHolder::Write(aCx, aValue, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
mBuffer->steal(&mData, &mDataLength);
|
||||
uint64_t* data = nullptr;
|
||||
size_t dataLength = 0;
|
||||
mBuffer->steal(&data, &dataLength);
|
||||
mBuffer = nullptr;
|
||||
mDataOwned = eJSAllocated;
|
||||
mSharedData = new SharedJSAllocatedData(data, dataLength);
|
||||
}
|
||||
|
||||
void
|
||||
StructuredCloneData::WriteIPCParams(IPC::Message* aMsg) const
|
||||
{
|
||||
WriteParam(aMsg, mDataLength);
|
||||
WriteParam(aMsg, DataLength());
|
||||
|
||||
if (mDataLength) {
|
||||
if (DataLength()) {
|
||||
// Structured clone data must be 64-bit aligned.
|
||||
aMsg->WriteBytes(mData, mDataLength, sizeof(uint64_t));
|
||||
aMsg->WriteBytes(Data(), DataLength(), sizeof(uint64_t));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,31 +96,29 @@ bool
|
||||
StructuredCloneData::ReadIPCParams(const IPC::Message* aMsg,
|
||||
void** aIter)
|
||||
{
|
||||
MOZ_ASSERT(!mData);
|
||||
MOZ_ASSERT(!Data());
|
||||
|
||||
if (!ReadParam(aMsg, aIter, &mDataLength)) {
|
||||
size_t dataLength = 0;
|
||||
if (!ReadParam(aMsg, aIter, &dataLength)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mDataLength) {
|
||||
if (!dataLength) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t* dataBuffer = nullptr;
|
||||
const char** buffer =
|
||||
const_cast<const char**>(reinterpret_cast<char**>(&mData));
|
||||
const_cast<const char**>(reinterpret_cast<char**>(&dataBuffer));
|
||||
// Structured clone data must be 64-bit aligned.
|
||||
if (!aMsg->ReadBytes(aIter, buffer, mDataLength, sizeof(uint64_t))) {
|
||||
if (!aMsg->ReadBytes(aIter, buffer, dataLength, sizeof(uint64_t))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t* data = static_cast<uint64_t*>(js_malloc(mDataLength));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
mSharedData = SharedJSAllocatedData::CreateFromExternalData(dataBuffer,
|
||||
dataLength);
|
||||
NS_ENSURE_TRUE(mSharedData, false);
|
||||
|
||||
memcpy(data, mData, mDataLength);
|
||||
mData = data;
|
||||
mDataOwned = eJSAllocated;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -128,17 +126,10 @@ bool
|
||||
StructuredCloneData::CopyExternalData(const void* aData,
|
||||
size_t aDataLength)
|
||||
{
|
||||
MOZ_ASSERT(!mData);
|
||||
uint64_t* data = static_cast<uint64_t*>(js_malloc(aDataLength));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(data, aData, aDataLength);
|
||||
mData = data;
|
||||
mDataLength = aDataLength;
|
||||
mDataOwned = eJSAllocated;
|
||||
|
||||
MOZ_ASSERT(!Data());
|
||||
mSharedData = SharedJSAllocatedData::CreateFromExternalData(aData,
|
||||
aDataLength);
|
||||
NS_ENSURE_TRUE(mSharedData, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
#ifndef mozilla_dom_ipc_StructuredCloneData_h
|
||||
#define mozilla_dom_ipc_StructuredCloneData_h
|
||||
|
||||
#include <algorithm>
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/StructuredCloneHolder.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
@@ -17,6 +20,51 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
namespace ipc {
|
||||
|
||||
class SharedJSAllocatedData final
|
||||
{
|
||||
public:
|
||||
SharedJSAllocatedData(uint64_t* aData, size_t aDataLength)
|
||||
: mData(aData), mDataLength(aDataLength)
|
||||
{
|
||||
MOZ_ASSERT(mData);
|
||||
}
|
||||
|
||||
static already_AddRefed<SharedJSAllocatedData>
|
||||
CreateFromExternalData(const void* aData, size_t aDataLength)
|
||||
{
|
||||
uint64_t* data = Allocate64bitSafely(aDataLength);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(data, aData, aDataLength);
|
||||
RefPtr<SharedJSAllocatedData> sharedData =
|
||||
new SharedJSAllocatedData(data, aDataLength);
|
||||
return sharedData.forget();
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(SharedJSAllocatedData)
|
||||
|
||||
uint64_t* Data() const { return mData; }
|
||||
size_t DataLength() const { return mDataLength; }
|
||||
|
||||
private:
|
||||
~SharedJSAllocatedData()
|
||||
{
|
||||
js_free(mData);
|
||||
}
|
||||
|
||||
static uint64_t*
|
||||
Allocate64bitSafely(size_t aSize)
|
||||
{
|
||||
// Structured cloning requires 64-bit aligment.
|
||||
return static_cast<uint64_t*>(js_malloc(std::max(sizeof(uint64_t), aSize)));
|
||||
}
|
||||
|
||||
uint64_t* mData;
|
||||
size_t mDataLength;
|
||||
};
|
||||
|
||||
class StructuredCloneData : public StructuredCloneHolder
|
||||
{
|
||||
public:
|
||||
@@ -24,18 +72,15 @@ public:
|
||||
: StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
|
||||
StructuredCloneHolder::TransferringNotSupported,
|
||||
StructuredCloneHolder::DifferentProcess)
|
||||
, mData(nullptr)
|
||||
, mDataLength(0)
|
||||
, mDataOwned(eNone)
|
||||
, mExternalData(nullptr)
|
||||
, mExternalDataLength(0)
|
||||
{}
|
||||
|
||||
StructuredCloneData(const StructuredCloneData&) = delete;
|
||||
|
||||
~StructuredCloneData()
|
||||
{
|
||||
if (mDataOwned == eJSAllocated) {
|
||||
js_free(mData);
|
||||
}
|
||||
MOZ_ASSERT(!(mExternalData && mSharedData));
|
||||
}
|
||||
|
||||
StructuredCloneData&
|
||||
@@ -63,22 +108,26 @@ public:
|
||||
|
||||
void UseExternalData(uint64_t* aData, size_t aDataLength)
|
||||
{
|
||||
MOZ_ASSERT(!mData);
|
||||
mData = aData;
|
||||
mDataLength = aDataLength;
|
||||
MOZ_ASSERT(mDataOwned == eNone);
|
||||
MOZ_ASSERT(!Data());
|
||||
mExternalData = aData;
|
||||
mExternalDataLength = aDataLength;
|
||||
}
|
||||
|
||||
bool CopyExternalData(const void* aData, size_t aDataLength);
|
||||
|
||||
uint64_t* Data() const
|
||||
{
|
||||
return mData;
|
||||
return mSharedData ? mSharedData->Data() : mExternalData;
|
||||
}
|
||||
|
||||
size_t DataLength() const
|
||||
{
|
||||
return mDataLength;
|
||||
return mSharedData ? mSharedData->DataLength() : mExternalDataLength;
|
||||
}
|
||||
|
||||
SharedJSAllocatedData* SharedData() const
|
||||
{
|
||||
return mSharedData;
|
||||
}
|
||||
|
||||
// For IPC serialization
|
||||
@@ -86,12 +135,10 @@ public:
|
||||
bool ReadIPCParams(const IPC::Message* aMessage, void** aIter);
|
||||
|
||||
private:
|
||||
uint64_t* mData;
|
||||
size_t mDataLength;
|
||||
enum {
|
||||
eNone,
|
||||
eJSAllocated,
|
||||
} mDataOwned;
|
||||
uint64_t* MOZ_NON_OWNING_REF mExternalData;
|
||||
size_t mExternalDataLength;
|
||||
|
||||
RefPtr<SharedJSAllocatedData> mSharedData;
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "mozilla/plugins/PluginWidgetChild.h"
|
||||
#include "mozilla/IMEStateManager.h"
|
||||
#include "mozilla/ipc/DocumentRendererChild.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
#include "ipc/Nuwa.h"
|
||||
#endif
|
||||
@@ -101,6 +102,7 @@
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIURILoader.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "nsDeviceContext.h"
|
||||
@@ -1262,6 +1264,31 @@ TabChild::RecvLoadURL(const nsCString& aURI,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvOpenURI(const URIParams& aURI, const uint32_t& aFlags)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsresult rv =
|
||||
NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
nsContentUtils::GetSystemPrincipal(),
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_DOCUMENT);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURILoader> loader = do_GetService("@mozilla.org/uriloader;1");
|
||||
if (NS_WARN_IF(!loader)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> context(do_QueryInterface(WebNavigation()));
|
||||
loader->OpenURI(channel, aFlags, context);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvCacheFileDescriptor(const nsString& aPath,
|
||||
const FileDescriptor& aFileDescriptor)
|
||||
|
||||
@@ -300,6 +300,8 @@ public:
|
||||
virtual bool RecvLoadURL(const nsCString& aURI,
|
||||
const BrowserConfiguration& aConfiguration,
|
||||
const ShowInfo& aInfo) override;
|
||||
virtual bool RecvOpenURI(const URIParams& aURI,
|
||||
const uint32_t& aFlags) override;
|
||||
virtual bool RecvCacheFileDescriptor(const nsString& aPath,
|
||||
const FileDescriptor& aFileDescriptor)
|
||||
override;
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@
|
||||
// This script is run when the preallocated process starts. It is injected as
|
||||
// a frame script.
|
||||
|
||||
const BrowserElementIsPreloaded = true;
|
||||
var BrowserElementIsPreloaded = true;
|
||||
|
||||
const DoPreloadPostfork = function(aCallback) {
|
||||
var DoPreloadPostfork = function(aCallback) {
|
||||
Services.obs.addObserver({
|
||||
_callback: aCallback,
|
||||
|
||||
|
||||
@@ -118,6 +118,8 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video suppo
|
||||
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_peerConnection_promiseSendOnly.html]
|
||||
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_peerConnection_relayOnly.html]
|
||||
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_peerConnection_callbacks.html]
|
||||
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
|
||||
[test_peerConnection_replaceTrack.html]
|
||||
|
||||
@@ -1266,18 +1266,15 @@ PeerConnectionWrapper.prototype = {
|
||||
* resolves when connected, rejects on failure
|
||||
*/
|
||||
waitForIceConnected : function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
var iceConnectedChanged = () => {
|
||||
if (this.isIceConnected()) {
|
||||
delete this.ice_connection_callbacks.waitForIceConnected;
|
||||
resolve();
|
||||
} else if (! this.isIceConnectionPending()) {
|
||||
delete this.ice_connection_callbacks.waitForIceConnected;
|
||||
resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) =>
|
||||
this.ice_connection_callbacks.waitForIceConnected = () => {
|
||||
if (this.isIceConnected()) {
|
||||
delete this.ice_connection_callbacks.waitForIceConnected;
|
||||
resolve();
|
||||
} else if (!this.isIceConnectionPending()) {
|
||||
delete this.ice_connection_callbacks.waitForIceConnected;
|
||||
reject(new Error('ICE failed'));
|
||||
}
|
||||
|
||||
this.ice_connection_callbacks.waitForIceConnected = iceConnectedChanged;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "1187775",
|
||||
title: "peer connection ICE fails on relay-only without TURN"
|
||||
});
|
||||
|
||||
function PC_LOCAL_NO_CANDIDATES(test) {
|
||||
var isnt = can => is(can, null, "No candidates: " + JSON.stringify(can));
|
||||
test.pcLocal._pc.addEventListener("icecandidate", e => isnt(e.candidate));
|
||||
}
|
||||
|
||||
function PC_BOTH_WAIT_FOR_ICE_FAILED(test) {
|
||||
var isFail = (f, reason, msg) =>
|
||||
f().then(() => { throw new Error(msg + " must fail"); },
|
||||
e => is(e.message, reason, msg + " must fail with: " + e.message));
|
||||
|
||||
return Promise.all([
|
||||
isFail(() => waitForIceConnected(test, test.pcLocal), "ICE failed", "Local ICE"),
|
||||
isFail(() => waitForIceConnected(test, test.pcRemote), "ICE failed", "Remote ICE")
|
||||
])
|
||||
.then(() => ok(true, "ICE on both sides must fail."));
|
||||
}
|
||||
|
||||
var pushPrefs = (...p) => new Promise(r => SpecialPowers.pushPrefEnv({set: p}, r));
|
||||
var test;
|
||||
|
||||
runNetworkTest(options =>
|
||||
pushPrefs(['media.peerconnection.ice.stun_client_maximum_transmits', 3],
|
||||
['media.peerconnection.ice.trickle_grace_period', 5000]).then(() => {
|
||||
options = options || {};
|
||||
options.config_local = options.config_local || {};
|
||||
var servers = options.config_local.iceServers || [];
|
||||
// remove any turn servers
|
||||
options.config_local.iceServers = servers.filter(server =>
|
||||
server.urls.every(u => !u.toLowerCase().startsWith('turn')));
|
||||
|
||||
// Here's the setting we're testing. Comment out and this test should fail:
|
||||
options.config_local.iceTransportPolicy = "relay";
|
||||
|
||||
test = new PeerConnectionTest(options);
|
||||
test.setMediaConstraints([{audio: true}, {video: true}],
|
||||
[{audio: true}, {video: true}]);
|
||||
test.chain.remove("PC_LOCAL_SETUP_ICE_LOGGER"); // Needed to suppress failing
|
||||
test.chain.remove("PC_REMOTE_SETUP_ICE_LOGGER"); // on ICE-failure.
|
||||
test.chain.insertAfter("PC_LOCAL_SETUP_ICE_HANDLER", PC_LOCAL_NO_CANDIDATES);
|
||||
test.chain.replace("PC_LOCAL_WAIT_FOR_ICE_CONNECTED", PC_BOTH_WAIT_FOR_ICE_FAILED);
|
||||
test.chain.removeAfter("PC_BOTH_WAIT_FOR_ICE_FAILED");
|
||||
test.run();
|
||||
}));
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3153,8 +3153,7 @@ PluginProfilerObserver::Observe(nsISupports *aSubject,
|
||||
} else if (!strcmp(aTopic, "profiler-stopped")) {
|
||||
mPmp->StopProfiler();
|
||||
} else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
|
||||
RefPtr<ProfileGatherer> gatherer = static_cast<ProfileGatherer*>(aSubject);
|
||||
mPmp->GatherAsyncProfile(gatherer);
|
||||
mPmp->GatherAsyncProfile();
|
||||
} else if (!strcmp(aTopic, "profiler-subprocess")) {
|
||||
nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
|
||||
mPmp->GatheredAsyncProfile(pse);
|
||||
|
||||
@@ -33,8 +33,9 @@
|
||||
if (expectingLoads > 0) {
|
||||
expectingLoads--;
|
||||
}
|
||||
if (!expectingLoads && !expectingErrors) {
|
||||
if (!expectingLoads && !expectingErrors && afterExpectCallback) {
|
||||
setTimeout(afterExpectCallback, 0);
|
||||
afterExpectCallback = null;
|
||||
}
|
||||
}
|
||||
function onImgError() {
|
||||
@@ -42,8 +43,9 @@
|
||||
if (expectingErrors > 0) {
|
||||
expectingErrors--;
|
||||
}
|
||||
if (!expectingLoads && !expectingErrors) {
|
||||
if (!expectingLoads && !expectingErrors && afterExpectCallback) {
|
||||
setTimeout(afterExpectCallback, 0);
|
||||
afterExpectCallback = null;
|
||||
}
|
||||
}
|
||||
function expectEvents(loads, errors, callback) {
|
||||
@@ -150,7 +152,7 @@
|
||||
expectEvents(0, 0, nextTest);
|
||||
});
|
||||
|
||||
// Re-binding image to document should be a no-op
|
||||
// re-binding the image to the document should be a no-op
|
||||
tests.push(function () {
|
||||
info("test 8");
|
||||
document.body.appendChild(img);
|
||||
@@ -167,19 +169,20 @@
|
||||
|
||||
expectEvents(1, 0, function() {
|
||||
is(img.currentSrc, testPNG50, "Should now have testPNG50 as current request");
|
||||
SpecialPowers.pushPrefEnv({'set': [ ["layout.css.devPixelsPerPx", "2.0"] ] },
|
||||
function() {
|
||||
// We don't currently dynamically switch, but doing so is
|
||||
// up to the UA so we may in the future. In which case
|
||||
// this test needs to be changed.
|
||||
is(img.currentSrc, testPNG50, "Should now have testPNG50 as current request");
|
||||
|
||||
// The preference change will trigger a load, as the image will change
|
||||
SpecialPowers.pushPrefEnv({'set': [ ["layout.css.devPixelsPerPx", "2.0"] ] });
|
||||
expectEvents(1, 0, function() {
|
||||
is(img.currentSrc, testPNG200, "Should now have testPNG200 as current request");
|
||||
img.src = img.src;
|
||||
is(img.currentSrc, testPNG50, "Should still have testPNG50 as current request");
|
||||
is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request");
|
||||
// img.src = img.src is special-cased by the spec. It should always
|
||||
// trigger an load event
|
||||
expectEvents(1, 0, function() {
|
||||
is(img.currentSrc, testPNG200, "Should now have testPNG200 as current request");
|
||||
nextTest();
|
||||
is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request");
|
||||
expectEvents(0, 0, nextTest);
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
@@ -206,6 +209,10 @@
|
||||
(tests.shift())();
|
||||
}, 0);
|
||||
} else {
|
||||
// Remove the event listeners to prevent the prefenv being popped from
|
||||
// causing test failures.
|
||||
img.removeEventListener("load", onImgLoad);
|
||||
img.removeEventListener("error", onImgError);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ FONT_PREF_LANG(Gujarati, "x-gujr", x_gujr),
|
||||
FONT_PREF_LANG(Gurmukhi, "x-guru", x_guru),
|
||||
FONT_PREF_LANG(Khmer, "x-khmr", x_khmr),
|
||||
FONT_PREF_LANG(Malayalam, "x-mlym", x_mlym),
|
||||
FONT_PREF_LANG(Mathematics, "x-math", x_math),
|
||||
FONT_PREF_LANG(Oriya, "x-orya", x_orya),
|
||||
FONT_PREF_LANG(Telugu, "x-telu", x_telu),
|
||||
FONT_PREF_LANG(Kannada, "x-knda", x_knda),
|
||||
|
||||
@@ -605,6 +605,12 @@ public:
|
||||
|
||||
virtual void FlushContentDrawing() {}
|
||||
|
||||
// If a device reset has occurred, update the necessary platform backend
|
||||
// bits.
|
||||
virtual bool UpdateForDeviceReset() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method, creates a draw target for a specific Azure backend.
|
||||
* Used by CreateOffscreenDrawTarget.
|
||||
|
||||
@@ -1195,6 +1195,30 @@ gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason)
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL CALLBACK
|
||||
InvalidateWindowForDeviceReset(HWND aWnd, LPARAM aMsg)
|
||||
{
|
||||
RedrawWindow(aWnd, nullptr, nullptr,
|
||||
RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_FRAME);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
gfxWindowsPlatform::UpdateForDeviceReset()
|
||||
{
|
||||
if (!DidRenderingDeviceReset()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trigger an ::OnPaint for each window.
|
||||
::EnumThreadWindows(GetCurrentThreadId(),
|
||||
InvalidateWindowForDeviceReset,
|
||||
0);
|
||||
|
||||
gfxCriticalNote << "Detected rendering device reset on refresh";
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &mem_size)
|
||||
{
|
||||
|
||||
@@ -213,7 +213,8 @@ public:
|
||||
*/
|
||||
virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) override;
|
||||
|
||||
virtual bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override;
|
||||
bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override;
|
||||
bool UpdateForDeviceReset() override;
|
||||
|
||||
mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) override;
|
||||
|
||||
|
||||
+4
-4
@@ -302,14 +302,14 @@ static inline char* js_strdup(const char* s)
|
||||
* Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
|
||||
* or the build will break.
|
||||
*/
|
||||
#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
|
||||
#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS) \
|
||||
template <class T, typename... Args> \
|
||||
QUALIFIERS T * \
|
||||
NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
|
||||
void* memory = ALLOCATOR(sizeof(T)); \
|
||||
return memory \
|
||||
? new(memory) T(mozilla::Forward<Args>(args)...) \
|
||||
: nullptr; \
|
||||
return MOZ_LIKELY(memory) \
|
||||
? new(memory) T(mozilla::Forward<Args>(args)...) \
|
||||
: nullptr; \
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -14,7 +14,7 @@ function ModuleGetExportedNames(exportStarSet = [])
|
||||
let module = this;
|
||||
|
||||
// Step 2
|
||||
if (module in exportStarSet)
|
||||
if (callFunction(ArrayIncludes, exportStarSet, module))
|
||||
return [];
|
||||
|
||||
// Step 3
|
||||
@@ -47,7 +47,7 @@ function ModuleGetExportedNames(exportStarSet = [])
|
||||
exportStarSet);
|
||||
for (let j = 0; j < starNames.length; j++) {
|
||||
let n = starNames[j];
|
||||
if (n !== "default" && !(n in exportedNames))
|
||||
if (n !== "default" && !callFunction(ArrayIncludes, exportedNames, n))
|
||||
_DefineDataProperty(exportedNames, namesCount++, n);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ function ModuleResolveExport(exportName, resolveSet = [], exportStarSet = [])
|
||||
}
|
||||
|
||||
// Step 7
|
||||
if (module in exportStarSet)
|
||||
if (callFunction(ArrayIncludes, exportStarSet, module))
|
||||
return null;
|
||||
|
||||
// Step 8
|
||||
@@ -214,9 +214,9 @@ function ModuleDeclarationInstantiation()
|
||||
let e = indirectExportEntries[i];
|
||||
let resolution = callFunction(module.resolveExport, module, e.exportName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT);
|
||||
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT, e.exportName);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT);
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, e.exportName);
|
||||
}
|
||||
|
||||
// Step 12
|
||||
@@ -231,9 +231,9 @@ function ModuleDeclarationInstantiation()
|
||||
let resolution = callFunction(importedModule.resolveExport, importedModule,
|
||||
imp.importName);
|
||||
if (resolution === null)
|
||||
ThrowSyntaxError(JSMSG_MISSING_IMPORT);
|
||||
ThrowSyntaxError(JSMSG_MISSING_IMPORT, imp.importName);
|
||||
if (resolution === "ambiguous")
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT);
|
||||
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT, imp.importName);
|
||||
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
using namespace js;
|
||||
using namespace js::frontend;
|
||||
|
||||
typedef JS::Rooted<ImportEntryObject*> RootedImportEntry;
|
||||
typedef JS::Rooted<ExportEntryObject*> RootedExportEntry;
|
||||
|
||||
template<typename T, Value ValueGetter(T* obj)>
|
||||
static bool
|
||||
ModuleValueGetterImpl(JSContext* cx, const CallArgs& args)
|
||||
@@ -121,7 +118,7 @@ ImportEntryObject::create(JSContext* cx,
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
RootedImportEntry self(cx, &obj->as<ImportEntryObject>());
|
||||
RootedImportEntryObject self(cx, &obj->as<ImportEntryObject>());
|
||||
self->initReservedSlot(ModuleRequestSlot, StringValue(moduleRequest));
|
||||
self->initReservedSlot(ImportNameSlot, StringValue(importName));
|
||||
self->initReservedSlot(LocalNameSlot, StringValue(localName));
|
||||
@@ -194,7 +191,7 @@ ExportEntryObject::create(JSContext* cx,
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
RootedExportEntry self(cx, &obj->as<ExportEntryObject>());
|
||||
RootedExportEntryObject self(cx, &obj->as<ExportEntryObject>());
|
||||
self->initReservedSlot(ExportNameSlot, StringOrNullValue(maybeExportName));
|
||||
self->initReservedSlot(ModuleRequestSlot, StringOrNullValue(maybeModuleRequest));
|
||||
self->initReservedSlot(ImportNameSlot, StringOrNullValue(maybeImportName));
|
||||
@@ -896,8 +893,9 @@ js::InitModuleClasses(JSContext* cx, HandleObject obj)
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ModuleBuilder
|
||||
|
||||
ModuleBuilder::ModuleBuilder(JSContext* cx)
|
||||
ModuleBuilder::ModuleBuilder(JSContext* cx, HandleModuleObject module)
|
||||
: cx_(cx),
|
||||
module_(cx, module),
|
||||
requestedModules_(cx, AtomVector(cx)),
|
||||
importedBoundNames_(cx, AtomVector(cx)),
|
||||
importEntries_(cx, ImportEntryVector(cx)),
|
||||
@@ -908,7 +906,7 @@ ModuleBuilder::ModuleBuilder(JSContext* cx)
|
||||
{}
|
||||
|
||||
bool
|
||||
ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject module)
|
||||
ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode)
|
||||
{
|
||||
MOZ_ASSERT(moduleNode->isKind(PNK_MODULE));
|
||||
|
||||
@@ -940,21 +938,21 @@ ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject
|
||||
}
|
||||
|
||||
for (const auto& e : exportEntries_) {
|
||||
RootedExportEntry exp(cx_, e);
|
||||
RootedExportEntryObject exp(cx_, e);
|
||||
if (!exp->moduleRequest()) {
|
||||
RootedImportEntry importEntry(cx_, importEntryFor(exp->localName()));
|
||||
RootedImportEntryObject importEntry(cx_, importEntryFor(exp->localName()));
|
||||
if (!importEntry) {
|
||||
if (!localExportEntries_.append(exp))
|
||||
if (!appendLocalExportEntry(exp))
|
||||
return false;
|
||||
} else {
|
||||
if (importEntry->importName() == cx_->names().star) {
|
||||
if (!localExportEntries_.append(exp))
|
||||
if (!appendLocalExportEntry(exp))
|
||||
return false;
|
||||
} else {
|
||||
RootedAtom exportName(cx_, exp->exportName());
|
||||
RootedAtom moduleRequest(cx_, importEntry->moduleRequest());
|
||||
RootedAtom importName(cx_, importEntry->importName());
|
||||
RootedExportEntry exportEntry(cx_);
|
||||
RootedExportEntryObject exportEntry(cx_);
|
||||
exportEntry = ExportEntryObject::create(cx_,
|
||||
exportName,
|
||||
moduleRequest,
|
||||
@@ -994,7 +992,7 @@ ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject
|
||||
if (!starExportEntries)
|
||||
return false;
|
||||
|
||||
module->initImportExportData(requestedModules,
|
||||
module_->initImportExportData(requestedModules,
|
||||
importEntries,
|
||||
localExportEntries,
|
||||
indirectExportEntries,
|
||||
@@ -1003,6 +1001,19 @@ ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::appendLocalExportEntry(HandleExportEntryObject exp)
|
||||
{
|
||||
if (!module_->initialEnvironment().lookup(cx_, AtomToId(exp->localName()))) {
|
||||
JSAutoByteString str;
|
||||
str.encodeLatin1(cx_, exp->localName());
|
||||
JS_ReportErrorNumber(cx_, GetErrorMessage, nullptr, JSMSG_MISSING_EXPORT, str.ptr());
|
||||
return false;
|
||||
}
|
||||
|
||||
return localExportEntries_.append(exp);
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::processImport(frontend::ParseNode* pn)
|
||||
{
|
||||
@@ -1025,7 +1036,7 @@ ModuleBuilder::processImport(frontend::ParseNode* pn)
|
||||
if (!importedBoundNames_.append(localName))
|
||||
return false;
|
||||
|
||||
RootedImportEntry importEntry(cx_);
|
||||
RootedImportEntryObject importEntry(cx_);
|
||||
importEntry = ImportEntryObject::create(cx_, module, importName, localName);
|
||||
if (!importEntry || !importEntries_.append(importEntry))
|
||||
return false;
|
||||
@@ -1049,7 +1060,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
||||
MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC));
|
||||
RootedAtom localName(cx_, spec->pn_left->pn_atom);
|
||||
RootedAtom exportName(cx_, spec->pn_right->pn_atom);
|
||||
if (!appendLocalExportEntry(exportName, localName))
|
||||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -1058,7 +1069,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
||||
RootedFunction func(cx_, kid->pn_funbox->function());
|
||||
RootedAtom localName(cx_, func->atom());
|
||||
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
|
||||
if (!appendLocalExportEntry(exportName, localName))
|
||||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -1068,7 +1079,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
||||
MOZ_ASSERT(cls.names());
|
||||
RootedAtom localName(cx_, cls.names()->innerBinding()->pn_atom);
|
||||
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
|
||||
if (!appendLocalExportEntry(exportName, localName))
|
||||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -1083,7 +1094,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
||||
MOZ_ASSERT(var->isKind(PNK_NAME));
|
||||
RootedAtom localName(cx_, var->pn_atom);
|
||||
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
|
||||
if (!appendLocalExportEntry(exportName, localName))
|
||||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -1093,7 +1104,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
|
||||
MOZ_ASSERT(isDefault);
|
||||
RootedAtom localName(cx_, cx_->names().starDefaultStar);
|
||||
RootedAtom exportName(cx_, cx_->names().default_);
|
||||
if (!appendLocalExportEntry(exportName, localName))
|
||||
if (!appendExportEntry(exportName, localName))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -1115,12 +1126,12 @@ ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
|
||||
if (spec->isKind(PNK_EXPORT_SPEC)) {
|
||||
RootedAtom bindingName(cx_, spec->pn_left->pn_atom);
|
||||
RootedAtom exportName(cx_, spec->pn_right->pn_atom);
|
||||
if (!appendIndirectExportEntry(exportName, module, bindingName))
|
||||
if (!appendExportFromEntry(exportName, module, bindingName))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(spec->isKind(PNK_EXPORT_BATCH_SPEC));
|
||||
RootedAtom importName(cx_, cx_->names().star);
|
||||
if (!appendIndirectExportEntry(nullptr, module, importName))
|
||||
if (!appendExportFromEntry(nullptr, module, importName))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1139,7 +1150,7 @@ ModuleBuilder::importEntryFor(JSAtom* localName)
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::appendLocalExportEntry(HandleAtom exportName, HandleAtom localName)
|
||||
ModuleBuilder::appendExportEntry(HandleAtom exportName, HandleAtom localName)
|
||||
{
|
||||
Rooted<ExportEntryObject*> exportEntry(cx_);
|
||||
exportEntry = ExportEntryObject::create(cx_, exportName, nullptr, nullptr, localName);
|
||||
@@ -1147,8 +1158,8 @@ ModuleBuilder::appendLocalExportEntry(HandleAtom exportName, HandleAtom localNam
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleBuilder::appendIndirectExportEntry(HandleAtom exportName, HandleAtom moduleRequest,
|
||||
HandleAtom importName)
|
||||
ModuleBuilder::appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
|
||||
HandleAtom importName)
|
||||
{
|
||||
Rooted<ExportEntryObject*> exportEntry(cx_);
|
||||
exportEntry = ExportEntryObject::create(cx_, exportName, moduleRequest, importName, nullptr);
|
||||
|
||||
@@ -54,6 +54,9 @@ class ImportEntryObject : public NativeObject
|
||||
JSAtom* localName();
|
||||
};
|
||||
|
||||
typedef Rooted<ImportEntryObject*> RootedImportEntryObject;
|
||||
typedef Handle<ImportEntryObject*> HandleImportEntryObject;
|
||||
|
||||
class ExportEntryObject : public NativeObject
|
||||
{
|
||||
public:
|
||||
@@ -80,6 +83,9 @@ class ExportEntryObject : public NativeObject
|
||||
JSAtom* localName();
|
||||
};
|
||||
|
||||
typedef Rooted<ExportEntryObject*> RootedExportEntryObject;
|
||||
typedef Handle<ExportEntryObject*> HandleExportEntryObject;
|
||||
|
||||
class IndirectBindingMap
|
||||
{
|
||||
public:
|
||||
@@ -268,9 +274,9 @@ class ModuleObject : public NativeObject
|
||||
class MOZ_STACK_CLASS ModuleBuilder
|
||||
{
|
||||
public:
|
||||
explicit ModuleBuilder(JSContext* cx);
|
||||
explicit ModuleBuilder(JSContext* cx, HandleModuleObject module);
|
||||
|
||||
bool buildAndInit(frontend::ParseNode* pn, HandleModuleObject module);
|
||||
bool buildAndInit(frontend::ParseNode* pn);
|
||||
|
||||
private:
|
||||
using AtomVector = TraceableVector<JSAtom*>;
|
||||
@@ -281,8 +287,8 @@ class MOZ_STACK_CLASS ModuleBuilder
|
||||
using RootedExportEntryVector = JS::Rooted<ExportEntryVector> ;
|
||||
|
||||
JSContext* cx_;
|
||||
RootedModuleObject module_;
|
||||
RootedAtomVector requestedModules_;
|
||||
|
||||
RootedAtomVector importedBoundNames_;
|
||||
RootedImportEntryVector importEntries_;
|
||||
RootedExportEntryVector exportEntries_;
|
||||
@@ -296,12 +302,14 @@ class MOZ_STACK_CLASS ModuleBuilder
|
||||
|
||||
ImportEntryObject* importEntryFor(JSAtom* localName);
|
||||
|
||||
bool appendLocalExportEntry(HandleAtom exportName, HandleAtom localName);
|
||||
bool appendIndirectExportEntry(HandleAtom exportName, HandleAtom moduleRequest,
|
||||
HandleAtom importName);
|
||||
bool appendExportEntry(HandleAtom exportName, HandleAtom localName);
|
||||
bool appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
|
||||
HandleAtom importName);
|
||||
|
||||
bool maybeAppendRequestedModule(HandleAtom module);
|
||||
|
||||
bool appendLocalExportEntry(HandleExportEntryObject exp);
|
||||
|
||||
template <typename T>
|
||||
ArrayObject* createArray(const TraceableVector<T>& vector);
|
||||
};
|
||||
|
||||
@@ -1010,6 +1010,10 @@ static const JSFunctionSpec object_static_methods[] = {
|
||||
JS_FN("setPrototypeOf", obj_setPrototypeOf, 2, 0),
|
||||
JS_FN("getOwnPropertyDescriptor", obj_getOwnPropertyDescriptor,2, 0),
|
||||
JS_FN("keys", obj_keys, 1, 0),
|
||||
#ifndef RELEASE_BUILD
|
||||
JS_SELF_HOSTED_FN("values", "ObjectValues", 1, JSPROP_DEFINE_LATE),
|
||||
JS_SELF_HOSTED_FN("entries", "ObjectEntries", 1, JSPROP_DEFINE_LATE),
|
||||
#endif
|
||||
JS_FN("is", obj_is, 2, 0),
|
||||
JS_FN("defineProperty", obj_defineProperty, 3, 0),
|
||||
JS_FN("defineProperties", obj_defineProperties, 2, 0),
|
||||
|
||||
@@ -134,3 +134,48 @@ function ObjectLookupGetter(name) {
|
||||
} while (object !== null);
|
||||
}
|
||||
|
||||
// Draft proposal http://tc39.github.io/proposal-object-values-entries/#Object.values
|
||||
function ObjectValues(O) {
|
||||
// Steps 1-2.
|
||||
var object = ToObject(O);
|
||||
|
||||
// Steps 3-4.
|
||||
// EnumerableOwnProperties is inlined here.
|
||||
var keys = OwnPropertyKeys(object, JSITER_OWNONLY | JSITER_HIDDEN);
|
||||
var values = [];
|
||||
var valuesCount = 0;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
if (!callFunction(std_Object_propertyIsEnumerable, object, key))
|
||||
continue;
|
||||
|
||||
var value = object[key];
|
||||
_DefineDataProperty(values, valuesCount++, value);
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
return values;
|
||||
}
|
||||
|
||||
// Draft proposal http://tc39.github.io/proposal-object-values-entries/#Object.entries
|
||||
function ObjectEntries(O) {
|
||||
// Steps 1-2.
|
||||
var object = ToObject(O);
|
||||
|
||||
// Steps 3-4.
|
||||
// EnumerableOwnProperties is inlined here.
|
||||
var keys = OwnPropertyKeys(object, JSITER_OWNONLY | JSITER_HIDDEN);
|
||||
var entries = [];
|
||||
var entriesCount = 0;
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
if (!callFunction(std_Object_propertyIsEnumerable, object, key))
|
||||
continue;
|
||||
|
||||
var value = object[key];
|
||||
_DefineDataProperty(entries, entriesCount++, [key, value]);
|
||||
}
|
||||
|
||||
// Step 5.
|
||||
return entries;
|
||||
}
|
||||
|
||||
@@ -927,6 +927,7 @@ js::ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
|
||||
return RegExpRunStatus_Error;
|
||||
} else if (reobj->needUpdateLastIndex()) {
|
||||
/* Steps 18.a-b. */
|
||||
MOZ_ASSERT(matches && !matches->empty());
|
||||
if (!SetLastIndex(cx, reobj, (*matches)[0].limit))
|
||||
return RegExpRunStatus_Error;
|
||||
}
|
||||
|
||||
@@ -298,8 +298,8 @@ GC(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
char buf[256] = { '\0' };
|
||||
#ifndef JS_MORE_DETERMINISTIC
|
||||
JS_snprintf(buf, sizeof(buf), "before %lu, after %lu\n",
|
||||
(unsigned long)preBytes, (unsigned long)cx->runtime()->gc.usage.gcBytes());
|
||||
JS_snprintf(buf, sizeof(buf), "before %" PRIuSIZE ", after %" PRIuSIZE "\n",
|
||||
preBytes, cx->runtime()->gc.usage.gcBytes());
|
||||
#endif
|
||||
JSString* str = JS_NewStringCopyZ(cx, buf);
|
||||
if (!str)
|
||||
|
||||
@@ -650,14 +650,14 @@ function ArrayShorthand(...dims) {
|
||||
if (!IsObject(this) || !ObjectIsTypeDescr(this))
|
||||
ThrowTypeError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
|
||||
var T = GetTypedObjectModule();
|
||||
var AT = GetTypedObjectModule().ArrayType;
|
||||
|
||||
if (dims.length == 0)
|
||||
ThrowTypeError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
|
||||
var accum = this;
|
||||
for (var i = dims.length - 1; i >= 0; i--)
|
||||
accum = new T.ArrayType(accum, dims[i]);
|
||||
accum = new AT(accum, dims[i]);
|
||||
return accum;
|
||||
}
|
||||
|
||||
@@ -1059,7 +1059,11 @@ function MapTypedSeqImpl(inArray, depth, outputType, func) {
|
||||
}
|
||||
|
||||
function DoMapTypedSeqDepthN() {
|
||||
var indices = new Uint32Array(depth);
|
||||
// Simulate Uint32Array(depth) with a dumber (and more accessible)
|
||||
// datastructure.
|
||||
var indices = new List();
|
||||
for (var i = 0; i < depth; i++)
|
||||
callFunction(std_Array_push, indices, 0);
|
||||
|
||||
for (var i = 0; i < totalLength; i++) {
|
||||
// Prepare input element and out pointer
|
||||
@@ -1156,9 +1160,9 @@ function FilterTypedSeqImpl(array, func) {
|
||||
inOffset += size;
|
||||
}
|
||||
|
||||
var T = GetTypedObjectModule();
|
||||
var AT = GetTypedObjectModule().ArrayType;
|
||||
|
||||
var resultType = new T.ArrayType(elementType, count);
|
||||
var resultType = new AT(elementType, count);
|
||||
var result = new resultType();
|
||||
for (var i = 0, j = 0; i < array.length; i++) {
|
||||
if (GET_BIT(flags, i))
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// Assertions, defined here instead of in the header above to make `assert`
|
||||
// invisible to C++.
|
||||
#ifdef DEBUG
|
||||
#define assert(b, info) if (!(b)) AssertionFailed(info)
|
||||
#define assert(b, info) if (!(b)) AssertionFailed(__FILE__ + ":" + __LINE__ + ": " + info)
|
||||
#else
|
||||
#define assert(b, info) // Elided assertion.
|
||||
#endif
|
||||
|
||||
@@ -135,9 +135,6 @@ var ignoreFunctions = {
|
||||
"JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoSuppressGCAnalysis instead
|
||||
"uint8 NS_IsMainThread()" : true,
|
||||
|
||||
// Bug 1056410 - devirtualization prevents the standard nsISupports::Release heuristic from working
|
||||
"uint32 nsXPConnect::Release()" : true,
|
||||
|
||||
// Has an indirect call under it by the name "__f", which seemed too
|
||||
// generic to ignore by itself.
|
||||
"void* std::_Locale_impl::~_Locale_impl(int32)" : true,
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 4431740,
|
||||
"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
|
||||
"size": 12057960,
|
||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"unpack": true
|
||||
|
||||
@@ -601,8 +601,8 @@ ModuleObject* BytecodeCompiler::compileModule()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ModuleBuilder builder(cx->asJSContext());
|
||||
if (!builder.buildAndInit(pn, module))
|
||||
ModuleBuilder builder(cx->asJSContext(), module);
|
||||
if (!builder.buildAndInit(pn))
|
||||
return nullptr;
|
||||
|
||||
parser->handler.freeTree(pn);
|
||||
|
||||
@@ -4413,13 +4413,25 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption)
|
||||
* i' to be hoisted out of the loop.
|
||||
*/
|
||||
MOZ_ASSERT(binding->isOp(JSOP_NOP));
|
||||
MOZ_ASSERT(emitOption != DefineVars && emitOption != AnnexB);
|
||||
MOZ_ASSERT(emitOption != DefineVars);
|
||||
MOZ_ASSERT_IF(emitOption == AnnexB, binding->pn_left->isKind(PNK_NAME));
|
||||
|
||||
/*
|
||||
* To allow the front end to rewrite var f = x; as f = x; when a
|
||||
* function f(){} precedes the var, detect simple name assignment
|
||||
* here and initialize the name.
|
||||
*/
|
||||
// To allow the front end to rewrite |var f = x;| as |f = x;| when a
|
||||
// |function f(){}| precedes the var, detect simple name assignment
|
||||
// here and initialize the name.
|
||||
//
|
||||
// There is a corner case where a function declaration synthesizes
|
||||
// an Annex B declaration, which in turn gets rewritten later as a
|
||||
// simple assignment due to hoisted function declaration of the
|
||||
// same name. For example,
|
||||
//
|
||||
// {
|
||||
// // Synthesizes an Annex B declaration because no 'f' binding
|
||||
// // yet exists. This later gets rewritten as an assignment when
|
||||
// // the outer function 'f' gets hoisted.
|
||||
// function f() {}
|
||||
// }
|
||||
// function f() {}
|
||||
if (binding->pn_left->isKind(PNK_NAME)) {
|
||||
if (!emitSingleVariable(pn, binding->pn_left, binding->pn_right, emitOption))
|
||||
return false;
|
||||
@@ -6728,6 +6740,16 @@ BytecodeEmitter::emitReturn(ParseNode* pn)
|
||||
if (!emit1((isGenerator || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
|
||||
return false;
|
||||
|
||||
// Make sure that we emit this before popping the blocks in prepareForNonLocalJump,
|
||||
// to ensure that the error is thrown while the scope-chain is still intact.
|
||||
if (isDerivedClassConstructor) {
|
||||
BindingIter bi = Bindings::thisBinding(cx, script);
|
||||
if (!emitLoadFromTopScope(bi))
|
||||
return false;
|
||||
if (!emit1(JSOP_CHECKRETURN))
|
||||
return false;
|
||||
}
|
||||
|
||||
NonLocalExitScope nle(this);
|
||||
|
||||
if (!nle.prepareForNonLocalJump(nullptr))
|
||||
@@ -6745,11 +6767,6 @@ BytecodeEmitter::emitReturn(ParseNode* pn)
|
||||
return false;
|
||||
} else if (isDerivedClassConstructor) {
|
||||
MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
|
||||
BindingIter bi = Bindings::thisBinding(cx, script);
|
||||
if (!emitLoadFromTopScope(bi))
|
||||
return false;
|
||||
if (!emit1(JSOP_CHECKRETURN))
|
||||
return false;
|
||||
if (!emit1(JSOP_RETRVAL))
|
||||
return false;
|
||||
} else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
|
||||
@@ -7145,6 +7162,18 @@ BytecodeEmitter::emitDeleteExpression(ParseNode* node)
|
||||
return emit1(JSOP_TRUE);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitDebugOnlyCheckSelfHosted()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (emitterMode == BytecodeEmitter::SelfHosting) {
|
||||
if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
|
||||
{
|
||||
@@ -7157,22 +7186,27 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
|
||||
//
|
||||
// argc is set to the amount of actually emitted args and the
|
||||
// emitting of args below is disabled by setting emitArgs to false.
|
||||
ParseNode* pn2 = pn->pn_head;
|
||||
const char* errorName = pn2->name() == cx->names().callFunction ?
|
||||
"callFunction" : "callContentFunction";
|
||||
if (pn->pn_count < 3) {
|
||||
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "callFunction", "1", "s");
|
||||
reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pn->getOp() != JSOP_CALL) {
|
||||
reportError(pn, JSMSG_NOT_CONSTRUCTOR, errorName);
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseNode* pn2 = pn->pn_head;
|
||||
ParseNode* funNode = pn2->pn_next;
|
||||
if (!emitTree(funNode))
|
||||
return false;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (pn2->name() != cx->names().callContentFunction) {
|
||||
if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
|
||||
if (!emitDebugOnlyCheckSelfHosted())
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
ParseNode* thisArg = funNode->pn_next;
|
||||
if (!emitTree(thisArg))
|
||||
@@ -7272,8 +7306,9 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
|
||||
// We shouldn't see foo(bar) = x in self-hosted code.
|
||||
MOZ_ASSERT(!(pn->pn_xflags & PNX_SETCALL));
|
||||
|
||||
// Calls to "forceInterpreter", "callFunction" or "resumeGenerator"
|
||||
// in self-hosted code generate inline bytecode.
|
||||
// Calls to "forceInterpreter", "callFunction",
|
||||
// "callContentFunction", or "resumeGenerator" in self-hosted
|
||||
// code generate inline bytecode.
|
||||
if (pn2->name() == cx->names().callFunction ||
|
||||
pn2->name() == cx->names().callContentFunction)
|
||||
{
|
||||
@@ -7296,6 +7331,10 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
|
||||
if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!emitDebugOnlyCheckSelfHosted())
|
||||
return false;
|
||||
|
||||
break;
|
||||
case PNK_ELEM:
|
||||
if (pn2->as<PropertyByValue>().isSuper()) {
|
||||
@@ -7309,6 +7348,10 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!emitDebugOnlyCheckSelfHosted())
|
||||
return false;
|
||||
|
||||
break;
|
||||
case PNK_FUNCTION:
|
||||
/*
|
||||
|
||||
@@ -608,6 +608,7 @@ struct BytecodeEmitter
|
||||
bool emitConditionalExpression(ConditionalExpression& conditional);
|
||||
|
||||
bool emitCallOrNew(ParseNode* pn);
|
||||
bool emitDebugOnlyCheckSelfHosted();
|
||||
bool emitSelfHostedCallFunction(ParseNode* pn);
|
||||
bool emitSelfHostedResumeGenerator(ParseNode* pn);
|
||||
bool emitSelfHostedForceInterpreter(ParseNode* pn);
|
||||
|
||||
@@ -1163,22 +1163,32 @@ ObjectBox::asModuleBox()
|
||||
return static_cast<ModuleBox*>(this);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
ObjectBox::TraceList(JSTracer* trc, ObjectBox* listHead)
|
||||
{
|
||||
for (ObjectBox* box = listHead; box; box = box->traceLink)
|
||||
box->trace(trc);
|
||||
}
|
||||
|
||||
void
|
||||
ObjectBox::trace(JSTracer* trc)
|
||||
{
|
||||
ObjectBox* box = this;
|
||||
while (box) {
|
||||
TraceRoot(trc, &box->object, "parser.object");
|
||||
if (box->isFunctionBox()) {
|
||||
FunctionBox* funbox = box->asFunctionBox();
|
||||
funbox->bindings.trace(trc);
|
||||
if (funbox->enclosingStaticScope_)
|
||||
TraceRoot(trc, &funbox->enclosingStaticScope_, "funbox-enclosingStaticScope");
|
||||
} else if (box->isModuleBox()) {
|
||||
ModuleBox* modulebox = box->asModuleBox();
|
||||
modulebox->bindings.trace(trc);
|
||||
modulebox->exportNames.trace(trc);
|
||||
}
|
||||
box = box->traceLink;
|
||||
}
|
||||
TraceRoot(trc, &object, "parser.object");
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBox::trace(JSTracer* trc)
|
||||
{
|
||||
ObjectBox::trace(trc);
|
||||
bindings.trace(trc);
|
||||
if (enclosingStaticScope_)
|
||||
TraceRoot(trc, &enclosingStaticScope_, "funbox-enclosingStaticScope");
|
||||
}
|
||||
|
||||
void
|
||||
ModuleBox::trace(JSTracer* trc)
|
||||
{
|
||||
ObjectBox::trace(trc);
|
||||
bindings.trace(trc);
|
||||
exportNames.trace(trc);
|
||||
}
|
||||
|
||||
@@ -1722,7 +1722,9 @@ class ObjectBox
|
||||
FunctionBox* asFunctionBox();
|
||||
bool isModuleBox() { return object->is<ModuleObject>(); }
|
||||
ModuleBox* asModuleBox();
|
||||
void trace(JSTracer* trc);
|
||||
virtual void trace(JSTracer* trc);
|
||||
|
||||
static void TraceList(JSTracer* trc, ObjectBox* listHead);
|
||||
|
||||
protected:
|
||||
friend struct CGObjectList;
|
||||
|
||||
+31
-17
@@ -855,7 +855,7 @@ template <typename ParseHandler>
|
||||
void
|
||||
Parser<ParseHandler>::trace(JSTracer* trc)
|
||||
{
|
||||
traceListHead->trace(trc);
|
||||
ObjectBox::TraceList(trc, traceListHead);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -5050,8 +5050,32 @@ template<>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::addExportName(JSAtom* exportName)
|
||||
{
|
||||
JS_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return SyntaxParseHandler::NodeFailure;
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<FullParseHandler>::addExportNamesForDeclaration(ParseNode* node)
|
||||
{
|
||||
MOZ_ASSERT(node->isArity(PN_LIST));
|
||||
for (ParseNode* binding = node->pn_head; binding; binding = binding->pn_next) {
|
||||
if (binding->isKind(PNK_ASSIGN))
|
||||
binding = binding->pn_left;
|
||||
MOZ_ASSERT(binding->isKind(PNK_NAME));
|
||||
if (!addExportName(binding->pn_atom))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool
|
||||
Parser<SyntaxParseHandler>::addExportNamesForDeclaration(Node node)
|
||||
{
|
||||
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
@@ -5228,15 +5252,8 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||
return null();
|
||||
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
|
||||
return null();
|
||||
|
||||
MOZ_ASSERT(kid->isArity(PN_LIST));
|
||||
for (ParseNode* var = kid->pn_head; var; var = var->pn_next) {
|
||||
if (var->isKind(PNK_ASSIGN))
|
||||
var = var->pn_left;
|
||||
MOZ_ASSERT(var->isKind(PNK_NAME));
|
||||
if (!addExportName(var->pn_atom))
|
||||
return null();
|
||||
}
|
||||
if (!addExportNamesForDeclaration(kid))
|
||||
return null();
|
||||
break;
|
||||
|
||||
case TOK_DEFAULT: {
|
||||
@@ -5280,6 +5297,8 @@ Parser<FullParseHandler>::exportDeclaration()
|
||||
kid = lexicalDeclaration(YieldIsName, tt == TOK_CONST);
|
||||
if (!kid)
|
||||
return null();
|
||||
if (!addExportNamesForDeclaration(kid))
|
||||
return null();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -8922,11 +8941,6 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
|
||||
return handler.newSetThis(thisName, nextMember);
|
||||
}
|
||||
|
||||
if (options().selfHostingMode && handler.isPropertyAccess(lhs)) {
|
||||
report(ParseError, false, null(), JSMSG_SELFHOSTED_METHOD_CALL);
|
||||
return null();
|
||||
}
|
||||
|
||||
nextMember = tt == TOK_LP ? handler.newCall() : handler.newTaggedTemplate();
|
||||
if (!nextMember)
|
||||
return null();
|
||||
|
||||
@@ -761,6 +761,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||
Node newBoundImportForCurrentName();
|
||||
bool namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet);
|
||||
bool addExportName(JSAtom* exportName);
|
||||
bool addExportNamesForDeclaration(Node node);
|
||||
|
||||
enum ClassContext { ClassStatement, ClassExpression };
|
||||
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext, DefaultHandling defaultHandling);
|
||||
|
||||
@@ -427,6 +427,8 @@ class FunctionBox : public ObjectBox, public SharedContext
|
||||
isDerivedClassConstructor() ||
|
||||
isGenerator();
|
||||
}
|
||||
|
||||
void trace(JSTracer* trc) override;
|
||||
};
|
||||
|
||||
class ModuleBox : public ObjectBox, public SharedContext
|
||||
@@ -442,6 +444,8 @@ class ModuleBox : public ObjectBox, public SharedContext
|
||||
ObjectBox* toObjectBox() override { return this; }
|
||||
ModuleObject* module() const { return &object->as<ModuleObject>(); }
|
||||
JSObject* staticScope() const override { return module(); }
|
||||
|
||||
void trace(JSTracer* trc) override;
|
||||
};
|
||||
|
||||
inline FunctionBox*
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from 'module1.js';
|
||||
export * from 'module1a.js';
|
||||
@@ -0,0 +1 @@
|
||||
export const a = 2;
|
||||
@@ -0,0 +1 @@
|
||||
export * from 'recursiveStarExport.js';
|
||||
@@ -0,0 +1,13 @@
|
||||
Function.prototype.prototype = function() {}
|
||||
|
||||
var type = TypedObject.uint8.array(4).array(4);
|
||||
var x = new type([
|
||||
[, , , 0],
|
||||
[, , , 0],
|
||||
[, , , 0],
|
||||
[, , , 0]
|
||||
]);
|
||||
|
||||
x.map(2, function(y) {
|
||||
return 0;
|
||||
});
|
||||
@@ -0,0 +1,2 @@
|
||||
// |jit-test| module; error: SyntaxError
|
||||
import { a } from "ambiguous.js";
|
||||
@@ -0,0 +1,2 @@
|
||||
// |jit-test| module; error: SyntaxError
|
||||
export { a } from "ambiguous.js";
|
||||
@@ -7,15 +7,26 @@ function testSyntaxError(source) {
|
||||
}, SyntaxError);
|
||||
}
|
||||
|
||||
// SyntexError due to duplicate exports
|
||||
testSyntaxError("export var v; export var v;");
|
||||
testSyntaxError("export var x, y, z; export var y;");
|
||||
|
||||
testSyntaxError("export let v; var w; export {w as v};");
|
||||
testSyntaxError("export const v; var w; export {w as v};");
|
||||
testSyntaxError("export var v; let w; export {w as v};");
|
||||
testSyntaxError("export var v; const w; export {w as v};");
|
||||
testSyntaxError("export default 1; export default 2;");
|
||||
testSyntaxError("export var default; export default 1;");
|
||||
testSyntaxError("export var default; export default function() {};");
|
||||
testSyntaxError("export var default; export default function foo() {};");
|
||||
testSyntaxError("export var default; export default export class { constructor() {} };");
|
||||
testSyntaxError("export var default; export default export class foo { constructor() {} };");
|
||||
|
||||
testSyntaxError("export default 1; export default function() {};");
|
||||
testSyntaxError("export default 1; export default function foo() {};");
|
||||
testSyntaxError("var v; export {v}; export {v};");
|
||||
testSyntaxError("var v, x; export {v}; export {x as v};");
|
||||
testSyntaxError("export default 1; export default export class { constructor() {} };");
|
||||
testSyntaxError("export default 1; export default export class foo { constructor() {} };");
|
||||
|
||||
// SyntaxError due to redeclared binding
|
||||
testSyntaxError("export let v; export let v;");
|
||||
testSyntaxError("export let x, y, z; export let y;");
|
||||
testSyntaxError("export const v = 0; export const v = 0;");
|
||||
testSyntaxError("export const x = 0, y = 0, z = 0; export const y = 0;");
|
||||
testSyntaxError("export var v; export let v;");
|
||||
testSyntaxError("export var v; export const v = 0;");
|
||||
testSyntaxError("export let v; export const v;");
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// |jit-test| module; error: SyntaxError
|
||||
import { foo } from "module1.js";
|
||||
@@ -0,0 +1,2 @@
|
||||
// |jit-test| module; error: SyntaxError
|
||||
export { foo } from "module1.js";
|
||||
@@ -0,0 +1,2 @@
|
||||
// |jit-test| module;
|
||||
import * as ns from "recursiveStarExport.js";
|
||||
@@ -0,0 +1,2 @@
|
||||
// |jit-test| module; error: SyntaxError: local binding for export 'b' not found
|
||||
export { b };
|
||||
+5
-5
@@ -317,7 +317,6 @@ MSG_DEF(JSMSG_RESERVED_ID, 1, JSEXN_SYNTAXERR, "{0} is a reserved id
|
||||
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
|
||||
MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL, 1, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level {0} declarations")
|
||||
MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups")
|
||||
MSG_DEF(JSMSG_SELFHOSTED_METHOD_CALL, 0, JSEXN_SYNTAXERR, "self-hosted code may not contain direct method calls")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
|
||||
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 0, JSEXN_SYNTAXERR, "missing ; before statement")
|
||||
@@ -526,8 +525,9 @@ MSG_DEF(JSMSG_REINIT_THIS, 0, JSEXN_REFERENCEERR, "super() called twice in
|
||||
|
||||
// Modules
|
||||
MSG_DEF(JSMSG_BAD_DEFAULT_EXPORT, 0, JSEXN_SYNTAXERR, "default export cannot be provided by export *")
|
||||
MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "indirect export not found")
|
||||
MSG_DEF(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "ambiguous indirect export")
|
||||
MSG_DEF(JSMSG_MISSING_IMPORT, 0, JSEXN_SYNTAXERR, "import not found")
|
||||
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 0, JSEXN_SYNTAXERR, "ambiguous import")
|
||||
MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT, 1, JSEXN_SYNTAXERR, "indirect export '{0}' not found")
|
||||
MSG_DEF(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, 1, JSEXN_SYNTAXERR, "ambiguous indirect export '{0}'")
|
||||
MSG_DEF(JSMSG_MISSING_IMPORT, 1, JSEXN_SYNTAXERR, "import '{0}' not found")
|
||||
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 1, JSEXN_SYNTAXERR, "ambiguous import '{0}'")
|
||||
MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT, 0, JSEXN_SYNTAXERR, "export not found for namespace")
|
||||
MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
|
||||
|
||||
+2
-1
@@ -2124,9 +2124,10 @@ TryNotes(JSContext* cx, HandleScript script, Sprinter* sp)
|
||||
Sprint(sp, "\nException table:\nkind stack start end\n");
|
||||
do {
|
||||
MOZ_ASSERT(tn->kind < ArrayLength(TryNoteNames));
|
||||
uint8_t startOff = script->pcToOffset(script->main()) + tn->start;
|
||||
Sprint(sp, " %-7s %6u %8u %8u\n",
|
||||
TryNoteNames[tn->kind], tn->stackDepth,
|
||||
tn->start, tn->start + tn->length);
|
||||
startOff, startOff + tn->length);
|
||||
} while (++tn != tnlimit);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
class base {}
|
||||
class derived extends base {
|
||||
constructor() {
|
||||
try {
|
||||
return;
|
||||
} catch (e) {
|
||||
try {
|
||||
return;
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
assertThrowsInstanceOf(() => new derived, ReferenceError);
|
||||
|
||||
if (typeof reportCompare === 'function')
|
||||
reportCompare(0,0,"OK");
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
if ("entries" in Object) {
|
||||
assertEq(Object.entries.length, 1);
|
||||
|
||||
var o, entries;
|
||||
|
||||
o = { a: 3, b: 2 };
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["a", 3], ["b", 2]]);
|
||||
|
||||
o = { get a() { return 17; }, b: 2 };
|
||||
entries = Object.entries(o),
|
||||
assertDeepEq(entries, [["a", 17], ["b", 2]]);
|
||||
|
||||
o = { __iterator__: function() { return Iterator({a: 2, b: 3}); } };
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["__iterator__", o.__iterator__]]);
|
||||
|
||||
o = { a: 1, b: 2 };
|
||||
delete o.a;
|
||||
o.a = 3;
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["b", 2], ["a", 3]]);
|
||||
|
||||
o = [0, 1, 2];
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["0", 0], ["1", 1], ["2", 2]]);
|
||||
|
||||
o = /./.exec("abc");
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["0", "a"], ["index", 0], ["input", "abc"]]);
|
||||
|
||||
o = { a: 1, b: 2, c: 3 };
|
||||
delete o.b;
|
||||
o.b = 5;
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["a", 1], ["c", 3], ["b", 5]]);
|
||||
|
||||
function f() { }
|
||||
f.prototype.p = 1;
|
||||
o = new f();
|
||||
o.g = 1;
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["g", 1]]);
|
||||
|
||||
var o = {get a() {delete this.b; return 1}, b: 2, c: 3};
|
||||
entries = Object.entries(o);
|
||||
assertDeepEq(entries, [["a", 1], ["c", 3]]);
|
||||
|
||||
assertThrowsInstanceOf(() => Object.entries(), TypeError);
|
||||
assertThrowsInstanceOf(() => Object.entries(undefined), TypeError);
|
||||
assertThrowsInstanceOf(() => Object.entries(null), TypeError);
|
||||
|
||||
assertDeepEq(Object.entries(1), []);
|
||||
assertDeepEq(Object.entries(true), []);
|
||||
if (typeof Symbol === "function")
|
||||
assertDeepEq(Object.entries(Symbol("foo")), []);
|
||||
|
||||
assertDeepEq(Object.entries("foo"), [["0", "f"], ["1", "o"], ["2", "o"]]);
|
||||
|
||||
entries = Object.entries({
|
||||
get a(){
|
||||
Object.defineProperty(this, "b", {enumerable: false});
|
||||
return "A";
|
||||
},
|
||||
b: "B"
|
||||
});
|
||||
assertDeepEq(entries, [["a", "A"]]);
|
||||
|
||||
let ownKeysCallCount = 0;
|
||||
let getOwnPropertyDescriptorCalls = [];
|
||||
let target = { a: 1, b: 2, c: 3 };
|
||||
o = new Proxy(target, {
|
||||
ownKeys() {
|
||||
ownKeysCallCount++;
|
||||
return ["c", "a"];
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
getOwnPropertyDescriptorCalls.push(key);
|
||||
return Object.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
});
|
||||
entries = Object.entries(o);
|
||||
assertEq(ownKeysCallCount, 1);
|
||||
assertDeepEq(entries, [["c", 3], ["a", 1]]);
|
||||
assertDeepEq(getOwnPropertyDescriptorCalls, ["c", "a"]);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
if ("values" in Object) {
|
||||
assertEq(Object.values.length, 1);
|
||||
|
||||
var o, values;
|
||||
|
||||
o = { a: 3, b: 2 };
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, [3, 2]);
|
||||
|
||||
o = { get a() { return 17; }, b: 2 };
|
||||
values = Object.values(o),
|
||||
assertDeepEq(values, [17, 2]);
|
||||
|
||||
o = { __iterator__: function() { return Iterator({a: 2, b: 3}); } };
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, [o.__iterator__]);
|
||||
|
||||
o = { a: 1, b: 2 };
|
||||
delete o.a;
|
||||
o.a = 3;
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, [2, 3]);
|
||||
|
||||
o = [0, 1, 2];
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, [0, 1, 2]);
|
||||
|
||||
o = /./.exec("abc");
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, ["a", 0, "abc"]);
|
||||
|
||||
o = { a: 1, b: 2, c: 3 };
|
||||
delete o.b;
|
||||
o.b = 5;
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, [1, 3, 5]);
|
||||
|
||||
function f() { }
|
||||
f.prototype.p = 1;
|
||||
o = new f();
|
||||
o.g = 1;
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, [1]);
|
||||
|
||||
var o = {get a() {delete this.b; return 1}, b: 2, c: 3};
|
||||
values = Object.values(o);
|
||||
assertDeepEq(values, [1, 3]);
|
||||
|
||||
assertThrowsInstanceOf(() => Object.values(), TypeError);
|
||||
assertThrowsInstanceOf(() => Object.values(undefined), TypeError);
|
||||
assertThrowsInstanceOf(() => Object.values(null), TypeError);
|
||||
|
||||
assertDeepEq(Object.values(1), []);
|
||||
assertDeepEq(Object.values(true), []);
|
||||
if (typeof Symbol === "function")
|
||||
assertDeepEq(Object.values(Symbol("foo")), []);
|
||||
|
||||
assertDeepEq(Object.values("foo"), ["f", "o", "o"]);
|
||||
|
||||
values = Object.values({
|
||||
get a(){
|
||||
Object.defineProperty(this, "b", {enumerable: false});
|
||||
return "A";
|
||||
},
|
||||
b: "B"
|
||||
});
|
||||
assertDeepEq(values, ["A"]);
|
||||
|
||||
let ownKeysCallCount = 0;
|
||||
let getOwnPropertyDescriptorCalls = [];
|
||||
let target = { a: 1, b: 2, c: 3 };
|
||||
o = new Proxy(target, {
|
||||
ownKeys() {
|
||||
ownKeysCallCount++;
|
||||
return ["c", "a"];
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
getOwnPropertyDescriptorCalls.push(key);
|
||||
return Object.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
});
|
||||
values = Object.values(o);
|
||||
assertEq(ownKeysCallCount, 1);
|
||||
assertDeepEq(values, [3, 1]);
|
||||
assertDeepEq(getOwnPropertyDescriptorCalls, ["c", "a"]);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
@@ -416,7 +416,6 @@ GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> globa
|
||||
return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
|
||||
InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
|
||||
InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&
|
||||
InitBareBuiltinCtor(cx, global, JSProto_Uint32Array) &&
|
||||
InitBareWeakMapCtor(cx, global) &&
|
||||
InitStopIterationClass(cx, global) &&
|
||||
InitSelfHostingCollectionIteratorFunctions(cx, global) &&
|
||||
|
||||
@@ -179,7 +179,7 @@ bool
|
||||
js::Debug_CheckSelfHosted(JSContext* cx, HandleValue fun)
|
||||
{
|
||||
#ifndef DEBUG
|
||||
MOZ_CRASH("Self hosted checks should only be done in Debug builds");
|
||||
MOZ_CRASH("self-hosted checks should only be done in Debug builds");
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(fun.isObject());
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ namespace js {
|
||||
*
|
||||
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 325;
|
||||
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 327;
|
||||
static const uint32_t XDR_BYTECODE_VERSION =
|
||||
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
|
||||
|
||||
|
||||
@@ -1628,6 +1628,8 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
|
||||
AutoRestore<TimeStamp> restoreTickStart(mTickStart);
|
||||
mTickStart = TimeStamp::Now();
|
||||
|
||||
gfxPlatform::GetPlatform()->UpdateForDeviceReset();
|
||||
|
||||
/*
|
||||
* The timer holds a reference to |this| while calling |Notify|.
|
||||
* However, implementations of |WillRefresh| are permitted to destroy
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
EXPORTS.mtransport += [
|
||||
'../dtlsidentity.h',
|
||||
'../m_cpp_utils.h',
|
||||
|
||||
@@ -63,7 +63,6 @@ if CONFIG['OS_TARGET'] in ['Darwin', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD'
|
||||
]
|
||||
elif CONFIG['OS_TARGET'] == 'Linux':
|
||||
DEFINES['LINUX'] = True
|
||||
DEFINES['USE_INTERFACE_PRIORITIZER'] = True
|
||||
LOCAL_INCLUDES += [
|
||||
'/media/mtransport/third_party/nrappkit/src/port/linux/include',
|
||||
]
|
||||
@@ -81,9 +80,6 @@ elif CONFIG['OS_TARGET'] == 'WINNT':
|
||||
'/media/mtransport/third_party/nrappkit/src/port/win32/include',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
DEFINES['USE_INTERFACE_PRIORITIZER'] = True
|
||||
|
||||
for var in ('HAVE_STRDUP', 'NR_SOCKET_IS_VOID_PTR'):
|
||||
DEFINES[var] = True
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
DIRS += [
|
||||
'/media/mtransport/third_party',
|
||||
'/media/mtransport/build',
|
||||
|
||||
@@ -106,6 +106,54 @@ nrappkit copyright:
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "runnable_utils.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/dom/TCPSocketBinding.h"
|
||||
#include "nsITCPSocketCallback.h"
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
// csi_platform.h deep in nrappkit defines LOG_INFO and LOG_WARNING
|
||||
#ifdef LOG_INFO
|
||||
#define LOG_TEMP_INFO LOG_INFO
|
||||
#undef LOG_INFO
|
||||
#endif
|
||||
#ifdef LOG_WARNING
|
||||
#define LOG_TEMP_WARNING LOG_WARNING
|
||||
#undef LOG_WARNING
|
||||
#endif
|
||||
#if defined(LOG_DEBUG)
|
||||
#define LOG_TEMP_DEBUG LOG_DEBUG
|
||||
#undef LOG_DEBUG
|
||||
#endif
|
||||
#undef strlcpy
|
||||
|
||||
// TCPSocketChild.h doesn't include TypedArray.h
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ArrayBuffer;
|
||||
}
|
||||
}
|
||||
#include "mozilla/dom/network/TCPSocketChild.h"
|
||||
|
||||
#ifdef LOG_TEMP_INFO
|
||||
#define LOG_INFO LOG_TEMP_INFO
|
||||
#endif
|
||||
#ifdef LOG_TEMP_WARNING
|
||||
#define LOG_WARNING LOG_TEMP_WARNING
|
||||
#endif
|
||||
|
||||
#ifdef LOG_TEMP_DEBUG
|
||||
#define LOG_DEBUG LOG_TEMP_DEBUG
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
#ifdef LOG_DEBUG
|
||||
#undef LOG_DEBUG
|
||||
#endif
|
||||
// cloned from csi_platform.h. Win32 doesn't like how we hide symbols
|
||||
#define LOG_DEBUG 7
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "nr_api.h"
|
||||
@@ -205,6 +253,31 @@ static void ClearSingletonOnShutdown()
|
||||
}
|
||||
#endif
|
||||
|
||||
static nsIThread* GetIOThreadAndAddUse_s()
|
||||
{
|
||||
// Always runs on STS thread!
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
// We need to safely release this on shutdown to avoid leaks
|
||||
if (!sThread) {
|
||||
sThread = new SingletonThreadHolder(NS_LITERAL_CSTRING("mtransport"));
|
||||
NS_DispatchToMainThread(mozilla::WrapRunnableNM(&ClearSingletonOnShutdown));
|
||||
}
|
||||
// Mark that we're using the shared thread and need it to stick around
|
||||
sThread->AddUse();
|
||||
return sThread->GetThread();
|
||||
#else
|
||||
static nsCOMPtr<nsIThread> sThread;
|
||||
if (!sThread) {
|
||||
(void) NS_NewNamedThread("mtransport", getter_AddRefs(sThread));
|
||||
}
|
||||
return sThread;
|
||||
#endif
|
||||
}
|
||||
|
||||
NrSocketIpc::NrSocketIpc(nsIEventTarget *aThread)
|
||||
: io_thread_(aThread)
|
||||
{}
|
||||
|
||||
static TimeStamp nr_socket_short_term_violation_time;
|
||||
static TimeStamp nr_socket_long_term_violation_time;
|
||||
|
||||
@@ -736,7 +809,7 @@ int NrSocket::connect(nr_transport_addr *addr) {
|
||||
ASSERT_ON_THREAD(ststhread_);
|
||||
int r,_status;
|
||||
PRNetAddr naddr;
|
||||
int32_t status;
|
||||
int32_t connect_status, getsockname_status;
|
||||
|
||||
if ((r=nr_transport_addr_to_praddr(addr, &naddr)))
|
||||
ABORT(r);
|
||||
@@ -747,13 +820,28 @@ int NrSocket::connect(nr_transport_addr *addr) {
|
||||
// Note: this just means we tried to connect, not that we
|
||||
// are actually live.
|
||||
connect_invoked_ = true;
|
||||
status = PR_Connect(fd_, &naddr, PR_INTERVAL_NO_WAIT);
|
||||
connect_status = PR_Connect(fd_, &naddr, PR_INTERVAL_NO_WAIT);
|
||||
if (connect_status != PR_SUCCESS) {
|
||||
if (PR_GetError() != PR_IN_PROGRESS_ERROR)
|
||||
ABORT(R_IO_ERROR);
|
||||
}
|
||||
|
||||
if (status != PR_SUCCESS) {
|
||||
if (PR_GetError() == PR_IN_PROGRESS_ERROR)
|
||||
ABORT(R_WOULDBLOCK);
|
||||
// If our local address is wildcard, then fill in the
|
||||
// address now.
|
||||
if(nr_transport_addr_is_wildcard(&my_addr_)){
|
||||
getsockname_status = PR_GetSockName(fd_, &naddr);
|
||||
if (getsockname_status != PR_SUCCESS){
|
||||
r_log(LOG_GENERIC, LOG_CRIT, "Couldn't get sock name for socket");
|
||||
ABORT(R_INTERNAL);
|
||||
}
|
||||
|
||||
ABORT(R_IO_ERROR);
|
||||
if((r=nr_praddr_to_transport_addr(&naddr,&my_addr_,addr->protocol,1)))
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
// Now return the WOULDBLOCK if needed.
|
||||
if (connect_status != PR_SUCCESS) {
|
||||
ABORT(R_WOULDBLOCK);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
@@ -907,10 +995,10 @@ abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(NrSocketIpcProxy, nsIUDPSocketInternal)
|
||||
NS_IMPL_ISUPPORTS(NrUdpSocketIpcProxy, nsIUDPSocketInternal)
|
||||
|
||||
nsresult
|
||||
NrSocketIpcProxy::Init(const RefPtr<NrSocketIpc>& socket)
|
||||
NrUdpSocketIpcProxy::Init(const RefPtr<NrUdpSocketIpc>& socket)
|
||||
{
|
||||
nsresult rv;
|
||||
sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||
@@ -923,7 +1011,7 @@ NrSocketIpcProxy::Init(const RefPtr<NrSocketIpc>& socket)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NrSocketIpcProxy::~NrSocketIpcProxy()
|
||||
NrUdpSocketIpcProxy::~NrUdpSocketIpcProxy()
|
||||
{
|
||||
// Send our ref to STS to be released
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
@@ -933,39 +1021,39 @@ NrSocketIpcProxy::~NrSocketIpcProxy()
|
||||
|
||||
// IUDPSocketInternal interfaces
|
||||
// callback while error happened in UDP socket operation
|
||||
NS_IMETHODIMP NrSocketIpcProxy::CallListenerError(const nsACString &message,
|
||||
const nsACString &filename,
|
||||
uint32_t line_number) {
|
||||
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerError(const nsACString &message,
|
||||
const nsACString &filename,
|
||||
uint32_t line_number) {
|
||||
return socket_->CallListenerError(message, filename, line_number);
|
||||
}
|
||||
|
||||
// callback while receiving UDP packet
|
||||
NS_IMETHODIMP NrSocketIpcProxy::CallListenerReceivedData(const nsACString &host,
|
||||
uint16_t port,
|
||||
const uint8_t *data,
|
||||
uint32_t data_length) {
|
||||
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerReceivedData(const nsACString &host,
|
||||
uint16_t port,
|
||||
const uint8_t *data,
|
||||
uint32_t data_length) {
|
||||
return socket_->CallListenerReceivedData(host, port, data, data_length);
|
||||
}
|
||||
|
||||
// callback while UDP socket is opened
|
||||
NS_IMETHODIMP NrSocketIpcProxy::CallListenerOpened() {
|
||||
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerOpened() {
|
||||
return socket_->CallListenerOpened();
|
||||
}
|
||||
|
||||
// callback while UDP socket is closed
|
||||
NS_IMETHODIMP NrSocketIpcProxy::CallListenerClosed() {
|
||||
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerClosed() {
|
||||
return socket_->CallListenerClosed();
|
||||
}
|
||||
|
||||
// NrSocketIpc Implementation
|
||||
NrSocketIpc::NrSocketIpc()
|
||||
: err_(false),
|
||||
state_(NR_INIT),
|
||||
io_thread_(GetIOThreadAndAddUse_s()),
|
||||
monitor_("NrSocketIpc") {
|
||||
// NrUdpSocketIpc Implementation
|
||||
NrUdpSocketIpc::NrUdpSocketIpc()
|
||||
: NrSocketIpc(GetIOThreadAndAddUse_s()),
|
||||
monitor_("NrUdpSocketIpc"),
|
||||
err_(false),
|
||||
state_(NR_INIT) {
|
||||
}
|
||||
|
||||
NrSocketIpc::~NrSocketIpc()
|
||||
NrUdpSocketIpc::~NrUdpSocketIpc()
|
||||
{
|
||||
// also guarantees socket_child_ is released from the io_thread, and
|
||||
// tells the SingletonThreadHolder we're done with it
|
||||
@@ -973,40 +1061,18 @@ NrSocketIpc::~NrSocketIpc()
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
// close(), but transfer the socket_child_ reference to die as well
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnableNM(&NrSocketIpc::release_child_i,
|
||||
mozilla::WrapRunnableNM(&NrUdpSocketIpc::release_child_i,
|
||||
socket_child_.forget().take(),
|
||||
sts_thread_),
|
||||
NS_DISPATCH_NORMAL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsIThread* NrSocketIpc::GetIOThreadAndAddUse_s()
|
||||
{
|
||||
// Always runs on STS thread!
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
// We need to safely release this on shutdown to avoid leaks
|
||||
if (!sThread) {
|
||||
sThread = new SingletonThreadHolder(NS_LITERAL_CSTRING("mtransport"));
|
||||
NS_DispatchToMainThread(mozilla::WrapRunnableNM(&ClearSingletonOnShutdown));
|
||||
}
|
||||
// Mark that we're using the shared thread and need it to stick around
|
||||
sThread->AddUse();
|
||||
return sThread->GetThread();
|
||||
#else
|
||||
static nsCOMPtr<nsIThread> sThread;
|
||||
if (!sThread) {
|
||||
(void) NS_NewNamedThread("mtransport", getter_AddRefs(sThread));
|
||||
}
|
||||
return sThread;
|
||||
#endif
|
||||
}
|
||||
|
||||
// IUDPSocketInternal interfaces
|
||||
// callback while error happened in UDP socket operation
|
||||
NS_IMETHODIMP NrSocketIpc::CallListenerError(const nsACString &message,
|
||||
const nsACString &filename,
|
||||
uint32_t line_number) {
|
||||
NS_IMETHODIMP NrUdpSocketIpc::CallListenerError(const nsACString &message,
|
||||
const nsACString &filename,
|
||||
uint32_t line_number) {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
|
||||
r_log(LOG_GENERIC, LOG_ERR, "UDP socket error:%s at %s:%d",
|
||||
@@ -1020,10 +1086,10 @@ NS_IMETHODIMP NrSocketIpc::CallListenerError(const nsACString &message,
|
||||
}
|
||||
|
||||
// callback while receiving UDP packet
|
||||
NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &host,
|
||||
uint16_t port,
|
||||
const uint8_t *data,
|
||||
uint32_t data_length) {
|
||||
NS_IMETHODIMP NrUdpSocketIpc::CallListenerReceivedData(const nsACString &host,
|
||||
uint16_t port,
|
||||
const uint8_t *data,
|
||||
uint32_t data_length) {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
|
||||
PRNetAddr addr;
|
||||
@@ -1050,15 +1116,15 @@ NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &host,
|
||||
RefPtr<nr_udp_message> msg(new nr_udp_message(addr, buf));
|
||||
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
|
||||
&NrSocketIpc::recv_callback_s,
|
||||
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
|
||||
&NrUdpSocketIpc::recv_callback_s,
|
||||
msg),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// callback while UDP socket is opened
|
||||
NS_IMETHODIMP NrSocketIpc::CallListenerOpened() {
|
||||
NS_IMETHODIMP NrUdpSocketIpc::CallListenerOpened() {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
ReentrantMonitorAutoEnter mon(monitor_);
|
||||
|
||||
@@ -1112,7 +1178,7 @@ NS_IMETHODIMP NrSocketIpc::CallListenerOpened() {
|
||||
}
|
||||
|
||||
// callback while UDP socket is closed
|
||||
NS_IMETHODIMP NrSocketIpc::CallListenerClosed() {
|
||||
NS_IMETHODIMP NrUdpSocketIpc::CallListenerClosed() {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
|
||||
ReentrantMonitorAutoEnter mon(monitor_);
|
||||
@@ -1123,8 +1189,10 @@ NS_IMETHODIMP NrSocketIpc::CallListenerClosed() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nr_socket public APIs
|
||||
int NrSocketIpc::create(nr_transport_addr *addr) {
|
||||
//
|
||||
// NrSocketBase methods.
|
||||
//
|
||||
int NrUdpSocketIpc::create(nr_transport_addr *addr) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
int r, _status;
|
||||
@@ -1138,12 +1206,6 @@ int NrSocketIpc::create(nr_transport_addr *addr) {
|
||||
ABORT(R_INTERNAL);
|
||||
}
|
||||
|
||||
// Bug 950660: Remote TCP socket is not supported yet.
|
||||
if (NS_WARN_IF(addr->protocol != IPPROTO_UDP)) {
|
||||
MOZ_ASSERT(false, "NrSocket over TCP is not e10s ready, see Bug 950660");
|
||||
ABORT(R_INTERNAL);
|
||||
}
|
||||
|
||||
sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(false, "Failed to get STS thread");
|
||||
@@ -1154,7 +1216,7 @@ int NrSocketIpc::create(nr_transport_addr *addr) {
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
// wildcard address will be resolved at NrSocketIpc::CallListenerVoid
|
||||
// wildcard address will be resolved at NrUdpSocketIpc::CallListenerVoid
|
||||
if ((r=nr_transport_addr_copy(&my_addr_, addr))) {
|
||||
ABORT(r);
|
||||
}
|
||||
@@ -1162,8 +1224,8 @@ int NrSocketIpc::create(nr_transport_addr *addr) {
|
||||
state_ = NR_CONNECTING;
|
||||
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
|
||||
&NrSocketIpc::create_i,
|
||||
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
|
||||
&NrUdpSocketIpc::create_i,
|
||||
host, static_cast<uint16_t>(port)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
@@ -1181,7 +1243,7 @@ abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int NrSocketIpc::sendto(const void *msg, size_t len, int flags,
|
||||
int NrUdpSocketIpc::sendto(const void *msg, size_t len, int flags,
|
||||
nr_transport_addr *to) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
@@ -1205,22 +1267,22 @@ int NrSocketIpc::sendto(const void *msg, size_t len, int flags,
|
||||
nsAutoPtr<DataBuffer> buf(new DataBuffer(static_cast<const uint8_t*>(msg), len));
|
||||
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
|
||||
&NrSocketIpc::sendto_i,
|
||||
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
|
||||
&NrUdpSocketIpc::sendto_i,
|
||||
addr, buf),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NrSocketIpc::close() {
|
||||
void NrUdpSocketIpc::close() {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
ReentrantMonitorAutoEnter mon(monitor_);
|
||||
state_ = NR_CLOSING;
|
||||
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
|
||||
&NrSocketIpc::close_i),
|
||||
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
|
||||
&NrUdpSocketIpc::close_i),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
//remove all enqueued messages
|
||||
@@ -1228,7 +1290,7 @@ void NrSocketIpc::close() {
|
||||
std::swap(received_msgs_, empty);
|
||||
}
|
||||
|
||||
int NrSocketIpc::recvfrom(void *buf, size_t maxlen, size_t *len, int flags,
|
||||
int NrUdpSocketIpc::recvfrom(void *buf, size_t maxlen, size_t *len, int flags,
|
||||
nr_transport_addr *from) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
@@ -1272,7 +1334,7 @@ abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int NrSocketIpc::getaddr(nr_transport_addr *addrp) {
|
||||
int NrUdpSocketIpc::getaddr(nr_transport_addr *addrp) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
ReentrantMonitorAutoEnter mon(monitor_);
|
||||
@@ -1284,38 +1346,39 @@ int NrSocketIpc::getaddr(nr_transport_addr *addrp) {
|
||||
return nr_transport_addr_copy(addrp, &my_addr_);
|
||||
}
|
||||
|
||||
int NrSocketIpc::connect(nr_transport_addr *addr) {
|
||||
int NrUdpSocketIpc::connect(nr_transport_addr *addr) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
int NrSocketIpc::write(const void *msg, size_t len, size_t *written) {
|
||||
int NrUdpSocketIpc::write(const void *msg, size_t len, size_t *written) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
int NrSocketIpc::read(void* buf, size_t maxlen, size_t *len) {
|
||||
int NrUdpSocketIpc::read(void* buf, size_t maxlen, size_t *len) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
int NrSocketIpc::listen(int backlog) {
|
||||
int NrUdpSocketIpc::listen(int backlog) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
int NrSocketIpc::accept(nr_transport_addr *addrp, nr_socket **sockp) {
|
||||
int NrUdpSocketIpc::accept(nr_transport_addr *addrp, nr_socket **sockp) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
// IO thread executors
|
||||
void NrSocketIpc::create_i(const nsACString &host, const uint16_t port) {
|
||||
void NrUdpSocketIpc::create_i(const nsACString &host, const uint16_t port) {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIUDPSocketChild> socketChild = do_CreateInstance("@mozilla.org/udp-socket-child;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
ReentrantMonitorAutoEnter mon(monitor_);
|
||||
err_ = true;
|
||||
MOZ_ASSERT(false, "Failed to create UDPSocketChild");
|
||||
return;
|
||||
@@ -1332,7 +1395,7 @@ void NrSocketIpc::create_i(const nsACString &host, const uint16_t port) {
|
||||
socketChild = nullptr;
|
||||
}
|
||||
|
||||
RefPtr<NrSocketIpcProxy> proxy(new NrSocketIpcProxy);
|
||||
RefPtr<NrUdpSocketIpcProxy> proxy(new NrUdpSocketIpcProxy);
|
||||
rv = proxy->Init(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
err_ = true;
|
||||
@@ -1351,17 +1414,16 @@ void NrSocketIpc::create_i(const nsACString &host, const uint16_t port) {
|
||||
}
|
||||
}
|
||||
|
||||
void NrSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf) {
|
||||
void NrUdpSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf) {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
|
||||
ReentrantMonitorAutoEnter mon(monitor_);
|
||||
|
||||
if (!socket_child_) {
|
||||
MOZ_ASSERT(false);
|
||||
err_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ReentrantMonitorAutoEnter mon(monitor_);
|
||||
|
||||
if (NS_FAILED(socket_child_->SendWithAddress(&addr,
|
||||
buf->data(),
|
||||
buf->len()))) {
|
||||
@@ -1369,7 +1431,7 @@ void NrSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf)
|
||||
}
|
||||
}
|
||||
|
||||
void NrSocketIpc::close_i() {
|
||||
void NrUdpSocketIpc::close_i() {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
|
||||
if (socket_child_) {
|
||||
@@ -1381,8 +1443,8 @@ void NrSocketIpc::close_i() {
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
// close(), but transfer the socket_child_ reference to die as well
|
||||
// static
|
||||
void NrSocketIpc::release_child_i(nsIUDPSocketChild* aChild,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread) {
|
||||
void NrUdpSocketIpc::release_child_i(nsIUDPSocketChild* aChild,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread) {
|
||||
RefPtr<nsIUDPSocketChild> socket_child_ref =
|
||||
already_AddRefed<nsIUDPSocketChild>(aChild);
|
||||
if (socket_child_ref) {
|
||||
@@ -1390,16 +1452,16 @@ void NrSocketIpc::release_child_i(nsIUDPSocketChild* aChild,
|
||||
}
|
||||
// Tell SingletonThreadHolder we're done with it
|
||||
RUN_ON_THREAD(sts_thread,
|
||||
mozilla::WrapRunnableNM(&NrSocketIpc::release_use_s),
|
||||
mozilla::WrapRunnableNM(&NrUdpSocketIpc::release_use_s),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void NrSocketIpc::release_use_s() {
|
||||
void NrUdpSocketIpc::release_use_s() {
|
||||
sThread->ReleaseUse();
|
||||
}
|
||||
#endif
|
||||
|
||||
void NrSocketIpc::recv_callback_s(RefPtr<nr_udp_message> msg) {
|
||||
void NrUdpSocketIpc::recv_callback_s(RefPtr<nr_udp_message> msg) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
{
|
||||
@@ -1417,6 +1479,448 @@ void NrSocketIpc::recv_callback_s(RefPtr<nr_udp_message> msg) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
// TCPSocket.
|
||||
class NrTcpSocketIpc::TcpSocketReadyRunner: public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit TcpSocketReadyRunner(NrTcpSocketIpc *sck)
|
||||
: socket_(sck) {}
|
||||
|
||||
NS_IMETHODIMP Run() {
|
||||
socket_->maybe_post_socket_ready();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<NrTcpSocketIpc> socket_;
|
||||
};
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(NrTcpSocketIpc,
|
||||
nsITCPSocketCallback)
|
||||
|
||||
NrTcpSocketIpc::NrTcpSocketIpc(nsIThread* aThread)
|
||||
: NrSocketIpc(static_cast<nsIEventTarget*>(aThread)),
|
||||
mirror_state_(NR_INIT),
|
||||
state_(NR_INIT),
|
||||
buffered_bytes_(0),
|
||||
tracking_number_(0) {
|
||||
}
|
||||
|
||||
NrTcpSocketIpc::~NrTcpSocketIpc()
|
||||
{
|
||||
// also guarantees socket_child_ is released from the io_thread
|
||||
|
||||
// close(), but transfer the socket_child_ reference to die as well
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnableNM(&NrTcpSocketIpc::release_child_i,
|
||||
socket_child_.forget().take(),
|
||||
sts_thread_),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
//
|
||||
// nsITCPSocketCallback methods
|
||||
//
|
||||
NS_IMETHODIMP NrTcpSocketIpc::UpdateReadyState(uint32_t aReadyState) {
|
||||
NrSocketIpcState temp = NR_INIT;
|
||||
switch (static_cast<dom::TCPReadyState>(aReadyState)) {
|
||||
case dom::TCPReadyState::Connecting:
|
||||
temp = NR_CONNECTING;
|
||||
break;
|
||||
case dom::TCPReadyState::Open:
|
||||
temp = NR_CONNECTED;
|
||||
break;
|
||||
case dom::TCPReadyState::Closing:
|
||||
temp = NR_CLOSING;
|
||||
break;
|
||||
case dom::TCPReadyState::Closed:
|
||||
temp = NR_CLOSED;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Invalid ReadyState");
|
||||
return NS_OK;
|
||||
}
|
||||
if (mirror_state_ != temp) {
|
||||
mirror_state_ = temp;
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
|
||||
&NrTcpSocketIpc::update_state_s,
|
||||
temp),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP NrTcpSocketIpc::UpdateBufferedAmount(uint32_t buffered_amount,
|
||||
uint32_t tracking_number) {
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
|
||||
&NrTcpSocketIpc::message_sent_s,
|
||||
buffered_amount,
|
||||
tracking_number),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP NrTcpSocketIpc::FireDataArrayEvent(const nsAString& aType,
|
||||
const InfallibleTArray<uint8_t>& buffer) {
|
||||
// Called when we received data.
|
||||
uint8_t *buf = const_cast<uint8_t*>(buffer.Elements());
|
||||
|
||||
nsAutoPtr<DataBuffer> data_buf(new DataBuffer(buf, buffer.Length()));
|
||||
RefPtr<nr_tcp_message> msg = new nr_tcp_message(data_buf);
|
||||
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
|
||||
&NrTcpSocketIpc::recv_message_s,
|
||||
msg),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP NrTcpSocketIpc::FireErrorEvent(const nsAString &type,
|
||||
const nsAString &name) {
|
||||
r_log(LOG_GENERIC, LOG_ERR,
|
||||
"Error from TCPSocketChild: type: %s, name: %s",
|
||||
NS_LossyConvertUTF16toASCII(type).get(), NS_LossyConvertUTF16toASCII(name).get());
|
||||
socket_child_ = nullptr;
|
||||
|
||||
mirror_state_ = NR_CLOSED;
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
|
||||
&NrTcpSocketIpc::update_state_s,
|
||||
NR_CLOSED),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// methods of nsITCPSocketCallback that we are not going to implement.
|
||||
|
||||
NS_IMETHODIMP NrTcpSocketIpc::FireDataEvent(JSContext* aCx,
|
||||
const nsAString &type,
|
||||
const JS::HandleValue data) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP NrTcpSocketIpc::FireDataStringEvent(const nsAString &type,
|
||||
const nsACString &data) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP NrTcpSocketIpc::FireEvent(const nsAString &type) {
|
||||
// XXX support type.mData == 'close' at least
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
//
|
||||
// NrSocketBase methods.
|
||||
//
|
||||
int NrTcpSocketIpc::create(nr_transport_addr *addr) {
|
||||
int r, _status;
|
||||
nsresult rv;
|
||||
int32_t port;
|
||||
nsCString host;
|
||||
|
||||
if (state_ != NR_INIT) {
|
||||
ABORT(R_INTERNAL);
|
||||
}
|
||||
|
||||
sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(false, "Failed to get STS thread");
|
||||
ABORT(R_INTERNAL);
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if ((r=nr_transport_addr_get_addrstring_and_port(addr, &host, &port))) {
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
if ((r=nr_transport_addr_copy(&my_addr_, addr))) {
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
_status = 0;
|
||||
abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::sendto(const void *msg, size_t len,
|
||||
int flags, nr_transport_addr *to) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::recvfrom(void * buf, size_t maxlen,
|
||||
size_t *len, int flags,
|
||||
nr_transport_addr *from) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::getaddr(nr_transport_addr *addrp) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
return nr_transport_addr_copy(addrp, &my_addr_);
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::close() {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
if (state_ == NR_CLOSED || state_ == NR_CLOSING) {
|
||||
return;
|
||||
}
|
||||
|
||||
state_ = NR_CLOSING;
|
||||
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
|
||||
&NrTcpSocketIpc::close_i),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
//remove all enqueued messages
|
||||
std::queue<RefPtr<nr_tcp_message>> empty;
|
||||
std::swap(msg_queue_, empty);
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::connect(nr_transport_addr *addr) {
|
||||
nsCString remote_addr, local_addr;
|
||||
int32_t remote_port, local_port;
|
||||
int r, _status;
|
||||
if ((r=nr_transport_addr_get_addrstring_and_port(addr,
|
||||
&remote_addr,
|
||||
&remote_port))) {
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
if ((r=nr_transport_addr_get_addrstring_and_port(&my_addr_,
|
||||
&local_addr,
|
||||
&local_port))) {
|
||||
MOZ_ASSERT(false); // shouldn't fail as it was sanity-checked in ::create()
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
state_ = mirror_state_ = NR_CONNECTING;
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
|
||||
&NrTcpSocketIpc::connect_i,
|
||||
remote_addr,
|
||||
static_cast<uint16_t>(remote_port),
|
||||
local_addr,
|
||||
static_cast<uint16_t>(local_port)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
// Make caller wait for ready to write.
|
||||
_status = R_WOULDBLOCK;
|
||||
abort:
|
||||
return _status;
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::write(const void *msg, size_t len, size_t *written) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
int _status = 0;
|
||||
if (state_ != NR_CONNECTED) {
|
||||
ABORT(R_FAILED);
|
||||
}
|
||||
|
||||
if (buffered_bytes_ + len >= nsITCPSocketCallback::BUFFER_SIZE) {
|
||||
ABORT(R_WOULDBLOCK);
|
||||
}
|
||||
|
||||
buffered_bytes_ += len;
|
||||
{
|
||||
InfallibleTArray<uint8_t>* arr = new InfallibleTArray<uint8_t>();
|
||||
arr->AppendElements(static_cast<const uint8_t*>(msg), len);
|
||||
// keep track of un-acknowleged writes by tracking number.
|
||||
writes_in_flight_.push_back(len);
|
||||
RUN_ON_THREAD(io_thread_,
|
||||
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
|
||||
&NrTcpSocketIpc::write_i,
|
||||
nsAutoPtr<InfallibleTArray<uint8_t>>(arr),
|
||||
++tracking_number_),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
*written = len;
|
||||
abort:
|
||||
return _status;
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::read(void* buf, size_t maxlen, size_t *len) {
|
||||
int _status = 0;
|
||||
if (state_ != NR_CONNECTED) {
|
||||
ABORT(R_FAILED);
|
||||
}
|
||||
|
||||
if (msg_queue_.size() == 0) {
|
||||
ABORT(R_WOULDBLOCK);
|
||||
}
|
||||
|
||||
{
|
||||
RefPtr<nr_tcp_message> msg(msg_queue_.front());
|
||||
size_t consumed_len = std::min(maxlen, msg->unread_bytes());
|
||||
memcpy(buf, msg->reading_pointer(), consumed_len);
|
||||
if (consumed_len < msg->unread_bytes()) {
|
||||
// There is still something left in buffer.
|
||||
msg->read_bytes += consumed_len;
|
||||
} else {
|
||||
msg_queue_.pop();
|
||||
}
|
||||
*len = consumed_len;
|
||||
}
|
||||
|
||||
abort:
|
||||
return _status;
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::listen(int backlog) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
int NrTcpSocketIpc::accept(nr_transport_addr *addrp, nr_socket **sockp) {
|
||||
MOZ_ASSERT(false);
|
||||
return R_INTERNAL;
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::connect_i(const nsACString &remote_addr,
|
||||
uint16_t remote_port,
|
||||
const nsACString &local_addr,
|
||||
uint16_t local_port) {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
mirror_state_ = NR_CONNECTING;
|
||||
|
||||
dom::TCPSocketChild* child = new dom::TCPSocketChild(NS_ConvertUTF8toUTF16(remote_addr), remote_port);
|
||||
socket_child_ = child;
|
||||
|
||||
// XXX remove remote!
|
||||
socket_child_->SendWindowlessOpenBind(this,
|
||||
remote_addr, remote_port,
|
||||
local_addr, local_port,
|
||||
/* use ssl */ false);
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::write_i(nsAutoPtr<InfallibleTArray<uint8_t>> arr,
|
||||
uint32_t tracking_number) {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
if (!socket_child_) {
|
||||
return;
|
||||
}
|
||||
socket_child_->SendSendArray(*arr, tracking_number);
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::close_i() {
|
||||
ASSERT_ON_THREAD(io_thread_);
|
||||
mirror_state_ = NR_CLOSING;
|
||||
if (!socket_child_) {
|
||||
return;
|
||||
}
|
||||
socket_child_->SendClose();
|
||||
}
|
||||
|
||||
// close(), but transfer the socket_child_ reference to die as well
|
||||
// static
|
||||
void NrTcpSocketIpc::release_child_i(dom::TCPSocketChild* aChild,
|
||||
nsCOMPtr<nsIEventTarget> sts_thread) {
|
||||
RefPtr<dom::TCPSocketChild> socket_child_ref =
|
||||
already_AddRefed<dom::TCPSocketChild>(aChild);
|
||||
if (socket_child_ref) {
|
||||
socket_child_ref->SendClose();
|
||||
}
|
||||
// io_thread_ is MainThread, so no use to release
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::message_sent_s(uint32_t buffered_amount,
|
||||
uint32_t tracking_number) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
size_t num_unacked_writes = tracking_number_ - tracking_number;
|
||||
while (writes_in_flight_.size() > num_unacked_writes) {
|
||||
writes_in_flight_.pop_front();
|
||||
}
|
||||
|
||||
for (size_t unacked_write_len : writes_in_flight_) {
|
||||
buffered_amount += unacked_write_len;
|
||||
}
|
||||
|
||||
r_log(LOG_GENERIC, LOG_ERR,
|
||||
"UpdateBufferedAmount: (tracking %u): %u, waiting: %s",
|
||||
tracking_number, buffered_amount,
|
||||
(poll_flags() & PR_POLL_WRITE) ? "yes" : "no");
|
||||
|
||||
buffered_bytes_ = buffered_amount;
|
||||
maybe_post_socket_ready();
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::recv_message_s(nr_tcp_message *msg) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
msg_queue_.push(msg);
|
||||
maybe_post_socket_ready();
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::update_state_s(NrSocketIpcState next_state) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
// only allow valid transitions
|
||||
switch (state_) {
|
||||
case NR_CONNECTING:
|
||||
if (next_state == NR_CONNECTED) {
|
||||
state_ = NR_CONNECTED;
|
||||
maybe_post_socket_ready();
|
||||
} else {
|
||||
state_ = next_state; // all states are valid from CONNECTING
|
||||
}
|
||||
break;
|
||||
case NR_CONNECTED:
|
||||
if (next_state != NR_CONNECTING) {
|
||||
state_ = next_state;
|
||||
}
|
||||
break;
|
||||
case NR_CLOSING:
|
||||
if (next_state == NR_CLOSED) {
|
||||
state_ = next_state;
|
||||
}
|
||||
break;
|
||||
case NR_CLOSED:
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("update_state_s while in illegal state");
|
||||
}
|
||||
}
|
||||
|
||||
void NrTcpSocketIpc::maybe_post_socket_ready() {
|
||||
bool has_event = false;
|
||||
if (state_ == NR_CONNECTED) {
|
||||
if (poll_flags() & PR_POLL_WRITE) {
|
||||
// This effectively polls via the event loop until the
|
||||
// NR_ASYNC_WAIT_WRITE is no longer armed.
|
||||
if (buffered_bytes_ < nsITCPSocketCallback::BUFFER_SIZE) {
|
||||
r_log(LOG_GENERIC, LOG_INFO, "Firing write callback (%u)",
|
||||
(uint32_t)buffered_bytes_);
|
||||
fire_callback(NR_ASYNC_WAIT_WRITE);
|
||||
has_event = true;
|
||||
}
|
||||
}
|
||||
if (poll_flags() & PR_POLL_READ) {
|
||||
if (msg_queue_.size()) {
|
||||
r_log(LOG_GENERIC, LOG_INFO, "Firing read callback (%u)",
|
||||
(uint32_t)msg_queue_.size());
|
||||
fire_callback(NR_ASYNC_WAIT_READ);
|
||||
has_event = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If any event has been posted, we post a runnable to see
|
||||
// if the events have to be posted again.
|
||||
if (has_event) {
|
||||
RefPtr<TcpSocketReadyRunner> runnable = new TcpSocketReadyRunner(this);
|
||||
NS_DispatchToCurrentThread(runnable);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // close namespace
|
||||
|
||||
|
||||
@@ -1457,16 +1961,30 @@ static nr_socket_vtbl nr_socket_local_vtbl={
|
||||
|
||||
int nr_socket_local_create(void *obj, nr_transport_addr *addr, nr_socket **sockp) {
|
||||
RefPtr<NrSocketBase> sock;
|
||||
int r, _status;
|
||||
|
||||
// create IPC bridge for content process
|
||||
if (XRE_IsParentProcess()) {
|
||||
sock = new NrSocket();
|
||||
} else {
|
||||
sock = new NrSocketIpc();
|
||||
switch (addr->protocol) {
|
||||
case IPPROTO_UDP:
|
||||
sock = new NrUdpSocketIpc();
|
||||
break;
|
||||
case IPPROTO_TCP:
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
{
|
||||
nsCOMPtr<nsIThread> main_thread;
|
||||
NS_GetMainThread(getter_AddRefs(main_thread));
|
||||
sock = new NrTcpSocketIpc(main_thread.get());
|
||||
}
|
||||
#else
|
||||
ABORT(R_REJECTED);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int r, _status;
|
||||
|
||||
r = sock->create(addr);
|
||||
if (r)
|
||||
ABORT(r);
|
||||
|
||||
@@ -61,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsITCPSocketCallback.h"
|
||||
#include "databuffer.h"
|
||||
#include "m_cpp_utils.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
@@ -72,6 +73,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
typedef struct nr_socket_vtbl_ nr_socket_vtbl;
|
||||
typedef struct nr_socket_ nr_socket;
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class TCPSocketChild;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace net {
|
||||
@@ -209,7 +218,22 @@ public:
|
||||
NR_CLOSED,
|
||||
};
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrSocketIpc)
|
||||
NrSocketIpc(nsIEventTarget* aThread);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIEventTarget> sts_thread_;
|
||||
// Note: for UDP PBackground, this is a thread held by SingletonThreadHolder.
|
||||
// For TCP PNecko, this is MainThread (and TCPSocket requires MainThread currently)
|
||||
const nsCOMPtr<nsIEventTarget> io_thread_;
|
||||
virtual ~NrSocketIpc() {};
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_ASSIGN(NrSocketIpc);
|
||||
};
|
||||
|
||||
class NrUdpSocketIpc : public NrSocketIpc {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrUdpSocketIpc, override)
|
||||
|
||||
NS_IMETHODIMP CallListenerError(const nsACString &message,
|
||||
const nsACString &filename,
|
||||
@@ -221,7 +245,7 @@ public:
|
||||
NS_IMETHODIMP CallListenerOpened();
|
||||
NS_IMETHODIMP CallListenerClosed();
|
||||
|
||||
NrSocketIpc();
|
||||
NrUdpSocketIpc();
|
||||
|
||||
// Implementations of the NrSocketBase APIs
|
||||
virtual int create(nr_transport_addr *addr) override;
|
||||
@@ -239,11 +263,9 @@ public:
|
||||
virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
|
||||
|
||||
private:
|
||||
virtual ~NrSocketIpc();
|
||||
virtual ~NrUdpSocketIpc();
|
||||
|
||||
DISALLOW_COPY_ASSIGN(NrSocketIpc);
|
||||
|
||||
static nsIThread* GetIOThreadAndAddUse_s();
|
||||
DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
|
||||
|
||||
// Main or private thread executors of the NrSocketBase APIs
|
||||
void create_i(const nsACString &host, const uint16_t port);
|
||||
@@ -256,32 +278,118 @@ private:
|
||||
// STS thread executor
|
||||
void recv_callback_s(RefPtr<nr_udp_message> msg);
|
||||
|
||||
ReentrantMonitor monitor_; // protects err_and state_
|
||||
bool err_;
|
||||
NrSocketIpcState state_;
|
||||
std::queue<RefPtr<nr_udp_message> > received_msgs_;
|
||||
|
||||
std::queue<RefPtr<nr_udp_message>> received_msgs_;
|
||||
|
||||
RefPtr<nsIUDPSocketChild> socket_child_; // only accessed from the io_thread
|
||||
nsCOMPtr<nsIEventTarget> sts_thread_;
|
||||
const nsCOMPtr<nsIEventTarget> io_thread_;
|
||||
ReentrantMonitor monitor_;
|
||||
};
|
||||
|
||||
// The socket child holds onto one of these, which just passes callbacks
|
||||
// through and makes sure the ref to the NrSocketIpc is released on STS.
|
||||
class NrSocketIpcProxy : public nsIUDPSocketInternal {
|
||||
class NrUdpSocketIpcProxy : public nsIUDPSocketInternal {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIUDPSOCKETINTERNAL
|
||||
|
||||
nsresult Init(const RefPtr<NrSocketIpc>& socket);
|
||||
nsresult Init(const RefPtr<NrUdpSocketIpc>& socket);
|
||||
|
||||
private:
|
||||
virtual ~NrSocketIpcProxy();
|
||||
virtual ~NrUdpSocketIpcProxy();
|
||||
|
||||
RefPtr<NrSocketIpc> socket_;
|
||||
RefPtr<NrUdpSocketIpc> socket_;
|
||||
nsCOMPtr<nsIEventTarget> sts_thread_;
|
||||
};
|
||||
|
||||
struct nr_tcp_message {
|
||||
explicit nr_tcp_message(nsAutoPtr<DataBuffer> &data)
|
||||
: read_bytes(0)
|
||||
, data(data) {
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_tcp_message);
|
||||
|
||||
const uint8_t *reading_pointer() const {
|
||||
return data->data() + read_bytes;
|
||||
}
|
||||
|
||||
size_t unread_bytes() const {
|
||||
return data->len() - read_bytes;
|
||||
}
|
||||
|
||||
size_t read_bytes;
|
||||
|
||||
private:
|
||||
~nr_tcp_message() {}
|
||||
DISALLOW_COPY_ASSIGN(nr_tcp_message);
|
||||
|
||||
nsAutoPtr<DataBuffer> data;
|
||||
};
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
|
||||
class NrTcpSocketIpc : public NrSocketIpc,
|
||||
public nsITCPSocketCallback {
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSITCPSOCKETCALLBACK
|
||||
|
||||
explicit NrTcpSocketIpc(nsIThread* aThread);
|
||||
|
||||
// Implementations of the NrSocketBase APIs
|
||||
virtual int create(nr_transport_addr *addr) override;
|
||||
virtual int sendto(const void *msg, size_t len,
|
||||
int flags, nr_transport_addr *to) override;
|
||||
virtual int recvfrom(void * buf, size_t maxlen,
|
||||
size_t *len, int flags,
|
||||
nr_transport_addr *from) override;
|
||||
virtual int getaddr(nr_transport_addr *addrp) override;
|
||||
virtual void close() override;
|
||||
virtual int connect(nr_transport_addr *addr) override;
|
||||
virtual int write(const void *msg, size_t len, size_t *written) override;
|
||||
virtual int read(void* buf, size_t maxlen, size_t *len) override;
|
||||
virtual int listen(int backlog) override;
|
||||
virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
|
||||
|
||||
private:
|
||||
class TcpSocketReadyRunner;
|
||||
DISALLOW_COPY_ASSIGN(NrTcpSocketIpc);
|
||||
virtual ~NrTcpSocketIpc();
|
||||
|
||||
// Main thread executors of the NrSocketBase APIs
|
||||
void connect_i(const nsACString &remote_addr,
|
||||
uint16_t remote_port,
|
||||
const nsACString &local_addr,
|
||||
uint16_t local_port);
|
||||
void write_i(nsAutoPtr<InfallibleTArray<uint8_t>> buf,
|
||||
uint32_t tracking_number);
|
||||
void close_i();
|
||||
|
||||
static void release_child_i(dom::TCPSocketChild* aChild, nsCOMPtr<nsIEventTarget> ststhread);
|
||||
|
||||
// STS thread executor
|
||||
void message_sent_s(uint32_t bufferedAmount, uint32_t tracking_number);
|
||||
void recv_message_s(nr_tcp_message *msg);
|
||||
void update_state_s(NrSocketIpcState next_state);
|
||||
void maybe_post_socket_ready();
|
||||
|
||||
// Accessed from UpdateReadyState (not sts_thread) to avoid sending
|
||||
// runnables when not needed
|
||||
NrSocketIpcState mirror_state_;
|
||||
|
||||
// variables that can only be accessed on STS.
|
||||
NrSocketIpcState state_;
|
||||
std::queue<RefPtr<nr_tcp_message>> msg_queue_;
|
||||
uint32_t buffered_bytes_;
|
||||
uint32_t tracking_number_;
|
||||
std::deque<size_t> writes_in_flight_;
|
||||
|
||||
// main thread.
|
||||
RefPtr<dom::TCPSocketChild> socket_child_;
|
||||
};
|
||||
#endif
|
||||
|
||||
int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr,
|
||||
nr_transport_addr *addr,
|
||||
int protocol);
|
||||
|
||||
@@ -380,13 +380,12 @@ void NrIceCtx::trickle_cb(void *arg, nr_ice_ctx *ice_ctx,
|
||||
|
||||
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
bool offerer,
|
||||
bool set_interface_priorities,
|
||||
bool allow_loopback,
|
||||
bool tcp_enabled,
|
||||
bool allow_link_local,
|
||||
bool hide_non_default,
|
||||
Policy policy) {
|
||||
|
||||
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy);
|
||||
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy);
|
||||
|
||||
// Initialize the crypto callbacks and logging stuff
|
||||
if (!initialized) {
|
||||
@@ -406,37 +405,11 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST_TCP, 125);
|
||||
NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0);
|
||||
|
||||
if (set_interface_priorities) {
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.eth1", 251);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.eth2", 249);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.ppp", 250);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.ppp0", 249);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.en2", 248);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.en3", 247);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.em0", 251);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.em1", 252);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet0", 240);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet1", 241);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet3", 239);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet4", 238);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet5", 237);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet6", 236);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet7", 235);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet8", 234);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233);
|
||||
NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
|
||||
}
|
||||
|
||||
int32_t stun_client_maximum_transmits = 7;
|
||||
int32_t ice_trickle_grace_period = 5000;
|
||||
int32_t ice_tcp_so_sock_count = 3;
|
||||
int32_t ice_tcp_listen_backlog = 10;
|
||||
nsAutoCString force_net_interface;
|
||||
#ifndef MOZILLA_XPCOMRT_API
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIPrefService> prefs =
|
||||
@@ -457,6 +430,9 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
branch->GetIntPref(
|
||||
"media.peerconnection.ice.tcp_listen_backlog",
|
||||
&ice_tcp_listen_backlog);
|
||||
branch->GetCharPref(
|
||||
"media.peerconnection.ice.force_interface",
|
||||
getter_Copies(force_net_interface));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -466,8 +442,6 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
ice_trickle_grace_period);
|
||||
NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,
|
||||
ice_tcp_so_sock_count);
|
||||
NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,
|
||||
ice_tcp_so_sock_count);
|
||||
NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG,
|
||||
ice_tcp_listen_backlog);
|
||||
|
||||
@@ -480,6 +454,11 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
if (allow_link_local) {
|
||||
NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1);
|
||||
}
|
||||
if (force_net_interface.Length() > 0) {
|
||||
// Stupid cast.... but needed
|
||||
const nsCString& flat = PromiseFlatCString(static_cast<nsACString&>(force_net_interface));
|
||||
NR_reg_set_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, const_cast<char*>(flat.get()));
|
||||
}
|
||||
}
|
||||
|
||||
// Create the ICE context
|
||||
@@ -488,6 +467,12 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER:
|
||||
NR_ICE_CTX_FLAGS_ANSWERER;
|
||||
flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
|
||||
if (policy == ICE_POLICY_RELAY) {
|
||||
flags |= NR_ICE_CTX_FLAGS_RELAY_ONLY;
|
||||
}
|
||||
|
||||
if (hide_non_default)
|
||||
flags |= NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS;
|
||||
|
||||
r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags,
|
||||
&ctx->ctx_);
|
||||
@@ -496,7 +481,6 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef USE_INTERFACE_PRIORITIZER
|
||||
nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
|
||||
if (!prioritizer) {
|
||||
MOZ_MTLOG(LogLevel::Error, "Couldn't create interface prioritizer.");
|
||||
@@ -508,7 +492,6 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||
MOZ_MTLOG(LogLevel::Error, "Couldn't set interface prioritizer.");
|
||||
return nullptr;
|
||||
}
|
||||
#endif // USE_INTERFACE_PRIORITIZER
|
||||
|
||||
if (ctx->generating_trickle()) {
|
||||
r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx);
|
||||
@@ -727,6 +710,9 @@ abort:
|
||||
|
||||
nsresult NrIceCtx::StartGathering() {
|
||||
ASSERT_ON_THREAD(sts_target_);
|
||||
if (policy_ == ICE_POLICY_NONE) {
|
||||
return NS_OK;
|
||||
}
|
||||
SetGatheringState(ICE_CTX_GATHER_STARTED);
|
||||
// This might start gathering for the first time, or again after
|
||||
// renegotiation, or might do nothing at all if gathering has already
|
||||
@@ -801,6 +787,11 @@ nsresult NrIceCtx::ParseGlobalAttributes(std::vector<std::string> attrs) {
|
||||
nsresult NrIceCtx::StartChecks() {
|
||||
int r;
|
||||
|
||||
if (policy_ == ICE_POLICY_NONE) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't start peer checks because policy == none");
|
||||
SetConnectionState(ICE_CTX_FAILED);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
r=nr_ice_peer_ctx_pair_candidates(peer_);
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't pair candidates on "
|
||||
|
||||
@@ -213,12 +213,13 @@ class NrIceCtx {
|
||||
ICE_POLICY_ALL
|
||||
};
|
||||
|
||||
// TODO(ekr@rtfm.com): Too many bools here. Bug 1193437.
|
||||
static RefPtr<NrIceCtx> Create(const std::string& name,
|
||||
bool offerer,
|
||||
bool set_interface_priorities = true,
|
||||
bool allow_loopback = false,
|
||||
bool tcp_enabled = true,
|
||||
bool allow_link_local = false,
|
||||
bool hide_non_default = false,
|
||||
Policy policy = ICE_POLICY_ALL);
|
||||
|
||||
// Deinitialize all ICE global state. Used only for testing.
|
||||
|
||||
@@ -307,15 +307,44 @@ nsresult NrIceMediaStream::GetCandidatePairs(std::vector<NrIceCandidatePair>*
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nr_ice_cand_pair *p1;
|
||||
nr_ice_cand_pair *p1, *p2;
|
||||
out_pairs->clear();
|
||||
|
||||
TAILQ_FOREACH(p1, &peer_stream->check_list, entry) {
|
||||
TAILQ_FOREACH(p1, &peer_stream->check_list, check_queue_entry) {
|
||||
MOZ_ASSERT(p1);
|
||||
MOZ_ASSERT(p1->local);
|
||||
MOZ_ASSERT(p1->remote);
|
||||
NrIceCandidatePair pair;
|
||||
|
||||
p2 = TAILQ_FIRST(&peer_stream->check_list);
|
||||
while (p2) {
|
||||
if (p1 == p2) {
|
||||
/* Don't compare with our self. */
|
||||
p2=TAILQ_NEXT(p2, check_queue_entry);
|
||||
continue;
|
||||
}
|
||||
if (strncmp(p1->codeword,p2->codeword,sizeof(p1->codeword))==0) {
|
||||
/* In case of duplicate pairs we only report the one winning pair */
|
||||
if (
|
||||
((p2->remote->component && (p2->remote->component->active == p2)) &&
|
||||
!(p1->remote->component && (p1->remote->component->active == p1))) ||
|
||||
((p2->peer_nominated || p2->nominated) &&
|
||||
!(p1->peer_nominated || p1->nominated)) ||
|
||||
(p2->priority > p1->priority) ||
|
||||
((p2->state == NR_ICE_PAIR_STATE_SUCCEEDED) &&
|
||||
(p1->state != NR_ICE_PAIR_STATE_SUCCEEDED))
|
||||
) {
|
||||
/* p2 is a better pair. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
p2=TAILQ_NEXT(p2, check_queue_entry);
|
||||
}
|
||||
if (p2) {
|
||||
/* p2 points to a duplicate but better pair so skip this one */
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (p1->state) {
|
||||
case NR_ICE_PAIR_STATE_FROZEN:
|
||||
pair.state = NrIceCandidatePair::State::STATE_FROZEN;
|
||||
|
||||
@@ -154,7 +154,7 @@ int NrIceResolver::resolve(nr_resolver_resource *resource,
|
||||
|
||||
if (resource->transport_protocol != IPPROTO_UDP &&
|
||||
resource->transport_protocol != IPPROTO_TCP) {
|
||||
MOZ_MTLOG(ML_ERROR, "Only UDP and TCP are is supported.");
|
||||
MOZ_MTLOG(ML_ERROR, "Only UDP and TCP are supported.");
|
||||
ABORT(R_NOT_FOUND);
|
||||
}
|
||||
pr = new PendingResolution(sts_thread_,
|
||||
|
||||
@@ -71,6 +71,10 @@ class NrIceResolver
|
||||
void DestroyResolver();
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceResolver)
|
||||
|
||||
int resolve(nr_resolver_resource *resource,
|
||||
int (*cb)(void *cb_arg, nr_transport_addr *addr),
|
||||
void *cb_arg, void **handle);
|
||||
|
||||
private:
|
||||
// Implementations of vtbl functions
|
||||
static int destroy(void **objp);
|
||||
@@ -80,10 +84,6 @@ class NrIceResolver
|
||||
static void resolve_cb(NR_SOCKET s, int how, void *cb_arg);
|
||||
static int cancel(void *obj, void *handle);
|
||||
|
||||
int resolve(nr_resolver_resource *resource,
|
||||
int (*cb)(void *cb_arg, nr_transport_addr *addr),
|
||||
void *cb_arg, void **handle);
|
||||
|
||||
class PendingResolution : public nsIDNSListener
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "logging.h"
|
||||
#include "nrinterfaceprioritizer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@@ -15,20 +17,32 @@ namespace {
|
||||
class LocalAddress {
|
||||
public:
|
||||
LocalAddress()
|
||||
: key_(),
|
||||
: ifname_(),
|
||||
addr_(),
|
||||
key_(),
|
||||
is_vpn_(-1),
|
||||
estimated_speed_(-1),
|
||||
type_preference_(-1),
|
||||
ip_version_(-1) {}
|
||||
|
||||
bool Init(const nr_local_addr& local_addr) {
|
||||
ifname_ = local_addr.addr.ifname;
|
||||
|
||||
char buf[MAXIFNAME + 41];
|
||||
int r = nr_transport_addr_fmt_ifname_addr_string(&local_addr.addr, buf, sizeof(buf));
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Error formatting interface address string.");
|
||||
MOZ_MTLOG(ML_ERROR, "Error formatting interface key.");
|
||||
return false;
|
||||
}
|
||||
key_ = buf;
|
||||
|
||||
r = nr_transport_addr_get_addrstring(&local_addr.addr, buf, sizeof(buf));
|
||||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Error formatting address string.");
|
||||
return false;
|
||||
}
|
||||
addr_ = buf;
|
||||
|
||||
is_vpn_ = (local_addr.interface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0;
|
||||
estimated_speed_ = local_addr.interface.estimated_speed;
|
||||
type_preference_ = GetNetworkTypePreference(local_addr.interface.type);
|
||||
@@ -56,13 +70,28 @@ public:
|
||||
return estimated_speed_ > rhs.estimated_speed_;
|
||||
}
|
||||
|
||||
// See if our hard-coded pref list helps us.
|
||||
auto thisindex = std::find(interface_preference_list().begin(),
|
||||
interface_preference_list().end(),
|
||||
ifname_);
|
||||
auto rhsindex = std::find(interface_preference_list().begin(),
|
||||
interface_preference_list().end(),
|
||||
rhs.ifname_);
|
||||
if (thisindex != rhsindex) {
|
||||
return thisindex < rhsindex;
|
||||
}
|
||||
|
||||
// Prefer IPV6 over IPV4
|
||||
if (ip_version_ != rhs.ip_version_) {
|
||||
return ip_version_ > rhs.ip_version_;
|
||||
}
|
||||
|
||||
// All things above are the same, we can at least sort with key.
|
||||
return key_ < rhs.key_;
|
||||
// Now we start getting into arbitrary stuff
|
||||
if (ifname_ != rhs.ifname_) {
|
||||
return ifname_ < rhs.ifname_;
|
||||
}
|
||||
|
||||
return addr_ < rhs.addr_;
|
||||
}
|
||||
|
||||
const std::string& GetKey() const {
|
||||
@@ -85,6 +114,48 @@ private:
|
||||
return 4;
|
||||
}
|
||||
|
||||
// TODO(bug 895790): Once we can get useful interface properties on Darwin,
|
||||
// we should remove this stuff.
|
||||
static const std::vector<std::string>& interface_preference_list()
|
||||
{
|
||||
static std::vector<std::string> list(build_interface_preference_list());
|
||||
return list;
|
||||
}
|
||||
|
||||
static std::vector<std::string> build_interface_preference_list()
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
result.push_back("rl0");
|
||||
result.push_back("wi0");
|
||||
result.push_back("en0");
|
||||
result.push_back("enp2s0");
|
||||
result.push_back("enp3s0");
|
||||
result.push_back("en1");
|
||||
result.push_back("en2");
|
||||
result.push_back("en3");
|
||||
result.push_back("eth0");
|
||||
result.push_back("eth1");
|
||||
result.push_back("eth2");
|
||||
result.push_back("em1");
|
||||
result.push_back("em0");
|
||||
result.push_back("ppp");
|
||||
result.push_back("ppp0");
|
||||
result.push_back("vmnet1");
|
||||
result.push_back("vmnet0");
|
||||
result.push_back("vmnet3");
|
||||
result.push_back("vmnet4");
|
||||
result.push_back("vmnet5");
|
||||
result.push_back("vmnet6");
|
||||
result.push_back("vmnet7");
|
||||
result.push_back("vmnet8");
|
||||
result.push_back("virbr0");
|
||||
result.push_back("wlan0");
|
||||
result.push_back("lo0");
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ifname_;
|
||||
std::string addr_;
|
||||
std::string key_;
|
||||
int is_vpn_;
|
||||
int estimated_speed_;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
Library('mtransport_standalone')
|
||||
|
||||
include('../common.build')
|
||||
include("/ipc/chromium/chromium-config.mozbuild")
|
||||
|
||||
# These files cannot be built in unified mode because of the redefinition of
|
||||
# getLogModule, UNIMPLEMENTED, nr_socket_long_term_violation_time,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user