merge mozilla-inbound to mozilla-central a=merge
authorIris Hsiao <ihsiao@mozilla.com>
Mon, 26 Sep 2016 18:34:20 +0800
changeset 315232 c55bcb7c777ea09431b4d16903ed079ae5632648
parent 315126 dca71ebb955d5bbfaa9c7fca0539f9aaf9e12b5d (current diff)
parent 315231 e1babcef001ebbfcd1852e86c15f924e3f0c2af4 (diff)
child 315248 eb840c87b5fdb85756a6f6c32458bfb05240c534
child 315268 4b5a9f8b52d493e4b867b666433fe2aae254c100
child 315274 87aeaae19f90e0a5f0809c5bcec3ea2276f07978
push id30744
push userihsiao@mozilla.com
push dateMon, 26 Sep 2016 10:35:40 +0000
treeherdermozilla-central@c55bcb7c777e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
dom/grid/test/chrome/test_grid_track_state.html
dom/media/MediaDecoder.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
gfx/layers/ipc/CompositorBridgeParent.cpp
js/src/jit-test/tests/wasm/spec/block_comments.wast
js/src/jit-test/tests/wasm/spec/block_comments.wast.js
js/src/jit-test/tests/wasm/spec/functions.wast
js/src/jit-test/tests/wasm/spec/functions.wast.js
js/src/jit-test/tests/wasm/spec/runaway-recursion.wast
js/src/jit-test/tests/wasm/spec/runaway-recursion.wast.js
js/src/jit-test/tests/wasm/totext1.js
js/src/jit-test/tests/wasm/totext2.js
layout/style/nsStyleStruct.h
taskcluster/taskgraph/decision.py
testing/luciddream/README.md
testing/luciddream/example-tests/luciddream.ini
testing/luciddream/example-tests/test.js
testing/luciddream/example-tests/test_sample.py
testing/luciddream/luciddream/__init__.py
testing/luciddream/luciddream/runluciddream.py
testing/luciddream/mach_commands.py
testing/luciddream/requirements.txt
testing/luciddream/setup.py
testing/mozharness/configs/luciddream/linux_config.py
testing/mozharness/scripts/luciddream_unittest.py
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/cross-origin/http-http/iframe-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/cross-origin/http-http/iframe-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/cross-origin/http-http/iframe-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/cross-origin/http-https/iframe-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/cross-origin/http-https/iframe-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/cross-origin/http-https/iframe-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/same-origin/http-http/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/attr-referrer/same-origin/http-https/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/fetch-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/fetch-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/fetch-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/iframe-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/iframe-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/iframe-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/script-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/script-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/script-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/xhr-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/xhr-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-http/xhr-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/fetch-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/fetch-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/fetch-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/iframe-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/iframe-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/iframe-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/script-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/script-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/script-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/xhr-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/xhr-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/cross-origin/http-https/xhr-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-http/fetch-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-http/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-http/script-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-http/xhr-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-https/fetch-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-https/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-https/script-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/http-rp/same-origin/http-https/xhr-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/fetch-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/fetch-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/fetch-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/iframe-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/iframe-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/iframe-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/script-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/script-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/script-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/xhr-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/xhr-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-http/xhr-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/fetch-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/fetch-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/fetch-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/iframe-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/iframe-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/iframe-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/script-tag/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/script-tag/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/script-tag/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/xhr-request/cross-origin.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/xhr-request/cross-origin.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/xhr-request/cross-origin.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-http/fetch-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-http/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-http/script-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-http/xhr-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-https/fetch-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-https/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-https/script-tag/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/same-origin/meta-referrer/same-origin/http-https/xhr-request/same-origin-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-http/iframe-tag/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-http/iframe-tag/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-http/iframe-tag/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/same-origin/http-http/iframe-tag/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/fetch-request/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/fetch-request/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/fetch-request/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/iframe-tag/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/iframe-tag/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/iframe-tag/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/script-tag/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/script-tag/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/script-tag/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/xhr-request/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/xhr-request/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-http/xhr-request/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-http/fetch-request/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-http/iframe-tag/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-http/script-tag/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-http/xhr-request/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/fetch-request/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/fetch-request/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/fetch-request/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/iframe-tag/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/iframe-tag/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/iframe-tag/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/script-tag/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/script-tag/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/script-tag/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/xhr-request/cross-insecure.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/xhr-request/cross-insecure.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-http/xhr-request/cross-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-http/fetch-request/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-http/iframe-tag/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-http/script-tag/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-http/xhr-request/same-insecure.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/cross-origin/http-http/iframe-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/cross-origin/http-http/iframe-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/cross-origin/http-http/iframe-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/same-origin/http-http/iframe-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/same-origin/http-http/iframe-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/same-origin/http-http/iframe-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/fetch-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/fetch-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/fetch-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/iframe-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/iframe-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/iframe-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/script-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/script-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/script-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/xhr-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/xhr-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-http/xhr-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/fetch-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/fetch-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/fetch-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/iframe-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/iframe-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/iframe-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/script-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/script-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/script-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/xhr-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/xhr-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-http/xhr-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/fetch-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/fetch-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/fetch-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/iframe-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/iframe-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/iframe-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/script-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/script-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/script-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/xhr-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/xhr-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-http/xhr-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/fetch-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/fetch-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/fetch-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/iframe-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/iframe-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/iframe-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/script-tag/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/script-tag/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/script-tag/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/xhr-request/insecure-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/xhr-request/insecure-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-http/xhr-request/insecure-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html.ini
testing/web-platform/meta/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html.ini
--- a/accessible/atk/nsStateMap.h
+++ b/accessible/atk/nsStateMap.h
@@ -73,17 +73,17 @@ static const AtkStateMap gAtkStateMap[] 
   { ATK_STATE_INDETERMINATE,                  kMapDirectly },   // states::MIXED                   = 1 << 5
   { kNone,                                    kMapDirectly },   // states::READONLY                = 1 << 6
   { kNone,                                    kMapDirectly },   // states::HOTTRACKED              = 1 << 7
   { ATK_STATE_DEFAULT,                        kMapDirectly },   // states::DEFAULT                 = 1 << 8
   { ATK_STATE_EXPANDED,                       kMapDirectly },   // states::EXPANDED                = 1 << 9
   { kNone,                                    kNoStateChange }, // states::COLLAPSED               = 1 << 10
   { ATK_STATE_BUSY,                           kMapDirectly },   // states::BUSY                    = 1 << 11
   { kNone,                                    kMapDirectly },   // states::FLOATING                = 1 << 12
-  { kNone,                                    kMapDirectly },   // states::CHECKABLE               = 1 << 13
+  { ATK_STATE_CHECKABLE,                      kMapDirectly },   // states::CHECKABLE               = 1 << 13
   { ATK_STATE_ANIMATED,                       kMapDirectly },   // states::ANIMATED                = 1 << 14
   { ATK_STATE_VISIBLE,                        kMapOpposite },   // states::INVISIBLE               = 1 << 15
   { ATK_STATE_SHOWING,                        kMapOpposite },   // states::OFFSCREEN               = 1 << 16
   { ATK_STATE_RESIZABLE,                      kMapDirectly },   // states::SIZEABLE                = 1 << 17
   { kNone,                                    kMapDirectly },   // states::MOVEABLE                = 1 << 18
   { kNone,                                    kMapDirectly },   // states::SELFVOICING             = 1 << 19
   { ATK_STATE_FOCUSABLE,                      kMapDirectly },   // states::FOCUSABLE               = 1 << 20
   { ATK_STATE_SELECTABLE,                     kMapDirectly },   // states::SELECTABLE              = 1 << 21
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -1370,17 +1370,17 @@ DocAccessible::RecreateAccessible(nsICon
 void
 DocAccessible::ProcessInvalidationList()
 {
   // Invalidate children of container accessible for each element in
   // invalidation list. Allow invalidation list insertions while container
   // children are recached.
   for (uint32_t idx = 0; idx < mInvalidationList.Length(); idx++) {
     nsIContent* content = mInvalidationList[idx];
-    if (!HasAccessible(content)) {
+    if (!HasAccessible(content) && content->HasID()) {
       Accessible* container = GetContainerAccessible(content);
       if (container) {
         // Check if the node is a target of aria-owns, and if so, don't process
         // it here and let DoARIAOwnsRelocation process it.
         AttrRelProviderArray* list =
           mDependentIDsHash.Get(nsDependentAtomString(content->GetID()));
         bool shouldProcess = !!list;
         if (shouldProcess) {
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -157,16 +157,19 @@ var handleContentContextMenu = function 
         contentDisposition =
           props.get("content-disposition", Ci.nsISupportsCString).data;
       } catch (e) {}
     } catch (e) {}
   }
 
   let selectionInfo = BrowserUtils.getSelectionDetails(content);
 
+  let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
+  let userContextId = loadContext.originAttributes.userContextId;
+
   if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
     let editFlags = SpellCheckHelper.isEditable(event.target, content);
     let spellInfo;
     if (editFlags &
         (SpellCheckHelper.EDITABLE | SpellCheckHelper.CONTENTEDITABLE)) {
       spellInfo =
         InlineSpellCheckerContent.initContextMenu(event, editFlags, this);
     }
@@ -180,17 +183,17 @@ var handleContentContextMenu = function 
 
     let customMenuItems = PageMenuChild.build(event.target);
     let principal = doc.nodePrincipal;
     sendRpcMessage("contextmenu",
                    { editFlags, spellInfo, customMenuItems, addonInfo,
                      principal, docLocation, charSet, baseURI, referrer,
                      referrerPolicy, contentType, contentDisposition,
                      frameOuterWindowID, selectionInfo, disableSetDesktopBg,
-                     loginFillInfo, parentAllowsMixedContent },
+                     loginFillInfo, parentAllowsMixedContent, userContextId },
                    { event, popupNode: event.target });
   }
   else {
     // Break out to the parent window and pass the add-on info along
     let browser = docShell.chromeEventHandler;
     let mainWin = browser.ownerGlobal;
     mainWin.gContextMenuContentData = {
       isRemote: false,
@@ -204,16 +207,17 @@ var handleContentContextMenu = function 
       referrer: referrer,
       referrerPolicy: referrerPolicy,
       contentType: contentType,
       contentDisposition: contentDisposition,
       selectionInfo: selectionInfo,
       disableSetDesktopBackground: disableSetDesktopBg,
       loginFillInfo,
       parentAllowsMixedContent,
+      userContextId,
     };
   }
 }
 
 Cc["@mozilla.org/eventlistenerservice;1"]
   .getService(Ci.nsIEventListenerService)
   .addSystemEventListener(global, "contextmenu", handleContentContextMenu, false);
 
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -141,24 +141,24 @@ nsContextMenu.prototype = {
         this.linkURI = makeURI(this.linkURL);
       } catch (ex) {}
 
       this.linkTextStr = this.selectionInfo.linkText;
       this.onPlainTextLink = true;
     }
 
     var inContainer = false;
-    var userContextId = this.browser.contentPrincipal.originAttributes.userContextId;
-    if (userContextId) {
+    if (gContextMenuContentData.userContextId) {
       inContainer = true;
       var item = document.getElementById("context-openlinkincontainertab");
 
-      item.setAttribute("data-usercontextid", userContextId);
+      item.setAttribute("data-usercontextid", gContextMenuContentData.userContextId);
 
-      var label = ContextualIdentityService.getUserContextLabel(userContextId);
+      var label =
+        ContextualIdentityService.getUserContextLabel(gContextMenuContentData.userContextId);
       item.setAttribute("label",
          gBrowserBundle.formatStringFromName("userContextOpenLink.label",
                                              [label], 1));
     }
 
     var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
     var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
     var showContainers = Services.prefs.getBoolPref("privacy.userContext.enabled");
@@ -970,17 +970,17 @@ nsContextMenu.prototype = {
                    noReferrer: this.linkHasNoReferrer };
     for (let p in extra) {
       params[p] = extra[p];
     }
 
     // If we want to change userContextId, we must be sure that we don't
     // propagate the referrer.
     if ("userContextId" in params &&
-        params.userContextId != this.principal.originAttributes.userContextId) {
+        params.userContextId != gContextMenuContentData.userContextId) {
       params.noReferrer = true;
     }
 
     return params;
   },
 
   // Open linked-to URL in a new window.
   openLink : function () {
@@ -1859,12 +1859,12 @@ nsContextMenu.prototype = {
   _checkTelemetryForMenu: function(aXulMenu) {
     this._telemetryClickID = null;
     this._telemetryPageContext = this._getTelemetryPageContextInfo();
     this._telemetryHadCustomItems = this.hasPageMenu;
     this._getTelemetryClickInfo(aXulMenu);
   },
 
   createContainerMenu: function(aEvent) {
-    var userContextId = this.browser.contentPrincipal.originAttributes.userContextId;
-    return createUserContextMenu(aEvent, false, userContextId);
+    return createUserContextMenu(aEvent, false,
+                                 gContextMenuContentData.userContextId);
   },
 };
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -4532,16 +4532,17 @@
                                           referrerPolicy: data.referrerPolicy,
                                           contentType: data.contentType,
                                           contentDisposition: data.contentDisposition,
                                           frameOuterWindowID: data.frameOuterWindowID,
                                           selectionInfo: data.selectionInfo,
                                           disableSetDesktopBackground: data.disableSetDesktopBg,
                                           loginFillInfo: data.loginFillInfo,
                                           parentAllowsMixedContent: data.parentAllowsMixedContent,
+                                          userContextId: data.userContextId,
                                         };
               let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
               let event = gContextMenuContentData.event;
               popup.openPopupAtScreen(event.screenX, event.screenY, true);
               break;
             }
             case "DOMServiceWorkerFocusClient":
             case "DOMWebNotificationClicked": {
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -119,22 +119,18 @@
 
 .identity-popup-expander {
   margin: 0;
   padding: 4px 0;
   min-width: auto;
   width: var(--identity-popup-expander-width);
   border: 0 none;
   -moz-appearance: none;
-  background-image: url("chrome://browser/skin/controlcenter/arrow-subview.svg"),
-                    linear-gradient(rgba(255,255,255,0.3), transparent);
+  background: url("chrome://browser/skin/controlcenter/arrow-subview.svg") center no-repeat;
   background-size: 16px, auto;
-  background-position: center;
-  background-repeat: no-repeat;
-  background-color: transparent;
 }
 
 .identity-popup-expander:-moz-locale-dir(rtl) {
   transform: scaleX(-1);
 }
 
 .identity-popup-expander[panel-multiview-anchor] {
   transition: background-color 250ms ease-in;
@@ -152,16 +148,18 @@
 
 .identity-popup-expander:-moz-focusring > .button-box,
 .identity-popup-expander[panel-multiview-anchor] > .button-box {
   border-style: none;
 }
 
 .identity-popup-expander:hover {
   background-color: var(--arrowpanel-dimmed);
+  background-image: url("chrome://browser/skin/controlcenter/arrow-subview.svg"),
+                    linear-gradient(rgba(255,255,255,0.3), transparent);
 }
 
 .identity-popup-expander:hover:active {
   background-color: var(--arrowpanel-dimmed-further);
   box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
 }
 
 /* CONTENT */
@@ -373,18 +371,16 @@ description#identity-popup-content-verif
 }
 
 .identity-popup-permission-icon {
   width: 16px;
   height: 16px;
 }
 
 .identity-popup-permission-icon.in-use {
-  fill: rgb(224, 41, 29);
-  opacity: 1;
   animation: 1.5s ease in-use-blink infinite;
 }
 
 @keyframes in-use-blink {
   50% { opacity: 0; }
 }
 
 .identity-popup-permission-label {
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -104,31 +104,29 @@
   width: 16px;
   height: 16px;
   margin-inline-start: -16px;
   position: relative;
   display: none;
 }
 
 #identity-box[sharing="camera"] > #sharing-icon {
-  list-style-image: url("chrome://browser/skin/notification-icons.svg#camera");
+  list-style-image: url("chrome://browser/skin/notification-icons.svg#camera-sharing");
 }
 
 #identity-box[sharing="microphone"] > #sharing-icon {
-  list-style-image: url("chrome://browser/skin/notification-icons.svg#microphone");
+  list-style-image: url("chrome://browser/skin/notification-icons.svg#microphone-sharing");
 }
 
 #identity-box[sharing="screen"] > #sharing-icon {
-  list-style-image: url("chrome://browser/skin/notification-icons.svg#screen");
+  list-style-image: url("chrome://browser/skin/notification-icons.svg#screen-sharing");
 }
 
 #identity-box[sharing] > #sharing-icon {
   display: -moz-box;
-  filter: url("chrome://browser/skin/filters.svg#fill");
-  fill: rgb(224, 41, 29);
   animation-delay: -1.5s;
 }
 
 #identity-box[sharing] > #identity-icon,
 #sharing-icon {
   animation: 3s linear pulse infinite;
 }
 
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -63,17 +63,17 @@
   skin/classic/browser/heartbeat-star-off.svg                  (../shared/heartbeat-star-off.svg)
   skin/classic/browser/connection-secure.svg                   (../shared/identity-block/connection-secure.svg)
 * skin/classic/browser/connection-mixed-passive-loaded.svg     (../shared/identity-block/connection-mixed-passive-loaded.svg)
 * skin/classic/browser/connection-mixed-active-loaded.svg      (../shared/identity-block/connection-mixed-active-loaded.svg)
 * skin/classic/browser/identity-icon.svg                       (../shared/identity-block/identity-icon.svg)
   skin/classic/browser/info.svg                                (../shared/info.svg)
 * skin/classic/browser/menuPanel.svg                           (../shared/menuPanel.svg)
 * skin/classic/browser/menuPanel-small.svg                     (../shared/menuPanel-small.svg)
-  skin/classic/browser/notification-icons.svg                  (../shared/notification-icons.svg)
+* skin/classic/browser/notification-icons.svg                  (../shared/notification-icons.svg)
 * skin/classic/browser/tracking-protection-16.svg              (../shared/identity-block/tracking-protection-16.svg)
   skin/classic/browser/newtab/close.png                        (../shared/newtab/close.png)
   skin/classic/browser/newtab/controls.svg                     (../shared/newtab/controls.svg)
   skin/classic/browser/newtab/whimsycorn.png                   (../shared/newtab/whimsycorn.png)
   skin/classic/browser/panel-icons.svg                         (../shared/panel-icons.svg)
   skin/classic/browser/preferences/in-content/favicon.ico      (../shared/incontentprefs/favicon.ico)
   skin/classic/browser/preferences/in-content/icons.svg        (../shared/incontentprefs/icons.svg)
   skin/classic/browser/preferences/in-content/search.css       (../shared/incontentprefs/search.css)
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -40,40 +40,24 @@
 }
 
 .popup-notification-icon {
   width: 64px;
   height: 64px;
   margin-inline-end: 10px;
 }
 
-.camera-icon,
-.geo-icon,
-.indexedDB-icon,
-.install-icon,
-.login-icon,
-.microphone-icon,
-.plugin-icon,
-.popup-icon,
-.screen-icon,
-.desktop-notification-icon,
-.popup-notification-icon[popupid="geolocation"],
-.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
-.popup-notification-icon[popupid="password"],
-.popup-notification-icon[popupid="webRTC-shareDevices"],
-.popup-notification-icon[popupid="webRTC-shareMicrophone"],
-.popup-notification-icon[popupid="webRTC-shareScreen"],
-.popup-notification-icon[popupid="web-notifications"] {
+.notification-anchor-icon:not(.plugin-blocked):-moz-lwtheme,
+#blocked-permissions-container > .blocked-permission-icon:-moz-lwtheme {
   filter: url(chrome://browser/skin/filters.svg#fill);
   fill: currentColor;
-  opacity: .4;
 }
 
-.notification-anchor-icon:not(.plugin-blocked):hover {
-  opacity: .6;
+.notification-anchor-icon:not(.plugin-blocked):not(:hover) {
+  opacity: .8;
 }
 
 /* INDIVIDUAL NOTIFICATIONS */
 
 .popup-notification-icon[popupid="web-notifications"],
 .desktop-notification-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#desktop-notification);
 }
@@ -129,37 +113,49 @@
   list-style-image: url(chrome://browser/skin/notification-icons.svg#login-detailed);
 }
 
 .camera-icon,
 .popup-notification-icon[popupid="webRTC-shareDevices"] {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#camera);
 }
 
+.camera-icon.in-use {
+  list-style-image: url(chrome://browser/skin/notification-icons.svg#camera-sharing);
+}
+
 .camera-icon.blocked-permission-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#camera-blocked);
 }
 
 .microphone-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#microphone);
 }
 
+.microphone-icon.in-use {
+  list-style-image: url(chrome://browser/skin/notification-icons.svg#microphone-sharing);
+}
+
 .microphone-icon.blocked-permission-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#microphone-blocked);
 }
 
 .popup-notification-icon[popupid="webRTC-shareMicrophone"] {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#microphone-detailed);
 }
 
 .popup-notification-icon[popupid="webRTC-shareScreen"],
 .screen-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#screen);
 }
 
+.screen-icon.in-use {
+  list-style-image: url(chrome://browser/skin/notification-icons.svg#screen-sharing);
+}
+
 .screen-icon.blocked-permission-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#screen-blocked);
 }
 
 /* This icon has a block sign in it, so we don't need a blocked version. */
 .popup-icon {
   list-style-image: url("chrome://browser/skin/notification-icons.svg#popup");
 }
@@ -236,18 +232,16 @@
 /* PLUGINS */
 
 .plugin-icon {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin);
 }
 
 .plugin-icon.plugin-blocked {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin-blocked);
-  fill: #d92215;
-  opacity: 1;
 }
 
 #notification-popup-box[hidden] {
   /* Override display:none to make the pluginBlockedNotification animation work
      when showing the notification repeatedly. */
   display: -moz-box;
   visibility: collapse;
 }
--- a/browser/themes/shared/notification-icons.svg
+++ b/browser/themes/shared/notification-icons.svg
@@ -1,28 +1,43 @@
 <?xml version="1.0"?>
 <!-- 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/. -->
 <svg xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
+     class="fieldtext"
      width="32" height="32" viewBox="0 0 32 32">
+#include icon-colors.inc.svg
   <style>
     use:not(:target) {
       display: none;
     }
     #strikeout {
       display: none;
     }
     .blocked:target ~ #strikeout {
       display: block;
     }
     .blocked {
       clip-path: url(#clip);
     }
+
+    #plugin-blocked,
+    #plugin-blocked:target ~ #strikeout {
+      fill: #d92215;
+      fill-opacity: 1;
+    }
+
+    #camera-sharing,
+    #microphone-sharing,
+    #screen-sharing {
+      fill: rgb(224, 41, 29);
+      fill-opacity: 1;
+    }
   </style>
 
   <defs>
     <path id="camera-icon" d="m 2,23 a 3,3 0 0 0 3,3 l 14,0 a 3,3 0 0 0 3,-3 l 0,-4 6,5.5 c 0.5,0.5 1,0.7 2,0.5 l 0,-18 c -1,-0.2 -1.5,0 -2,0.5 l -6,5.5 0,-4 a 3,3 0 0 0 -3,-3 l -14,0 a 3,3 0 0 0 -3,3 z" />
     <path id="desktop-notification-icon" d="m 2,20 a 4,4 0 0 0 4,4 l 13,0 7,7 0,-7 a 4,4 0 0 0 4,-4 l 0,-12 a 4,4 0 0 0 -4,-4 l -20,0 a 4,4 0 0 0 -4,4 z m 5,-2 a 1,1 0 1 1 0,-2 l 10,0 a 1,1 0 1 1 0,2 z m 0,-4 a 1,1 0 1 1 0,-2 l 14,0 a 1,1 0 1 1 0,2 z m 0,-4 a 1,1 0 1 1 0,-2 l 18,0 a 1,1 0 1 1 0,2 z" />
     <path id="geo-linux-icon" d="m 2,15.9 a 14,14 0 1 1 0,0.2 z m 4,2.1 a 10,10 0 0 0 8,8 l 0,-4 4,0 0,4 a 10,10 0 0 0 8,-8 l -4,0 0,-4 4,0 a 10,10 0 0 0 -8,-8 l 0,4 -4,0 0,-4 a 10,10 0 0 0 -8,8 l 4,0 0,4 z" />
     <path id="geo-linux-detailed-icon" d="m 2,15.9 a 14,14 0 1 1 0,0.2 z m 3,2.1 a 11,11 0 0 0 9,9 l 1,-5 2,0 1,5 a 11,11 0 0 0 9,-9 l -5,-1 0,-2 5,-1 a 11,11 0 0 0 -9,-9 l -1,5 -2,0 -1,-5 a 11,11 0 0 0 -9,9 l 5,1 0,2 z" />
     <path id="geo-osx-icon" d="m 0,16 16,0 0,16 12,-28 z" />
@@ -38,34 +53,37 @@
     <path id="screen-icon" d="m 2,18 a 2,2 0 0 0 2,2 l 2,0 0,-6 a 4,4 0 0 1 4,-4 l 14,0 0,-6 a 2,2 0 0 0 -2,-2 l -18,0 a 2,2 0 0 0 -2,2 z m 6,10 a 2,2 0 0 0 2,2 l 18,0 a 2,2 0 0 0 2,-2 l 0,-14 a 2,2 0 0 0 -2,-2 l -18,0 a 2,2 0 0 0 -2,2 z" />
 
     <clipPath id="clip">
       <path d="m 0,0 0,31 31,-31 z m 6,32 26,0 0,-26 z"/>
     </clipPath>
   </defs>
 
   <use id="camera" xlink:href="#camera-icon" />
+  <use id="camera-sharing" xlink:href="#camera-icon"/>
   <use id="camera-blocked" class="blocked" xlink:href="#camera-icon" />
   <use id="desktop-notification" xlink:href="#desktop-notification-icon" />
   <use id="desktop-notification-blocked" class="blocked" xlink:href="#desktop-notification-icon" />
   <use id="geo-osx" xlink:href="#geo-osx-icon" />
   <use id="geo-osx-blocked" class="blocked" xlink:href="#geo-osx-icon" />
   <use id="geo-linux" xlink:href="#geo-linux-icon" />
   <use id="geo-linux-blocked" class="blocked" xlink:href="#geo-linux-icon" />
   <use id="geo-linux-detailed" xlink:href="#geo-linux-detailed-icon" />
   <use id="geo-windows" xlink:href="#geo-windows-icon" />
   <use id="geo-windows-blocked" class="blocked" xlink:href="#geo-windows-icon" />
   <use id="geo-windows-detailed" xlink:href="#geo-windows-detailed-icon" />
   <use id="indexedDB" xlink:href="#indexedDB-icon" />
   <use id="indexedDB-blocked" class="blocked" xlink:href="#indexedDB-icon" />
   <use id="login" xlink:href="#login-icon" />
   <use id="login-detailed" xlink:href="#login-detailed-icon" />
   <use id="microphone" xlink:href="#microphone-icon" />
+  <use id="microphone-sharing" xlink:href="#microphone-icon"/>
   <use id="microphone-blocked" class="blocked" xlink:href="#microphone-icon" />
   <use id="microphone-detailed" xlink:href="#microphone-detailed-icon" />
   <use id="plugin" xlink:href="#plugin-icon" />
   <use id="plugin-blocked" class="blocked" xlink:href="#plugin-icon" />
   <use id="popup" xlink:href="#popup-icon" />
   <use id="screen" xlink:href="#screen-icon" />
+  <use id="screen-sharing" xlink:href="#screen-icon"/>
   <use id="screen-blocked" class="blocked" xlink:href="#screen-icon" />
 
   <path id="strikeout" d="m 2,28 2,2 26,-26 -2,-2 z"/>
 </svg>
--- a/browser/themes/shared/plugin-doorhanger.inc.css
+++ b/browser/themes/shared/plugin-doorhanger.inc.css
@@ -46,24 +46,20 @@
 
 .click-to-play-plugins-notification-link,
 .center-item-link {
   margin: 0;
 }
 
 .messageImage[value="plugin-hidden"] {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin);
-  filter: url(chrome://browser/skin/filters.svg#fill);
-  fill: #808080;
 }
 
 /* Keep any changes to this style in sync with pluginProblem.css */
 notification.pluginVulnerable {
   background-color: rgb(72,72,72);
   background-image: url(chrome://mozapps/skin/plugins/contentPluginStripe.png);
   color: white;
 }
 
 notification.pluginVulnerable .messageImage {
   list-style-image: url(chrome://browser/skin/notification-icons.svg#plugin-blocked);
-  filter: url(chrome://browser/skin/filters.svg#fill);
-  fill: #d92215;
 }
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -62,17 +62,16 @@ SEARCH_PATHS = [
     'dom/bindings/parser',
     'dom/media/test/external',
     'layout/tools/reftest',
     'other-licenses/ply',
     'taskcluster',
     'testing',
     'testing/firefox-ui/harness',
     'testing/firefox-ui/tests',
-    'testing/luciddream',
     'testing/marionette/harness',
     'testing/marionette/harness/marionette/runner/mixins/browsermob-proxy-py',
     'testing/marionette/client',
     'testing/mozbase/mozcrash',
     'testing/mozbase/mozdebug',
     'testing/mozbase/mozdevice',
     'testing/mozbase/mozfile',
     'testing/mozbase/mozhttpd',
@@ -114,17 +113,16 @@ MACH_MODULES = [
     'python/mozboot/mozboot/mach_commands.py',
     'python/mozbuild/mozbuild/mach_commands.py',
     'python/mozbuild/mozbuild/backend/mach_commands.py',
     'python/mozbuild/mozbuild/compilation/codecomplete.py',
     'python/mozbuild/mozbuild/frontend/mach_commands.py',
     'services/common/tests/mach_commands.py',
     'taskcluster/mach_commands.py',
     'testing/firefox-ui/mach_commands.py',
-    'testing/luciddream/mach_commands.py',
     'testing/mach_commands.py',
     'testing/marionette/mach_commands.py',
     'testing/mochitest/mach_commands.py',
     'testing/mozharness/mach_commands.py',
     'testing/talos/mach_commands.py',
     'testing/web-platform/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
     'tools/docs/mach_commands.py',
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1737,17 +1737,17 @@ Element::BindToTree(nsIDocument* aDocume
   // It would be cleanest to mark nodes as dirty when (a) they're created and
   // (b) they're unbound from a tree. However, we can't easily do (a) right now,
   // because IsStyledByServo() is not always easy to check at node creation time,
   // and the bits have different meaning in the non-IsStyledByServo case.
   //
   // So for now, we just mark nodes as dirty when they're inserted into a
   // document or shadow tree.
   if (IsStyledByServo() && IsInComposedDoc()) {
-    MOZ_ASSERT(!ServoData().get());
+    MOZ_ASSERT(!HasServoData());
     SetIsDirtyForServo();
   }
 
   // XXXbz script execution during binding can trigger some of these
   // postcondition asserts....  But we do want that, since things will
   // generally be quite broken when that happens.
   NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document");
   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
@@ -1852,20 +1852,20 @@ Element::UnbindFromTree(bool aDeep, bool
     DeleteProperty(nsGkAtoms::animationsProperty);
   }
 
   ClearInDocument();
 
   // Computed styled data isn't useful for detached nodes, and we'll need to
   // recomputed it anyway if we ever insert the nodes back into a document.
   if (IsStyledByServo()) {
-    ServoData().reset();
+    ClearServoData();
   } else {
 #ifdef MOZ_STYLO
-    MOZ_ASSERT(!ServoData());
+    MOZ_ASSERT(!HasServoData());
 #endif
   }
 
   // Editable descendant count only counts descendants that
   // are in the uncomposed document.
   ResetEditableDescendantCount();
 
   if (aNullParent || !mParent->IsInShadowTree()) {
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -562,17 +562,17 @@ nsGenericDOMDataNode::BindToTree(nsIDocu
   // It would be cleanest to mark nodes as dirty when (a) they're created and
   // (b) they're unbound from a tree. However, we can't easily do (a) right now,
   // because IsStyledByServo() is not always easy to check at node creation time,
   // and the bits have different meaning in the non-IsStyledByServo case.
   //
   // So for now, we just mark nodes as dirty when they're inserted into a
   // document or shadow tree.
   if (IsStyledByServo() && IsInComposedDoc()) {
-    MOZ_ASSERT(!ServoData().get());
+    MOZ_ASSERT(!HasServoData());
     SetIsDirtyForServo();
   }
 
   NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document");
   NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
   NS_POSTCONDITION(aBindingParent == GetBindingParent(),
                    "Bound to wrong binding parent");
 
@@ -600,20 +600,20 @@ nsGenericDOMDataNode::UnbindFromTree(boo
     }
     SetParentIsContent(false);
   }
   ClearInDocument();
 
   // Computed styled data isn't useful for detached nodes, and we'll need to
   // recomputed it anyway if we ever insert the nodes back into a document.
   if (IsStyledByServo()) {
-    ServoData().reset();
+    ClearServoData();
   } else {
 #ifdef MOZ_STYLO
-    MOZ_ASSERT(!ServoData());
+    MOZ_ASSERT(!HasServoData());
 #endif
   }
 
   if (aNullParent || !mParent->IsInShadowTree()) {
     UnsetFlags(NODE_IS_IN_SHADOW_TREE);
 
     // Begin keeping track of our subtree root.
     SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -147,16 +147,19 @@ nsINode::nsSlots::Unlink()
 }
 
 //----------------------------------------------------------------------
 
 nsINode::~nsINode()
 {
   MOZ_ASSERT(!HasSlots(), "nsNodeUtils::LastRelease was not called?");
   MOZ_ASSERT(mSubtreeRoot == this, "Didn't restore state properly?");
+#ifdef MOZ_STYLO
+  ClearServoData();
+#endif
 }
 
 void*
 nsINode::GetProperty(uint16_t aCategory, nsIAtom *aPropertyName,
                      nsresult *aStatus) const
 {
   return OwnerDoc()->PropertyTable(aCategory)->GetProperty(this, aPropertyName,
                                                            aStatus);
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -3,16 +3,17 @@
 /* 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/. */
 
 #ifndef nsINode_h___
 #define nsINode_h___
 
 #include "mozilla/Likely.h"
+#include "mozilla/ServoTypes.h"
 #include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"               // for member, local
 #include "nsGkAtoms.h"              // for nsGkAtoms::baseURIProperty
 #include "nsIDOMNode.h"
 #include "mozilla/dom/NodeInfo.h"            // member (in nsCOMPtr)
 #include "nsIVariant.h"             // for use in GetUserData()
 #include "nsNodeInfoManager.h"      // for use in NodePrincipal()
 #include "nsPropertyTable.h"        // for typedefs
@@ -48,31 +49,17 @@ class nsINode;
 class nsINodeList;
 class nsIPresShell;
 class nsIPrincipal;
 class nsIURI;
 class nsNodeSupportsWeakRefTearoff;
 class nsNodeWeakReference;
 class nsDOMMutationObserver;
 
-// We declare the bare minimum infrastructure here to allow us to have a
-// UniquePtr<ServoNodeData> on nsINode.
-struct ServoNodeData;
-extern "C" void Servo_NodeData_Drop(ServoNodeData*);
-namespace mozilla {
-template<>
-class DefaultDelete<ServoNodeData>
-{
-public:
-  void operator()(ServoNodeData* aPtr) const
-  {
-    Servo_NodeData_Drop(aPtr);
-  }
-};
-} // namespace mozilla
+extern "C" void Servo_Node_ClearNodeData(nsINode*);
 
 namespace mozilla {
 class EventListenerManager;
 namespace dom {
 /**
  * @return true if aChar is what the DOM spec defines as 'space character'.
  * http://dom.spec.whatwg.org/#space-character
  */
@@ -2085,19 +2072,27 @@ public:
   void SetOn##name_(mozilla::dom::EventHandlerNonNull* listener);
 #define TOUCH_EVENT EVENT
 #define DOCUMENT_ONLY_EVENT EVENT
 #include "mozilla/EventNameList.h"
 #undef DOCUMENT_ONLY_EVENT
 #undef TOUCH_EVENT
 #undef EVENT
 
-  mozilla::UniquePtr<ServoNodeData>& ServoData() {
+  bool HasServoData() {
 #ifdef MOZ_STYLO
-    return mServoNodeData;
+    return !!mServoData.Get();
+#else
+    MOZ_CRASH("Accessing servo node data in non-stylo build");
+#endif
+  }
+
+  void ClearServoData() {
+#ifdef MOZ_STYLO
+    Servo_Node_ClearNodeData(this);
 #else
     MOZ_CRASH("Accessing servo node data in non-stylo build");
 #endif
   }
 
 protected:
   static bool Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb);
   static void Unlink(nsINode *tmp);
@@ -2132,18 +2127,18 @@ protected:
     // object itself, or is reset by ClearSubtreeRootPointer.
     nsINode* MOZ_NON_OWNING_REF mSubtreeRoot;
   };
 
   // Storage for more members that are usually not needed; allocated lazily.
   nsSlots* mSlots;
 
 #ifdef MOZ_STYLO
-  // Layout data managed by Servo.
-  mozilla::UniquePtr<ServoNodeData> mServoNodeData;
+  // Per-node data managed by Servo.
+  mozilla::ServoCell<ServoNodeData*> mServoData;
 #endif
 };
 
 inline nsIDOMNode* GetAsDOMNode(nsINode* aNode)
 {
   return aNode ? aNode->AsDOMNode() : nullptr;
 }
 
--- a/dom/base/nsWrapperCache.cpp
+++ b/dom/base/nsWrapperCache.cpp
@@ -64,65 +64,62 @@ nsWrapperCache::ReleaseWrapper(void* aSc
 
 #ifdef DEBUG
 
 class DebugWrapperTraversalCallback : public nsCycleCollectionTraversalCallback
 {
 public:
   explicit DebugWrapperTraversalCallback(JSObject* aWrapper)
     : mFound(false)
-    , mWrapper(aWrapper)
+    , mWrapper(JS::GCCellPtr(aWrapper))
   {
     mFlags = WANT_ALL_TRACES;
   }
 
   NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt aRefCount,
                                            const char* aObjName)
   {
   }
   NS_IMETHOD_(void) DescribeGCedNode(bool aIsMarked,
                                      const char* aObjName,
                                      uint64_t aCompartmentAddress)
   {
   }
 
-  NS_IMETHOD_(void) NoteJSObject(JSObject* aChild)
+  NS_IMETHOD_(void) NoteJSChild(const JS::GCCellPtr& aChild)
   {
     if (aChild == mWrapper) {
       mFound = true;
     }
   }
-  NS_IMETHOD_(void) NoteJSScript(JSScript* aChild)
-  {
-  }
   NS_IMETHOD_(void) NoteXPCOMChild(nsISupports* aChild)
   {
   }
   NS_IMETHOD_(void) NoteNativeChild(void* aChild,
                                     nsCycleCollectionParticipant* aHelper)
   {
   }
 
   NS_IMETHOD_(void) NoteNextEdgeName(const char* aName)
   {
   }
 
   bool mFound;
 
 private:
-  JSObject* mWrapper;
+  JS::GCCellPtr mWrapper;
 };
 
 static void
 DebugWrapperTraceCallback(JS::GCCellPtr aPtr, const char* aName, void* aClosure)
 {
   DebugWrapperTraversalCallback* callback =
     static_cast<DebugWrapperTraversalCallback*>(aClosure);
   if (aPtr.is<JSObject>()) {
-    callback->NoteJSObject(&aPtr.as<JSObject>());
+    callback->NoteJSChild(aPtr);
   }
 }
 
 void
 nsWrapperCache::CheckCCWrapperTraversal(void* aScriptObjectHolder,
                                         nsScriptObjectTracer* aTracer)
 {
   JSObject* wrapper = GetWrapper();
--- a/dom/base/test/referrerHelper.js
+++ b/dom/base/test/referrerHelper.js
@@ -109,127 +109,175 @@ var EXPECTED_RESULTS = {
   //    origin as "ping URL", send a referrer."
   'link-ping': {
     // Same-origin
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': '',
       'origin': '',
       'origin-when-cross-origin': '',
-      'no-referrer-when-downgrade': ''
+      'no-referrer-when-downgrade': '',
+      'same-origin': '',
+      'strict-origin': '',
+      'strict-origin-when-cross-origin':''
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
       'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/',
-      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade'
+      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade',
+      'same-origin': '',
+      'strict-origin': 'http://example.com/',
+      'strict-origin-when-cross-origin':'http://example.com/'
     },
     // Encrypted and not same-origin
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': '',
       'origin': '',
       'origin-when-cross-origin': '',
-      'no-referrer-when-downgrade': ''
+      'no-referrer-when-downgrade': '',
+      'same-origin': '',
+      'strict-origin': '',
+      'strict-origin-when-cross-origin':''
     },
     // Encrypted
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': '',
       'origin': '',
       'origin-when-cross-origin': '',
-      'no-referrer-when-downgrade': ''
+      'no-referrer-when-downgrade': '',
+      'same-origin': '',
+      'strict-origin': '',
+      'strict-origin-when-cross-origin':''
     }
   },
   // form is tested in a 2nd level iframe.
   'form': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=form',
       'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin&type=form',
-      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=form'
+      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=form',
+      'same-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=same-origin&type=form',
+      'strict-origin': 'http://example.com/',
+      'strict-origin-when-cross-origin':'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=strict-origin-when-cross-origin&type=form'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=form',
       'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/',
-      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=form'
+      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=form',
+      'same-origin': '',
+      'strict-origin': 'http://example.com/',
+      'strict-origin-when-cross-origin':'http://example.com/'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=form',
       'origin': 'https://example.com/',
       'origin-when-cross-origin': 'https://example.com/',
-      'no-referrer-when-downgrade': ''
+      'no-referrer-when-downgrade': '',
+      'same-origin': '',
+      'strict-origin': '',
+      'strict-origin-when-cross-origin':''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=form',
       'origin': 'https://example.com/',
      'origin-when-cross-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin&type=form',
-      'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=form'
+      'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=form',
+      'same-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=same-origin&type=form',
+      'strict-origin': 'https://example.com/',
+      'strict-origin-when-cross-origin':'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=strict-origin-when-cross-origin&type=form'
     }
   },
   // window.location is tested in a 2nd level iframe.
   'window.location': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url&type=window.location',
      'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin&type=window.location',
-      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=window.location'
+      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade&type=window.location',
+      'same-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=same-origin&type=window.location',
+      'strict-origin': 'http://example.com/',
+      'strict-origin-when-cross-origin':'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=http&policy=strict-origin-when-cross-origin&type=window.location'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url&type=window.location',
       'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/',
-      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location'
+      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location',
+      'same-origin': '',
+      'strict-origin': 'http://example.com/',
+      'strict-origin-when-cross-origin':'http://example.com/'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url&type=window.location',
       'origin': 'https://example.com/',
       'origin-when-cross-origin': 'https://example.com/',
-      'no-referrer-when-downgrade': ''
+      'no-referrer-when-downgrade': '',
+      'same-origin': '',
+      'strict-origin': '',
+      'strict-origin-when-cross-origin':''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url&type=window.location',
       'origin': 'https://example.com/',
       'origin-when-cross-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin&type=window.location',
-      'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location'
+      'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade&type=window.location',
+      'same-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=same-origin&type=window.location',
+      'strict-origin': 'https://example.com/',
+      'strict-origin-when-cross-origin':'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-2nd-level-iframe&scheme-from=https&scheme-to=https&policy=strict-origin-when-cross-origin&type=window.location'
     }
   },
   'default': {
     'http-to-http': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=unsafe-url',
       'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=origin-when-cross-origin',
-      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade'
+      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=no-referrer-when-downgrade',
+      'same-origin': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=same-origin',
+      'strict-origin': 'http://example.com/',
+      'strict-origin-when-cross-origin':'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=http&policy=strict-origin-when-cross-origin'
     },
     'http-to-https': {
       'no-referrer': '',
       'unsafe-url': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=unsafe-url',
       'origin': 'http://example.com/',
       'origin-when-cross-origin': 'http://example.com/',
-      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade'
+      'no-referrer-when-downgrade': 'http://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=http&scheme-to=https&policy=no-referrer-when-downgrade',
+      'same-origin': '',
+      'strict-origin': 'http://example.com/',
+      'strict-origin-when-cross-origin':'http://example.com/'
     },
     'https-to-http': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=http&policy=unsafe-url',
       'origin': 'https://example.com/',
       'origin-when-cross-origin': 'https://example.com/',
-      'no-referrer-when-downgrade': ''
+      'no-referrer-when-downgrade': '',
+      'same-origin': '',
+      'strict-origin': '',
+      'strict-origin-when-cross-origin':''
     },
     'https-to-https': {
       'no-referrer': '',
       'unsafe-url': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=unsafe-url',
       'origin': 'https://example.com/',
       'origin-when-cross-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=origin-when-cross-origin',
-      'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade'
+      'no-referrer-when-downgrade': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=no-referrer-when-downgrade',
+      'same-origin': 'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=same-origin',
+      'strict-origin': 'https://example.com/',
+      'strict-origin-when-cross-origin':'https://example.com/tests/dom/base/test/bug704320.sjs?action=create-1st-level-iframe&scheme-from=https&scheme-to=https&policy=strict-origin-when-cross-origin'
     }
   }
 };
--- a/dom/base/test/test_anchor_area_referrer.html
+++ b/dom/base/test/test_anchor_area_referrer.html
@@ -30,40 +30,88 @@
          META_POLICY: 'unsafe-url',
          DESC: "origin (anchor) with unsafe-url in meta",
          RESULT: 'origin'},
         {ATTRIBUTE_POLICY: 'no-referrer',
          NAME: 'no-referrer-with-origin-in-meta',
          META_POLICY: 'origin',
          DESC: "no-referrer (anchor) with origin in meta",
          RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         DESC: "same-origin with origin in meta",
+         RESULT: 'full'},
         {NAME: 'no-referrer-in-meta',
          META_POLICY: 'no-referrer',
          DESC: "no-referrer in meta",
          RESULT: 'none'},
 
          // Test if element attr would override meta referr policy.
 
          // 1. Downgrade.
         {ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
          NAME: 'origin-in-meta-downgrade-in-attr',
          META_POLICY: 'origin',
          DESC: 'origin in meta downgrade in attr',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'http',
          RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin-when-cross-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
 
          // 2. No downgrade.
         {ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
          NAME: 'origin-in-meta-downgrade-in-attr',
          META_POLICY: 'origin',
          DESC: 'origin in meta downgrade in attr',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'https',
          RESULT: 'full'},
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin-when-cross-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'full'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'strict-origin-when-cross-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         DESC: "strict-origin-when-cross-origin with origin in meta",
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         DESC: "same-origin with origin in meta",
+         RESULT: 'none'},
+
          // End of element attr overriding test..
 
         {ATTRIBUTE_POLICY: 'origin',
          NAME: 'origin-with-no-meta',
          META_POLICY: '',
          DESC: "origin (anchor) with no meta",
          RESULT: 'origin'}]}
   ];
--- a/dom/base/test/test_bug704320.html
+++ b/dom/base/test/test_bug704320.html
@@ -18,16 +18,19 @@ var generateURLArray = (function(from, t
   const schemeTo = '&scheme-to=';
 
   return [
     from + baseURL + from + schemeTo + to + '&policy=no-referrer-when-downgrade',
     from + baseURL + from + schemeTo + to + '&policy=no-referrer',
     from + baseURL + from + schemeTo + to + '&policy=unsafe-url',
     from + baseURL + from + schemeTo + to + '&policy=origin',
     from + baseURL + from + schemeTo + to + '&policy=origin-when-cross-origin',
+    from + baseURL + from + schemeTo + to + '&policy=same-origin',
+    from + baseURL + from + schemeTo + to + '&policy=strict-origin',
+    from + baseURL + from + schemeTo + to + '&policy=strict-origin-when-cross-origin',
   ];
 });
 
 var testIframeUrls = generateURLArray('http', 'http');
 testIframeUrls = testIframeUrls.concat(generateURLArray('https', 'https'));
 testIframeUrls = testIframeUrls.concat(generateURLArray('http', 'https'));
 testIframeUrls = testIframeUrls.concat(generateURLArray('https', 'http'));
 
--- a/dom/base/test/test_iframe_referrer.html
+++ b/dom/base/test/test_iframe_referrer.html
@@ -11,17 +11,17 @@
   * regular loads
   * regression tests that meta referrer is still working even if attribute referrers are enabled
   https://bugzilla.mozilla.org/show_bug.cgi?id=1175736
   -->
 
   <script type="application/javascript;version=1.7">
 
   const SJS = "://example.com/tests/dom/base/test/referrer_testserver.sjs?";
-  const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY"];
+  const PARAMS = ["ATTRIBUTE_POLICY", "NEW_ATTRIBUTE_POLICY", "META_POLICY", "SCHEME_FROM", "SCHEME_TO"];
 
   const testCases = [
     {ACTION: ["generate-iframe-policy-test"],
       TESTS: [
         {ATTRIBUTE_POLICY: 'unsafe-url',
          NAME: 'unsafe-url-with-origin-in-meta',
          META_POLICY: 'origin',
          DESC: "unsafe-url (iframe) with origin in meta",
@@ -39,17 +39,69 @@
         {NAME: 'no-referrer-in-meta',
          META_POLICY: 'no-referrer',
          DESC: "no-referrer in meta",
          RESULT: 'none'},
         {ATTRIBUTE_POLICY: 'origin',
          NAME: 'origin-with-no-meta',
          META_POLICY: '',
          DESC: "origin (iframe) with no meta",
-         RESULT: 'origin'}]}
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         DESC: "same-origin with origin in meta",
+         RESULT: 'full'},
+
+         // 1. Downgrade.
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin-when-cross-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+
+         // 2. No downgrade.
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'origin in meta strict-origin-when-cross-origin in attr',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'full'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'strict-origin-when-cross-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         DESC: "strict-origin-when-cross-origin with origin in meta",
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         DESC: "same-origin with origin in meta",
+         RESULT: 'none'},
+        ]}
   ];
   </script>
   <script type="application/javascript;version=1.7" src="/tests/dom/base/test/referrer_helper.js"></script>
 </head>
 <body onload="tests.next();">
   <iframe id="testframe"></iframe>
 </body>
 </html>
--- a/dom/base/test/test_link_prefetch.html
+++ b/dom/base/test/test_link_prefetch.html
@@ -32,31 +32,53 @@
          DESC: "prefetch-origin with unsafe-url in meta",
          RESULT: 'origin'},
         {ATTRIBUTE_POLICY: 'no-referrer',
          NAME: 'prefetch-no-referrer-with-origin-in-meta',
          META_POLICY: 'origin',
          REL: 'prefetch',
          DESC: "prefetch-no-referrer with origin in meta",
          RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'prefetch-same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         REL: 'prefetch',
+         DESC: "prefetch-same-origin with origin in meta",
+         RESULT: 'full'},
         {NAME: 'prefetch-no-referrer-in-meta',
          META_POLICY: 'no-referrer',
          REL: 'prefetch',
          DESC: "prefetch-no-referrer in meta",
          RESULT: 'none'},
 
          // Downgrade.
         {ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
          NAME: 'prefetch-origin-in-meta-downgrade-in-attr',
          META_POLICY: 'origin',
          DESC: 'prefetch-origin in meta downgrade in attr',
          REL: 'prefetch',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'http',
          RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'prefetch-origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'prefetch-origin in meta strict-origin in attr',
+         REL: 'prefetch',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'prefetch-origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'prefetch-origin in meta strict-origin-when-cross-origin in attr',
+         REL: 'prefetch',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
 
          // No downgrade.
         {ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
          NAME: 'prefetch-origin-in-meta-downgrade-in-attr',
          META_POLICY: 'origin',
          DESC: 'prefetch-origin in meta downgrade in attr',
          REL: 'prefetch',
          SCHEME_FROM: 'https',
@@ -65,16 +87,33 @@
 
         {ATTRIBUTE_POLICY: 'origin',
          NAME: 'prefetch-origin-with-no-meta',
          META_POLICY: '',
          REL: 'prefetch',
          DESC: "prefetch-origin with no meta",
          RESULT: 'origin'},
 
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'prefetch-origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'prefetch-origin in meta strict-origin in attr',
+         REL: 'prefetch',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'prefetch-origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'prefetch-origin in meta strict-origin-when-cross-origin in attr',
+         REL: 'prefetch',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'full'},
+
         // Cross origin
         {ATTRIBUTE_POLICY: 'origin-when-cross-origin',
          NAME: 'prefetch-origin-when-cross-origin-with-no-meta',
          META_POLICY: '',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'http',
          REL: 'prefetch',
          DESC: "prefetch-origin-when-cross-origin with no meta",
@@ -98,16 +137,32 @@
         {ATTRIBUTE_POLICY: 'origin-when-cross-origin',
          NAME: 'prefetch-origin-when-cross-origin-with-origin-in-meta',
          META_POLICY: 'origin',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'http',
          REL: 'prefetch',
          DESC: "prefetch-origin-when-cross-origin with origin in meta",
          RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'prefetch-strict-origin-when-cross-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         REL: 'prefetch',
+         DESC: "prefetch-strict-origin-when-cross-origin with origin in meta",
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'prefetch-same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         REL: 'prefetch',
+         DESC: "prefetch-same-origin with origin in meta",
+         RESULT: 'none'},
 
         // Invalid
         {ATTRIBUTE_POLICY: 'default',
          NAME: 'prefetch-default-with-no-meta',
          META_POLICY: '',
          REL: 'prefetch',
          DESC: "prefetch-default with no meta",
          RESULT: 'full'},
--- a/dom/base/test/test_link_stylesheet.html
+++ b/dom/base/test/test_link_stylesheet.html
@@ -32,31 +32,53 @@
          DESC: "stylesheet-origin with unsafe-url in meta",
          RESULT: 'origin'},
         {ATTRIBUTE_POLICY: 'no-referrer',
          NAME: 'stylesheet-no-referrer-with-origin-in-meta',
          META_POLICY: 'origin',
          REL: 'stylesheet',
          DESC: "stylesheet-no-referrer with origin in meta",
          RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'stylesheet-same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         REL: 'stylesheet',
+         DESC: "stylesheet-same-origin with origin in meta",
+         RESULT: 'full'},
         {NAME: 'stylesheet-no-referrer-in-meta',
          META_POLICY: 'no-referrer',
          REL: 'stylesheet',
          DESC: "stylesheet-no-referrer in meta",
          RESULT: 'none'},
 
          // Downgrade.
         {ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
          NAME: 'stylesheet-origin-in-meta-downgrade-in-attr',
          META_POLICY: 'origin',
          DESC: 'stylesheet-origin in meta downgrade in attr',
          REL: 'stylesheet',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'http',
          RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'stylesheet-origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'stylesheet-origin in meta strict-origin in attr',
+         REL: 'stylesheet',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'stylesheet-origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'stylesheet-origin in meta strict-origin-when-cross-origin in attr',
+         REL: 'stylesheet',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'http',
+         RESULT: 'none'},
 
           // No downgrade.
         {ATTRIBUTE_POLICY: 'no-referrer-when-downgrade',
          NAME: 'stylesheet-origin-in-meta-downgrade-in-attr',
          META_POLICY: 'origin',
          DESC: 'stylesheet-origin in meta downgrade in attr',
          REL: 'stylesheet',
          SCHEME_FROM: 'https',
@@ -65,16 +87,33 @@
 
         {ATTRIBUTE_POLICY: 'origin',
          NAME: 'stylesheet-origin-with-no-meta',
          META_POLICY: '',
          REL: 'stylesheet',
          DESC: "stylesheet-origin with no meta",
          RESULT: 'origin'},
 
+        {ATTRIBUTE_POLICY: 'strict-origin',
+         NAME: 'stylesheet-origin-in-meta-strict-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'stylesheet-origin in meta strict-origin in attr',
+         REL: 'stylesheet',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'stylesheet-origin-in-meta-strict-origin-when-cross-origin-in-attr',
+         META_POLICY: 'origin',
+         DESC: 'stylesheet-origin in meta strict-origin-when-cross-origin in attr',
+         REL: 'stylesheet',
+         SCHEME_FROM: 'https',
+         SCHEME_TO: 'https',
+         RESULT: 'full'},
+
         // Cross origin
         {ATTRIBUTE_POLICY: 'origin-when-cross-origin',
          NAME: 'stylesheet-origin-when-cross-origin-with-no-meta',
          META_POLICY: '',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'http',
          REL: 'stylesheet',
          DESC: "stylesheet-origin-when-cross-origin with no meta",
@@ -98,16 +137,32 @@
         {ATTRIBUTE_POLICY: 'origin-when-cross-origin',
          NAME: 'stylesheet-origin-when-cross-origin-with-origin-in-meta',
          META_POLICY: 'origin',
          SCHEME_FROM: 'https',
          SCHEME_TO: 'http',
          REL: 'stylesheet',
          DESC: "stylesheet-origin-when-cross-origin with origin in meta",
          RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'strict-origin-when-cross-origin',
+         NAME: 'stylesheet-strict-origin-when-cross-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         REL: 'stylesheet',
+         DESC: "stylesheet-strict-origin-when-cross-origin with origin in meta",
+         RESULT: 'origin'},
+        {ATTRIBUTE_POLICY: 'same-origin',
+         NAME: 'stylesheet-same-origin-with-origin-in-meta',
+         META_POLICY: 'origin',
+         SCHEME_FROM: 'http',
+         SCHEME_TO: 'https',
+         REL: 'stylesheet',
+         DESC: "stylesheet-same-origin with origin in meta",
+         RESULT: 'none'},
 
         // Invalid
         {ATTRIBUTE_POLICY: 'default',
          NAME: 'stylesheet-default-with-no-meta',
          META_POLICY: '',
          REL: 'stylesheet',
          DESC: "stylesheet-default with no meta",
          RESULT: 'full'},
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4004,33 +4004,33 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
 
       if (style == Style::FILL) {
         params.context->SetPattern(pattern);
       } else {
         params.textStrokePattern = pattern;
       }
     }
 
+    const ContextState& state = *mState;
+    drawOpts.mAlpha = state.globalAlpha;
+    drawOpts.mCompositionOp = mCtx->UsedOperation();
+    params.drawOpts = &drawOpts;
+
     if (style == Style::STROKE) {
-      const ContextState& state = *mState;
-      drawOpts.mAlpha = state.globalAlpha;
-      drawOpts.mCompositionOp = mCtx->UsedOperation();
-
       strokeOpts.mLineWidth = state.lineWidth;
       strokeOpts.mLineJoin = state.lineJoin;
       strokeOpts.mLineCap = state.lineCap;
       strokeOpts.mMiterLimit = state.miterLimit;
       strokeOpts.mDashLength = state.dash.Length();
       strokeOpts.mDashPattern =
         (strokeOpts.mDashLength > 0) ? state.dash.Elements() : 0;
       strokeOpts.mDashOffset = state.dashOffset;
 
       params.drawMode = DrawMode::GLYPH_STROKE;
       params.strokeOpts = &strokeOpts;
-      params.drawOpts = &drawOpts;
     }
 
     mTextRun->Draw(gfxTextRun::Range(mTextRun.get()), point, params);
   }
 
   // current text run
   RefPtr<gfxTextRun> mTextRun;
 
--- a/dom/filesystem/compat/FileSystemDirectoryEntry.h
+++ b/dom/filesystem/compat/FileSystemDirectoryEntry.h
@@ -19,18 +19,18 @@ class FileSystemDirectoryReader;
 class FileSystemDirectoryEntry : public FileSystemEntry
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileSystemDirectoryEntry,
                                            FileSystemEntry)
 
   FileSystemDirectoryEntry(nsIGlobalObject* aGlobalObject,
-                          Directory* aDirectory,
-                          FileSystem* aFileSystem);
+                           Directory* aDirectory,
+                           FileSystem* aFileSystem);
 
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual bool
   IsDirectory() const override
   {
     return true;
--- a/dom/filesystem/compat/FileSystemRootDirectoryReader.h
+++ b/dom/filesystem/compat/FileSystemRootDirectoryReader.h
@@ -15,18 +15,18 @@ namespace dom {
 class FileSystemRootDirectoryReader final : public FileSystemDirectoryReader
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FileSystemRootDirectoryReader,
                                            FileSystemDirectoryReader)
 
   explicit FileSystemRootDirectoryReader(nsIGlobalObject* aGlobalObject,
-                                                   FileSystem* aFileSystem,
-                                                   const Sequence<RefPtr<FileSystemEntry>>& aEntries);
+                                         FileSystem* aFileSystem,
+                                         const Sequence<RefPtr<FileSystemEntry>>& aEntries);
 
   virtual void
   ReadEntries(FileSystemEntriesCallback& aSuccessCallback,
               const Optional<OwningNonNull<ErrorCallback>>& aErrorCallback,
               ErrorResult& aRv) override;
 
 private:
   ~FileSystemRootDirectoryReader();
--- a/dom/grid/GridLines.cpp
+++ b/dom/grid/GridLines.cpp
@@ -75,30 +75,30 @@ GridLines::SetLineInfo(const ComputedGri
   }
 
   uint32_t trackCount = aTrackInfo->mEndFragmentTrack -
                         aTrackInfo->mStartFragmentTrack;
 
   // If there is at least one track, line count is one more
   // than the number of tracks.
   if (trackCount > 0) {
-    double endOfLastTrack = 0.0;
-    double startOfNextTrack;
+    nscoord lastTrackEdge = 0;
+    nscoord startOfNextTrack;
+    uint32_t repeatIndex = 0;
+    uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length();
+    uint32_t numAddedLines = 0;
 
     for (uint32_t i = aTrackInfo->mStartFragmentTrack;
          i < aTrackInfo->mEndFragmentTrack + 1;
          i++) {
       uint32_t line1Index = i + 1;
 
       startOfNextTrack = (i < aTrackInfo->mEndFragmentTrack) ?
                          aTrackInfo->mPositions[i] :
-                         endOfLastTrack;
-
-      GridLine* line = new GridLine(this);
-      mLines.AppendElement(line);
+                         lastTrackEdge;
 
       nsTArray<nsString> lineNames;
       if (aLineInfo) {
         lineNames = aLineInfo->mNames.SafeElementAt(i, nsTArray<nsString>());
       }
 
       // Add in names from grid areas where this line is used as a boundary.
       for (auto area : aAreas) {
@@ -123,36 +123,129 @@ GridLines::SetLineInfo(const ComputedGri
           }
         }
 
         if (haveNameToAdd && !lineNames.Contains(nameToAdd)) {
           lineNames.AppendElement(nameToAdd);
         }
       }
 
+      if (i >= aTrackInfo->mRepeatFirstTrack &&
+          repeatIndex < numRepeatTracks) {
+        numAddedLines += AppendRemovedAutoFits(aTrackInfo,
+                                               aLineInfo,
+                                               lastTrackEdge,
+                                               repeatIndex,
+                                               numRepeatTracks,
+                                               lineNames);
+      }
+
+      RefPtr<GridLine> line = new GridLine(this);
+      mLines.AppendElement(line);
       line->SetLineValues(
         lineNames,
-        nsPresContext::AppUnitsToDoubleCSSPixels(endOfLastTrack),
+        nsPresContext::AppUnitsToDoubleCSSPixels(lastTrackEdge),
         nsPresContext::AppUnitsToDoubleCSSPixels(startOfNextTrack -
-                                                 endOfLastTrack),
-        line1Index,
+                                                 lastTrackEdge),
+        line1Index + numAddedLines,
         (
           // Implicit if there are no explicit tracks, or if the index
           // is before the first explicit track, or after
           // a track beyond the last explicit track.
           (aTrackInfo->mNumExplicitTracks == 0) ||
           (i < aTrackInfo->mNumLeadingImplicitTracks) ||
           (i > aTrackInfo->mNumLeadingImplicitTracks +
                aTrackInfo->mNumExplicitTracks) ?
             GridDeclaration::Implicit :
             GridDeclaration::Explicit
         )
       );
 
       if (i < aTrackInfo->mEndFragmentTrack) {
-        endOfLastTrack = aTrackInfo->mPositions[i] + aTrackInfo->mSizes[i];
+        lastTrackEdge = aTrackInfo->mPositions[i] + aTrackInfo->mSizes[i];
       }
     }
   }
 }
 
+uint32_t
+GridLines::AppendRemovedAutoFits(const ComputedGridTrackInfo* aTrackInfo,
+                                 const ComputedGridLineInfo* aLineInfo,
+                                 nscoord aLastTrackEdge,
+                                 uint32_t& aRepeatIndex,
+                                 uint32_t aNumRepeatTracks,
+                                 nsTArray<nsString>& aLineNames)
+{
+  // Check to see if lineNames contains ALL of the before line names.
+  bool alreadyHasBeforeLineNames = true;
+  for (const auto& beforeName : aLineInfo->mNamesBefore) {
+    if (!aLineNames.Contains(beforeName)) {
+      alreadyHasBeforeLineNames = false;
+      break;
+    }
+  }
+
+  bool extractedExplicitLineNames = false;
+  nsTArray<nsString> explicitLineNames;
+  uint32_t linesAdded = 0;
+  while (aRepeatIndex < aNumRepeatTracks &&
+         aTrackInfo->mRemovedRepeatTracks[aRepeatIndex]) {
+    // If this is not the very first call to this function, and if we
+    // haven't already added a line this call, pull all the explicit
+    // names to pass along to the next line that will be added after
+    // this function completes.
+    if (aRepeatIndex > 0 &&
+        linesAdded == 0) {
+      // Find the names that didn't match the before or after names,
+      // and extract them.
+      for (const auto& name : aLineNames) {
+        if (!aLineInfo->mNamesBefore.Contains(name) &&
+            !aLineInfo->mNamesAfter.Contains(name)) {
+          explicitLineNames.AppendElement(name);
+        }
+      }
+      for (const auto& extractedName : explicitLineNames) {
+        aLineNames.RemoveElement(extractedName);
+      }
+      extractedExplicitLineNames = true;
+    }
+
+    // If this is the second or later time through, or didn't already
+    // have before names, add them.
+    if (linesAdded > 0 || !alreadyHasBeforeLineNames) {
+      aLineNames.AppendElements(aLineInfo->mNamesBefore);
+    }
+
+    RefPtr<GridLine> line = new GridLine(this);
+    mLines.AppendElement(line);
+    line->SetLineValues(
+      aLineNames,
+      nsPresContext::AppUnitsToDoubleCSSPixels(aLastTrackEdge),
+      nsPresContext::AppUnitsToDoubleCSSPixels(0),
+      aTrackInfo->mRepeatFirstTrack + aRepeatIndex + 1,
+      GridDeclaration::Explicit
+    );
+
+    // No matter what, the next line should have the after names associated
+    // with it. If we go through the loop again, the before names will also
+    // be added.
+    aLineNames = aLineInfo->mNamesAfter;
+    aRepeatIndex++;
+
+    linesAdded++;
+  }
+  aRepeatIndex++;
+
+  if (extractedExplicitLineNames) {
+    // Pass on the explicit names we saved to the next explicit line.
+    aLineNames.AppendElements(explicitLineNames);
+  }
+
+  if (alreadyHasBeforeLineNames && linesAdded > 0) {
+    // If we started with before names, pass them on to the next explicit
+    // line.
+    aLineNames.AppendElements(aLineInfo->mNamesBefore);
+  }
+  return linesAdded;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/grid/GridLines.h
+++ b/dom/grid/GridLines.h
@@ -40,16 +40,23 @@ public:
   GridLine* IndexedGetter(uint32_t aIndex, bool& aFound);
 
   void SetLineInfo(const ComputedGridTrackInfo* aTrackInfo,
                    const ComputedGridLineInfo* aLineInfo,
                    const nsTArray<RefPtr<GridArea>>& aAreas,
                    bool aIsRow);
 
 protected:
+  uint32_t AppendRemovedAutoFits(const ComputedGridTrackInfo* aTrackInfo,
+                                 const ComputedGridLineInfo* aLineInfo,
+                                 nscoord aLastTrackEdge,
+                                 uint32_t& aRepeatIndex,
+                                 uint32_t aNumRepeatTracks,
+                                 nsTArray<nsString>& aLineNames);
+
   RefPtr<GridDimension> mParent;
   nsTArray<RefPtr<GridLine>> mLines;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_GridLines_h */
--- a/dom/grid/GridTracks.cpp
+++ b/dom/grid/GridTracks.cpp
@@ -67,32 +67,68 @@ GridTracks::SetTrackInfo(const ComputedG
 {
   // rebuild the tracks based on aTrackInfo
   mTracks.Clear();
 
   if (!aTrackInfo) {
     return;
   }
 
+  nscoord lastTrackEdge = 0;
+  uint32_t repeatIndex = 0;
+  auto AppendRemovedAutoFits = [this, &aTrackInfo, &lastTrackEdge,
+                                &repeatIndex]()
+  {
+    uint32_t numRepeatTracks = aTrackInfo->mRemovedRepeatTracks.Length();
+    // Add in removed auto-fit tracks
+    while (repeatIndex < numRepeatTracks &&
+         aTrackInfo->mRemovedRepeatTracks[repeatIndex]) {
+
+      RefPtr<GridTrack> track = new GridTrack(this);
+      mTracks.AppendElement(track);
+      track->SetTrackValues(
+        nsPresContext::AppUnitsToDoubleCSSPixels(lastTrackEdge),
+        nsPresContext::AppUnitsToDoubleCSSPixels(0),
+        GridDeclaration::Explicit,
+        GridTrackState::Removed
+      );
+      repeatIndex++;
+    }
+    repeatIndex++;
+  };
+
   for (size_t i = aTrackInfo->mStartFragmentTrack;
        i < aTrackInfo->mEndFragmentTrack;
        i++) {
-    GridTrack* track = new GridTrack(this);
+    if (i >= aTrackInfo->mRepeatFirstTrack) {
+      // Append removed auto-fit tracks, if appropriate. The
+      // AppendRemovedAutoFits function exits early once it has been called
+      // aTrackInfo->mRemovedRepeatTracks.Length() times -- a check we don't
+      // replicate here or at subsequent calling sites.
+      AppendRemovedAutoFits();
+    }
+
+    RefPtr<GridTrack> track = new GridTrack(this);
     mTracks.AppendElement(track);
     track->SetTrackValues(
       nsPresContext::AppUnitsToDoubleCSSPixels(aTrackInfo->mPositions[i]),
       nsPresContext::AppUnitsToDoubleCSSPixels(aTrackInfo->mSizes[i]),
       (
         // Implicit if index is before the first explicit track, or after
         // the last explicit track.
         (i < aTrackInfo->mNumLeadingImplicitTracks) ||
         (i >= aTrackInfo->mNumLeadingImplicitTracks +
               aTrackInfo->mNumExplicitTracks) ?
           GridDeclaration::Implicit :
           GridDeclaration::Explicit
       ),
       GridTrackState(aTrackInfo->mStates[i])
     );
+
+    lastTrackEdge = aTrackInfo->mPositions[i] + aTrackInfo->mSizes[i];
   }
+
+  // Append any trailing removed auto-fit tracks.
+  AppendRemovedAutoFits();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/grid/test/chrome.ini
+++ b/dom/grid/test/chrome.ini
@@ -1,7 +1,7 @@
 [chrome/test_grid_areas.html]
 [chrome/test_grid_fragmentation.html]
 [chrome/test_grid_implicit.html]
 [chrome/test_grid_lines.html]
 [chrome/test_grid_object.html]
-[chrome/test_grid_track_state.html]
+[chrome/test_grid_repeats.html]
 [chrome/test_grid_tracks.html]
rename from dom/grid/test/chrome/test_grid_track_state.html
rename to dom/grid/test/chrome/test_grid_repeats.html
--- a/dom/grid/test/chrome/test_grid_track_state.html
+++ b/dom/grid/test/chrome/test_grid_repeats.html
@@ -10,140 +10,349 @@ body {
 }
 .wrapper {
 	display: grid;
 	width: 600px;
 	grid-gap: 0px;
 	background-color: #f00;
 }
 .grid1 {
-	grid-template-columns: 50px 0 repeat(auto-fit, 100px);
+	grid-template-columns: 50px 0px repeat(auto-fit, 100px);
 }
 .grid2 {
-	grid-template-columns: 50px 0 [real-before] repeat(auto-fit, [before] 100px [after]) [real-after];
+	grid-template-columns: 50px 0px [real-before] repeat(auto-fit, [before] 100px [after]) [real-after] 0px [final];
 }
 .grid3 {
 	grid-template-columns: repeat(3, 66px) [real-before] repeat(auto-fit, [before] 100px [after]) [real-after];
 }
 .grid4 {
 	grid-template-columns: repeat(2, 100px) repeat(auto-fill, 50px);
 }
 .grid5 {
 	grid-template-columns: [real-before] repeat(auto-fit, [before] 100px [after]) [real-after];
 }
+.grid6 {
+	grid-template-columns: [first] 0px [real-before] repeat(auto-fit, [before] 100px [after]) [real-after];
+}
+.grid7 {
+	grid-template-columns: [real-before] repeat(auto-fit, [before] 100px [after]) [real-after] 0px [final];
+}
+.grid8 {
+	grid-template-columns: [real-before] repeat(auto-fit, [before] 1000px [after]) [real-after];
+}
+.grid9 {
+	grid-template-columns: [real-before] repeat(auto-fit, 100px [after]) [real-after];
+}
+.grid10 {
+	grid-template-columns: [real-before] repeat(auto-fit, [before] 100px) [real-after];
+}
 .box {
 	background-color: #444;
 	color: #fff;
 }
 .a {
 	grid-column: auto;
 }
 .b {
 	grid-column: 4;
 }
 .c {
 	grid-column: 6;
 }
 .d {
 	grid-column: 7;
 }
+.e {
+	grid-column: 5;
+}
 
 </style>
 
 <script>
 'use strict';
 
 SimpleTest.waitForExplicitFinish();
 
+function testLines(elementName, grid, expectedValues) {
+	for (let i = 0; i < grid.cols.lines.length; i++) {
+		is(grid.cols.lines[i].number, (i + 1), elementName + " line " + (i + 1) + " has expected number.");
+		is(grid.cols.lines[i].start, expectedValues[i].start, elementName + " line " + (i + 1) + " has expected start.");
+		is(grid.cols.lines[i].breadth, 0, elementName + " line " + (i + 1) + " has zero breadth.");
+		is(grid.cols.lines[i].names + "", expectedValues[i].names, elementName + " line " + (i + 1) + " has expected names.");
+	}
+}
+
 function runTests() {
 	let wrapper = document.getElementById("wrapper1");
 	let grid = wrapper.getGridFragments()[0];
-	
-	// test auto-fit count after removal
-	is(grid.cols.tracks.length, 3, "Grid column track array compensates for removed auto-fit columns.");
-	
+
+	// test auto-fit count
+	is(grid.cols.tracks.length, 7, "Grid column track array reports removed auto-fit columns.");
+
 	// test resolved value of grid-template-columns
 	let templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
 	is(templateColumnsText, "50px 0px 0px 100px 0px 0px 0px",
 		"Resolved value of grid-template-columns reports removed auto-fits as '0px'.");
-	
-	is(grid.cols.tracks[0].breadth, 50, "Column 1 is breadth 50.");
-	is(grid.cols.tracks[1].breadth, 0, "Column 2 is breadth 0.");
-	is(grid.cols.tracks[2].breadth, 100, "Column 3 is breadth 100.");
 
-	
+	// test starts, breadths, and states
+	let expectedValues = [
+		{ "start": 0,
+		  "breadth": 50,
+		  "state": "static" },
+		{ "start": 50,
+		  "breadth": 0,
+		  "state": "static" },
+		{ "start": 50,
+		  "breadth": 0,
+		  "state": "removed" },
+		{ "start": 50,
+		  "breadth": 100,
+		  "state": "repeat" },
+		{ "start": 150,
+		  "breadth": 0,
+		  "state": "removed" },
+		{ "start": 150,
+		  "breadth": 0,
+		  "state": "removed" },
+		{ "start": 150,
+		  "breadth": 0,
+		  "state": "removed" },
+	];
+	for (let i = 0; i < grid.cols.tracks.length; i++) {
+		is(grid.cols.tracks[i].start, expectedValues[i].start, "Column " + (i + 1) + " has expected start.");
+		is(grid.cols.tracks[i].breadth, expectedValues[i].breadth, "Column " + (i + 1) + " has expected breadth.");
+		is(grid.cols.tracks[i].state, expectedValues[i].state, "Column " + (i + 1) + " has expected state.");
+	}
+
+
 	wrapper = document.getElementById("wrapper2");
 	grid = wrapper.getGridFragments()[0];
-	
+
+	// test auto-fit count
+	is(grid.cols.lines.length, 9, "Grid column line array reports removed auto-fit columns.");
+
 	// test resolved value of grid-template-columns
 	templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
-	is(templateColumnsText, "50px 0px [real-before before] 0px [after before] 100px [after before] 0px [after before] 100px [after before] 0px [after real-after]",
+	is(templateColumnsText, "50px 0px [real-before before] 0px [after before] 100px [after before] 0px [after before] 100px [after before] 0px [after real-after] 0px [final]",
 		"Resolved value of grid-template-columns reports lines for removed tracks.");
-	
-	
+
+	// test starts and names
+	expectedValues = [
+		{ "start": 0,
+		  "names": "" },
+		{ "start": 50,
+		  "names": "" },
+		{ "start": 50,
+		  "names": "real-before,before" },
+		{ "start": 50,
+		  "names": "after,before" },
+		{ "start": 150,
+		  "names": "after,before" },
+		{ "start": 150,
+		  "names": "after,before" },
+		{ "start": 250,
+		  "names": "after,before" },
+		{ "start": 250,
+		  "names": "after,real-after" },
+		{ "start": 250,
+		  "names": "final" },
+	];
+	testLines("wrapper2", grid, expectedValues);
+
+
 	wrapper = document.getElementById("wrapper3");
 	grid = wrapper.getGridFragments()[0];
-	
+
 	// test resolved value of grid-template-columns
 	templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
 	is(templateColumnsText, "66px 66px 66px [real-before before] 100px [after before] 0px [after before] 100px [after before] 100px [after real-after]",
 		"Resolved value of grid-template-columns reports lines for removed tracks.");
-	
-	
+
+
 	wrapper = document.getElementById("wrapper4");
 	grid = wrapper.getGridFragments()[0];
-	
+
 	// test auto-fill count of tracks
 	is(grid.cols.tracks.length, 10, "Grid column track array respects auto-fill columns.");
-	
+
 	if (grid.cols.tracks.length == 10) {
 		// test for static and repeat
 		is(grid.cols.tracks[1].state, "static", "Grid column track 2 is marked as static.");
 		is(grid.cols.tracks[2].state, "repeat", "Grid column track 3 is marked as repeat.");
 	}
-	
-	
+
+
 	wrapper = document.getElementById("wrapper5");
 	grid = wrapper.getGridFragments()[0];
-	
+
 	// test resolved value of grid-template-columns
 	templateColumnsText = getComputedStyle(wrapper).gridTemplateColumns;
-	is(templateColumnsText, "[real-before before] 0px [after before] 0px [after before] 0px [after before] 0px [after before] 0px [after before] 0px [after real-after]",
-		"Resolved value of grid-template-columns no longer lists 'none' when all auto-fit tracks are empty.");
-	
+	is(templateColumnsText, "[real-before before] 0px [after before] 0px [after before] 0px [after before] 0px [after before] 0px [after before] 0px [after real-after]", "Resolved value of grid-template-columns no longer lists 'none' when all auto-fit tracks are empty.");
+
+
+	wrapper = document.getElementById("wrapper6");
+	grid = wrapper.getGridFragments()[0];
+
+	// test starts and names
+	expectedValues = [
+		{ "start": 0,
+		  "names": "first" },
+		{ "start": 0,
+		  "names": "real-before,before" },
+		{ "start": 0,
+		  "names": "after,before" },
+		{ "start": 0,
+		  "names": "after,before" },
+		{ "start": 100,
+		  "names": "after,before" },
+		{ "start": 100,
+		  "names": "after,before" },
+		{ "start": 100,
+		  "names": "after,before" },
+		{ "start": 100,
+		  "names": "after,real-after" },
+	];
+	testLines("wrapper6", grid, expectedValues);
+
+
+	wrapper = document.getElementById("wrapper7");
+	grid = wrapper.getGridFragments()[0];
+
+	// test starts and names
+	expectedValues = [
+		{ "start": 0,
+		  "names": "real-before,before" },
+		{ "start": 0,
+		  "names": "after,before" },
+		{ "start": 0,
+		  "names": "after,before" },
+		{ "start": 0,
+		  "names": "after,before" },
+		{ "start": 100,
+		  "names": "after,before" },
+		{ "start": 100,
+		  "names": "after,before" },
+		{ "start": 100,
+		  "names": "after,real-after" },
+		{ "start": 100,
+		  "names": "final" },
+	];
+	testLines("wrapper7", grid, expectedValues);
+
+
+	wrapper = document.getElementById("wrapper8");
+	grid = wrapper.getGridFragments()[0];
+
+	// test starts and names
+	expectedValues = [
+		{ "start": 0,
+		  "names": "real-before,before" },
+		{ "start": 0,
+		  "names": "after,real-after" },
+	];
+	testLines("wrapper8", grid, expectedValues);
+
+
+	wrapper = document.getElementById("wrapper9");
+	grid = wrapper.getGridFragments()[0];
+
+	// test starts and names
+	expectedValues = [
+		{ "start": 0,
+		  "names": "real-before" },
+		{ "start": 0,
+		  "names": "after" },
+		{ "start": 0,
+		  "names": "after" },
+		{ "start": 0,
+		  "names": "after" },
+		{ "start": 100,
+		  "names": "after" },
+		{ "start": 200,
+		  "names": "after" },
+		{ "start": 200,
+		  "names": "after,real-after" },
+	];
+	testLines("wrapper9", grid, expectedValues);
+
+
+	wrapper = document.getElementById("wrapper10");
+	grid = wrapper.getGridFragments()[0];
+
+	// test starts and names
+	expectedValues = [
+		{ "start": 0,
+		  "names": "real-before,before" },
+		{ "start": 0,
+		  "names": "before" },
+		{ "start": 0,
+		  "names": "before" },
+		{ "start": 0,
+		  "names": "before" },
+		{ "start": 100,
+		  "names": "before" },
+		{ "start": 200,
+		  "names": "before" },
+		{ "start": 200,
+		  "names": "real-after" },
+	];
+	testLines("wrapper10", grid, expectedValues);
+
 	SimpleTest.finish();
 }
 </script>
 </head>
 <body onLoad="runTests();">
 
 	<div id="wrapper1" class="wrapper grid1">
 		<div id="boxB" class="box b">B</div>
 	</div>
-		
+
 	<br/>
-	
 	<div id="wrapper2" class="wrapper grid2">
 		<div id="boxB" class="box b">B</div>
 		<div id="boxC" class="box c">C</div>
 	</div>
-		
+
 	<br/>
-	
 	<div id="wrapper3" class="wrapper grid3">
 		<div id="boxB" class="box b">B</div>
 		<div id="boxC" class="box c">C</div>
 		<div id="boxD" class="box d">D</div>
 	</div>
-		
+
 	<br/>
-	
 	<div id="wrapper4" class="wrapper grid4">
 		<div id="boxA" class="box a">A</div>
 	</div>
-	
+
 	<br/>
-	
 	<div id="wrapper5" class="wrapper grid5">
 	</div>
-	
+
+	<br/>
+	<div id="wrapper6" class="wrapper grid6">
+		<div id="boxB" class="box b">B</div>
+	</div>
+
+	<br/>
+	<div id="wrapper7" class="wrapper grid7">
+		<div id="boxB" class="box b">B</div>
+	</div>
+
+	<br/>
+	<div id="wrapper8" class="wrapper grid8">
+	</div>
+
+	<br/>
+	<div id="wrapper9" class="wrapper grid9">
+		<div id="boxB" class="box b">B</div>
+		<div id="boxE" class="box e">E</div>
+	</div>
+
+	<br/>
+	<div id="wrapper10" class="wrapper grid10">
+		<div id="boxB" class="box b">B</div>
+		<div id="boxE" class="box e">E</div>
+	</div>
+
 </body>
 </html>
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1190,16 +1190,19 @@ nsGenericHTMLElement::ParseReferrerAttri
                                              nsAttrValue& aResult)
 {
   static const nsAttrValue::EnumTable kReferrerTable[] = {
     { net::kRPS_No_Referrer, static_cast<int16_t>(net::RP_No_Referrer) },
     { net::kRPS_Origin, static_cast<int16_t>(net::RP_Origin) },
     { net::kRPS_Origin_When_Cross_Origin, static_cast<int16_t>(net::RP_Origin_When_Crossorigin) },
     { net::kRPS_No_Referrer_When_Downgrade, static_cast<int16_t>(net::RP_No_Referrer_When_Downgrade) },
     { net::kRPS_Unsafe_URL, static_cast<int16_t>(net::RP_Unsafe_URL) },
+    { net::kRPS_Strict_Origin, static_cast<int16_t>(net::RP_Strict_Origin) },
+    { net::kRPS_Same_Origin, static_cast<int16_t>(net::RP_Same_Origin) },
+    { net::kRPS_Strict_Origin_When_Cross_Origin, static_cast<int16_t>(net::RP_Strict_Origin_When_Cross_Origin) },
     { nullptr, 0 }
   };
   return aResult.ParseEnumValue(aString, kReferrerTable, false);
 }
 
 bool
 nsGenericHTMLElement::ParseFrameborderValue(const nsAString& aString,
                                             nsAttrValue& aResult)
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -3000,26 +3000,16 @@ private:
     MOZ_ASSERT(NS_IsMainThread());
     if (RefPtr<TabParent> tabParent = TabParent::GetTabParentFromLayersId(mLayersId)) {
       tabParent->LayerTreeUpdate(mEpoch, mActive);
     }
     return NS_OK;
   }
 };
 
-/* static */ void
-TabParent::ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive)
-{
-  MOZ_ASSERT(!NS_IsMainThread());
-
-  RefPtr<LayerTreeUpdateRunnable> runnable =
-    new LayerTreeUpdateRunnable(aLayersId, aEpoch, aActive);
-  NS_DispatchToMainThread(runnable);
-}
-
 void
 TabParent::LayerTreeUpdate(uint64_t aEpoch, bool aActive)
 {
   // Ignore updates from old epochs. They might tell us that layers are
   // available when we've already sent a message to clear them. We can't trust
   // the update in that case since layers could disappear anytime after that.
   if (aEpoch != mLayerTreeEpoch || mIsDestroyed) {
     return;
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -561,17 +561,16 @@ public:
 
   bool IsInitedByParent() const { return mInitedByParent; }
 
   static TabParent* GetNextTabParent();
 
   bool SendLoadRemoteScript(const nsString& aURL,
                             const bool& aRunInGlobalScope);
 
-  static void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive);
   void LayerTreeUpdate(uint64_t aEpoch, bool aActive);
 
   virtual bool
   RecvInvokeDragSession(nsTArray<IPCDataTransfer>&& aTransfers,
                         const uint32_t& aAction,
                         const OptionalShmem& aVisualDnDData,
                         const uint32_t& aWidth, const uint32_t& aHeight,
                         const uint32_t& aStride, const uint8_t& aFormat,
new file mode 100644
--- /dev/null
+++ b/dom/ipc/tests/blob_verify.sjs
@@ -0,0 +1,20 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+                             "nsIBinaryInputStream",
+                             "setInputStream");
+const BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1",
+                              "nsIBinaryOutputStream",
+                              "setOutputStream");
+
+function handleRequest(request, response) {
+  var bodyStream = new BinaryInputStream(request.bodyInputStream);
+  var bodyBytes = [];
+  while ((bodyAvail = bodyStream.available()) > 0)
+    Array.prototype.push.apply(bodyBytes, bodyStream.readByteArray(bodyAvail));
+
+  var bos = new BinaryOutputStream(response.bodyOutputStream);
+
+  response.processAsync();
+  bos.writeByteArray(bodyBytes, bodyBytes.length);
+  response.finish();
+}
--- a/dom/ipc/tests/mochitest.ini
+++ b/dom/ipc/tests/mochitest.ini
@@ -48,8 +48,12 @@ support-files =
 [test_permission_when_oop_app_crashes.html]
 skip-if = true || os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app  ### Bug 1255339: blacklist because no more mozApps
 support-files =
   file_app.sjs
   file_app.template.webapp
   test_permission_helper.js
   test_permission_embed.html
   test_permission_framescript.js
+[test_temporaryfile_stream.html]
+support-files =
+  blob_verify.sjs
+  !/dom/canvas/test/captureStream_common.js
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/ipc/tests/test_temporaryfile_stream.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Send an nsTemporaryFileInputStream cross-process</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="/tests/dom/canvas/test/captureStream_common.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<div id="content">
+</div>
+<script class="testbody" type="text/javascript">
+function startTest() {
+  var canvas = document.createElement("canvas");
+  canvas.width = canvas.height = 100;
+  document.getElementById("content").appendChild(canvas);
+
+  var helper = new CaptureStreamTestHelper2D(100, 100);
+  helper.drawColor(canvas, helper.red);
+
+  var stream = canvas.captureStream(0);
+
+  var blob;
+
+  mediaRecorder = new MediaRecorder(stream);
+  is(mediaRecorder.stream, stream,
+     "Media recorder stream = canvas stream at the start of recording");
+
+  mediaRecorder.onwarning = () => ok(false, "warning unexpectedly fired");
+
+  mediaRecorder.onerror = () => ok(false, "Recording failed");
+
+  mediaRecorder.ondataavailable = ev => {
+    is(blob, undefined, "Should only get one dataavailable event");
+    blob = ev.data;
+  };
+
+  mediaRecorder.onstart = () => {
+    info("Got 'start' event");
+    // We just want one frame encoded, to see that the recorder produces something readable.
+    mediaRecorder.stop();
+  };
+
+  mediaRecorder.onstop = () => {
+    info("Got 'stop' event");
+    ok(blob, "Should have gotten a data blob");
+    var xhr = new XMLHttpRequest();
+    xhr.open('POST', 'blob_verify.sjs', true);
+    xhr.onload = () => {
+      var video = document.createElement("video");
+      video.id = "recorded-video";
+      video.src = URL.createObjectURL(xhr.response);
+      video.play();
+      video.onerror = err => {
+        ok(false, "Should be able to play the recording. Got error. code=" + video.error.code);
+        SimpleTest.finish();
+      };
+      document.getElementById("content").appendChild(video);
+      helper.waitForPixelColor(video, helper.red, 128, "Should become red")
+        .then(SimpleTest.finish);
+    };
+    xhr.onerror = () => {
+      ok(false, "XHR error");
+      SimpleTest.finish();
+    }
+    xhr.responseType = "blob";
+    xhr.send(blob);
+  };
+
+  mediaRecorder.start();
+  is(mediaRecorder.state, "recording", "Media recorder should be recording");
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({set:[["media.recorder.max_memory", 1]]}, startTest);
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/AudioStream.cpp
+++ b/dom/media/AudioStream.cpp
@@ -397,19 +397,22 @@ AudioStream::SetVolume(double aVolume)
   }
 }
 
 void
 AudioStream::Start()
 {
   MonitorAutoLock mon(mMonitor);
   MOZ_ASSERT(mState == INITIALIZED);
+  mState = STARTED;
   auto r = InvokeCubeb(cubeb_stream_start);
-  mState = r == CUBEB_OK ? STARTED : ERRORED;
-  LOG("started, state %s", mState == STARTED ? "STARTED" : "ERRORED");
+  if (r != CUBEB_OK) {
+    mState = ERRORED;
+  }
+  LOG("started, state %s", mState == STARTED ? "STARTED" : mState == DRAINED ? "DRAINED" : "ERRORED");
 }
 
 void
 AudioStream::Pause()
 {
   MonitorAutoLock mon(mMonitor);
   MOZ_ASSERT(mState != INITIALIZED, "Must be Start()ed.");
   MOZ_ASSERT(mState != STOPPED, "Already Pause()ed.");
@@ -591,22 +594,26 @@ long
 AudioStream::DataCallback(void* aBuffer, long aFrames)
 {
   MonitorAutoLock mon(mMonitor);
   MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown");
 
   auto writer = AudioBufferWriter(
     reinterpret_cast<AudioDataValue*>(aBuffer), mOutChannels, aFrames);
 
-  // FIXME: cubeb_pulse sometimes calls us before cubeb_stream_start() is called.
-  // We don't want to consume audio data until Start() is called by the client.
-  if (mState == INITIALIZED) {
-    NS_WARNING("data callback fires before cubeb_stream_start() is called");
-    mAudioClock.UpdateFrameHistory(0, aFrames);
-    return writer.WriteZeros(aFrames);
+  if (!strcmp(cubeb_get_backend_id(CubebUtils::GetCubebContext()), "winmm")) {
+    // Don't consume audio data until Start() is called.
+    // Expected only with cubeb winmm backend.
+    if (mState == INITIALIZED) {
+      NS_WARNING("data callback fires before cubeb_stream_start() is called");
+      mAudioClock.UpdateFrameHistory(0, aFrames);
+      return writer.WriteZeros(aFrames);
+    }
+  } else {
+    MOZ_ASSERT(mState != INITIALIZED);
   }
 
   // NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN)
   // Bug 996162
 
   if (mAudioClock.GetInputRate() == mAudioClock.GetOutputRate()) {
     GetUnprocessed(writer);
   } else {
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
@@ -47,17 +47,17 @@ public:
     : ITextureClientAllocationHelper(gfx::SurfaceFormat::UNKNOWN,
                                      aSize,
                                      BackendSelector::Content,
                                      TextureFlags::DEALLOCATE_CLIENT,
                                      ALLOC_DISALLOW_BUFFERTEXTURECLIENT)
     , mGrallocFormat(aGrallocFormat)
   {}
 
-  already_AddRefed<TextureClient> Allocate(CompositableForwarder* aAllocator) override
+  already_AddRefed<TextureClient> Allocate(TextureForwarder* aAllocator) override
   {
     uint32_t usage = android::GraphicBuffer::USAGE_SW_READ_OFTEN |
                      android::GraphicBuffer::USAGE_SW_WRITE_OFTEN |
                      android::GraphicBuffer::USAGE_HW_TEXTURE;
 
     GrallocTextureData* texData = GrallocTextureData::Create(mSize, mGrallocFormat,
                                                              gfx::BackendType::NONE,
                                                              usage, aAllocator);
--- a/dom/media/test/fragment_play.js
+++ b/dom/media/test/fragment_play.js
@@ -14,17 +14,17 @@ function onLoadedMetadata() {
   v.play();
 }
 
 function onSeeked() {
   if (completed)
     return;
 
   var s = start == null ? 0 : start;
-  ok(v.currentTime == s, "seeked currentTime is " + v.currentTime + " != " + s);
+  ok(v.currentTime - s < 0.1, "seeked currentTime is " + v.currentTime + " != " + s + " (fuzzy compare +-0.1)");
 
   seekedRaised = true;
 }
 
 function onTimeUpdate() {
   if (completed)
     return;
 
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -835,16 +835,25 @@ AudioContext::OnStateChanged(void* aProm
   // This can happen if close() was called right after creating the
   // AudioContext, before the context has switched to "running".
   if (mAudioContextState == AudioContextState::Closed &&
       aNewState == AudioContextState::Running &&
       !aPromise) {
     return;
   }
 
+  // This can happen if this is called in reaction to a
+  // MediaStreamGraph shutdown, and a AudioContext was being
+  // suspended at the same time, for example if a page was being
+  // closed.
+  if (mAudioContextState == AudioContextState::Closed &&
+      aNewState == AudioContextState::Suspended) {
+    return;
+  }
+
 #ifndef WIN32 // Bug 1170547
 #ifndef XP_MACOSX
 #ifdef DEBUG
 
   if (!((mAudioContextState == AudioContextState::Suspended &&
        aNewState == AudioContextState::Running)   ||
       (mAudioContextState == AudioContextState::Running   &&
        aNewState == AudioContextState::Suspended) ||
--- a/dom/presentation/ipc/PresentationBuilderChild.cpp
+++ b/dom/presentation/ipc/PresentationBuilderChild.cpp
@@ -90,17 +90,17 @@ PresentationBuilderChild::RecvOnAnswer(c
     return false;
   }
   return true;
 }
 
 bool
 PresentationBuilderChild::RecvOnIceCandidate(const nsString& aCandidate)
 {
-  if (NS_WARN_IF(NS_FAILED(mBuilder->OnIceCandidate(aCandidate)))) {
+  if (NS_WARN_IF(mBuilder && NS_FAILED(mBuilder->OnIceCandidate(aCandidate)))) {
     return false;
   }
   return true;
 }
 
 // nsPresentationSessionTransportBuilderListener
 NS_IMETHODIMP
 PresentationBuilderChild::OnSessionTransport(nsIPresentationSessionTransport* aTransport)
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -1067,16 +1067,22 @@ class CSPReportSenderRunnable final : pu
       nsCOMPtr<nsIURI> blockedURI = do_QueryInterface(mBlockedContentSource);
       // if mBlockedContentSource is not a URI, it could be a string
       nsCOMPtr<nsISupportsCString> blockedString = do_QueryInterface(mBlockedContentSource);
 
       nsCString blockedDataStr;
 
       if (blockedURI) {
         blockedURI->GetSpec(blockedDataStr);
+        bool isData = false;
+        rv = blockedURI->SchemeIs("data", &isData);
+        if (NS_SUCCEEDED(rv) && isData) {
+          blockedDataStr.Truncate(40);
+          blockedDataStr.AppendASCII("...");
+        }
       } else if (blockedString) {
         blockedString->GetData(blockedDataStr);
       }
 
       if (blockedDataStr.Length() > 0) {
         nsString blockedDataChar16 = NS_ConvertUTF8toUTF16(blockedDataStr);
         const char16_t* params[] = { mViolatedDirective.get(),
                                      blockedDataChar16.get() };
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_data-uri_blocked.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1242019
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 587377</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+  <img width='1' height='1' title='' alt='' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKTWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/sl0p8zAAA6NGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMTEgNzkuMTU4MzI1LCAyMDE1LzA5LzEwLTAxOjEwOjIwICAgICAgICAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoTWFjaW50b3NoKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxNi0wMi0wOFQxMzoyNjo1MSswOTowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMTYtMDItMDhUMTM6MjY6NTErMDk6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE2LTAyLTA4VDEzOjI2OjUxKzA5OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDplN2QyMjJjOS03Nzg2LTRhMjktOTlhMy0yYjRjNWI4YTA5MWY8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo5OWE3ZTJmOC0wZWFhLTExNzktYTE4NS05M2Y1MjZhZGU2ZDg8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDoyYmY3M2M3Ny03NzczLTQzNjAtYThiZS1kY2UyZTgzMWQ2YmM8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MmJmNzNjNzctNzc3My00MzYwLWE4YmUtZGNlMmU4MzFkNmJjPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE2LTAyLTA4VDEzOjI2OjUxKzA5OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGkgcmRmOnBhcnNlVHlwZT0iUmVzb3VyY2UiPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6YWN0aW9uPnNhdmVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZTdkMjIyYzktNzc4Ni00YTI5LTk5YTMtMmI0YzViOGEwOTFmPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE2LTAyLTA4VDEzOjI2OjUxKzA5OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoTWFjaW50b3NoKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3BuZzwvZGM6Zm9ybWF0PgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOklDQ1Byb2ZpbGU+c1JHQiBJRUM2MTk2Ni0yLjE8L3Bob3Rvc2hvcDpJQ0NQcm9maWxlPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWERpbWVuc2lvbj4xPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjE8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PoAp5ZwAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAABNJREFUeNpi+P//PwMAAAD//wMACPwC/tOldWEAAAAASUVORK5CYII='>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_data-uri_blocked.html^headers^
@@ -0,0 +1,1 @@
+Content-Security-Policy: default-src 'self'; img-src 'none'
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -183,16 +183,18 @@ support-files =
   file_sandbox_9.html
   file_sandbox_10.html
   file_sandbox_11.html
   file_sandbox_12.html
   file_require_sri_meta.sjs
   file_require_sri_meta.js
   file_sendbeacon.html
   file_upgrade_insecure_docwrite_iframe.sjs
+  file_data-uri_blocked.html
+  file_data-uri_blocked.html^headers^
 
 [test_base-uri.html]
 [test_blob_data_schemes.html]
 [test_connect-src.html]
 [test_CSP.html]
 [test_allow_https_schemes.html]
 skip-if = buildapp == 'b2g' #no ssl support
 [test_bug663567.html]
@@ -277,8 +279,9 @@ tags = mcb
 [test_meta_whitespace_skipping.html]
 [test_iframe_sandbox.html]
 [test_iframe_sandbox_top_1.html]
 [test_sandbox.html]
 [test_ping.html]
 [test_require_sri_meta.html]
 [test_sendbeacon.html]
 [test_upgrade_insecure_docwrite_iframe.html]
+[test_bug1242019.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_bug1242019.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1242019
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1242019</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.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=1242019">Mozilla Bug 1242019</a>
+<p id="display"></p>
+
+<iframe id="cspframe"></iframe>
+
+<pre id="test">
+
+<script class="testbody" type="text/javascript">
+function cleanup() {
+  SpecialPowers.postConsoleSentinel();
+  SimpleTest.finish();
+};
+
+var expectedURI = "data:image/png;base64,iVBORw0KGgoAAAANSU"
+
+SpecialPowers.registerConsoleListener(function ConsoleMsgListener(aMsg) {
+  // look for the message with data uri and see the data uri is truncated to 40 chars
+  data_start = aMsg.message.indexOf(expectedURI) 
+  if (data_start > -1) {
+    data_uri = "";
+    data_uri = aMsg.message.substr(data_start);
+    // this will either match the elipsis after the URI or the . at the end of the message
+    data_uri = data_uri.substr(0, data_uri.indexOf("."));
+    if (data_uri == "") {
+      return;
+    }
+
+    ok(data_uri.length == 40, "Data URI only shows 40 characters in the console");
+    SimpleTest.executeSoon(cleanup);
+  }
+});
+
+// set up and start testing
+SimpleTest.waitForExplicitFinish();
+document.getElementById('cspframe').src = 'file_data-uri_blocked.html';
+</script>
+</pre>
+</body>
+</html>
--- a/dom/webidl/Grid.webidl
+++ b/dom/webidl/Grid.webidl
@@ -9,20 +9,20 @@
 /**
  * Explicit and implicit types apply to tracks, lines, and areas.
  * https://drafts.csswg.org/css-grid/#explicit-grids
  * https://drafts.csswg.org/css-grid/#implicit-grids
  */
 enum GridDeclaration { "explicit", "implicit" };
 
 /**
- * Tracks expanded from auto-fill or auto-fit have repeat state, other tracks
- * are static.
+ * Tracks expanded from auto-fill are repeat , auto-fits with elements are
+ * also repeat, auto-fits with no elements are removed, other tracks are static.
  */
-enum GridTrackState { "static", "repeat" };
+enum GridTrackState { "static", "repeat", "removed" };
 
 [ChromeOnly]
 interface Grid
 {
   readonly attribute GridDimension rows;
   readonly attribute GridDimension cols;
   [Cached, Constant]
   readonly attribute sequence<GridArea> areas;
--- a/dom/workers/test/referrer_worker.html
+++ b/dom/workers/test/referrer_worker.html
@@ -32,35 +32,44 @@ function finish() {
   }, 0);
 }
 
 var testCases = {
   'same-origin':  { 'Referrer-Policy' : { 'default' : 'full',
                                           'origin' : 'origin',
                                           'origin-when-cross-origin' : 'full',
                                           'unsafe-url' : 'full',
+                                          'same-origin' : 'full',
+                                          'strict-origin' : 'origin',
+                                          'strict-origin-when-cross-origin' : 'full',
                                           'no-referrer' : 'none',
                                           'unsafe-url, no-referrer' : 'none',
                                           'invalid' : 'full' }},
 
   'cross-origin':  { 'Referrer-Policy' : { 'default' : 'full',
                                            'origin' : 'origin',
                                            'origin-when-cross-origin' : 'origin',
                                            'unsafe-url' : 'full',
+                                           'same-origin' : 'none',
+                                           'strict-origin' : 'origin',
+                                           'strict-origin-when-cross-origin' : 'origin',
                                            'no-referrer' : 'none',
                                            'unsafe-url, no-referrer' : 'none',
                                            'invalid' : 'full' }},
 
   // Downgrading in worker is blocked entirely without unblock option
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1198078#c17
   // Skip the downgrading test
   /* 'downgrade':  { 'Referrer-Policy' : { 'default' : 'full',
                                           'origin'  : 'full',
                                           'origin-when-cross-origin"'  : 'full',
                                           'unsafe-url'  : 'full',
+                                          'same-origin' : 'none',
+                                          'strict-origin' : 'none',
+                                          'strict-origin-when-cross-origin' : 'none',
                                           'no-referrer'  : 'full',
                                           'unsafe-url, no-referrer' : 'none',
                                           'invalid'  : 'full' }}, */
 
 
 };
 
 var advance = function() { tests.next(); };
--- a/dom/workers/test/serviceworkers/fetch/hsts/realindex.html
+++ b/dom/workers/test/serviceworkers/fetch/hsts/realindex.html
@@ -1,4 +1,8 @@
 <!DOCTYPE html>
 <script>
-  window.parent.postMessage({status: "protocol", data: location.protocol}, "*");
+  var securityInfoPresent = !!SpecialPowers.wrap(document).docShell.currentDocumentChannel.securityInfo;
+  window.parent.postMessage({status: "protocol",
+                             data: location.protocol,
+                             securityInfoPresent: securityInfoPresent},
+                            "*");
 </script>
--- a/dom/workers/test/serviceworkers/test_hsts_upgrade_intercept.html
+++ b/dom/workers/test/serviceworkers/test_hsts_upgrade_intercept.html
@@ -24,16 +24,17 @@
     iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/register.html";
     window.onmessage = function(e) {
       if (e.data.status == "ok") {
         ok(e.data.result, e.data.message);
       } else if (e.data.status == "registrationdone") {
         iframe.src = "http://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/index.html";
       } else if (e.data.status == "protocol") {
         is(e.data.data, "https:", "Correct protocol expected");
+        ok(e.data.securityInfoPresent, "Security info present on intercepted value");
         switch (++framesLoaded) {
         case 1:
           iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/embedder.html";
           break;
         case 2:
           iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/hsts/image.html";
           break;
         }
--- a/gfx/2d/DrawTargetD2D1.cpp
+++ b/gfx/2d/DrawTargetD2D1.cpp
@@ -1338,17 +1338,19 @@ DrawTargetD2D1::FinalizeDrawing(Composit
     RefPtr<ID2D1Effect> blendEffect;
     HRESULT hr = mDC->CreateEffect(CLSID_D2D1Blend, getter_AddRefs(blendEffect));
 
     if (FAILED(hr) || !blendEffect) {
       gfxWarning() << "Failed to create blend effect!";
       return;
     }
 
-    RefPtr<ID2D1Image> tmpImage = GetImageForLayerContent();
+    // We don't need to preserve the current content of this layer as the output
+    // of the blend effect should completely replace it.
+    RefPtr<ID2D1Image> tmpImage = GetImageForLayerContent(false);
 
     blendEffect->SetInput(0, tmpImage);
     blendEffect->SetInput(1, source);
     blendEffect->SetValue(D2D1_BLEND_PROP_MODE, D2DBlendMode(aOp));
 
     mDC->DrawImage(blendEffect, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY);
 
     // This may seem a little counter intuitive. If this is false, we go through the regular
@@ -1427,17 +1429,17 @@ DrawTargetD2D1::GetDeviceSpaceClipRect(D
     if (!iter->mIsPixelAligned) {
       aIsPixelAligned = false;
     }
   }
   return true;
 }
 
 already_AddRefed<ID2D1Image>
-DrawTargetD2D1::GetImageForLayerContent()
+DrawTargetD2D1::GetImageForLayerContent(bool aShouldPreserveContent)
 {
   if (!CurrentLayer().mCurrentList) {
     RefPtr<ID2D1Bitmap> tmpBitmap;
     HRESULT hr = mDC->CreateBitmap(D2DIntSize(mSize), D2D1::BitmapProperties(D2DPixelFormat(mFormat)), getter_AddRefs(tmpBitmap));
     if (FAILED(hr)) {
       gfxCriticalError(CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(mSize))) << "[D2D1.1] 6CreateBitmap failure " << mSize << " Code: " << hexa(hr) << " format " << (int)mFormat;
       // For now, crash in this scenario; this should happen because tmpBitmap is
       // null and CopyFromBitmap call below dereferences it.
@@ -1464,19 +1466,21 @@ DrawTargetD2D1::GetImageForLayerContent(
       mDC->CreateBitmap(mBitmap->GetPixelSize(), nullptr, 0, &props, getter_AddRefs(tmpBitmap));
       mDC->SetTransform(D2D1::IdentityMatrix());
       mDC->SetTarget(tmpBitmap);
       mDC->DrawImage(list, D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR, D2D1_COMPOSITE_MODE_BOUNDED_SOURCE_COPY);
       mDC->SetTarget(CurrentTarget());
     }
 
     DCCommandSink sink(mDC);
-    list->Stream(&sink);
 
-    PushAllClips();
+    if (aShouldPreserveContent) {
+      list->Stream(&sink);
+      PushAllClips();
+    }
 
     if (mDidComplexBlendWithListInList) {
       return tmpBitmap.forget();
     }
 
     return list.forget();
   }
 }
--- a/gfx/2d/DrawTargetD2D1.h
+++ b/gfx/2d/DrawTargetD2D1.h
@@ -181,17 +181,17 @@ private:
     if (mTransformDirty) {
       mDC->SetTransform(D2DMatrix(mTransform));
       mTransformDirty = false;
     }
   }
   void AddDependencyOnSource(SourceSurfaceD2D1* aSource);
 
   // Must be called with all clips popped and an identity matrix set.
-  already_AddRefed<ID2D1Image> GetImageForLayerContent();
+  already_AddRefed<ID2D1Image> GetImageForLayerContent(bool aShouldPreserveContent = true);
 
   ID2D1Image* CurrentTarget()
   {
     if (CurrentLayer().mCurrentList) {
       return CurrentLayer().mCurrentList;
     }
     return mBitmap;
   }
--- a/gfx/ipc/RemoteCompositorSession.cpp
+++ b/gfx/ipc/RemoteCompositorSession.cpp
@@ -20,17 +20,19 @@ RemoteCompositorSession::RemoteComposito
                                                  CompositorWidgetDelegate* aWidgetDelegate,
                                                  APZCTreeManagerChild* aAPZ,
                                                  const uint64_t& aRootLayerTreeId)
  : CompositorSession(aWidgetDelegate, aChild, aRootLayerTreeId),
    mWidget(aWidget),
    mAPZ(aAPZ)
 {
   GPUProcessManager::Get()->RegisterSession(this);
-  mAPZ->SetCompositorSession(this);
+  if (mAPZ) {
+    mAPZ->SetCompositorSession(this);
+  }
 }
 
 RemoteCompositorSession::~RemoteCompositorSession()
 {
   // This should have been shutdown first.
   MOZ_ASSERT(!mCompositorBridgeChild);
 }
 
@@ -58,27 +60,35 @@ RemoteCompositorSession::SetContentContr
 }
 
 GeckoContentController*
 RemoteCompositorSession::GetContentController()
 {
   return mContentController.get();
 }
 
+nsIWidget*
+RemoteCompositorSession::GetWidget()
+{
+  return mWidget;
+}
+
 RefPtr<IAPZCTreeManager>
 RemoteCompositorSession::GetAPZCTreeManager() const
 {
   return mAPZ;
 }
 
 void
 RemoteCompositorSession::Shutdown()
 {
   mContentController = nullptr;
-  mAPZ->SetCompositorSession(nullptr);
+  if (mAPZ) {
+    mAPZ->SetCompositorSession(nullptr);
+  }
   mCompositorBridgeChild->Destroy();
   mCompositorBridgeChild = nullptr;
   mCompositorWidgetDelegate = nullptr;
   mWidget = nullptr;
   GPUProcessManager::Get()->UnregisterSession(this);
 }
 
 } // namespace layers
--- a/gfx/ipc/RemoteCompositorSession.h
+++ b/gfx/ipc/RemoteCompositorSession.h
@@ -21,16 +21,17 @@ public:
                           CompositorWidgetDelegate* aWidgetDelegate,
                           APZCTreeManagerChild* aAPZ,
                           const uint64_t& aRootLayerTreeId);
   ~RemoteCompositorSession() override;
 
   CompositorBridgeParent* GetInProcessBridge() const override;
   void SetContentController(GeckoContentController* aController) override;
   GeckoContentController* GetContentController();
+  nsIWidget* GetWidget();
   RefPtr<IAPZCTreeManager> GetAPZCTreeManager() const override;
   void Shutdown() override;
 
   void NotifySessionLost();
 
 private:
   nsBaseWidget* mWidget;
   RefPtr<APZCTreeManagerChild> mAPZ;
--- a/gfx/layers/apz/public/GeckoContentController.h
+++ b/gfx/layers/apz/public/GeckoContentController.h
@@ -3,16 +3,17 @@
 /* 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/. */
 
 #ifndef mozilla_layers_GeckoContentController_h
 #define mozilla_layers_GeckoContentController_h
 
 #include "FrameMetrics.h"               // for FrameMetrics, etc
+#include "InputData.h"                  // for PinchGestureInput
 #include "Units.h"                      // for CSSPoint, CSSRect, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
 #include "mozilla/EventForwards.h"      // for Modifiers
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 
 class Runnable;
@@ -58,16 +59,37 @@ public:
    */
   virtual void HandleTap(TapType aType,
                          const LayoutDevicePoint& aPoint,
                          Modifiers aModifiers,
                          const ScrollableLayerGuid& aGuid,
                          uint64_t aInputBlockId) = 0;
 
   /**
+   * When the apz.allow_zooming pref is set to false, the APZ will not
+   * translate pinch gestures to actual zooming. Instead, it will call this
+   * method to notify gecko of the pinch gesture, and allow it to deal with it
+   * however it wishes. Note that this function is not called if the pinch is
+   * prevented by content calling preventDefault() on the touch events, or via
+   * use of the touch-action property.
+   * @param aType One of PINCHGESTURE_START, PINCHGESTURE_SCALE, or
+   *        PINCHGESTURE_END, indicating the phase of the pinch.
+   * @param aGuid The guid of the APZ that is detecting the pinch. This is
+   *        generally the root APZC for the layers id.
+   * @param aSpanChange For the START or END event, this is always 0.
+   *        For a SCALE event, this is the difference in span between the
+   *        previous state and the new state.
+   * @param aModifiers The keyboard modifiers depressed during the pinch.
+   */
+  virtual void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                                  const ScrollableLayerGuid& aGuid,
+                                  LayoutDeviceCoord aSpanChange,
+                                  Modifiers aModifiers) = 0;
+
+  /**
    * Schedules a runnable to run on the controller/UI thread at some time
    * in the future.
    * This method must always be called on the controller thread.
    */
   virtual void PostDelayedTask(already_AddRefed<Runnable> aRunnable, int aDelayMs) = 0;
 
   /**
    * Returns true if we are currently on the thread that can send repaint requests.
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1302,16 +1302,24 @@ nsEventStatus AsyncPanZoomController::On
 
   mPinchPaintTimerSet = false;
   // Note that there may not be a touch block at this point, if we received the
   // PinchGestureEvent directly from widget code without any touch events.
   if (HasReadyTouchBlock() && !GetCurrentTouchBlock()->TouchActionAllowsPinchZoom()) {
     return nsEventStatus_eIgnore;
   }
 
+  // For platforms that don't support APZ zooming, dispatch a message to the
+  // content controller, it may want to do something else with this gesture.
+  if (!gfxPrefs::APZAllowZooming()) {
+    if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
+      controller->NotifyPinchGesture(aEvent.mType, GetGuid(), 0, aEvent.modifiers);
+    }
+  }
+
   SetState(PINCHING);
   mX.SetVelocity(0);
   mY.SetVelocity(0);
   mLastZoomFocus = aEvent.mLocalFocusPoint - mFrameMetrics.GetCompositionBounds().TopLeft();
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
@@ -1321,16 +1329,25 @@ nsEventStatus AsyncPanZoomController::On
   if (HasReadyTouchBlock() && !GetCurrentTouchBlock()->TouchActionAllowsPinchZoom()) {
     return nsEventStatus_eIgnore;
   }
 
   if (mState != PINCHING) {
     return nsEventStatus_eConsumeNoDefault;
   }
 
+  if (!gfxPrefs::APZAllowZooming()) {
+    if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
+      controller->NotifyPinchGesture(aEvent.mType, GetGuid(),
+          ViewAs<LayoutDevicePixel>(aEvent.mCurrentSpan - aEvent.mPreviousSpan,
+            PixelCastJustification::LayoutDeviceIsParentLayerForRCDRSF),
+          aEvent.modifiers);
+    }
+  }
+
   // Only the root APZC is zoomable, and the root APZC is not allowed to have
   // different x and y scales. If it did, the calculations in this function
   // would have to be adjusted (as e.g. it would no longer be valid to take
   // the minimum or maximum of the ratios of the widths and heights of the
   // page rect and the composition bounds).
   MOZ_ASSERT(mFrameMetrics.IsRootContent());
   MOZ_ASSERT(mFrameMetrics.GetZoom().AreScalesSame());
 
@@ -1425,27 +1442,33 @@ nsEventStatus AsyncPanZoomController::On
   APZC_LOG("%p got a scale-end in state %d\n", this, mState);
 
   mPinchPaintTimerSet = false;
 
   if (HasReadyTouchBlock() && !GetCurrentTouchBlock()->TouchActionAllowsPinchZoom()) {
     return nsEventStatus_eIgnore;
   }
 
+  if (!gfxPrefs::APZAllowZooming()) {
+    if (RefPtr<GeckoContentController> controller = GetGeckoContentController()) {
+      controller->NotifyPinchGesture(aEvent.mType, GetGuid(), 0, aEvent.modifiers);
+    }
+  }
+
   SetState(NOTHING);
 
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
     ScheduleComposite();
     RequestContentRepaint();
     UpdateSharedCompositorFrameMetrics();
   }
 
   // Non-negative focus point would indicate that one finger is still down
-  if (aEvent.mFocusPoint.x != -1 && aEvent.mFocusPoint.y != -1) {
+  if (aEvent.mLocalFocusPoint.x != -1 && aEvent.mLocalFocusPoint.y != -1) {
     mPanDirRestricted = false;
     mX.StartTouch(aEvent.mLocalFocusPoint.x, aEvent.mTime);
     mY.StartTouch(aEvent.mLocalFocusPoint.y, aEvent.mTime);
     SetState(TOUCHING);
   } else {
     // Otherwise, handle the fingers being lifted.
     ReentrantMonitorAutoEnter lock(mMonitor);
 
--- a/gfx/layers/apz/src/GestureEventListener.cpp
+++ b/gfx/layers/apz/src/GestureEventListener.cpp
@@ -39,17 +39,17 @@ static bool sLongTapEnabled = true;
 
 ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent)
 {
   const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
   const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
   return (firstTouch + secondTouch) / 2;
 }
 
-float GetCurrentSpan(const MultiTouchInput& aEvent)
+ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent)
 {
   const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint;
   const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint;
   ParentLayerPoint delta = secondTouch - firstTouch;
   return delta.Length();
 }
 
 TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType)
@@ -266,17 +266,17 @@ nsEventStatus GestureEventListener::Hand
   }
 
   case GESTURE_MULTI_TOUCH_DOWN: {
     if (mLastTouchInput.mTouches.Length() < 2) {
       NS_WARNING("Wrong input: less than 2 moving points in GESTURE_MULTI_TOUCH_DOWN state");
       break;
     }
 
-    float currentSpan = GetCurrentSpan(mLastTouchInput);
+    ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
 
     mSpanChange += fabsf(currentSpan - mPreviousSpan);
     if (mSpanChange > PINCH_START_THRESHOLD) {
       SetState(GESTURE_PINCH);
       PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START,
                                    mLastTouchInput.mTime,
                                    mLastTouchInput.mTimeStamp,
                                    GetCurrentFocus(mLastTouchInput),
@@ -298,17 +298,17 @@ nsEventStatus GestureEventListener::Hand
   case GESTURE_PINCH: {
     if (mLastTouchInput.mTouches.Length() < 2) {
       NS_WARNING("Wrong input: less than 2 moving points in GESTURE_PINCH state");
       // Prevent APZC::OnTouchMove() from handling this wrong input
       rv = nsEventStatus_eConsumeNoDefault;
       break;
     }
 
-    float currentSpan = GetCurrentSpan(mLastTouchInput);
+    ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput);
 
     PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE,
                                  mLastTouchInput.mTime,
                                  mLastTouchInput.mTimeStamp,
                                  GetCurrentFocus(mLastTouchInput),
                                  currentSpan,
                                  mPreviousSpan,
                                  mLastTouchInput.modifiers);
--- a/gfx/layers/apz/src/GestureEventListener.h
+++ b/gfx/layers/apz/src/GestureEventListener.h
@@ -166,23 +166,23 @@ private:
   GestureState mState;
 
   /**
    * Total change in span since we detected a pinch gesture. Only used when we
    * are in the |GESTURE_WAITING_PINCH| state and need to know how far zoomed
    * out we are compared to our original pinch span. Note that this does _not_
    * continue to be updated once we jump into the |GESTURE_PINCH| state.
    */
-  float mSpanChange;
+  ParentLayerCoord mSpanChange;
 
   /**
    * Previous span calculated for the purposes of setting inside a
    * PinchGestureInput.
    */
-  float mPreviousSpan;
+  ParentLayerCoord mPreviousSpan;
 
   /**
    * Cached copy of the last touch input.
    */
   MultiTouchInput mLastTouchInput;
 
   /**
    * Cached copy of the last tap gesture input.
--- a/gfx/layers/apz/test/gtest/APZTestCommon.h
+++ b/gfx/layers/apz/test/gtest/APZTestCommon.h
@@ -73,16 +73,17 @@ static TimeStamp GetStartupTime() {
 }
 
 class MockContentController : public GeckoContentController {
 public:
   MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
   MOCK_METHOD2(RequestFlingSnap, void(const FrameMetrics::ViewID& aScrollId, const mozilla::CSSPoint& aDestination));
   MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration));
   MOCK_METHOD5(HandleTap, void(TapType, const LayoutDevicePoint&, Modifiers, const ScrollableLayerGuid&, uint64_t));
+  MOCK_METHOD4(NotifyPinchGesture, void(PinchGestureInput::PinchGestureType, const ScrollableLayerGuid&, LayoutDeviceCoord, Modifiers));
   // Can't use the macros with already_AddRefed :(
   void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) {
     RefPtr<Runnable> task = aTask;
   }
   bool IsRepaintThread() {
     return NS_IsMainThread();
   }
   void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) {
--- a/gfx/layers/apz/test/gtest/TestPinching.cpp
+++ b/gfx/layers/apz/test/gtest/TestPinching.cpp
@@ -97,16 +97,40 @@ protected:
 };
 
 class APZCPinchGestureDetectorTester : public APZCPinchTester {
 public:
   APZCPinchGestureDetectorTester()
     : APZCPinchTester(AsyncPanZoomController::USE_GESTURE_DETECTOR)
   {
   }
+
+  void DoPinchWithPreventDefaultTest() {
+    FrameMetrics originalMetrics = GetPinchableFrameMetrics();
+    apzc->SetFrameMetrics(originalMetrics);
+
+    MakeApzcWaitForMainThread();
+    MakeApzcZoomable();
+
+    int touchInputId = 0;
+    uint64_t blockId = 0;
+    PinchWithTouchInput(apzc, ScreenIntPoint(250, 300), 1.25, touchInputId,
+        nullptr, nullptr, &blockId);
+
+    // Send the prevent-default notification for the touch block
+    apzc->ContentReceivedInputBlock(blockId, true);
+
+    // verify the metrics didn't change (i.e. the pinch was ignored)
+    FrameMetrics fm = apzc->GetFrameMetrics();
+    EXPECT_EQ(originalMetrics.GetZoom(), fm.GetZoom());
+    EXPECT_EQ(originalMetrics.GetScrollOffset().x, fm.GetScrollOffset().x);
+    EXPECT_EQ(originalMetrics.GetScrollOffset().y, fm.GetScrollOffset().y);
+
+    apzc->AssertStateIsReset();
+  }
 };
 
 TEST_F(APZCPinchTester, Pinch_DefaultGestures_NoTouchAction) {
   SCOPED_GFX_PREF(TouchActionEnabled, bool, false);
   DoPinchTest(true);
 }
 
 TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_NoTouchAction) {
@@ -132,38 +156,42 @@ TEST_F(APZCPinchGestureDetectorTester, P
 TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNotAllowZoom) {
   SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
   nsTArray<uint32_t> behaviors;
   behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
   behaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::PINCH_ZOOM);
   DoPinchTest(false, &behaviors);
 }
 
-TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault) {
-  FrameMetrics originalMetrics = GetPinchableFrameMetrics();
-  apzc->SetFrameMetrics(originalMetrics);
+TEST_F(APZCPinchGestureDetectorTester, Pinch_UseGestureDetector_TouchActionNone_NoAPZZoom) {
+  SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
+  SCOPED_GFX_PREF(APZAllowZooming, bool, false);
 
-  MakeApzcWaitForMainThread();
-  MakeApzcZoomable();
+  // Since we are preventing the pinch action via touch-action we should not be
+  // sending the pinch gesture notifications that would normally be sent when
+  // APZAllowZooming is false.
+  EXPECT_CALL(*mcc, NotifyPinchGesture(_, _, _, _)).Times(0);
+  nsTArray<uint32_t> behaviors = { mozilla::layers::AllowedTouchBehavior::NONE,
+                                   mozilla::layers::AllowedTouchBehavior::NONE };
+  DoPinchTest(false, &behaviors);
+}
 
-  int touchInputId = 0;
-  uint64_t blockId = 0;
-  PinchWithTouchInput(apzc, ScreenIntPoint(250, 300), 1.25, touchInputId,
-      nullptr, nullptr, &blockId);
+TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault) {
+  DoPinchWithPreventDefaultTest();
+}
 
-  // Send the prevent-default notification for the touch block
-  apzc->ContentReceivedInputBlock(blockId, true);
+TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault_NoAPZZoom) {
+  SCOPED_GFX_PREF(APZAllowZooming, bool, false);
 
-  // verify the metrics didn't change (i.e. the pinch was ignored)
-  FrameMetrics fm = apzc->GetFrameMetrics();
-  EXPECT_EQ(originalMetrics.GetZoom(), fm.GetZoom());
-  EXPECT_EQ(originalMetrics.GetScrollOffset().x, fm.GetScrollOffset().x);
-  EXPECT_EQ(originalMetrics.GetScrollOffset().y, fm.GetScrollOffset().y);
+  // Since we are preventing the pinch action we should not be sending the pinch
+  // gesture notifications that would normally be sent when APZAllowZooming is
+  // false.
+  EXPECT_CALL(*mcc, NotifyPinchGesture(_, _, _, _)).Times(0);
 
-  apzc->AssertStateIsReset();
+  DoPinchWithPreventDefaultTest();
 }
 
 TEST_F(APZCPinchTester, Panning_TwoFinger_ZoomDisabled) {
   // set up APZ
   apzc->SetFrameMetrics(GetPinchableFrameMetrics());
   MakeApzcUnzoomable();
 
   nsEventStatus statuses[3];  // scalebegin, scale, scaleend
@@ -174,8 +202,38 @@ TEST_F(APZCPinchTester, Panning_TwoFinge
 
   // It starts from (300, 300), then moves the focus point from (250, 350) to
   // (200, 300) pans by (50, 50) screen pixels, but there is a 2x zoom, which
   // causes the scroll offset to change by half of that (25, 25) pixels.
   EXPECT_EQ(325, fm.GetScrollOffset().x);
   EXPECT_EQ(325, fm.GetScrollOffset().y);
   EXPECT_EQ(2.0, fm.GetZoom().ToScaleFactor().scale);
 }
+
+TEST_F(APZCPinchGestureDetectorTester, Pinch_APZZoom_Disabled) {
+  SCOPED_GFX_PREF(APZAllowZooming, bool, false);
+
+  FrameMetrics originalMetrics = GetPinchableFrameMetrics();
+  apzc->SetFrameMetrics(originalMetrics);
+
+  // When APZAllowZooming is false, the ZoomConstraintsClient produces
+  // ZoomConstraints with mAllowZoom set to false.
+  MakeApzcUnzoomable();
+
+  // With APZAllowZooming false, we expect the NotifyPinchGesture function to
+  // get called as the pinch progresses, but the metrics shouldn't change.
+  EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_START, apzc->GetGuid(), LayoutDeviceCoord(0), _)).Times(1);
+  EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_SCALE, apzc->GetGuid(), _, _)).Times(AtLeast(1));
+  EXPECT_CALL(*mcc, NotifyPinchGesture(PinchGestureInput::PINCHGESTURE_END, apzc->GetGuid(), LayoutDeviceCoord(0), _)).Times(1);
+
+  int touchInputId = 0;
+  uint64_t blockId = 0;
+  PinchWithTouchInput(apzc, ScreenIntPoint(250, 300), 1.25, touchInputId,
+      nullptr, nullptr, &blockId);
+
+  // verify the metrics didn't change (i.e. the pinch was ignored inside APZ)
+  FrameMetrics fm = apzc->GetFrameMetrics();
+  EXPECT_EQ(originalMetrics.GetZoom(), fm.GetZoom());
+  EXPECT_EQ(originalMetrics.GetScrollOffset().x, fm.GetScrollOffset().x);
+  EXPECT_EQ(originalMetrics.GetScrollOffset().y, fm.GetScrollOffset().y);
+
+  apzc->AssertStateIsReset();
+}
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -898,11 +898,40 @@ APZCCallbackHelper::IsDisplayportSuppres
 /* static */ bool
 APZCCallbackHelper::IsScrollInProgress(nsIScrollableFrame* aFrame)
 {
   return aFrame->IsProcessingAsyncScroll()
          || nsLayoutUtils::CanScrollOriginClobberApz(aFrame->LastScrollOrigin())
          || aFrame->LastSmoothScrollOrigin();
 }
 
+/* static */ void
+APZCCallbackHelper::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                                       LayoutDeviceCoord aSpanChange,
+                                       Modifiers aModifiers,
+                                       nsIWidget* aWidget)
+{
+  EventMessage msg;
+  switch (aType) {
+    case PinchGestureInput::PINCHGESTURE_START:
+      msg = eMagnifyGestureStart;
+      break;
+    case PinchGestureInput::PINCHGESTURE_SCALE:
+      msg = eMagnifyGestureUpdate;
+      break;
+    case PinchGestureInput::PINCHGESTURE_END:
+      msg = eMagnifyGesture;
+      break;
+    case PinchGestureInput::PINCHGESTURE_SENTINEL:
+    default:
+      MOZ_ASSERT_UNREACHABLE("Invalid gesture type");
+      return;
+  }
+
+  WidgetSimpleGestureEvent event(true, msg, aWidget);
+  event.mDelta = aSpanChange;
+  event.mModifiers = aModifiers;
+  DispatchWidgetEvent(event);
+}
+
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/apz/util/APZCCallbackHelper.h
+++ b/gfx/layers/apz/util/APZCCallbackHelper.h
@@ -2,16 +2,17 @@
 /* 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/. */
 
 #ifndef mozilla_layers_APZCCallbackHelper_h
 #define mozilla_layers_APZCCallbackHelper_h
 
 #include "FrameMetrics.h"
+#include "InputData.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/Function.h"
 #include "mozilla/layers/APZUtils.h"
 #include "nsIDOMWindowUtils.h"
 
 class nsIContent;
 class nsIDocument;
 class nsIPresShell;
@@ -182,16 +183,25 @@ public:
 
     /*
      * Check if the scrollable frame is currently in the middle of an async
      * or smooth scroll. We want to discard certain scroll input if this is
      * true to prevent clobbering higher priority origins.
      */
     static bool
     IsScrollInProgress(nsIScrollableFrame* aFrame);
+
+    /* Notify content of the progress of a pinch gesture that APZ won't do
+     * zooming for (because the apz.allow_zooming pref is false). This function
+     * will dispatch appropriate WidgetSimpleGestureEvent events to gecko.
+     */
+    static void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                                   LayoutDeviceCoord aSpanChange,
+                                   Modifiers aModifiers,
+                                   nsIWidget* aWidget);
 private:
   static uint64_t sLastTargetAPZCNotificationInputBlock;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* mozilla_layers_APZCCallbackHelper_h */
--- a/gfx/layers/apz/util/ChromeProcessController.cpp
+++ b/gfx/layers/apz/util/ChromeProcessController.cpp
@@ -203,16 +203,38 @@ ChromeProcessController::HandleTap(TapTy
     // Should never happen, but we need to handle this case branch for the
     // compiler to be happy.
     MOZ_ASSERT(false);
     break;
   }
 }
 
 void
+ChromeProcessController::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                                            const ScrollableLayerGuid& aGuid,
+                                            LayoutDeviceCoord aSpanChange,
+                                            Modifiers aModifiers)
+{
+  if (MessageLoop::current() != mUILoop) {
+    mUILoop->PostTask(NewRunnableMethod
+                      <PinchGestureInput::PinchGestureType,
+                       ScrollableLayerGuid,
+                       LayoutDeviceCoord,
+                       Modifiers>(this,
+                          &ChromeProcessController::NotifyPinchGesture,
+                          aType, aGuid, aSpanChange, aModifiers));
+    return;
+  }
+
+  if (mWidget) {
+    APZCCallbackHelper::NotifyPinchGesture(aType, aSpanChange, aModifiers, mWidget.get());
+  }
+}
+
+void
 ChromeProcessController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
                                               APZStateChange aChange,
                                               int aArg)
 {
   if (MessageLoop::current() != mUILoop) {
     mUILoop->PostTask(NewRunnableMethod
                       <ScrollableLayerGuid,
                        APZStateChange,
--- a/gfx/layers/apz/util/ChromeProcessController.h
+++ b/gfx/layers/apz/util/ChromeProcessController.h
@@ -48,16 +48,20 @@ public:
   virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
   virtual bool IsRepaintThread() override;
   virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) override;
   virtual void HandleTap(TapType aType,
                          const mozilla::LayoutDevicePoint& aPoint,
                          Modifiers aModifiers,
                          const ScrollableLayerGuid& aGuid,
                          uint64_t aInputBlockId) override;
+  virtual void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                                  const ScrollableLayerGuid& aGuid,
+                                  LayoutDeviceCoord aSpanChange,
+                                  Modifiers aModifiers) override;
   virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
                                     APZStateChange aChange,
                                     int aArg) override;
   virtual void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
                                          const nsString& aEvent) override;
   virtual void NotifyFlushComplete() override;
 private:
   nsCOMPtr<nsIWidget> mWidget;
--- a/gfx/layers/apz/util/ContentProcessController.cpp
+++ b/gfx/layers/apz/util/ContentProcessController.cpp
@@ -139,16 +139,27 @@ ContentProcessController::HandleTap(
                         const ScrollableLayerGuid& aGuid,
                         uint64_t aInputBlockId)
 {
   // This should never get called
   MOZ_ASSERT(false);
 }
 
 void
+ContentProcessController::NotifyPinchGesture(
+                        PinchGestureInput::PinchGestureType aType,
+                        const ScrollableLayerGuid& aGuid,
+                        LayoutDeviceCoord aSpanChange,
+                        Modifiers aModifiers)
+{
+  // This should never get called
+  MOZ_ASSERT_UNREACHABLE("Unexpected message to content process");
+}
+
+void
 ContentProcessController::NotifyAPZStateChange(
                                   const ScrollableLayerGuid& aGuid,
                                   APZStateChange aChange,
                                   int aArg)
 {
   if (mBrowser) {
     mBrowser->NotifyAPZStateChange(aGuid.mScrollId, aChange, aArg);
   }
--- a/gfx/layers/apz/util/ContentProcessController.h
+++ b/gfx/layers/apz/util/ContentProcessController.h
@@ -49,16 +49,21 @@ public:
   void RequestContentRepaint(const FrameMetrics& frame) override;
 
   void HandleTap(TapType aType,
                  const LayoutDevicePoint& aPoint,
                  Modifiers aModifiers,
                  const ScrollableLayerGuid& aGuid,
                  uint64_t aInputBlockId) override;
 
+  void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                          const ScrollableLayerGuid& aGuid,
+                          LayoutDeviceCoord aSpanChange,
+                          Modifiers aModifiers) override;
+
   void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
                             APZStateChange aChange,
                             int aArg) override;
 
   void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
                                  const nsString& aEvent) override;
 
   void NotifyFlushComplete() override;
--- a/gfx/layers/ipc/APZCTreeManagerChild.cpp
+++ b/gfx/layers/ipc/APZCTreeManagerChild.cpp
@@ -3,16 +3,17 @@
 /* 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 "mozilla/layers/APZCTreeManagerChild.h"
 
 #include "InputData.h"                  // for InputData
 #include "mozilla/dom/TabParent.h"      // for TabParent
+#include "mozilla/layers/APZCCallbackHelper.h" // for APZCCallbackHelper
 #include "mozilla/layers/RemoteCompositorSession.h" // for RemoteCompositorSession
 
 namespace mozilla {
 namespace layers {
 
 APZCTreeManagerChild::APZCTreeManagerChild()
   : mCompositorSession(nullptr)
 {
@@ -236,16 +237,36 @@ APZCTreeManagerChild::RecvHandleTap(cons
   }
   dom::TabParent* tab = dom::TabParent::GetTabParentFromLayersId(aGuid.mLayersId);
   if (tab) {
     tab->SendHandleTap(aType, aPoint, aModifiers, aGuid, aInputBlockId);
   }
   return true;
 }
 
+bool
+APZCTreeManagerChild::RecvNotifyPinchGesture(const PinchGestureType& aType,
+                                             const ScrollableLayerGuid& aGuid,
+                                             const LayoutDeviceCoord& aSpanChange,
+                                             const Modifiers& aModifiers)
+{
+  // This will only get sent from the GPU process to the parent process, so
+  // this function should never get called in the content process.
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // We want to handle it in this process regardless of what the target guid
+  // of the pinch is. This may change in the future.
+  if (mCompositorSession &&
+      mCompositorSession->GetWidget()) {
+    APZCCallbackHelper::NotifyPinchGesture(aType, aSpanChange, aModifiers, mCompositorSession->GetWidget());
+  }
+  return true;
+}
+
 void
 APZCTreeManagerChild::OnProcessingError(
         Result aCode,
         const char* aReason)
 {
   MOZ_RELEASE_ASSERT(aCode != MsgDropped);
 }
 
--- a/gfx/layers/ipc/APZCTreeManagerChild.h
+++ b/gfx/layers/ipc/APZCTreeManagerChild.h
@@ -93,16 +93,21 @@ public:
 
 protected:
   bool RecvHandleTap(const TapType& aType,
                      const LayoutDevicePoint& aPoint,
                      const Modifiers& aModifiers,
                      const ScrollableLayerGuid& aGuid,
                      const uint64_t& aInputBlockId) override;
 
+  bool RecvNotifyPinchGesture(const PinchGestureType& aType,
+                              const ScrollableLayerGuid& aGuid,
+                              const LayoutDeviceCoord& aSpanChange,
+                              const Modifiers& aModifiers) override;
+
   virtual
   ~APZCTreeManagerChild() { }
 
 private:
   MOZ_NON_OWNING_REF RemoteCompositorSession* mCompositorSession;
 };
 
 } // namespace layers
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -27,16 +27,17 @@
 #include "nsAutoPtr.h"
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsIObserver.h"                // for nsIObserver
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop, etc
 #include "FrameLayerBuilder.h"
 #include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/TabParent.h"
 #include "mozilla/Unused.h"
 #include "mozilla/DebugOnly.h"
 #if defined(XP_WIN)
 #include "WinUtils.h"
 #endif
 #include "mozilla/widget/CompositorWidget.h"
 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
 # include "mozilla/widget/CompositorWidgetChild.h"
@@ -862,16 +863,32 @@ CompositorBridgeChild::RecvParentAsyncMe
       default:
         NS_ERROR("unknown AsyncParentMessageData type");
         return false;
     }
   }
   return true;
 }
 
+bool
+CompositorBridgeChild::RecvObserveLayerUpdate(const uint64_t& aLayersId,
+                                              const uint64_t& aEpoch,
+                                              const bool& aActive)
+{
+  // This message is sent via the window compositor, not the tab compositor -
+  // however it still has a layers id.
+  MOZ_ASSERT(aLayersId);
+  MOZ_ASSERT(XRE_IsParentProcess());
+
+  if (RefPtr<dom::TabParent> tab = dom::TabParent::GetTabParentFromLayersId(aLayersId)) {
+    tab->LayerTreeUpdate(aEpoch, aActive);
+  }
+  return true;
+}
+
 void
 CompositorBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient)
 {
   if (!aClient) {
     return;
   }
 
   if (!(aClient->GetFlags() & TextureFlags::RECYCLE) &&
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -245,16 +245,20 @@ private:
                                                 const uint32_t& aAPZCId) override;
 
   virtual bool RecvReleaseSharedCompositorFrameMetrics(const ViewID& aId,
                                                        const uint32_t& aAPZCId) override;
 
   virtual bool
   RecvRemotePaintIsReady() override;
 
+  bool RecvObserveLayerUpdate(const uint64_t& aLayersId,
+                              const uint64_t& aEpoch,
+                              const bool& aActive) override;
+
   // Class used to store the shared FrameMetrics, mutex, and APZCId  in a hash table
   class SharedFrameMetricsData {
   public:
     SharedFrameMetricsData(
         const mozilla::ipc::SharedMemoryBasic::Handle& metrics,
         const CrossProcessMutexHandle& handle,
         const uint64_t& aLayersId,
         const uint32_t& aAPZCId);
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -2433,21 +2433,19 @@ CompositorBridgeParent::GetIndirectShado
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
   if (sIndirectLayerTrees.end() == cit) {
     return nullptr;
   }
   return &cit->second;
 }
 
-/* static */ APZCTreeManagerParent*
-CompositorBridgeParent::GetApzcTreeManagerParentForRoot(uint64_t aContentLayersId)
+static CompositorBridgeParent::LayerTreeState*
+GetStateForRoot(uint64_t aContentLayersId, const MonitorAutoLock& aProofOfLock)
 {
-  MonitorAutoLock lock(*sIndirectLayerTreesLock);
-
   CompositorBridgeParent::LayerTreeState* state = nullptr;
   LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aContentLayersId);
   if (sIndirectLayerTrees.end() != itr) {
     state = &itr->second;
   }
 
   // |state| is the state for the content process, but we want the APZCTMParent
   // for the parent process owning that content process. So we have to jump to
@@ -2456,19 +2454,37 @@ CompositorBridgeParent::GetApzcTreeManag
   // content processes, because RootLayerTreeId() will bypass any intermediate
   // processes' ids and go straight to the root.
   if (state) {
     uint64_t rootLayersId = state->mParent->RootLayerTreeId();
     itr = sIndirectLayerTrees.find(rootLayersId);
     state = (sIndirectLayerTrees.end() != itr) ? &itr->second : nullptr;
   }
 
+  return state;
+}
+
+/* static */ APZCTreeManagerParent*
+CompositorBridgeParent::GetApzcTreeManagerParentForRoot(uint64_t aContentLayersId)
+{
+  MonitorAutoLock lock(*sIndirectLayerTreesLock);
+  CompositorBridgeParent::LayerTreeState* state =
+      GetStateForRoot(aContentLayersId, lock);
   return state ? state->mApzcTreeManagerParent : nullptr;
 }
 
+/* static */ GeckoContentController*
+CompositorBridgeParent::GetGeckoContentControllerForRoot(uint64_t aContentLayersId)
+{
+  MonitorAutoLock lock(*sIndirectLayerTreesLock);
+  CompositorBridgeParent::LayerTreeState* state =
+      GetStateForRoot(aContentLayersId, lock);
+  return state ? state->mController.get() : nullptr;
+}
+
 PTextureParent*
 CompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
                                             const LayersBackend& aLayersBackend,
                                             const TextureFlags& aFlags,
                                             const uint64_t& aId,
                                             const uint64_t& aSerial)
 {
   return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial);
@@ -2691,17 +2707,19 @@ CrossProcessCompositorBridgeParent::Shad
 
   // Send the 'remote paint ready' message to the content thread if it has already asked.
   if(mNotifyAfterRemotePaint)  {
     Unused << SendRemotePaintIsReady();
     mNotifyAfterRemotePaint = false;
   }
 
   if (aLayerTree->ShouldParentObserveEpoch()) {
-    dom::TabParent::ObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true);
+    // Note that we send this through the window compositor, since this needs
+    // to reach the widget owning the tab.
+    Unused << state->mParent->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), true);
   }
 
   aLayerTree->SetPendingTransactionId(aTransactionId);
 }
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
 //#define PLUGINS_LOG(...) printf_stderr("CP [%s]: ", __FUNCTION__);
 //                         printf_stderr(__VA_ARGS__);
@@ -2920,17 +2938,23 @@ CrossProcessCompositorBridgeParent::Forc
 }
 
 void
 CrossProcessCompositorBridgeParent::NotifyClearCachedResources(LayerTransactionParent* aLayerTree)
 {
   uint64_t id = aLayerTree->GetId();
   MOZ_ASSERT(id != 0);
 
-  dom::TabParent::ObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), false);
+  const CompositorBridgeParent::LayerTreeState* state =
+    CompositorBridgeParent::GetIndirectShadowTree(id);
+  if (state && state->mParent) {
+    // Note that we send this through the window compositor, since this needs
+    // to reach the widget owning the tab.
+    Unused << state->mParent->SendObserveLayerUpdate(id, aLayerTree->GetChildEpoch(), false);
+  }
 }
 
 bool
 CrossProcessCompositorBridgeParent::SetTestSampleTime(
   LayerTransactionParent* aLayerTree, const TimeStamp& aTime)
 {
   uint64_t id = aLayerTree->GetId();
   MOZ_ASSERT(id != 0);
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -475,16 +475,22 @@ public:
    * if one is found, will always be connected to the parent process rather
    * than a content process. Note that unless the compositor process is
    * separated this is expected to return null, because if the compositor is
    * living in the gecko parent process then there is no APZCTreeManagerParent
    * for the parent process.
    */
   static APZCTreeManagerParent* GetApzcTreeManagerParentForRoot(
         uint64_t aContentLayersId);
+  /**
+   * Same as the GetApzcTreeManagerParentForRoot function, but returns
+   * the GeckoContentController for the parent process.
+   */
+  static GeckoContentController* GetGeckoContentControllerForRoot(
+        uint64_t aContentLayersId);
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
   /**
    * Calculates and requests the main thread update plugin positioning, clip,
    * and visibility via ipc.
    */
   bool UpdatePluginWindowState(uint64_t aId);
 
--- a/gfx/layers/ipc/PAPZCTreeManager.ipdl
+++ b/gfx/layers/ipc/PAPZCTreeManager.ipdl
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include "mozilla/GfxMessageUtils.h";
 include "ipc/nsGUIEventIPC.h";
 
 include protocol PCompositorBridge;
 
 using CSSRect from "Units.h";
+using LayoutDeviceCoord from "Units.h";
 using LayoutDeviceIntPoint from "Units.h";
 using mozilla::LayoutDevicePoint from "Units.h";
 using ScreenPoint from "Units.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
 using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
 using mozilla::layers::AsyncDragMetrics from "mozilla/layers/AsyncDragMetrics.h";
 using mozilla::layers::GeckoContentController::TapType from "mozilla/layers/GeckoContentController.h";
@@ -26,16 +27,17 @@ using class mozilla::WidgetMouseEventBas
 using mozilla::WidgetMouseEvent::Reason from "mozilla/MouseEvents.h";
 using class mozilla::WidgetTouchEvent from "mozilla/TouchEvents.h";
 using class mozilla::WidgetWheelEvent from "mozilla/MouseEvents.h";
 using class mozilla::InputData from "InputData.h";
 using class mozilla::MultiTouchInput from "InputData.h";
 using class mozilla::MouseInput from "InputData.h";
 using class mozilla::PanGestureInput from "InputData.h";
 using class mozilla::PinchGestureInput from "InputData.h";
+using mozilla::PinchGestureInput::PinchGestureType from "InputData.h";
 using class mozilla::TapGestureInput from "InputData.h";
 using class mozilla::ScrollWheelInput from "InputData.h";
 
 namespace mozilla {
 namespace layers {
 
 /**
  * PAPZCTreeManager is a protocol for remoting an IAPZCTreeManager. PAPZCTreeManager
@@ -123,12 +125,15 @@ parent:
              ScrollableLayerGuid    aOutTargetGuid);
 
   async __delete__();
 
 child:
 
   async HandleTap(TapType aType, LayoutDevicePoint point, Modifiers aModifiers,
                   ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
+
+  async NotifyPinchGesture(PinchGestureType aType, ScrollableLayerGuid aGuid,
+                           LayoutDeviceCoord aSpanChange, Modifiers aModifiers);
 };
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -110,16 +110,18 @@ child:
   /**
    * Drop any buffers that might be retained on the child compositor
    * side.
    */
   async ClearCachedResources(uint64_t id);
 
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
+  async ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive);
+
 parent:
   // Must be called before Initialize().
   async PCompositorWidget(CompositorWidgetInitData aInitData);
 
   // When out-of-process, this must be called to finish initialization.
   sync Initialize(uint64_t rootLayerTreeId);
 
   // Returns whether this Compositor has APZ enabled or not.
--- a/gfx/layers/ipc/RemoteContentController.cpp
+++ b/gfx/layers/ipc/RemoteContentController.cpp
@@ -81,16 +81,55 @@ RemoteContentController::HandleTap(TapTy
     // environment, so we must be on the main thread.
     MOZ_ASSERT(XRE_IsParentProcess());
     MOZ_ASSERT(NS_IsMainThread());
     tab->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
   }
 }
 
 void
+RemoteContentController::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                                            const ScrollableLayerGuid& aGuid,
+                                            LayoutDeviceCoord aSpanChange,
+                                            Modifiers aModifiers)
+{
+  APZThreadUtils::AssertOnControllerThread();
+
+  // For now we only ever want to handle this NotifyPinchGesture message in
+  // the parent process, even if the APZ is sending it to a content process.
+
+  // If we're in the GPU process, try to find a handle to the parent process
+  // and send it there.
+  if (XRE_IsGPUProcess()) {
+    MOZ_ASSERT(MessageLoop::current() == mCompositorThread);
+
+    // The raw pointer to APZCTreeManagerParent is ok here because we are on the
+    // compositor thread.
+    APZCTreeManagerParent* apzctmp =
+        CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId);
+    if (apzctmp) {
+      Unused << apzctmp->SendNotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
+      return;
+    }
+  }
+
+  // If we're in the parent process, handle it directly. We don't have a handle
+  // to the widget though, so we fish out the ChromeProcessController and
+  // delegate to that instead.
+  if (XRE_IsParentProcess()) {
+    MOZ_ASSERT(NS_IsMainThread());
+    RefPtr<GeckoContentController> rootController =
+        CompositorBridgeParent::GetGeckoContentControllerForRoot(aGuid.mLayersId);
+    if (rootController) {
+      rootController->NotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
+    }
+  }
+}
+
+void
 RemoteContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
 {
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelayMs);
 #else
   (MessageLoop::current() ? MessageLoop::current() : mCompositorThread)->
     PostDelayedTask(Move(aTask), aDelayMs);
 #endif
--- a/gfx/layers/ipc/RemoteContentController.h
+++ b/gfx/layers/ipc/RemoteContentController.h
@@ -43,16 +43,21 @@ public:
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
 
   virtual void HandleTap(TapType aTapType,
                          const LayoutDevicePoint& aPoint,
                          Modifiers aModifiers,
                          const ScrollableLayerGuid& aGuid,
                          uint64_t aInputBlockId) override;
 
+  virtual void NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
+                                  const ScrollableLayerGuid& aGuid,
+                                  LayoutDeviceCoord aSpanChange,
+                                  Modifiers aModifiers) override;
+
   virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
 
   virtual bool IsRepaintThread() override;
 
   virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) override;
 
   virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override;
 
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2017,16 +2017,20 @@ gfxFont::Draw(const gfxTextRun *aTextRun
                  "GLYPH_PATH cannot be used with GLYPH_FILL, GLYPH_STROKE or GLYPH_STROKE_UNDERNEATH");
 
     if (aStart >= aEnd) {
         return;
     }
 
     FontDrawParams fontParams;
 
+    if (aRunParams.drawOpts) {
+        fontParams.drawOptions = *aRunParams.drawOpts;
+    }
+
     fontParams.scaledFont = GetScaledFont(aRunParams.dt);
     if (!fontParams.scaledFont) {
         return;
     }
 
     fontParams.haveSVGGlyphs = GetFontEntry()->TryGetSVGData(this);
     fontParams.haveColorGlyphs = GetFontEntry()->TryGetColorGlyphs();
     fontParams.contextPaint = aRunParams.runContextPaint;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -95,18 +95,16 @@
 #ifdef MOZ_WIDGET_ANDROID
 #include "TexturePoolOGL.h"
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 #include "mozilla/layers/GrallocTextureHost.h"
 #endif
 
-#include "mozilla/Hal.h"
-
 #ifdef USE_SKIA
 # ifdef __GNUC__
 #  pragma GCC diagnostic push
 #  pragma GCC diagnostic ignored "-Wshadow"
 # endif
 # include "skia/include/core/SkGraphics.h"
 # ifdef USE_SKIA_GPU
 #  include "skia/include/gpu/GrContext.h"
@@ -139,16 +137,17 @@ class mozilla::gl::SkiaGLGlue : public G
 #include "nsIXULRuntime.h"
 #include "VsyncSource.h"
 #include "SoftwareVsyncSource.h"
 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
 #include "mozilla/dom/ContentChild.h"
 #include "gfxVR.h"
 #include "VRManagerChild.h"
 #include "mozilla/gfx/GPUParent.h"
+#include "prsystem.h"
 
 namespace mozilla {
 namespace layers {
 #ifdef MOZ_WIDGET_GONK
 void InitGralloc();
 #endif
 void ShutdownTileCache();
 } // namespace layers
@@ -501,17 +500,18 @@ gfxPlatform::gfxPlatform()
     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO);
     uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
 #ifdef USE_SKIA
     canvasMask |= BackendTypeBit(BackendType::SKIA);
     contentMask |= BackendTypeBit(BackendType::SKIA);
 #endif
     InitBackendPrefs(canvasMask, BackendType::CAIRO,
                      contentMask, BackendType::CAIRO);
-    mTotalSystemMemory = mozilla::hal::GetTotalSystemMemory();
+
+    mTotalSystemMemory = PR_GetPhysicalMemorySize();
 
     VRManager::ManagerInit();
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
@@ -1269,36 +1269,39 @@ bool gfxPlatform::UseAcceleratedCanvas()
 
 void
 gfxPlatform::InitializeSkiaCacheLimits()
 {
   if (UseAcceleratedCanvas()) {
 #ifdef USE_SKIA_GPU
     bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
     int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
-    int cacheSizeLimit = gfxPrefs::CanvasSkiaGLCacheSize();
+    uint64_t cacheSizeLimit = std::max(gfxPrefs::CanvasSkiaGLCacheSize(), (int32_t)0);
 
     // Prefs are in megabytes, but we want the sizes in bytes
     cacheSizeLimit *= 1024*1024;
 
     if (usingDynamicCache) {
       if (mTotalSystemMemory < 512*1024*1024) {
         // We need a very minimal cache on anything smaller than 512mb.
         // Note the large jump as we cross 512mb (from 2mb to 32mb).
         cacheSizeLimit = 2*1024*1024;
       } else if (mTotalSystemMemory > 0) {
         cacheSizeLimit = mTotalSystemMemory / 16;
       }
     }
 
+    // Ensure cache size doesn't overflow on 32-bit platforms.
+    cacheSizeLimit = std::min(cacheSizeLimit, (uint64_t)SIZE_MAX);
+
   #ifdef DEBUG
-    printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit);
+    printf_stderr("Determined SkiaGL cache limits: Size %" PRIu64 ", Items: %i\n", cacheSizeLimit, cacheItemLimit);
   #endif
 
-    mSkiaGlue->GetGrContext()->setResourceCacheLimits(cacheItemLimit, cacheSizeLimit);
+    mSkiaGlue->GetGrContext()->setResourceCacheLimits(cacheItemLimit, (size_t)cacheSizeLimit);
 #endif
   }
 }
 
 SkiaGLGlue*
 gfxPlatform::GetSkiaGLGlue()
 {
 #ifdef USE_SKIA_GPU
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -765,17 +765,17 @@ protected:
     int8_t  mFallbackUsesCmaps;
 
     // max character limit for words in word cache
     int32_t mWordCacheCharLimit;
 
     // max number of entries in word cache
     int32_t mWordCacheMaxEntries;
 
-    uint32_t mTotalSystemMemory;
+    uint64_t mTotalSystemMemory;
 
     // Hardware vsync source. Only valid on parent process
     RefPtr<mozilla::gfx::VsyncSource> mVsyncSource;
 
     RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
 
 private:
     /**
--- a/intl/unicharutil/util/nsBidiUtils.h
+++ b/intl/unicharutil/util/nsBidiUtils.h
@@ -268,13 +268,14 @@ typedef enum nsCharType nsCharType;
  */
 
 #define IS_IN_BMP_RTL_BLOCK(c) ((0x590 <= (c)) && ((c) <= 0x8ff))
 #define IS_RTL_PRESENTATION_FORM(c) (((0xfb1d <= (c)) && ((c) <= 0xfdff)) || \
                                      ((0xfe70 <= (c)) && ((c) <= 0xfefc)))
 #define IS_IN_SMP_RTL_BLOCK(c) (((0x10800 <= (c)) && ((c) <= 0x10fff)) || \
                                 ((0x1e800 <= (c)) && ((c) <= 0x1eFFF)))
 #define UCS2_CHAR_IS_BIDI(c) ((IS_IN_BMP_RTL_BLOCK(c)) || \
-                              (IS_RTL_PRESENTATION_FORM(c)))
+                              (IS_RTL_PRESENTATION_FORM(c)) || \
+                              (c) == 0xD802 || (c) == 0xD803)
 #define UTF32_CHAR_IS_BIDI(c)  ((IS_IN_BMP_RTL_BLOCK(c)) || \
                                (IS_RTL_PRESENTATION_FORM(c)) || \
                                (IS_IN_SMP_RTL_BLOCK(c)))
 #endif  /* nsBidiUtils_h__ */
--- a/intl/unicharutil/util/nsUnicodeProperties.cpp
+++ b/intl/unicharutil/util/nsUnicodeProperties.cpp
@@ -1,10 +1,11 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set ts=4 sw=4 sts=4 et cindent: */
+/* 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 "nsUnicodeProperties.h"
 #include "nsUnicodePropertyData.cpp"
 
 #include "mozilla/ArrayUtils.h"
 #include "nsCharTraits.h"
@@ -498,16 +499,44 @@ ClusterIterator::Next()
             mPos++;
         }
     }
 
     NS_ASSERTION(mText < mPos && mPos <= mLimit,
                  "ClusterIterator::Next has overshot the string!");
 }
 
+void
+ClusterReverseIterator::Next()
+{
+    if (AtEnd()) {
+        NS_WARNING("ClusterReverseIterator has already reached the end");
+        return;
+    }
+
+    uint32_t ch;
+    do {
+        ch = *--mPos;
+
+        if (NS_IS_LOW_SURROGATE(ch) && mPos > mLimit &&
+            NS_IS_HIGH_SURROGATE(*(mPos - 1))) {
+            ch = SURROGATE_TO_UCS4(*--mPos, ch);
+        }
+
+        if (!IsClusterExtender(ch)) {
+            break;
+        }
+    } while (mPos > mLimit);
+
+    // XXX May need to handle conjoining Jamo
+
+    NS_ASSERTION(mPos >= mLimit,
+                 "ClusterReverseIterator::Next has overshot the string!");
+}
+
 uint32_t
 CountGraphemeClusters(const char16_t* aText, uint32_t aLength)
 {
   ClusterIterator iter(aText, aLength);
   uint32_t result = 0;
   while (!iter.AtEnd()) {
     ++result;
     iter.Next();
--- a/intl/unicharutil/util/nsUnicodeProperties.h
+++ b/intl/unicharutil/util/nsUnicodeProperties.h
@@ -1,10 +1,11 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set ts=4 sw=4 sts=4 et cindent: */
+/* 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/. */
 
 #ifndef NS_UNICODEPROPERTIES_H
 #define NS_UNICODEPROPERTIES_H
 
 #include "nsBidiUtils.h"
 #include "nsIUGenCategory.h"
@@ -151,13 +152,37 @@ private:
 #ifdef DEBUG
     const char16_t* mText;
 #endif
 };
 
 // Count the number of grapheme clusters in the given string
 uint32_t CountGraphemeClusters(const char16_t* aText, uint32_t aLength);
 
+// A simple reverse iterator for a string of char16_t codepoints that
+// advances by Unicode grapheme clusters
+class ClusterReverseIterator
+{
+public:
+    ClusterReverseIterator(const char16_t* aText, uint32_t aLength)
+        : mPos(aText + aLength), mLimit(aText)
+    { }
+
+    operator const char16_t* () const {
+        return mPos;
+    }
+
+    bool AtEnd() const {
+        return mPos <= mLimit;
+    }
+
+    void Next();
+
+private:
+    const char16_t* mPos;
+    const char16_t* mLimit;
+};
+
 } // end namespace unicode
 
 } // end namespace mozilla
 
 #endif /* NS_UNICODEPROPERTIES_H */
--- a/ipc/glue/InputStreamParams.ipdlh
+++ b/ipc/glue/InputStreamParams.ipdlh
@@ -25,16 +25,23 @@ struct FileInputStreamParams
 
 struct PartialFileInputStreamParams
 {
   FileInputStreamParams fileStreamParams;
   uint64_t begin;
   uint64_t length;
 };
 
+struct TemporaryFileInputStreamParams
+{
+  uint32_t fileDescriptorIndex;
+  uint64_t startPos;
+  uint64_t endPos;
+};
+
 struct MultiplexInputStreamParams
 {
   InputStreamParams[] streams;
   uint32_t currentStream;
   nsresult status;
   bool startedReadingCurrent;
 };
 
@@ -51,16 +58,17 @@ struct SameProcessInputStreamParams
   intptr_t addRefedInputStream;
 };
 
 union InputStreamParams
 {
   StringInputStreamParams;
   FileInputStreamParams;
   PartialFileInputStreamParams;
+  TemporaryFileInputStreamParams;
   BufferedInputStreamParams;
   MIMEInputStreamParams;
   MultiplexInputStreamParams;
   RemoteInputStreamParams;
   SameProcessInputStreamParams;
 };
 
 union OptionalInputStreamParams
--- a/ipc/glue/InputStreamUtils.cpp
+++ b/ipc/glue/InputStreamUtils.cpp
@@ -88,16 +88,20 @@ DeserializeInputStream(const InputStream
     case InputStreamParams::TFileInputStreamParams:
       serializable = do_CreateInstance(kFileInputStreamCID);
       break;
 
     case InputStreamParams::TPartialFileInputStreamParams:
       serializable = do_CreateInstance(kPartialFileInputStreamCID);
       break;
 
+    case InputStreamParams::TTemporaryFileInputStreamParams:
+      serializable = new nsTemporaryFileInputStream();
+      break;
+
     case InputStreamParams::TBufferedInputStreamParams:
       serializable = do_CreateInstance(kBufferedInputStreamCID);
       break;
 
     case InputStreamParams::TMIMEInputStreamParams:
       serializable = do_CreateInstance(kMIMEInputStreamCID);
       break;
 
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -641,19 +641,17 @@ class alignas(8) DispatchWrapper
     // Mimic a pointer type, so that we can drop into Rooted.
     T* operator &() { return &storage; }
     const T* operator &() const { return &storage; }
     operator T&() { return storage; }
     operator const T&() const { return storage; }
 
     // Trace the contained storage (of unknown type) using the trace function
     // we set aside when we did know the type.
-    MOZ_UBSAN_BLACKLIST_FUNCTION static void TraceWrapped(JSTracer* trc, T* thingp,
-                                                          const char* name)
-    {
+    static void TraceWrapped(JSTracer* trc, T* thingp, const char* name) {
         auto wrapper = reinterpret_cast<DispatchWrapper*>(
                            uintptr_t(thingp) - offsetof(DispatchWrapper, storage));
         wrapper->tracer(trc, &wrapper->storage, name);
     }
 };
 
 } /* namespace js */
 
--- a/js/public/SweepingAPI.h
+++ b/js/public/SweepingAPI.h
@@ -52,14 +52,14 @@ class WeakCache : public js::WeakCacheBa
       : sweeper(other.sweeper),
         cache(mozilla::Move(other.cache))
     {
     }
 
     const T& get() const { return cache; }
     T& get() { return cache; }
 
-    MOZ_UBSAN_BLACKLIST_FUNCTION void sweep() { sweeper(&cache); }
+    void sweep() { sweeper(&cache); }
 };
 
 } // namespace JS
 
 #endif // js_SweepingAPI_h
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -2950,87 +2950,106 @@ class MOZ_STACK_CLASS FunctionValidator
     }
 
     /**************************************************************** Labels */
   private:
     bool writeBr(uint32_t absolute, Expr expr = Expr::Br) {
         MOZ_ASSERT(expr == Expr::Br || expr == Expr::BrIf);
         MOZ_ASSERT(absolute < blockDepth_);
         return encoder().writeExpr(expr) &&
-               encoder().writeVarU32(0) &&  // break arity
                encoder().writeVarU32(blockDepth_ - 1 - absolute);
     }
     void removeLabel(PropertyName* label, LabelMap* map) {
         LabelMap::Ptr p = map->lookup(label);
         MOZ_ASSERT(p);
         map->remove(p);
     }
 
   public:
     bool pushBreakableBlock() {
         return encoder().writeExpr(Expr::Block) &&
+               encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
                breakableStack_.append(blockDepth_++);
     }
     bool popBreakableBlock() {
         JS_ALWAYS_TRUE(breakableStack_.popCopy() == --blockDepth_);
         return encoder().writeExpr(Expr::End);
     }
 
     bool pushUnbreakableBlock(const NameVector* labels = nullptr) {
         if (labels) {
             for (PropertyName* label : *labels) {
                 if (!breakLabels_.putNew(label, blockDepth_))
                     return false;
             }
         }
         blockDepth_++;
-        return encoder().writeExpr(Expr::Block);
+        return encoder().writeExpr(Expr::Block) &&
+               encoder().writeFixedU8(uint8_t(ExprType::Void));
     }
     bool popUnbreakableBlock(const NameVector* labels = nullptr) {
         if (labels) {
             for (PropertyName* label : *labels)
                 removeLabel(label, &breakLabels_);
         }
         --blockDepth_;
         return encoder().writeExpr(Expr::End);
     }
 
     bool pushContinuableBlock() {
         return encoder().writeExpr(Expr::Block) &&
+               encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
                continuableStack_.append(blockDepth_++);
     }
     bool popContinuableBlock() {
         JS_ALWAYS_TRUE(continuableStack_.popCopy() == --blockDepth_);
         return encoder().writeExpr(Expr::End);
     }
 
     bool pushLoop() {
-        return encoder().writeExpr(Expr::Loop) &&
+        return encoder().writeExpr(Expr::Block) &&
+               encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
+               encoder().writeExpr(Expr::Loop) &&
+               encoder().writeFixedU8(uint8_t(ExprType::Void)) &&
                breakableStack_.append(blockDepth_++) &&
                continuableStack_.append(blockDepth_++);
     }
     bool popLoop() {
         JS_ALWAYS_TRUE(continuableStack_.popCopy() == --blockDepth_);
         JS_ALWAYS_TRUE(breakableStack_.popCopy() == --blockDepth_);
-        return encoder().writeExpr(Expr::End);
-    }
-
-    bool pushIf() {
+        return encoder().writeExpr(Expr::End) &&
+               encoder().writeExpr(Expr::End);
+    }
+
+    bool pushIf(size_t* typeAt) {
         ++blockDepth_;
-        return encoder().writeExpr(Expr::If);
+        return encoder().writeExpr(Expr::If) &&
+               encoder().writePatchableFixedU7(typeAt);
     }
     bool switchToElse() {
         MOZ_ASSERT(blockDepth_ > 0);
         return encoder().writeExpr(Expr::Else);
     }
+    void setIfType(size_t typeAt, ExprType type) {
+        encoder().patchFixedU7(typeAt, uint8_t(type));
+    }
     bool popIf() {
         MOZ_ASSERT(blockDepth_ > 0);
         --blockDepth_;
         return encoder().writeExpr(Expr::End);
     }
+    bool popIf(size_t typeAt, ExprType type) {
+        MOZ_ASSERT(blockDepth_ > 0);
+        --blockDepth_;
+        if (!encoder().writeExpr(Expr::End))
+            return false;
+
+        setIfType(typeAt, type);
+        return true;
+    }
 
     bool writeBreakIf() {
         return writeBr(breakableStack_.back(), Expr::BrIf);
     }
     bool writeContinueIf() {
         return writeBr(continuableStack_.back(), Expr::BrIf);
     }
     bool writeUnlabeledBreakOrContinue(bool isBreak) {
@@ -3807,16 +3826,19 @@ IsLiteralOrConst(FunctionValidator& f, P
 
     *lit = ExtractNumericLiteral(f.m(), pn);
     return true;
 }
 
 static bool
 CheckFinalReturn(FunctionValidator& f, ParseNode* lastNonEmptyStmt)
 {
+    if (!f.encoder().writeExpr(Expr::End))
+        return false;
+
     if (!f.hasAlreadyReturned()) {
         f.setReturnedType(ExprType::Void);
         return true;
     }
 
     if (!lastNonEmptyStmt->isKind(PNK_RETURN) && !IsVoid(f.returnedType()))
         return f.fail(lastNonEmptyStmt, "void incompatible with previous return type");
 
@@ -4137,44 +4159,44 @@ CheckStoreArray(FunctionValidator& f, Pa
         break;
       default:
         MOZ_CRASH("Unexpected view type");
     }
 
     switch (viewType) {
       case Scalar::Int8:
       case Scalar::Uint8:
-        if (!f.encoder().writeExpr(Expr::I32Store8))
+        if (!f.encoder().writeExpr(Expr::I32TeeStore8))
             return false;
         break;
       case Scalar::Int16:
       case Scalar::Uint16:
-        if (!f.encoder().writeExpr(Expr::I32Store16))
+        if (!f.encoder().writeExpr(Expr::I32TeeStore16))
             return false;
         break;
       case Scalar::Int32:
       case Scalar::Uint32:
-        if (!f.encoder().writeExpr(Expr::I32Store))
+        if (!f.encoder().writeExpr(Expr::I32TeeStore))
             return false;
         break;
       case Scalar::Float32:
         if (rhsType.isFloatish()) {
-            if (!f.encoder().writeExpr(Expr::F32Store))
+            if (!f.encoder().writeExpr(Expr::F32TeeStore))
                 return false;
         } else {
-            if (!f.encoder().writeExpr(Expr::F64StoreF32))
+            if (!f.encoder().writeExpr(Expr::F64TeeStoreF32))
                 return false;
         }
         break;
       case Scalar::Float64:
         if (rhsType.isFloatish()) {
-            if (!f.encoder().writeExpr(Expr::F32StoreF64))
+            if (!f.encoder().writeExpr(Expr::F32TeeStoreF64))
                 return false;
         } else {
-            if (!f.encoder().writeExpr(Expr::F64Store))
+            if (!f.encoder().writeExpr(Expr::F64TeeStore))
                 return false;
         }
         break;
       default: MOZ_CRASH("unexpected scalar type");
     }
 
     if (!WriteArrayAccessFlags(f, viewType))
         return false;
@@ -4188,17 +4210,17 @@ CheckAssignName(FunctionValidator& f, Pa
 {
     RootedPropertyName name(f.cx(), lhs->name());
 
     if (const FunctionValidator::Local* lhsVar = f.lookupLocal(name)) {
         Type rhsType;
         if (!CheckExpr(f, rhs, &rhsType))
             return false;
 
-        if (!f.encoder().writeExpr(Expr::SetLocal))
+        if (!f.encoder().writeExpr(Expr::TeeLocal))
             return false;
         if (!f.encoder().writeVarU32(lhsVar->slot))
             return false;
 
         if (!(rhsType <= lhsVar->type)) {
             return f.failf(lhs, "%s is not a subtype of %s",
                            rhsType.toChars(), lhsVar->type.toChars());
         }
@@ -4212,17 +4234,17 @@ CheckAssignName(FunctionValidator& f, Pa
 
         Type rhsType;
         if (!CheckExpr(f, rhs, &rhsType))
             return false;
 
         Type globType = global->varOrConstType();
         if (!(rhsType <= globType))
             return f.failf(lhs, "%s is not a subtype of %s", rhsType.toChars(), globType.toChars());
-        if (!f.encoder().writeExpr(Expr::SetGlobal))
+        if (!f.encoder().writeExpr(Expr::TeeGlobal))
             return false;
         if (!f.encoder().writeVarU32(global->varOrConstIndex()))
             return false;
 
         *type = rhsType;
         return true;
     }
 
@@ -4711,30 +4733,25 @@ CheckInternalCall(FunctionValidator& f, 
                   Type ret, Type* type)
 {
     MOZ_ASSERT(ret.isCanonical());
 
     ValTypeVector args;
     if (!CheckCallArgs<CheckIsArgType>(f, callNode, &args))
         return false;
 
-    uint32_t arity = args.length();
     Sig sig(Move(args), ret.canonicalToExprType());
 
     ModuleValidator::Func* callee;
     if (!CheckFunctionSignature(f.m(), callNode, Move(sig), calleeName, &callee))
         return false;
 
     if (!f.writeCall(callNode, Expr::Call))
         return false;
 
-    // Call arity
-    if (!f.encoder().writeVarU32(arity))
-        return false;
-
     // Function's index, to find out the function's entry
     if (!f.encoder().writeVarU32(callee->index()))
         return false;
 
     *type = Type::ret(ret);
     return true;
 }
 
@@ -4800,28 +4817,23 @@ CheckFuncPtrCall(FunctionValidator& f, P
 
     if (!indexType.isIntish())
         return f.failf(indexNode, "%s is not a subtype of intish", indexType.toChars());
 
     ValTypeVector args;
     if (!CheckCallArgs<CheckIsArgType>(f, callNode, &args))
         return false;
 
-    uint32_t arity = args.length();
     Sig sig(Move(args), ret.canonicalToExprType());
 
     uint32_t tableIndex;
     if (!CheckFuncPtrTableAgainstExisting(f.m(), tableNode, name, Move(sig), mask, &tableIndex))
         return false;
 
-    if (!f.writeCall(callNode, Expr::CallIndirect))
-        return false;
-
-    // Call arity
-    if (!f.encoder().writeVarU32(arity))
+    if (!f.writeCall(callNode, Expr::OldCallIndirect))
         return false;
 
     // Call signature
     if (!f.encoder().writeVarU32(f.m().funcPtrTable(tableIndex).sigIndex()))
         return false;
 
     *type = Type::ret(ret);
     return true;
@@ -4846,30 +4858,25 @@ CheckFFICall(FunctionValidator& f, Parse
         return f.fail(callNode, "FFI calls can't return float");
     if (ret.isSimd())
         return f.fail(callNode, "FFI calls can't return SIMD values");
 
     ValTypeVector args;
     if (!CheckCallArgs<CheckIsExternType>(f, callNode, &args))
         return false;
 
-    uint32_t arity = args.length();
     Sig sig(Move(args), ret.canonicalToExprType());
 
     uint32_t importIndex;
     if (!f.m().declareImport(calleeName, Move(sig), ffiIndex, &importIndex))
         return false;
 
     if (!f.writeCall(callNode, Expr::CallImport))
         return false;
 
-    // Call arity
-    if (!f.encoder().writeVarU32(arity))
-        return false;
-
     // Import index
     if (!f.encoder().writeVarU32(importIndex))
         return false;
 
     *type = Type::ret(ret);
     return true;
 }
 
@@ -5668,16 +5675,20 @@ CoerceResult(FunctionValidator& f, Parse
              Type* type)
 {
     MOZ_ASSERT(expected.isCanonical());
 
     // At this point, the bytecode resembles this:
     //      | the thing we wanted to coerce | current position |>
     switch (expected.which()) {
       case Type::Void:
+        if (!actual.isVoid()) {
+            if (!f.encoder().writeExpr(Expr::Drop))
+                return false;
+        }
         break;
       case Type::Int:
         if (!actual.isIntish())
             return f.failf(expr, "%s is not a subtype of intish", actual.toChars());
         break;
       case Type::Float:
         if (!CheckFloatCoercionArg(f, expr, actual))
             return false;
@@ -5920,25 +5931,31 @@ CheckComma(FunctionValidator& f, ParseNo
     MOZ_ASSERT(comma->isKind(PNK_COMMA));
     ParseNode* operands = ListHead(comma);
 
     // The block depth isn't taken into account here, because a comma list can't
     // contain breaks and continues and nested control flow structures.
     if (!f.encoder().writeExpr(Expr::Block))
         return false;
 
+    size_t typeAt;
+    if (!f.encoder().writePatchableFixedU7(&typeAt))
+        return false;
+
     ParseNode* pn = operands;
     for (; NextNode(pn); pn = NextNode(pn)) {
         if (!CheckAsExprStatement(f, pn))
             return false;
     }
 
     if (!CheckExpr(f, pn, type))
         return false;
 
+    f.encoder().patchFixedU7(typeAt, uint8_t(Type::canonicalize(*type).canonicalToExprType()));
+
     return f.encoder().writeExpr(Expr::End);
 }
 
 static bool
 CheckConditional(FunctionValidator& f, ParseNode* ternary, Type* type)
 {
     MOZ_ASSERT(ternary->isKind(PNK_CONDITIONAL));
 
@@ -5948,17 +5965,18 @@ CheckConditional(FunctionValidator& f, P
 
     Type condType;
     if (!CheckExpr(f, cond, &condType))
         return false;
 
     if (!condType.isInt())
         return f.failf(cond, "%s is not a subtype of int", condType.toChars());
 
-    if (!f.pushIf())
+    size_t typeAt;
+    if (!f.pushIf(&typeAt))
         return false;
 
     Type thenType;
     if (!CheckExpr(f, thenExpr, &thenType))
         return false;
 
     if (!f.switchToElse())
         return false;
@@ -5976,17 +5994,17 @@ CheckConditional(FunctionValidator& f, P
     } else if (thenType.isSimd() && elseType == thenType) {
         *type = thenType;
     } else {
         return f.failf(ternary, "then/else branches of conditional must both produce int, float, "
                        "double or SIMD types, current types are %s and %s",
                        thenType.toChars(), elseType.toChars());
     }
 
-    if (!f.popIf())
+    if (!f.popIf(typeAt, Type::canonicalize(*type).canonicalToExprType()))
         return false;
 
     return true;
 }
 
 static bool
 IsValidIntMultiplyConstant(ModuleValidator& m, ParseNode* expr)
 {
@@ -6347,20 +6365,31 @@ CheckExpr(FunctionValidator& f, ParseNod
 }
 
 static bool
 CheckStatement(FunctionValidator& f, ParseNode* stmt);
 
 static bool
 CheckAsExprStatement(FunctionValidator& f, ParseNode* expr)
 {
-    Type ignored;
-    if (expr->isKind(PNK_CALL))
+    if (expr->isKind(PNK_CALL)) {
+        Type ignored;
         return CheckCoercedCall(f, expr, Type::Void, &ignored);
-    return CheckExpr(f, expr, &ignored);
+    }
+
+    Type resultType;
+    if (!CheckExpr(f, expr, &resultType))
+        return false;
+
+    if (!resultType.isVoid()) {
+        if (!f.encoder().writeExpr(Expr::Drop))
+            return false;
+    }
+
+    return true;
 }
 
 static bool
 CheckExprStatement(FunctionValidator& f, ParseNode* exprStmt)
 {
     MOZ_ASSERT(exprStmt->isKind(PNK_SEMI));
     ParseNode* expr = UnaryKid(exprStmt);
     if (!expr)
@@ -6398,20 +6427,22 @@ CheckLoopConditionOnEntry(FunctionValida
 static bool
 CheckWhile(FunctionValidator& f, ParseNode* whileStmt, const NameVector* labels = nullptr)
 {
     MOZ_ASSERT(whileStmt->isKind(PNK_WHILE));
     ParseNode* cond = BinaryLeft(whileStmt);
     ParseNode* body = BinaryRight(whileStmt);
 
     // A while loop `while(#cond) #body` is equivalent to:
-    // (loop $after_loop $top
-    //    (brIf $after_loop (i32.eq 0 #cond))
-    //    #body
-    //    (br $top)
+    // (block $after_loop
+    //    (loop $top
+    //       (brIf $after_loop (i32.eq 0 #cond))
+    //       #body
+    //       (br $top)
+    //    )
     // )
     if (labels && !f.addLabels(*labels, 0, 1))
         return false;
 
     if (!f.pushLoop())
         return false;
 
     if (!CheckLoopConditionOnEntry(f, cond))
@@ -6440,21 +6471,23 @@ CheckFor(FunctionValidator& f, ParseNode
 
     ParseNode* maybeInit = TernaryKid1(forHead);
     ParseNode* maybeCond = TernaryKid2(forHead);
     ParseNode* maybeInc = TernaryKid3(forHead);
 
     // A for-loop `for (#init; #cond; #inc) #body` is equivalent to:
     // (block                                               // depth X
     //   (#init)
-    //   (loop $after_loop $loop_top                        // depth X+2 (loop)
-    //     (brIf $after (eq 0 #cond))
-    //     (block $after_body #body)                        // depth X+3
-    //     #inc
-    //     (br $loop_top)
+    //   (block $after_loop                                 // depth X+1 (block)
+    //     (loop $loop_top                                  // depth X+2 (loop)
+    //       (brIf $after (eq 0 #cond))
+    //       (block $after_body #body)                      // depth X+3
+    //       #inc
+    //       (br $loop_top)
+    //     )
     //   )
     // )
     // A break in the body should break out to $after_loop, i.e. depth + 1.
     // A continue in the body should break out to $after_body, i.e. depth + 3.
     if (labels && !f.addLabels(*labels, 1, 3))
         return false;
 
     if (!f.pushUnbreakableBlock())
@@ -6501,19 +6534,21 @@ CheckFor(FunctionValidator& f, ParseNode
 static bool
 CheckDoWhile(FunctionValidator& f, ParseNode* whileStmt, const NameVector* labels = nullptr)
 {
     MOZ_ASSERT(whileStmt->isKind(PNK_DOWHILE));
     ParseNode* body = BinaryLeft(whileStmt);
     ParseNode* cond = BinaryRight(whileStmt);
 
     // A do-while loop `do { #body } while (#cond)` is equivalent to:
-    // (loop $after_loop $top       // depth X
-    //   (block #body)              // depth X+2
-    //   (brIf #cond $top)
+    // (block $after_loop           // depth X
+    //   (loop $top                 // depth X+1
+    //     (block #body)            // depth X+2
+    //     (brIf #cond $top)
+    //   )
     // )
     // A break should break out of the entire loop, i.e. at depth 0.
     // A continue should break out to the condition, i.e. at depth 2.
     if (labels && !f.addLabels(*labels, 0, 2))
         return false;
 
     if (!f.pushLoop())
         return false;
@@ -6595,18 +6630,21 @@ CheckIf(FunctionValidator& f, ParseNode*
     ParseNode* elseStmt = TernaryKid3(ifStmt);
 
     Type condType;
     if (!CheckExpr(f, cond, &condType))
         return false;
     if (!condType.isInt())
         return f.failf(cond, "%s is not a subtype of int", condType.toChars());
 
-    if (!f.pushIf())
-        return false;
+    size_t typeAt;
+    if (!f.pushIf(&typeAt))
+        return false;
+
+    f.setIfType(typeAt, ExprType::Void);
 
     if (!CheckStatement(f, thenStmt))
         return false;
 
     if (elseStmt) {
         if (!f.switchToElse())
             return false;
 
@@ -6741,18 +6779,23 @@ CheckSwitch(FunctionValidator& f, ParseN
 
     if (switchBody->isKind(PNK_LEXICALSCOPE)) {
         if (!switchBody->isEmptyScope())
             return f.fail(switchBody, "switch body may not contain lexical declarations");
         switchBody = switchBody->scopeBody();
     }
 
     ParseNode* stmt = ListHead(switchBody);
-    if (!stmt)
-        return CheckSwitchExpr(f, switchExpr);
+    if (!stmt) {
+        if (!CheckSwitchExpr(f, switchExpr))
+            return false;
+        if (!f.encoder().writeExpr(Expr::Drop))
+            return false;
+        return true;
+    }
 
     if (!CheckDefaultAtEnd(f, stmt))
         return false;
 
     int32_t low = 0, high = 0;
     uint32_t tableLength = 0;
     if (!CheckSwitchRange(f, stmt, &low, &high, &tableLength))
         return false;
@@ -6805,35 +6848,31 @@ CheckSwitch(FunctionValidator& f, ParseN
         if (!CheckSwitchExpr(f, switchExpr))
             return false;
     }
 
     // Start the br_table block.
     if (!f.encoder().writeExpr(Expr::BrTable))
         return false;
 
-    // The br_table arity.
-    if (!f.encoder().writeVarU32(0))
-        return false;
-
     // Write the number of cases (tableLength - 1 + 1 (default)).
     // Write the number of cases (tableLength - 1 + 1 (default)).
     if (!f.encoder().writeVarU32(tableLength))
         return false;
 
     // Each case value describes the relative depth to the actual block. When
     // a case is not explicitly defined, it goes to the default.
     for (size_t i = 0; i < tableLength; i++) {
         uint32_t target = caseDepths[i] == CASE_NOT_DEFINED ? defaultDepth : caseDepths[i];
-        if (!f.encoder().writeFixedU32(target))
+        if (!f.encoder().writeVarU32(target))
             return false;
     }
 
     // Write the default depth.
-    if (!f.encoder().writeFixedU32(defaultDepth))
+    if (!f.encoder().writeVarU32(defaultDepth))
         return false;
 
     // Our br_table is done. Close its block, write the cases down in order.
     if (!f.popUnbreakableBlock())
         return false;
 
     for (; stmt && !IsDefaultCase(stmt); stmt = NextNode(stmt)) {
         if (!CheckStatement(f, CaseBody(stmt)))
@@ -6888,19 +6927,16 @@ CheckReturn(FunctionValidator& f, ParseN
 
         if (!CheckReturnType(f, expr, Type::canonicalize(type)))
             return false;
     }
 
     if (!f.encoder().writeExpr(Expr::Return))
         return false;
 
-    if (!f.encoder().writeVarU32(expr ? 1 : 0))
-        return false;
-
     return true;
 }
 
 static bool
 CheckStatementList(FunctionValidator& f, ParseNode* stmtList, const NameVector* labels /*= nullptr */)
 {
     MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
 
--- a/js/src/asmjs/WasmAST.h
+++ b/js/src/asmjs/WasmAST.h
@@ -190,94 +190,129 @@ enum class AstExprKind
     Block,
     Branch,
     BranchTable,
     Call,
     CallIndirect,
     ComparisonOperator,
     Const,
     ConversionOperator,
+    Drop,
+    First,
     GetGlobal,
     GetLocal,
     If,
     Load,
+    Nop,
+    Pop,
     Return,
     SetGlobal,
     SetLocal,
+    TeeLocal,
     Store,
     TernaryOperator,
     UnaryOperator,
     NullaryOperator,
     Unreachable
 };
 
 class AstExpr : public AstNode
 {
     const AstExprKind kind_;
+    ExprType type_;
 
   protected:
-    explicit AstExpr(AstExprKind kind)
-      : kind_(kind)
+    AstExpr(AstExprKind kind, ExprType type)
+      : kind_(kind), type_(type)
     {}
 
   public:
     AstExprKind kind() const { return kind_; }
 
+    bool isVoid() const { return IsVoid(type_); }
+
+    // Note that for nodes other than blocks and block-like things, this
+    // may return ExprType::Limit for nodes with non-void types.
+    ExprType type() const { return type_; }
+
     template <class T>
     T& as() {
         MOZ_ASSERT(kind() == T::Kind);
         return static_cast<T&>(*this);
     }
 };
 
+struct AstNop : AstExpr
+{
+   static const AstExprKind Kind = AstExprKind::Nop;
+   AstNop()
+      : AstExpr(AstExprKind::Nop, ExprType::Void)
+   {}
+};
+
 struct AstUnreachable : AstExpr
 {
     static const AstExprKind Kind = AstExprKind::Unreachable;
     AstUnreachable()
-      : AstExpr(AstExprKind::Unreachable)
+      : AstExpr(AstExprKind::Unreachable, ExprType::Void)
     {}
 };
 
+class AstDrop : public AstExpr
+{
+    AstExpr& value_;
+
+  public:
+    static const AstExprKind Kind = AstExprKind::Drop;
+    explicit AstDrop(AstExpr& value)
+      : AstExpr(AstExprKind::Drop, ExprType::Void),
+        value_(value)
+    {}
+    AstExpr& value() const {
+        return value_;
+    }
+};
+
 class AstConst : public AstExpr
 {
     const Val val_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Const;
     explicit AstConst(Val val)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         val_(val)
     {}
     Val val() const { return val_; }
 };
 
 class AstGetLocal : public AstExpr
 {
     AstRef local_;
 
   public:
     static const AstExprKind Kind = AstExprKind::GetLocal;
     explicit AstGetLocal(AstRef local)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         local_(local)
     {}
     AstRef& local() {
         return local_;
     }
 };
 
 class AstSetLocal : public AstExpr
 {
     AstRef local_;
     AstExpr& value_;
 
   public:
     static const AstExprKind Kind = AstExprKind::SetLocal;
     AstSetLocal(AstRef local, AstExpr& value)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Void),
         local_(local),
         value_(value)
     {}
     AstRef& local() {
         return local_;
     }
     AstExpr& value() const {
         return value_;
@@ -286,78 +321,96 @@ class AstSetLocal : public AstExpr
 
 class AstGetGlobal : public AstExpr
 {
     AstRef global_;
 
   public:
     static const AstExprKind Kind = AstExprKind::GetGlobal;
     explicit AstGetGlobal(AstRef global)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         global_(global)
     {}
     AstRef& global() {
         return global_;
     }
 };
 
 class AstSetGlobal : public AstExpr
 {
     AstRef global_;
     AstExpr& value_;
 
   public:
     static const AstExprKind Kind = AstExprKind::SetGlobal;
     AstSetGlobal(AstRef global, AstExpr& value)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Void),
         global_(global),
         value_(value)
     {}
     AstRef& global() {
         return global_;
     }
     AstExpr& value() const {
         return value_;
     }
 };
 
+class AstTeeLocal : public AstExpr
+{
+    AstRef local_;
+    AstExpr& value_;
+
+  public:
+    static const AstExprKind Kind = AstExprKind::TeeLocal;
+    AstTeeLocal(AstRef local, AstExpr& value)
+      : AstExpr(Kind, ExprType::Limit),
+        local_(local),
+        value_(value)
+    {}
+    AstRef& local() {
+        return local_;
+    }
+    AstExpr& value() const {
+        return value_;
+    }
+};
+
 class AstBlock : public AstExpr
 {
     Expr expr_;
-    AstName breakName_;
-    AstName continueName_;
+    AstName name_;
     AstExprVector exprs_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Block;
-    explicit AstBlock(Expr expr, AstName breakName, AstName continueName, AstExprVector&& exprs)
-      : AstExpr(Kind),
+    explicit AstBlock(Expr expr, ExprType type, AstName name, AstExprVector&& exprs)
+      : AstExpr(Kind, type),
         expr_(expr),
-        breakName_(breakName),
-        continueName_(continueName),
+        name_(name),
         exprs_(Move(exprs))
     {}
 
     Expr expr() const { return expr_; }
-    AstName breakName() const { return breakName_; }
-    AstName continueName() const { return continueName_; }
+    AstName name() const { return name_; }
     const AstExprVector& exprs() const { return exprs_; }
 };
 
 class AstBranch : public AstExpr
 {
     Expr expr_;
     AstExpr* cond_;
     AstRef target_;
     AstExpr* value_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Branch;
-    explicit AstBranch(Expr expr, AstExpr* cond, AstRef target, AstExpr* value)
-      : AstExpr(Kind),
+    explicit AstBranch(Expr expr, ExprType type,
+                       AstExpr* cond, AstRef target, AstExpr* value)
+      : AstExpr(Kind, type),
         expr_(expr),
         cond_(cond),
         target_(target),
         value_(value)
     {}
 
     Expr expr() const { return expr_; }
     AstRef& target() { return target_; }
@@ -368,80 +421,77 @@ class AstBranch : public AstExpr
 class AstCall : public AstExpr
 {
     Expr expr_;
     AstRef func_;
     AstExprVector args_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Call;
-    AstCall(Expr expr, AstRef func, AstExprVector&& args)
-      : AstExpr(Kind), expr_(expr), func_(func), args_(Move(args))
+    AstCall(Expr expr, ExprType type, AstRef func, AstExprVector&& args)
+      : AstExpr(Kind, type), expr_(expr), func_(func), args_(Move(args))
     {}
 
     Expr expr() const { return expr_; }
     AstRef& func() { return func_; }
     const AstExprVector& args() const { return args_; }
 };
 
 class AstCallIndirect : public AstExpr
 {
     AstRef sig_;
+    AstExprVector args_;
     AstExpr* index_;
-    AstExprVector args_;
 
   public:
     static const AstExprKind Kind = AstExprKind::CallIndirect;
-    AstCallIndirect(AstRef sig, AstExpr* index, AstExprVector&& args)
-      : AstExpr(Kind), sig_(sig), index_(index), args_(Move(args))
+    AstCallIndirect(AstRef sig, ExprType type, AstExprVector&& args, AstExpr* index)
+      : AstExpr(Kind, type), sig_(sig), args_(Move(args)), index_(index)
     {}
     AstRef& sig() { return sig_; }
+    const AstExprVector& args() const { return args_; }
     AstExpr* index() const { return index_; }
-    const AstExprVector& args() const { return args_; }
 };
 
 class AstReturn : public AstExpr
 {
     AstExpr* maybeExpr_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Return;
     explicit AstReturn(AstExpr* maybeExpr)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Void),
         maybeExpr_(maybeExpr)
     {}
     AstExpr* maybeExpr() const { return maybeExpr_; }
 };
 
 class AstIf : public AstExpr
 {
     AstExpr* cond_;
-    AstName thenName_;
+    AstName name_;
     AstExprVector thenExprs_;
-    AstName elseName_;
     AstExprVector elseExprs_;
 
   public:
     static const AstExprKind Kind = AstExprKind::If;
-    AstIf(AstExpr* cond, AstName thenName, AstExprVector&& thenExprs,
-          AstName elseName, AstExprVector&& elseExprs)
-      : AstExpr(Kind),
+    AstIf(ExprType type, AstExpr* cond, AstName name,
+          AstExprVector&& thenExprs, AstExprVector&& elseExprs)
+      : AstExpr(Kind, type),
         cond_(cond),
-        thenName_(thenName),
+        name_(name),
         thenExprs_(Move(thenExprs)),
-        elseName_(elseName),
         elseExprs_(Move(elseExprs))
     {}
 
     AstExpr& cond() const { return *cond_; }
     const AstExprVector& thenExprs() const { return thenExprs_; }
     bool hasElse() const { return elseExprs_.length(); }
     const AstExprVector& elseExprs() const { MOZ_ASSERT(hasElse()); return elseExprs_; }
-    AstName thenName() const { return thenName_; }
-    AstName elseName() const { return elseName_; }
+    AstName name() const { return name_; }
 };
 
 class AstLoadStoreAddress
 {
     AstExpr* base_;
     int32_t flags_;
     int32_t offset_;
 
@@ -460,17 +510,17 @@ class AstLoadStoreAddress
 class AstLoad : public AstExpr
 {
     Expr expr_;
     AstLoadStoreAddress address_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Load;
     explicit AstLoad(Expr expr, const AstLoadStoreAddress &address)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         expr_(expr),
         address_(address)
     {}
 
     Expr expr() const { return expr_; }
     const AstLoadStoreAddress& address() const { return address_; }
 };
 
@@ -479,17 +529,17 @@ class AstStore : public AstExpr
     Expr expr_;
     AstLoadStoreAddress address_;
     AstExpr* value_;
 
   public:
     static const AstExprKind Kind = AstExprKind::Store;
     explicit AstStore(Expr expr, const AstLoadStoreAddress &address,
                           AstExpr* value)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Void),
         expr_(expr),
         address_(address),
         value_(value)
     {}
 
     Expr expr() const { return expr_; }
     const AstLoadStoreAddress& address() const { return address_; }
     AstExpr& value() const { return *value_; }
@@ -500,18 +550,18 @@ class AstBranchTable : public AstExpr
     AstExpr& index_;
     AstRef default_;
     AstRefVector table_;
     AstExpr* value_;
 
   public:
     static const AstExprKind Kind = AstExprKind::BranchTable;
     explicit AstBranchTable(AstExpr& index, AstRef def, AstRefVector&& table,
-                                AstExpr* maybeValue)
-      : AstExpr(Kind),
+                            AstExpr* maybeValue)
+      : AstExpr(Kind, ExprType::Void),
         index_(index),
         default_(def),
         table_(Move(table)),
         value_(maybeValue)
     {}
     AstExpr& index() const { return index_; }
     AstRef& def() { return default_; }
     AstRefVector& table() { return table_; }
@@ -537,30 +587,16 @@ class AstFunc : public AstNode
     {}
     AstRef& sig() { return sig_; }
     const AstValTypeVector& vars() const { return vars_; }
     const AstNameVector& locals() const { return localNames_; }
     const AstExprVector& body() const { return body_; }
     AstName name() const { return name_; }
 };
 
-class AstResizable
-{
-    uint32_t initial_;
-    Maybe<uint32_t> maximum_;
-
-  public:
-    AstResizable() : initial_(0), maximum_() {}
-    AstResizable(uint32_t initial, Maybe<uint32_t> maximum)
-      : initial_(initial), maximum_(maximum)
-    {}
-    uint32_t initial() const { return initial_; }
-    const Maybe<uint32_t>& maximum() const { return maximum_; }
-};
-
 class AstGlobal : public AstNode
 {
     AstName name_;
     uint32_t flags_;
     ValType type_;
     Maybe<AstExpr*> init_;
 
   public:
@@ -585,40 +621,40 @@ typedef AstVector<AstGlobal*> AstGlobalV
 class AstImport : public AstNode
 {
     AstName name_;
     AstName module_;
     AstName field_;
     DefinitionKind kind_;
 
     AstRef funcSig_;
-    AstResizable resizable_;
+    ResizableLimits resizable_;
     AstGlobal global_;
 
   public:
     AstImport(AstName name, AstName module, AstName field, AstRef funcSig)
       : name_(name), module_(module), field_(field), kind_(DefinitionKind::Function), funcSig_(funcSig)
     {}
-    AstImport(AstName name, AstName module, AstName field, DefinitionKind kind, AstResizable resizable)
+    AstImport(AstName name, AstName module, AstName field, DefinitionKind kind, ResizableLimits resizable)
       : name_(name), module_(module), field_(field), kind_(kind), resizable_(resizable)
     {}
     AstImport(AstName name, AstName module, AstName field, AstGlobal global)
       : name_(name), module_(module), field_(field), kind_(DefinitionKind::Global), global_(global)
     {}
 
     AstName name() const { return name_; }
     AstName module() const { return module_; }
     AstName field() const { return field_; }
 
     DefinitionKind kind() const { return kind_; }
     AstRef& funcSig() {
         MOZ_ASSERT(kind_ == DefinitionKind::Function);
         return funcSig_;
     }
-    AstResizable resizable() const {
+    ResizableLimits resizable() const {
         MOZ_ASSERT(kind_ == DefinitionKind::Memory || kind_ == DefinitionKind::Table);
         return resizable_;
     }
     const AstGlobal& global() const {
         MOZ_ASSERT(kind_ == DefinitionKind::Global);
         return global_;
     }
 };
@@ -693,70 +729,73 @@ class AstStartFunc : public AstNode
 
 class AstModule : public AstNode
 {
   public:
     typedef AstVector<AstFunc*> FuncVector;
     typedef AstVector<AstImport*> ImportVector;
     typedef AstVector<AstExport*> ExportVector;
     typedef AstVector<AstSig*> SigVector;
+    typedef AstVector<AstName> NameVector;
 
   private:
     typedef AstHashMap<AstSig*, uint32_t, AstSig> SigMap;
 
     LifoAlloc&           lifo_;
     SigVector            sigs_;
     SigMap               sigMap_;
     ImportVector         imports_;
-    Maybe<AstResizable>  table_;
-    Maybe<AstResizable>  memory_;
+    NameVector           funcImportNames_;
+    Maybe<ResizableLimits> table_;
+    Maybe<ResizableLimits> memory_;
     ExportVector         exports_;
     Maybe<AstStartFunc>  startFunc_;
     FuncVector           funcs_;
     AstDataSegmentVector dataSegments_;
     AstElemSegmentVector elemSegments_;
     AstGlobalVector      globals_;
 
   public:
     explicit AstModule(LifoAlloc& lifo)
       : lifo_(lifo),
         sigs_(lifo),
         sigMap_(lifo),
         imports_(lifo),
+        funcImportNames_(lifo),
         exports_(lifo),
         funcs_(lifo),
         dataSegments_(lifo),
         elemSegments_(lifo),
         globals_(lifo)
     {}
     bool init() {
         return sigMap_.init();
     }
-    bool setMemory(AstResizable memory) {
+    bool setMemory(ResizableLimits memory) {
         if (memory_)
             return false;
         memory_.emplace(memory);
         return true;
     }
     bool hasMemory() const {
         return !!memory_;
     }
-    const AstResizable& memory() const {
+    const ResizableLimits& memory() const {
         return *memory_;
     }
-    bool setTable(AstResizable table) {
+    bool setTable(ResizableLimits table) {
         if (table_)
             return false;
         table_.emplace(table);
         return true;
     }
     bool hasTable() const {
         return !!table_;
     }
-    const AstResizable& table() const {
+    const ResizableLimits& table() const {
         return *table_;
     }
     bool append(AstDataSegment* seg) {
         return dataSegments_.append(seg);
     }
     const AstDataSegmentVector& dataSegments() const {
         return dataSegments_;
     }
@@ -802,21 +841,29 @@ class AstModule : public AstNode
     }
     bool append(AstFunc* func) {
         return funcs_.append(func);
     }
     const FuncVector& funcs() const {
         return funcs_;
     }
     bool append(AstImport* imp) {
+        if (imp->kind() == DefinitionKind::Function) {
+            if (!funcImportNames_.append(imp->name()))
+                return false;
+        }
+
         return imports_.append(imp);
     }
     const ImportVector& imports() const {
         return imports_;
     }
+    const NameVector& funcImportNames() const {
+        return funcImportNames_;
+    }
     bool append(AstExport* exp) {
         return exports_.append(exp);
     }
     const ExportVector& exports() const {
         return exports_;
     }
     bool append(AstGlobal* glob) {
         return globals_.append(glob);
@@ -828,49 +875,49 @@ class AstModule : public AstNode
 
 class AstNullaryOperator final : public AstExpr
 {
     Expr expr_;
 
   public:
     static const AstExprKind Kind = AstExprKind::NullaryOperator;
     explicit AstNullaryOperator(Expr expr)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         expr_(expr)
     {}
 
     Expr expr() const { return expr_; }
 };
 
 class AstUnaryOperator final : public AstExpr
 {
     Expr expr_;
     AstExpr* op_;
 
   public:
     static const AstExprKind Kind = AstExprKind::UnaryOperator;
     explicit AstUnaryOperator(Expr expr, AstExpr* op)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         expr_(expr), op_(op)
     {}
 
     Expr expr() const { return expr_; }
     AstExpr* op() const { return op_; }
 };
 
 class AstBinaryOperator final : public AstExpr
 {
     Expr expr_;
     AstExpr* lhs_;
     AstExpr* rhs_;
 
   public:
     static const AstExprKind Kind = AstExprKind::BinaryOperator;
     explicit AstBinaryOperator(Expr expr, AstExpr* lhs, AstExpr* rhs)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         expr_(expr), lhs_(lhs), rhs_(rhs)
     {}
 
     Expr expr() const { return expr_; }
     AstExpr* lhs() const { return lhs_; }
     AstExpr* rhs() const { return rhs_; }
 };
 
@@ -879,17 +926,17 @@ class AstTernaryOperator : public AstExp
     Expr expr_;
     AstExpr* op0_;
     AstExpr* op1_;
     AstExpr* op2_;
 
   public:
     static const AstExprKind Kind = AstExprKind::TernaryOperator;
     AstTernaryOperator(Expr expr, AstExpr* op0, AstExpr* op1, AstExpr* op2)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         expr_(expr), op0_(op0), op1_(op1), op2_(op2)
     {}
 
     Expr expr() const { return expr_; }
     AstExpr* op0() const { return op0_; }
     AstExpr* op1() const { return op1_; }
     AstExpr* op2() const { return op2_; }
 };
@@ -898,37 +945,67 @@ class AstComparisonOperator final : publ
 {
     Expr expr_;
     AstExpr* lhs_;
     AstExpr* rhs_;
 
   public:
     static const AstExprKind Kind = AstExprKind::ComparisonOperator;
     explicit AstComparisonOperator(Expr expr, AstExpr* lhs, AstExpr* rhs)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         expr_(expr), lhs_(lhs), rhs_(rhs)
     {}
 
     Expr expr() const { return expr_; }
     AstExpr* lhs() const { return lhs_; }
     AstExpr* rhs() const { return rhs_; }
 };
 
 class AstConversionOperator final : public AstExpr
 {
     Expr expr_;
     AstExpr* op_;
 
   public:
     static const AstExprKind Kind = AstExprKind::ConversionOperator;
     explicit AstConversionOperator(Expr expr, AstExpr* op)
-      : AstExpr(Kind),
+      : AstExpr(Kind, ExprType::Limit),
         expr_(expr), op_(op)
     {}
 
     Expr expr() const { return expr_; }
     AstExpr* op() const { return op_; }
 };
 
+// This is an artificial AST node which can fill operand slots in an AST
+// constructed from parsing or decoding stack-machine code that doesn't have
+// an inherent AST structure.
+class AstPop final : public AstExpr
+{
+  public:
+    static const AstExprKind Kind = AstExprKind::Pop;
+    AstPop()
+      : AstExpr(Kind, ExprType::Void)
+    {}
+};
+
+// This is an artificial AST node which can be used to represent some forms
+// of stack-machine code in an AST form. It similar to Block, but returns the
+// value of its first operand, rather than the last.
+class AstFirst : public AstExpr
+{
+    AstExprVector exprs_;
+
+  public:
+    static const AstExprKind Kind = AstExprKind::First;
+    explicit AstFirst(AstExprVector&& exprs)
+      : AstExpr(Kind, ExprType::Limit),
+        exprs_(Move(exprs))
+    {}
+
+    AstExprVector& exprs() { return exprs_; }
+    const AstExprVector& exprs() const { return exprs_; }
+};
+
 } // end wasm namespace
 } // end js namespace
 
 #endif // namespace wasmast_h
--- a/js/src/asmjs/WasmBaselineCompile.cpp
+++ b/js/src/asmjs/WasmBaselineCompile.cpp
@@ -1320,23 +1320,16 @@ class BaseCompiler
         x.setSlot(Stk::LocalF64, slot);
     }
 
     void pushLocalF32(uint32_t slot) {
         Stk& x = push();
         x.setSlot(Stk::LocalF32, slot);
     }
 
-    // Push a void value.  Like constants this is never flushed to memory,
-    // it just helps maintain the invariants of the type system.
-
-    void pushVoid() {
-        push();
-    }
-
     // PRIVATE.  Call only from other popI32() variants.
     // v must be the stack top.
 
     void popI32(Stk& v, RegI32 r) {
         switch (v.kind()) {
           case Stk::ConstI32:
             loadConstI32(r.reg, v);
             break;
@@ -1600,20 +1593,42 @@ class BaseCompiler
           case Stk::None:
             stk_.popBack();
             return AnyReg();
           default:
             MOZ_CRASH("Compiler bug: unexpected value on stack");
         }
     }
 
+    MOZ_MUST_USE
+    AnyReg allocJoinReg(ExprType type) {
+        switch (type) {
+          case ExprType::I32:
+            allocGPR(joinRegI32.reg);
+            return AnyReg(joinRegI32);
+          case ExprType::I64:
+            allocInt64(joinRegI64.reg);
+            return AnyReg(joinRegI64);
+          case ExprType::F32:
+            allocFPU(joinRegF32.reg);
+            return AnyReg(joinRegF32);
+          case ExprType::F64:
+            allocFPU(joinRegF64.reg);
+            return AnyReg(joinRegF64);
+          case ExprType::Void:
+            MOZ_CRASH("Compiler bug: allocating void join reg");
+          default:
+            MOZ_CRASH("Compiler bug: unexpected type");
+        }
+    }
+
     void pushJoinReg(AnyReg r) {
         switch (r.tag) {
           case AnyReg::NONE:
-            pushVoid();
+            MOZ_CRASH("Compile bug: attempting to push void");
             break;
           case AnyReg::I32:
             pushI32(r.i32());
             break;
           case AnyReg::I64:
             pushI64(r.i64());
             break;
           case AnyReg::F64:
@@ -1623,16 +1638,17 @@ class BaseCompiler
             pushF32(r.f32());
             break;
         }
     }
 
     void freeJoinReg(AnyReg r) {
         switch (r.tag) {
           case AnyReg::NONE:
+            MOZ_CRASH("Compile bug: attempting to free void reg");
             break;
           case AnyReg::I32:
             freeI32(r.i32());
             break;
           case AnyReg::I64:
             freeI64(r.i64());
             break;
           case AnyReg::F64:
@@ -1732,37 +1748,35 @@ class BaseCompiler
 
     Vector<Control, 8, SystemAllocPolicy> ctl_;
 
     MOZ_MUST_USE
     bool pushControl(UniquePooledLabel* label, UniquePooledLabel* otherLabel = nullptr) {
         uint32_t framePushed = masm.framePushed();
         uint32_t stackSize = stk_.length();
 
-        // Always a void value at the beginning of a block, ensures
-        // stack is never empty even if the block has no expressions.
-        if (!deadCode_)
-            pushVoid();
-
         if (!ctl_.emplaceBack(Control(framePushed, stackSize)))
             return false;
         if (label)
             ctl_.back().label = label->release();
         if (otherLabel)
             ctl_.back().otherLabel = otherLabel->release();
         ctl_.back().deadOnArrival = deadCode_;
         return true;
     }
 
     void popControl() {
         Control last = ctl_.popCopy();
         if (last.label)
             freeLabel(last.label);
         if (last.otherLabel)
             freeLabel(last.otherLabel);
+
+        if (deadCode_ && !ctl_.empty())
+            popValueStackTo(ctl_.back().stackSize);
     }
 
     Control& controlItem(uint32_t relativeDepth) {
         return ctl_[ctl_.length() - 1 - relativeDepth];
     }
 
     MOZ_MUST_USE
     PooledLabel* newLabel() {
@@ -3142,50 +3156,54 @@ class BaseCompiler
     bool emitBrIf();
     MOZ_MUST_USE
     bool emitBrTable();
     MOZ_MUST_USE
     bool emitReturn();
     MOZ_MUST_USE
     bool emitCallArgs(const ValTypeVector& args, FunctionCall& baselineCall);
     MOZ_MUST_USE
-    bool skipCall(const ValTypeVector& args, ExprType maybeReturnType = ExprType::Limit);
-    MOZ_MUST_USE
     bool emitCallImportCommon(uint32_t lineOrBytecode, uint32_t funcImportIndex);
     MOZ_MUST_USE
     bool emitCall(uint32_t callOffset);
     MOZ_MUST_USE
     bool emitCallImport(uint32_t callOffset);
     MOZ_MUST_USE
-    bool emitCallIndirect(uint32_t callOffset);
+    bool emitCallIndirect(uint32_t callOffset, bool oldStyle);
     MOZ_MUST_USE
     bool emitUnaryMathBuiltinCall(uint32_t callOffset, SymbolicAddress callee, ValType operandType);
     MOZ_MUST_USE
     bool emitBinaryMathBuiltinCall(uint32_t callOffset, SymbolicAddress callee, ValType operandType);
     MOZ_MUST_USE
     bool emitGetLocal();
     MOZ_MUST_USE
     bool emitSetLocal();
+    bool emitTeeLocal();
+    MOZ_MUST_USE
     MOZ_MUST_USE
     bool emitGetGlobal();
     MOZ_MUST_USE
     bool emitSetGlobal();
     MOZ_MUST_USE
+    bool emitTeeGlobal();
+    MOZ_MUST_USE
     bool emitLoad(ValType type, Scalar::Type viewType);
     MOZ_MUST_USE
     bool emitStore(ValType resultType, Scalar::Type viewType);
     MOZ_MUST_USE
-    bool emitStoreWithCoercion(ValType resultType, Scalar::Type viewType);
+    bool emitTeeStore(ValType resultType, Scalar::Type viewType);
+    MOZ_MUST_USE
+    bool emitTeeStoreWithCoercion(ValType resultType, Scalar::Type viewType);
     MOZ_MUST_USE
     bool emitSelect();
 
-    void endBlock();
-    void endLoop();
+    void endBlock(ExprType type, bool isFunctionBody);
+    void endLoop(ExprType type);
     void endIfThen();
-    void endIfThenElse();
+    void endIfThenElse(ExprType type);
 
     void doReturn(ExprType returnType);
     void pushReturned(const FunctionCall& call, ExprType type);
 
     void emitCompareI32(JSOp compareOp, MCompare::CompareType compareType);
     void emitCompareI64(JSOp compareOp, MCompare::CompareType compareType);
     void emitCompareF32(JSOp compareOp, MCompare::CompareType compareType);
     void emitCompareF64(JSOp compareOp, MCompare::CompareType compareType);
@@ -4427,96 +4445,91 @@ BaseCompiler::emitBlock()
 
     if (!deadCode_)
         sync();                    // Simplifies branching out from block
 
     return pushControl(&blockEnd);
 }
 
 void
-BaseCompiler::endBlock()
+BaseCompiler::endBlock(ExprType type, bool isFunctionBody)
 {
     Control& block = controlItem(0);
 
     // Save the value.
     AnyReg r;
-    if (!deadCode_)
+    if (!deadCode_ && !IsVoid(type))
         r = popJoinReg();
 
     // Leave the block.
     popStackOnBlockExit(block.framePushed);
 
     // Bind after cleanup: branches out will have popped the stack.
     if (block.label->used()) {
         masm.bind(block.label);
+        if (deadCode_ && !IsVoid(type))
+            r = allocJoinReg(type);
         deadCode_ = false;
     }
 
-    popValueStackTo(block.stackSize);
-    popControl();
+    MOZ_ASSERT(stk_.length() == block.stackSize);
 
     // Retain the value stored in joinReg by all paths.
-    if (!deadCode_)
-        pushJoinReg(r);
+    if (!deadCode_) {
+        if (!IsVoid(type))
+            pushJoinReg(r);
+
+        if (isFunctionBody)
+            doReturn(func_.sig().ret());
+    }
+
+    popControl();
 }
 
 bool
 BaseCompiler::emitLoop()
 {
     if (!iter_.readLoop())
         return false;
 
-    UniquePooledLabel blockEnd(newLabel());
-    if (!blockEnd)
-        return false;
-
     UniquePooledLabel blockCont(newLabel());
     if (!blockCont)
         return false;
 
     if (!deadCode_)
         sync();                    // Simplifies branching out from block
 
-    if (!pushControl(&blockEnd))
-        return false;
-
     if (!pushControl(&blockCont))
         return false;
 
     if (!deadCode_) {
         masm.bind(controlItem(0).label);
         addInterruptCheck();
     }
 
     return true;
 }
 
 void
-BaseCompiler::endLoop()
+BaseCompiler::endLoop(ExprType type)
 {
-    Control& block = controlItem(1);
+    Control& block = controlItem(0);
 
     AnyReg r;
-    if (!deadCode_)
+    if (!deadCode_ && !IsVoid(type))
         r = popJoinReg();
 
     popStackOnBlockExit(block.framePushed);
 
-    // Bind after cleanup: branches out will have popped the stack.
-    if (block.label->used()) {
-        masm.bind(block.label);
-        deadCode_ = false;
-    }
-
-    popValueStackTo(block.stackSize);
-    popControl();
+    MOZ_ASSERT(stk_.length() == block.stackSize);
+
     popControl();
 
     // Retain the value stored in joinReg by all paths.
-    if (!deadCode_)
+    if (!deadCode_ && !IsVoid(type))
         pushJoinReg(r);
 }
 
 // The bodies of the "then" and "else" arms can be arbitrary sequences
 // of expressions, they push control and increment the nesting and can
 // even be targeted by jumps.  A branch to the "if" block branches to
 // the exit of the if, ie, it's like "break".  Consider:
 //
@@ -4571,22 +4584,19 @@ BaseCompiler::endIfThen()
     if (ifThen.otherLabel->used())
         masm.bind(ifThen.otherLabel);
 
     if (ifThen.label->used())
         masm.bind(ifThen.label);
 
     deadCode_ = ifThen.deadOnArrival;
 
-    popValueStackTo(ifThen.stackSize);
+    MOZ_ASSERT(stk_.length() == ifThen.stackSize);
+
     popControl();
-
-    // No value to preserve.
-    if (!deadCode_)
-        pushVoid();
 }
 
 bool
 BaseCompiler::emitElse()
 {
     ExprType thenType;
     Nothing unused_thenValue;
     if (!iter_.readElse(&thenType, &unused_thenValue))
@@ -4596,90 +4606,89 @@ BaseCompiler::emitElse()
 
     // See comment in endIfThenElse, below.
 
     // Exit the "then" branch.
 
     ifThenElse.deadThenBranch = deadCode_;
 
     AnyReg r;
-    if (!deadCode_)
+    if (!deadCode_ && !IsVoid(thenType))
         r = popJoinReg();
 
     popStackOnBlockExit(ifThenElse.framePushed);
 
     if (!deadCode_)
         masm.jump(ifThenElse.label);
 
     if (ifThenElse.otherLabel->used())
         masm.bind(ifThenElse.otherLabel);
 
     // Reset to the "else" branch.
 
-    popValueStackTo(ifThenElse.stackSize);
-
-    if (!deadCode_)
+    MOZ_ASSERT(stk_.length() == ifThenElse.stackSize);
+
+    if (!deadCode_ && !IsVoid(thenType))
         freeJoinReg(r);
 
     deadCode_ = ifThenElse.deadOnArrival;
 
-    // The following pushVoid() duplicates the pushVoid() in
-    // pushControl() that sets up a value in the "then" block: a block
-    // never leaves the stack empty, and both the "then" and "else"
-    // arms are implicit blocks.
-    if (!deadCode_)
-        pushVoid();
-
     return true;
 }
 
 void
-BaseCompiler::endIfThenElse()
+BaseCompiler::endIfThenElse(ExprType type)
 {
     Control& ifThenElse = controlItem(0);
 
     // The expression type is not a reliable guide to what we'll find
     // on the stack, we could have (if E (i32.const 1) (unreachable))
     // in which case the "else" arm is AnyType but the type of the
     // full expression is I32.  So restore whatever's there, not what
     // we want to find there.  The "then" arm has the same constraint.
 
     AnyReg r;
-    if (!deadCode_)
+    if (!deadCode_ && !IsVoid(type))
         r = popJoinReg();
 
     popStackOnBlockExit(ifThenElse.framePushed);
 
     if (ifThenElse.label->used())
         masm.bind(ifThenElse.label);
 
-    deadCode_ = ifThenElse.deadOnArrival ||
-                (ifThenElse.deadThenBranch && deadCode_ && !ifThenElse.label->bound());
-
-    popValueStackTo(ifThenElse.stackSize);
+    if (!ifThenElse.deadOnArrival &&
+        (!ifThenElse.deadThenBranch || !deadCode_ || ifThenElse.label->bound())) {
+        if (deadCode_ && !IsVoid(type))
+            r = allocJoinReg(type);
+        deadCode_ = false;
+    }
+
+    MOZ_ASSERT(stk_.length() == ifThenElse.stackSize);
+
     popControl();
 
-    if (!deadCode_)
+    if (!deadCode_ && !IsVoid(type))
         pushJoinReg(r);
 }
 
 bool
 BaseCompiler::emitEnd()
 {
     LabelKind kind;
     ExprType type;
     Nothing unused_value;
     if (!iter_.readEnd(&kind, &type, &unused_value))
         return false;
 
     switch (kind) {
-      case LabelKind::Block: endBlock(); break;
-      case LabelKind::Loop:  endLoop(); break;
+      case LabelKind::Block: endBlock(type, iter_.controlStackEmpty()); break;
+      case LabelKind::Loop:  endLoop(type); break;
+      case LabelKind::UnreachableThen:
       case LabelKind::Then:  endIfThen(); break;
-      case LabelKind::Else:  endIfThenElse(); break;
+      case LabelKind::Else:  endIfThenElse(type); break;
     }
 
     return true;
 }
 
 bool
 BaseCompiler::emitBr()
 {
@@ -4689,37 +4698,36 @@ BaseCompiler::emitBr()
     if (!iter_.readBr(&relativeDepth, &type, &unused_value))
         return false;
 
     if (deadCode_)
         return true;
 
     Control& target = controlItem(relativeDepth);
 
-    // If there is no value then generate one for popJoinReg() to
-    // consume.
-
-    if (IsVoid(type))
-        pushVoid();
-
     // Save any value in the designated join register, where the
     // normal block exit code will also leave it.
 
-    AnyReg r = popJoinReg();
+    AnyReg r;
+    if (!IsVoid(type))
+        r = popJoinReg();
 
     popStackBeforeBranch(target.framePushed);
     masm.jump(target.label);
 
     // The register holding the join value is free for the remainder
     // of this block.
 
-    freeJoinReg(r);
+    if (!IsVoid(type))
+        freeJoinReg(r);
 
     deadCode_ = true;
 
+    popValueStackTo(ctl_.back().stackSize);
+
     return true;
 }
 
 bool
 BaseCompiler::emitBrIf()
 {
     uint32_t relativeDepth;
     ExprType type;
@@ -4727,63 +4735,45 @@ BaseCompiler::emitBrIf()
     if (!iter_.readBrIf(&relativeDepth, &type, &unused_value, &unused_condition))
         return false;
 
     if (deadCode_)
         return true;
 
     Control& target = controlItem(relativeDepth);
 
-    Label notTaken;
-
-    // Conditional branches are a little awkward.  If the branch is
-    // taken we must pop the execution stack along that edge, which
-    // means that the branch instruction becomes inverted to jump
-    // around a cleanup + unconditional branch pair.
-    //
-    // TODO / OPTIMIZE: We can generate better code if no cleanup code
-    // need be executed along the taken edge.
-    //
     // TODO / OPTIMIZE: Optimize boolean evaluation for control by
     // allowing a conditional expression to be left on the stack and
     // reified here as part of the branch instruction.
 
     // We'll need the joinreg later, so don't use it for rc.
     // We assume joinRegI32 and joinRegI64 overlap.
     if (type == ExprType::I32 || type == ExprType::I64)
         needI32(joinRegI32);
 
     // Condition value is on top, always I32.
     RegI32 rc = popI32();
 
-    // There may or may not be a value underneath, to be carried along
-    // the taken edge.
-    if (IsVoid(type))
-        pushVoid();
-
     if (type == ExprType::I32 || type == ExprType::I64)
         freeI32(joinRegI32);
 
     // Save any value in the designated join register, where the
     // normal block exit code will also leave it.
-    AnyReg r = popJoinReg();
-
-    masm.branch32(Assembler::Equal, rc.reg, Imm32(0), &notTaken);
-
-    popStackBeforeBranch(target.framePushed);
-    masm.jump(target.label);
-
-    masm.bind(&notTaken);
-
-    // These registers are free in the remainder of the block.
+    AnyReg r;
+    if (!IsVoid(type))
+        r = popJoinReg();
+
+    masm.branch32(Assembler::NotEqual, rc.reg, Imm32(0), target.label);
+
+    // This register is free in the remainder of the block.
     freeI32(rc);
-    freeJoinReg(r);
-
-    // The non-taken edge currently carries a void value.
-    pushVoid();
+
+    // br_if returns its value(s).
+    if (!IsVoid(type))
+        pushJoinReg(r);
 
     return true;
 }
 
 bool
 BaseCompiler::emitBrTable()
 {
     uint32_t tableLength;
@@ -4797,45 +4787,42 @@ BaseCompiler::emitBrTable()
         return false;
 
     Uint32Vector depths;
     if (!depths.reserve(tableLength))
         return false;
 
     for (size_t i = 0; i < tableLength; ++i) {
         uint32_t depth;
-        if (!iter_.readBrTableEntry(type, &depth))
+        if (!iter_.readBrTableEntry(&type, &unused_value, &depth))
             return false;
         depths.infallibleAppend(depth);
     }
 
     uint32_t defaultDepth;
-    if (!iter_.readBrTableEntry(type, &defaultDepth))
+    if (!iter_.readBrTableDefault(&type, &unused_value, &defaultDepth))
         return false;
 
     if (deadCode_)
         return true;
 
     // We'll need the joinreg later, so don't use it for rc.
     // We assume joinRegI32 and joinRegI64 overlap.
     if (type == ExprType::I32 || type == ExprType::I64)
         needI32(joinRegI32);
 
     // Table switch value always on top.
     RegI32 rc = popI32();
 
-    // There may or may not be a value underneath, to be carried along
-    // the taken edge.
-    if (IsVoid(type))
-        pushVoid();
-
     if (type == ExprType::I32 || type == ExprType::I64)
         freeI32(joinRegI32);
 
-    AnyReg r = popJoinReg();
+    AnyReg r;
+    if (!IsVoid(type))
+        r = popJoinReg();
 
     Label dispatchCode;
     masm.branch32(Assembler::Below, rc.reg, Imm32(tableLength), &dispatchCode);
 
     // This is the out-of-range stub.  rc is dead here but we don't need it.
 
     popStackBeforeBranch(controlItem(defaultDepth).framePushed);
     masm.jump(controlItem(defaultDepth).label);
@@ -4866,21 +4853,24 @@ BaseCompiler::emitBrTable()
     masm.bind(&dispatchCode);
     tableSwitch(&theTable, rc);
 
     deadCode_ = true;
 
     // Clean up.
 
     freeI32(rc);
-    freeJoinReg(r);
+    if (!IsVoid(type))
+        freeJoinReg(r);
 
     for (uint32_t i = 0; i < tableLength; i++)
         freeLabel(stubs[i]);
 
+    popValueStackTo(ctl_.back().stackSize);
+
     return true;
 }
 
 void
 BaseCompiler::doReturn(ExprType type)
 {
     switch (type) {
       case ExprType::Void: {
@@ -4925,16 +4915,18 @@ BaseCompiler::emitReturn()
         return false;
 
     if (deadCode_)
         return true;
 
     doReturn(func_.sig().ret());
     deadCode_ = true;
 
+    popValueStackTo(ctl_.back().stackSize);
+
     return true;
 }
 
 bool
 BaseCompiler::emitCallArgs(const ValTypeVector& args, FunctionCall& baselineCall)
 {
     MOZ_ASSERT(!deadCode_);
 
@@ -4956,48 +4948,23 @@ BaseCompiler::emitCallArgs(const ValType
     loadFromFramePtr(WasmTlsReg, frameOffsetFromSlot(tlsSlot_, MIRType::Pointer));
 
     if (!iter_.readCallArgsEnd(numArgs))
         return false;
 
     return true;
 }
 
-bool
-BaseCompiler::skipCall(const ValTypeVector& args, ExprType maybeReturnType)
-{
-    MOZ_ASSERT(deadCode_);
-
-    uint32_t numArgs = args.length();
-    for (size_t i = 0; i < numArgs; ++i) {
-        ValType argType = args[i];
-        Nothing arg_;
-        if (!iter_.readCallArg(argType, numArgs, i, &arg_))
-            return false;
-    }
-
-    if (!iter_.readCallArgsEnd(numArgs))
-        return false;
-
-    if (maybeReturnType != ExprType::Limit) {
-        if (!iter_.readCallReturn(maybeReturnType))
-            return false;
-    }
-
-    return true;
-}
-
 void
 BaseCompiler::pushReturned(const FunctionCall& call, ExprType type)
 {
     switch (type) {
-      case ExprType::Void: {
-        pushVoid();
+      case ExprType::Void:
+        MOZ_CRASH("Compiler bug: attempt to push void return");
         break;
-      }
       case ExprType::I32: {
         RegI32 rv = needI32();
         captureReturnedI32(rv);
         pushI32(rv);
         break;
       }
       case ExprType::I64: {
         RegI64 rv = needI64();
@@ -5038,17 +5005,17 @@ BaseCompiler::pushReturned(const Functio
 
 bool
 BaseCompiler::emitCallImportCommon(uint32_t lineOrBytecode, uint32_t funcImportIndex)
 {
     const FuncImportGenDesc& funcImport = mg_.funcImports[funcImportIndex];
     const Sig& sig = *funcImport.sig;
 
     if (deadCode_)
-        return skipCall(sig.args(), sig.ret());
+        return true;
 
     sync();
 
     uint32_t numArgs = sig.args().length();
     size_t stackSpace = stackConsumed(numArgs);
 
     FunctionCall baselineCall(lineOrBytecode);
     beginCall(baselineCall, EscapesSandbox(true), IsBuiltinCall(false));
@@ -5064,45 +5031,44 @@ BaseCompiler::emitCallImportCommon(uint3
     endCall(baselineCall);
 
     // TODO / OPTIMIZE: It would be better to merge this freeStack()
     // into the one in endCall, if we can.
 
     popValueStackBy(numArgs);
     masm.freeStack(stackSpace);
 
-    pushReturned(baselineCall, sig.ret());
+    if (!IsVoid(sig.ret()))
+        pushReturned(baselineCall, sig.ret());
 
     return true;
 }
 
 bool
 BaseCompiler::emitCall(uint32_t callOffset)
 {
     uint32_t lineOrBytecode = readCallSiteLineOrBytecode(callOffset);
 
     uint32_t calleeIndex;
-    uint32_t arity;
-    if (!iter_.readCall(&calleeIndex, &arity))
+    if (!iter_.readCall(&calleeIndex))
         return false;
 
-    // For asm.js and old-format wasm code, imports are not part of the function
-    // index space so in these cases firstFuncDefIndex is fixed to 0, even if
-    // there are function imports.
+    // For asm.js, imports are not part of the function index space so in
+    // these cases firstFuncDefIndex is fixed to 0, even if there are
+    // function imports.
     if (calleeIndex < mg_.firstFuncDefIndex)
         return emitCallImportCommon(lineOrBytecode, calleeIndex);
 
+    if (deadCode_)
+        return true;
+
+    sync();
+
     uint32_t funcDefIndex = calleeIndex - mg_.firstFuncDefIndex;
     const Sig& sig = *mg_.funcDefSigs[funcDefIndex];
-
-    if (deadCode_)
-        return skipCall(sig.args(), sig.ret());
-
-    sync();
-
     uint32_t numArgs = sig.args().length();
     size_t stackSpace = stackConsumed(numArgs);
 
     FunctionCall baselineCall(lineOrBytecode);
     beginCall(baselineCall, EscapesSandbox(false), IsBuiltinCall(false));
 
     if (!emitCallArgs(sig.args(), baselineCall))
         return false;
@@ -5115,105 +5081,114 @@ BaseCompiler::emitCall(uint32_t callOffs
     endCall(baselineCall);
 
     // TODO / OPTIMIZE: It would be better to merge this freeStack()
     // into the one in endCall, if we can.
 
     popValueStackBy(numArgs);
     masm.freeStack(stackSpace);
 
-    pushReturned(baselineCall, sig.ret());
+    if (!IsVoid(sig.ret()))
+        pushReturned(baselineCall, sig.ret());
 
     return true;
 }
 
 bool
 BaseCompiler::emitCallImport(uint32_t callOffset)
 {
     MOZ_ASSERT(!mg_.firstFuncDefIndex);
 
     uint32_t lineOrBytecode = readCallSiteLineOrBytecode(callOffset);
 
     uint32_t funcImportIndex;
-    uint32_t arity;
-    if (!iter_.readCallImport(&funcImportIndex, &arity))
+    if (!iter_.readCallImport(&funcImportIndex))
         return false;
 
     return emitCallImportCommon(lineOrBytecode, funcImportIndex);
 }
 
 bool
-BaseCompiler::emitCallIndirect(uint32_t callOffset)
+BaseCompiler::emitCallIndirect(uint32_t callOffset, bool oldStyle)
 {
     uint32_t lineOrBytecode = readCallSiteLineOrBytecode(callOffset);
 
     uint32_t sigIndex;
-    uint32_t arity;
-    if (!iter_.readCallIndirect(&sigIndex, &arity))
-        return false;
-
     Nothing callee_;
+    if (oldStyle) {
+        if (!iter_.readOldCallIndirect(&sigIndex))
+            return false;
+    } else {
+        if (!iter_.readCallIndirect(&sigIndex, &callee_))
+            return false;
+    }
+
+    if (deadCode_)
+        return true;
+
+    sync();
 
     const SigWithId& sig = mg_.sigs[sigIndex];
 
-    if (deadCode_) {
-        return skipCall(sig.args()) && iter_.readCallIndirectCallee(&callee_) &&
-               iter_.readCallReturn(sig.ret());
-    }
-
-    sync();
-
-    // Stack: ... index arg1 .. argn
+    // new style: Stack: ... arg1 .. argn index
+    // old style: Stack: ... index arg1 .. argn
+
+    Stk callee;
+    if (!oldStyle)
+        callee = stk_.popCopy();
 
     uint32_t numArgs = sig.args().length();
-    size_t stackSpace = stackConsumed(numArgs+1);
+    size_t stackSpace;
+    if (oldStyle)
+        stackSpace = stackConsumed(numArgs+1);
+    else
+        stackSpace = stackConsumed(numArgs);
 
     FunctionCall baselineCall(lineOrBytecode);
     beginCall(baselineCall, EscapesSandbox(false), IsBuiltinCall(false));
 
     if (!emitCallArgs(sig.args(), baselineCall))
         return false;
 
-    if (!iter_.readCallIndirectCallee(&callee_))
-        return false;
+    if (oldStyle) {
+        if (!iter_.readOldCallIndirectCallee(&callee_))
+            return false;
+
+        callee = peek(numArgs);
+    }
 
     if (!iter_.readCallReturn(sig.ret()))
         return false;
 
-    Stk& callee = peek(numArgs);
-
     callIndirect(sigIndex, callee, baselineCall);
 
     endCall(baselineCall);
 
     // TODO / OPTIMIZE: It would be better to merge this freeStack()
     // into the one in endCall, if we can.
 
-    popValueStackBy(numArgs+1);
+    if (oldStyle)
+        popValueStackBy(numArgs+1);
+    else
+        popValueStackBy(numArgs);
     masm.freeStack(stackSpace);
 
-    pushReturned(baselineCall, sig.ret());
+    if (!IsVoid(sig.ret()))
+        pushReturned(baselineCall, sig.ret());
 
     return true;
 }
 
+
 bool
 BaseCompiler::emitUnaryMathBuiltinCall(uint32_t callOffset, SymbolicAddress callee,
                                        ValType operandType)
 {
-    if (deadCode_) {
-        switch (operandType) {
-          case ValType::F64:
-            return skipCall(SigD_, ExprType::F64);
-          case ValType::F32:
-            return skipCall(SigF_, ExprType::F32);
-          default:
-            MOZ_CRASH("Compiler bug: not a float type");
-        }
-    }
+    if (deadCode_)
+        return true;
 
     uint32_t lineOrBytecode = readCallSiteLineOrBytecode(callOffset);
 
     sync();
 
     uint32_t numArgs = 1;
     size_t stackSpace = stackConsumed(numArgs);
 
@@ -5256,17 +5231,17 @@ BaseCompiler::emitUnaryMathBuiltinCall(u
 
 bool
 BaseCompiler::emitBinaryMathBuiltinCall(uint32_t callOffset, SymbolicAddress callee,
                                         ValType operandType)
 {
     MOZ_ASSERT(operandType == ValType::F64);
 
     if (deadCode_)
-        return skipCall(SigDD_, ExprType::F64);
+        return true;
 
     uint32_t lineOrBytecode = 0;
     if (callee == SymbolicAddress::ModD) {
         // Not actually a call in the binary representation
     } else {
         readCallSiteLineOrBytecode(callOffset);
     }
 
@@ -5345,16 +5320,63 @@ BaseCompiler::emitSetLocal()
     if (deadCode_)
         return true;
 
     switch (locals_[slot]) {
       case ValType::I32: {
         RegI32 rv = popI32();
         syncLocal(slot);
         storeToFrameI32(rv.reg, frameOffsetFromSlot(slot, MIRType::Int32));
+        freeI32(rv);
+        break;
+      }
+      case ValType::I64: {
+        RegI64 rv = popI64();
+        syncLocal(slot);
+        storeToFrameI64(rv.reg, frameOffsetFromSlot(slot, MIRType::Int64));
+        freeI64(rv);
+        break;
+      }
+      case ValType::F64: {
+        RegF64 rv = popF64();
+        syncLocal(slot);
+        storeToFrameF64(rv.reg, frameOffsetFromSlot(slot, MIRType::Double));
+        freeF64(rv);
+        break;
+      }
+      case ValType::F32: {
+        RegF32 rv = popF32();
+        syncLocal(slot);
+        storeToFrameF32(rv.reg, frameOffsetFromSlot(slot, MIRType::Float32));
+        freeF32(rv);
+        break;
+      }
+      default:
+        MOZ_CRASH("Local variable type");
+    }
+
+    return true;
+}
+
+bool
+BaseCompiler::emitTeeLocal()
+{
+    uint32_t slot;
+    Nothing unused_value;
+    if (!iter_.readTeeLocal(locals_, &slot, &unused_value))
+        return false;
+
+    if (deadCode_)
+        return true;
+
+    switch (locals_[slot]) {
+      case ValType::I32: {
+        RegI32 rv = popI32();
+        syncLocal(slot);
+        storeToFrameI32(rv.reg, frameOffsetFromSlot(slot, MIRType::Int32));
         pushI32(rv);
         break;
       }
       case ValType::I64: {
         RegI64 rv = popI64();
         syncLocal(slot);
         storeToFrameI64(rv.reg, frameOffsetFromSlot(slot, MIRType::Int64));
         pushI64(rv);
@@ -5458,16 +5480,57 @@ BaseCompiler::emitSetGlobal()
         return true;
 
     const GlobalDesc& global = mg_.globals[id];
 
     switch (global.type()) {
       case ValType::I32: {
         RegI32 rv = popI32();
         storeGlobalVarI32(global.offset(), rv);
+        break;
+      }
+      case ValType::I64: {
+        RegI64 rv = popI64();
+        storeGlobalVarI64(global.offset(), rv);
+        break;
+      }
+      case ValType::F32: {
+        RegF32 rv = popF32();
+        storeGlobalVarF32(global.offset(), rv);
+        break;
+      }
+      case ValType::F64: {
+        RegF64 rv = popF64();
+        storeGlobalVarF64(global.offset(), rv);
+        break;
+      }
+      default:
+        MOZ_CRASH("Global variable type");
+        break;
+    }
+    return true;
+}
+
+bool
+BaseCompiler::emitTeeGlobal()
+{
+    uint32_t id;
+    Nothing unused_value;
+    if (!iter_.readTeeGlobal(mg_.globals, &id, &unused_value))
+        return false;
+
+    if (deadCode_)
+        return true;
+
+    const GlobalDesc& global = mg_.globals[id];
+
+    switch (global.type()) {
+      case ValType::I32: {
+        RegI32 rv = popI32();
+        storeGlobalVarI32(global.offset(), rv);
         pushI32(rv);
         break;
       }
       case ValType::I64: {
         RegI64 rv = popI64();
         storeGlobalVarI64(global.offset(), rv);
         pushI64(rv);
         break;
@@ -5566,16 +5629,76 @@ BaseCompiler::emitStore(ValType resultTy
 
     switch (resultType) {
       case ValType::I32: {
         RegI32 rp, rv;
         pop2xI32(&rp, &rv);
         if (!store(access, rp, AnyReg(rv)))
             return false;
         freeI32(rp);
+        freeI32(rv);
+        break;
+      }
+      case ValType::I64: {
+        RegI64 rv = popI64();
+        RegI32 rp = popI32();
+        if (!store(access, rp, AnyReg(rv)))
+            return false;
+        freeI32(rp);
+        freeI64(rv);
+        break;
+      }
+      case ValType::F32: {
+        RegF32 rv = popF32();
+        RegI32 rp = popI32();
+        if (!store(access, rp, AnyReg(rv)))
+            return false;
+        freeI32(rp);
+        freeF32(rv);
+        break;
+      }
+      case ValType::F64: {
+        RegF64 rv = popF64();
+        RegI32 rp = popI32();
+        if (!store(access, rp, AnyReg(rv)))
+            return false;
+        freeI32(rp);
+        freeF64(rv);
+        break;
+      }
+      default:
+        MOZ_CRASH("store type");
+        break;
+    }
+    return true;
+}
+
+bool
+BaseCompiler::emitTeeStore(ValType resultType, Scalar::Type viewType)
+{
+    LinearMemoryAddress<Nothing> addr;
+    Nothing unused_value;
+    if (!iter_.readTeeStore(resultType, Scalar::byteSize(viewType), &addr, &unused_value))
+        return false;
+
+    if (deadCode_)
+        return true;
+
+    // TODO / OPTIMIZE: Disable bounds checking on constant accesses
+    // below the minimum heap length.
+
+    MWasmMemoryAccess access(viewType, addr.align, addr.offset);
+
+    switch (resultType) {
+      case ValType::I32: {
+        RegI32 rp, rv;
+        pop2xI32(&rp, &rv);
+        if (!store(access, rp, AnyReg(rv)))
+            return false;
+        freeI32(rp);
         pushI32(rv);
         break;
       }
       case ValType::I64: {
         RegI64 rv = popI64();
         RegI32 rp = popI32();
         if (!store(access, rp, AnyReg(rv)))
             return false;
@@ -5606,70 +5729,64 @@ BaseCompiler::emitStore(ValType resultTy
         break;
     }
     return true;
 }
 
 bool
 BaseCompiler::emitSelect()
 {
-    ExprType type;
+    ValType type;
     Nothing unused_trueValue;
     Nothing unused_falseValue;
     Nothing unused_condition;
     if (!iter_.readSelect(&type, &unused_trueValue, &unused_falseValue, &unused_condition))
         return false;
 
     if (deadCode_)
         return true;
 
     // I32 condition on top, then false, then true.
 
     RegI32 rc = popI32();
     switch (type) {
-      case AnyType:
-      case ExprType::Void: {
-        popValueStackBy(2);
-        pushVoid();
-        break;
-      }
-      case ExprType::I32: {
+      case ValType::I32: {
         Label done;
         RegI32 r0, r1;
         pop2xI32(&r0, &r1);
         masm.branch32(Assembler::NotEqual, rc.reg, Imm32(0), &done);
         moveI32(r1, r0);
         masm.bind(&done);
         freeI32(r1);
         pushI32(r0);
         break;
       }
-      case ExprType::I64: {
+      case ValType::I64: {
         Label done;
         RegI64 r0, r1;
         pop2xI64(&r0,