Merge mozilla-central to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 30 Jun 2015 14:25:40 +0200
changeset 250666 1f967726f39a964c765f1d1cfb25026971cbf908
parent 250665 7341164aa82a601eed1b0338a27c25c2315dffbf (current diff)
parent 250662 291614a686f1402b08db75699a8aa4c487d0f17f (diff)
child 250667 6c08586a13ff2d1c2c1c0f3009e4b699fded6e2a
push idunknown
push userunknown
push dateunknown
milestone42.0a1
Merge mozilla-central to fx-team
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_ee-v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v1_self_signed.der
security/manager/ssl/tests/unit/test_cert_version/v1_self_signed_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_ee-v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v2_self_signed.der
security/manager/ssl/tests/unit/test_cert_version/v2_self_signed_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v3_missing_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v3_self_signed.der
security/manager/ssl/tests/unit/test_cert_version/v3_self_signed_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v1_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v2_int_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int_missing_bc-v1_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int_missing_bc-v1_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int_missing_bc-v2_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int_missing_bc-v2_ca_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int_missing_bc-v3_ca.der
security/manager/ssl/tests/unit/test_cert_version/v4_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_self_signed.der
security/manager/ssl/tests/unit/test_cert_version/v4_self_signed_bc.der
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "27fe0f4261e3685187769411f2f74cff19287b19", 
+        "git_revision": "5997b406e77ea726fbd9047057a1c3504f6cd6d4", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "cef2cd7250a76a1ebfd260d63e85207d72575d33", 
+    "revision": "c050d923dd3c87275a0d3668e54e08aed99f7678", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="27fe0f4261e3685187769411f2f74cff19287b19"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5997b406e77ea726fbd9047057a1c3504f6cd6d4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="3e60c2413c0183754ec8459081f162c0f1dcdeed"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -691,16 +691,17 @@
 
 @RESPATH@/components/EngineeringMode.manifest
 @RESPATH@/components/EngineeringModeAPI.js
 @RESPATH@/components/EngineeringModeService.js
 
 #ifdef MOZ_DEBUG
 @RESPATH@/components/TestInterfaceJS.js
 @RESPATH@/components/TestInterfaceJS.manifest
+@RESPATH@/components/TestInterfaceJSMaplike.js
 #endif
 
 @RESPATH@/components/PACGenerator.js
 @RESPATH@/components/PACGenerator.manifest
 
 ; Modules
 @RESPATH@/modules/*
 
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1672,16 +1672,19 @@ pref("browser.newtab.preload", true);
 pref("browser.newtabpage.introShown", false);
 
 // Remembers if the about:newtab update intro has been shown
 pref("browser.newtabpage.updateIntroShown", false);
 
 // Toggles the content of 'about:newtab'. Shows the grid when enabled.
 pref("browser.newtabpage.enabled", true);
 
+// Toggles the enhanced content of 'about:newtab'. Shows sponsored tiles.
+sticky_pref("browser.newtabpage.enhanced", true);
+
 // number of rows of newtab grid
 pref("browser.newtabpage.rows", 3);
 
 // number of columns of newtab grid
 pref("browser.newtabpage.columns", 5);
 
 // directory tiles download URL
 pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v3/links/fetch/%LOCALE%/%CHANNEL%");
--- a/browser/base/content/newtab/intro.js
+++ b/browser/base/content/newtab/intro.js
@@ -1,16 +1,17 @@
 #ifdef 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/. */
 #endif
 
 const PREF_INTRO_SHOWN = "browser.newtabpage.introShown";
 const PREF_UPDATE_INTRO_SHOWN = "browser.newtabpage.updateIntroShown";
+const PREF_NEWTAB_ENHANCED = "browser.newtabpage.enhanced";
 
 // These consts indicate the type of intro/onboarding we show.
 const WELCOME = "welcome";
 const UPDATE = "update";
 
 // The maximum paragraph ID listed for 'newtab.intro.paragraph'
 // strings in newTab.properties
 const MAX_PARAGRAPH_ID = 9;
@@ -200,16 +201,19 @@ let gIntro = {
         this._paragraphs.push(newTabString(name, substringMappings[i]));
       } catch (ex) {
         // Paragraph with this ID doesn't exist so continue
       }
     }
   },
 
   showIfNecessary: function() {
+    if (!Services.prefs.getBoolPref(PREF_NEWTAB_ENHANCED)) {
+      return;
+    }
     if (!Services.prefs.getBoolPref(PREF_INTRO_SHOWN)) {
       this._onboardingType = WELCOME;
       this.showPanel();
     } else if (!Services.prefs.getBoolPref(PREF_UPDATE_INTRO_SHOWN)) {
       this._onboardingType = UPDATE;
       this.showPanel();
     }
     Services.prefs.setBoolPref(PREF_INTRO_SHOWN, true);
--- a/browser/base/content/newtab/page.js
+++ b/browser/base/content/newtab/page.js
@@ -49,16 +49,17 @@ let gPage = {
       gCustomize.updateSelected();
 
       let enabled = gAllPages.enabled;
       this._updateAttributes(enabled);
 
       // Update thumbnails to the new enhanced setting
       if (aData == "browser.newtabpage.enhanced") {
         this.update();
+        gIntro.showIfNecessary();
       }
 
       // Initialize the whole page if we haven't done that, yet.
       if (enabled) {
         this._init();
       } else {
         gUndoDialog.hide();
       }
--- a/browser/components/privatebrowsing/test/browser/browser.ini
+++ b/browser/components/privatebrowsing/test/browser/browser.ini
@@ -11,17 +11,16 @@ support-files =
   browser_privatebrowsing_placesTitleNoUpdate.html
   browser_privatebrowsing_protocolhandler_page.html
   browser_privatebrowsing_windowtitle_page.html
   head.js
   popup.html
   title.sjs
 
 [browser_privatebrowsing_DownloadLastDirWithCPS.js]
-skip-if = (os == "win" && os_version == "6.2") # bug 1173801
 [browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js]
 [browser_privatebrowsing_aboutSessionRestore.js]
 [browser_privatebrowsing_cache.js]
 [browser_privatebrowsing_certexceptionsui.js]
 [browser_privatebrowsing_concurrent.js]
 [browser_privatebrowsing_cookieacceptdialog.js]
 skip-if = e10s # Bug 1139953 - Accept cookie dialog shown in private window when e10s enabled
 [browser_privatebrowsing_crh.js]
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -618,16 +618,17 @@
 
 ; InputMethod API
 @RESPATH@/components/MozKeyboard.js
 @RESPATH@/components/InputMethod.manifest
 
 #ifdef MOZ_DEBUG
 @RESPATH@/components/TestInterfaceJS.js
 @RESPATH@/components/TestInterfaceJS.manifest
+@RESPATH@/components/TestInterfaceJSMaplike.js
 #endif
 
 @RESPATH@/components/PACGenerator.js
 @RESPATH@/components/PACGenerator.manifest
 
 ; Modules
 @RESPATH@/browser/modules/*
 @RESPATH@/modules/*
--- a/browser/modules/DirectoryLinksProvider.jsm
+++ b/browser/modules/DirectoryLinksProvider.jsm
@@ -383,17 +383,17 @@ let DirectoryLinksProvider = {
     return "en-US";
   },
 
   /**
    * Set appropriate default ping behavior controlled by enhanced pref
    */
   _setDefaultEnhanced: function DirectoryLinksProvider_setDefaultEnhanced() {
     if (!Services.prefs.prefHasUserValue(PREF_NEWTAB_ENHANCED)) {
-      let enhanced = true;
+      let enhanced = Services.prefs.getBoolPref(PREF_NEWTAB_ENHANCED);
       try {
         // Default to not enhanced if DNT is set to tell websites to not track
         if (Services.prefs.getBoolPref("privacy.donottrackheader.enabled")) {
           enhanced = false;
         }
       }
       catch(ex) {}
       Services.prefs.setBoolPref(PREF_NEWTAB_ENHANCED, enhanced);
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -4580,18 +4580,17 @@ nsDocShell::GetDocument()
 {
   NS_ENSURE_SUCCESS(EnsureContentViewer(), nullptr);
   return mContentViewer->GetDocument();
 }
 
 nsPIDOMWindow*
 nsDocShell::GetWindow()
 {
-  NS_ENSURE_SUCCESS(EnsureScriptEnvironment(), nullptr);
-  return mScriptGlobal;
+  return NS_SUCCEEDED(EnsureScriptEnvironment()) ? mScriptGlobal : nullptr;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetDeviceSizeIsPageSize(bool aValue)
 {
   if (mDeviceSizeIsPageSize != aValue) {
     mDeviceSizeIsPageSize = aValue;
     nsRefPtr<nsPresContext> presContext;
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -608,17 +608,17 @@ Link::UpdateURLSearchParams()
 
   mSearchParams->ParseInput(search);
 }
 
 void
 Link::CreateSearchParamsIfNeeded()
 {
   if (!mSearchParams) {
-    mSearchParams = new URLSearchParams(this);
+    mSearchParams = new URLSearchParams(this, this);
     UpdateURLSearchParams();
   }
 }
 
 void
 Link::Unlink()
 {
   if (mSearchParams) {
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -21,96 +21,98 @@
 #include "nsContentUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(URL)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(URL)
-  if (tmp->mSearchParams) {
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mSearchParams)
-  }
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mSearchParams)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(URL)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSearchParams)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(URL)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(URL)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URL)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-URL::URL(already_AddRefed<nsIURI> aURI)
-  : mURI(aURI)
+URL::URL(nsISupports* aParent, already_AddRefed<nsIURI> aURI)
+  : mParent(aParent)
+  , mURI(aURI)
 {
 }
 
-bool
-URL::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
+JSObject*
+URL::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
-  return URLBinding::Wrap(aCx, this, aGivenProto, aReflector);
+  return URLBinding::Wrap(aCx, this, aGivenProto);
 }
 
 /* static */ already_AddRefed<URL>
 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
                  URL& aBase, ErrorResult& aRv)
 {
-  return Constructor(aUrl, aBase.GetURI(), aRv);
+  return Constructor(aGlobal.GetAsSupports(), aUrl, aBase.GetURI(), aRv);
 }
 
 /* static */ already_AddRefed<URL>
 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
                  const Optional<nsAString>& aBase, ErrorResult& aRv)
 {
   if (aBase.WasPassed()) {
-    return Constructor(aUrl, aBase.Value(), aRv);
+    return Constructor(aGlobal.GetAsSupports(), aUrl, aBase.Value(), aRv);
   }
 
-  return Constructor(aUrl, nullptr, aRv);
+  return Constructor(aGlobal.GetAsSupports(), aUrl, nullptr, aRv);
 }
 
 /* static */ already_AddRefed<URL>
 URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
                  const nsAString& aBase, ErrorResult& aRv)
 {
-  return Constructor(aUrl, aBase, aRv);
+  return Constructor(aGlobal.GetAsSupports(), aUrl, aBase, aRv);
 }
 
 /* static */ already_AddRefed<URL>
-URL::Constructor(const nsAString& aUrl, const nsAString& aBase,
-                 ErrorResult& aRv)
+URL::Constructor(nsISupports* aParent, const nsAString& aUrl,
+                 const nsAString& aBase, ErrorResult& aRv)
 {
   nsCOMPtr<nsIURI> baseUri;
   nsresult rv = NS_NewURI(getter_AddRefs(baseUri), aBase, nullptr, nullptr,
                           nsContentUtils::GetIOService());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aRv.ThrowTypeError(MSG_INVALID_URL, &aBase);
     return nullptr;
   }
 
-  return Constructor(aUrl, baseUri, aRv);
+  return Constructor(aParent, aUrl, baseUri, aRv);
 }
 
 /* static */
 already_AddRefed<URL>
-URL::Constructor(const nsAString& aUrl, nsIURI* aBase, ErrorResult& aRv)
+URL::Constructor(nsISupports* aParent, const nsAString& aUrl, nsIURI* aBase,
+                 ErrorResult& aRv)
 {
   nsCOMPtr<nsIURI> uri;
   nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, nullptr, aBase,
                           nsContentUtils::GetIOService());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     aRv.ThrowTypeError(MSG_INVALID_URL, &aUrl);
     return nullptr;
   }
 
-  nsRefPtr<URL> url = new URL(uri.forget());
+  nsRefPtr<URL> url = new URL(aParent, uri.forget());
   return url.forget();
 }
 
 void
 URL::CreateObjectURL(const GlobalObject& aGlobal,
                      Blob& aBlob,
                      const objectURLOptions& aOptions,
                      nsAString& aResult,
@@ -528,15 +530,15 @@ bool IsChromeURI(nsIURI* aURI)
       return isChrome;
   return false;
 }
 
 void
 URL::CreateSearchParamsIfNeeded()
 {
   if (!mSearchParams) {
-    mSearchParams = new URLSearchParams(this);
+    mSearchParams = new URLSearchParams(mParent, this);
     UpdateURLSearchParams();
   }
 }
 
 }
 }
--- a/dom/base/URL.h
+++ b/dom/base/URL.h
@@ -6,16 +6,17 @@
 #ifndef URL_h___
 #define URL_h___
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/URLSearchParams.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
+#include "nsWrapperCache.h"
 
 class nsISupports;
 class nsIURI;
 
 namespace mozilla {
 
 class ErrorResult;
 class DOMMediaStream;
@@ -27,43 +28,51 @@ class MediaSource;
 class GlobalObject;
 struct objectURLOptions;
 
 namespace workers {
 class URLProxy;
 }
 
 class URL final : public URLSearchParamsObserver
+                , public nsWrapperCache
 {
   ~URL() {}
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(URL)
 
-  explicit URL(already_AddRefed<nsIURI> aURI);
+  URL(nsISupports* aParent, already_AddRefed<nsIURI> aURI);
 
   // WebIDL methods
-  bool
-  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
+  nsISupports* GetParentObject() const
+  {
+    return mParent;
+  }
+
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               URL& aBase, ErrorResult& aRv);
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               const Optional<nsAString>& aBase, ErrorResult& aRv);
   // Versions of Constructor that we can share with workers and other code.
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               const nsAString& aBase, ErrorResult& aRv);
   static already_AddRefed<URL>
-  Constructor(const nsAString& aUrl, const nsAString& aBase, ErrorResult& aRv);
+  Constructor(nsISupports* aParent, const nsAString& aUrl,
+              const nsAString& aBase, ErrorResult& aRv);
   static already_AddRefed<URL>
-  Constructor(const nsAString& aUrl, nsIURI* aBase, ErrorResult& aRv);
+  Constructor(nsISupports* aParent, const nsAString& aUrl,
+              nsIURI* aBase, ErrorResult& aRv);
 
   static void CreateObjectURL(const GlobalObject& aGlobal,
                               Blob& aBlob,
                               const objectURLOptions& aOptions,
                               nsAString& aResult,
                               ErrorResult& aError);
   static void CreateObjectURL(const GlobalObject& aGlobal,
                               DOMMediaStream& aStream,
@@ -145,16 +154,17 @@ private:
 
   static void CreateObjectURLInternal(const GlobalObject& aGlobal,
                                       nsISupports* aObject,
                                       const nsACString& aScheme,
                                       const objectURLOptions& aOptions,
                                       nsAString& aResult,
                                       ErrorResult& aError);
 
+  nsCOMPtr<nsISupports> mParent;
   nsCOMPtr<nsIURI> mURI;
   nsRefPtr<URLSearchParams> mSearchParams;
 
   friend class mozilla::dom::workers::URLProxy;
 };
 
 bool IsChromeURI(nsIURI* aURI);
 
--- a/dom/base/URLSearchParams.cpp
+++ b/dom/base/URLSearchParams.cpp
@@ -288,32 +288,38 @@ URLParams::Serialize(nsAString& aValue) 
     }
 
     SerializeString(NS_ConvertUTF16toUTF8(mParams[i].mKey), aValue);
     aValue.Append('=');
     SerializeString(NS_ConvertUTF16toUTF8(mParams[i].mValue), aValue);
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(URLSearchParams, mObserver)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(URLSearchParams, mParent, mObserver)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(URLSearchParams)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(URLSearchParams)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(URLSearchParams)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-URLSearchParams::URLSearchParams(URLSearchParamsObserver* aObserver)
-  : mParams(new URLParams()), mObserver(aObserver)
+URLSearchParams::URLSearchParams(nsISupports* aParent,
+                                 URLSearchParamsObserver* aObserver)
+  : mParams(new URLParams())
+  , mParent(aParent)
+  , mObserver(aObserver)
 {
 }
 
-URLSearchParams::URLSearchParams(const URLSearchParams& aOther)
-  : mParams(new URLParams(*aOther.mParams.get())), mObserver(aOther.mObserver)
+URLSearchParams::URLSearchParams(nsISupports* aParent,
+                                 const URLSearchParams& aOther)
+  : mParams(new URLParams(*aOther.mParams.get()))
+  , mParent(aParent)
+  , mObserver(aOther.mObserver)
 {
 }
 
 URLSearchParams::~URLSearchParams()
 {
   DeleteAll();
 }
 
@@ -323,27 +329,31 @@ URLSearchParams::WrapObject(JSContext* a
   return URLSearchParamsBinding::Wrap(aCx, this, aGivenProto);
 }
 
 /* static */ already_AddRefed<URLSearchParams>
 URLSearchParams::Constructor(const GlobalObject& aGlobal,
                              const nsAString& aInit,
                              ErrorResult& aRv)
 {
-  nsRefPtr<URLSearchParams> sp = new URLSearchParams(nullptr);
+  nsRefPtr<URLSearchParams> sp =
+    new URLSearchParams(aGlobal.GetAsSupports(), nullptr);
   sp->ParseInput(NS_ConvertUTF16toUTF8(aInit));
+
   return sp.forget();
 }
 
 /* static */ already_AddRefed<URLSearchParams>
 URLSearchParams::Constructor(const GlobalObject& aGlobal,
                              URLSearchParams& aInit,
                              ErrorResult& aRv)
 {
-  nsRefPtr<URLSearchParams> sp = new URLSearchParams(aInit);
+  nsRefPtr<URLSearchParams> sp =
+    new URLSearchParams(aGlobal.GetAsSupports(), aInit);
+
   return sp.forget();
 }
 
 void
 URLSearchParams::ParseInput(const nsACString& aInput)
 {
   mParams->ParseInput(aInput);
 }
--- a/dom/base/URLSearchParams.h
+++ b/dom/base/URLSearchParams.h
@@ -109,24 +109,26 @@ class URLSearchParams final : public nsI
                               public nsWrapperCache
 {
   ~URLSearchParams();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(URLSearchParams)
 
-  explicit URLSearchParams(URLSearchParamsObserver* aObserver);
+  URLSearchParams(nsISupports* aParent,
+                  URLSearchParamsObserver* aObserver);
 
-  explicit URLSearchParams(const URLSearchParams& aOther);
+  URLSearchParams(nsISupports* aParent,
+                  const URLSearchParams& aOther);
 
   // WebIDL methods
   nsISupports* GetParentObject() const
   {
-    return nullptr;
+    return mParent;
   }
 
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   static already_AddRefed<URLSearchParams>
   Constructor(const GlobalObject& aGlobal, const nsAString& aInit,
               ErrorResult& aRv);
@@ -169,15 +171,16 @@ public:
 private:
   void AppendInternal(const nsAString& aName, const nsAString& aValue);
 
   void DeleteAll();
 
   void NotifyObserver();
 
   UniquePtr<URLParams> mParams;
+  nsCOMPtr<nsISupports> mParent;
   nsRefPtr<URLSearchParamsObserver> mObserver;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_URLSearchParams_h */
--- a/dom/base/nsIGlobalObject.h
+++ b/dom/base/nsIGlobalObject.h
@@ -17,16 +17,17 @@
 
 class nsACString;
 class nsCString;
 class nsCycleCollectionTraversalCallback;
 class nsIPrincipal;
 
 class nsIGlobalObject : public nsISupports
 {
+  nsTArray<nsCString> mHostObjectURIs;
   bool mIsDying;
 
 protected:
   nsIGlobalObject()
    : mIsDying(false)
   {}
 
 public:
@@ -64,20 +65,16 @@ public:
   // Any CC class inheriting nsIGlobalObject should call these 2 methods if it
   // exposes the URL API.
   void UnlinkHostObjectURIs();
   void TraverseHostObjectURIs(nsCycleCollectionTraversalCallback &aCb);
 
 protected:
   virtual ~nsIGlobalObject();
 
-private:
-  nsTArray<nsCString> mHostObjectURIs;
-
-protected:
   void
   StartDying()
   {
     mIsDying = true;
   }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject,
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1087,22 +1087,22 @@ nsJSContext::AddSupportsPrimitiveTojsval
       break;
     }
     case nsISupportsPrimitive::TYPE_ID :
     case nsISupportsPrimitive::TYPE_PRUINT64 :
     case nsISupportsPrimitive::TYPE_PRINT64 :
     case nsISupportsPrimitive::TYPE_PRTIME :
     case nsISupportsPrimitive::TYPE_VOID : {
       NS_WARNING("Unsupported primitive type used");
-      *aArgv = JSVAL_NULL;
+      aArgv->setNull();
       break;
     }
     default : {
       NS_WARNING("Unknown primitive type used");
-      *aArgv = JSVAL_NULL;
+      aArgv->setNull();
       break;
     }
   }
   return NS_OK;
 }
 
 #ifdef MOZ_JPROF
 
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2811,10 +2811,94 @@ SystemGlobalResolve(JSContext* cx, JS::H
 bool
 SystemGlobalEnumerate(JSContext* cx, JS::Handle<JSObject*> obj)
 {
   bool ignored = false;
   return EnumerateGlobal(cx, obj) &&
          ResolveSystemBinding(cx, obj, JSID_VOIDHANDLE, &ignored);
 }
 
+template<decltype(JS::NewMapObject) Method>
+bool
+GetMaplikeSetlikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                               size_t aSlotIndex,
+                               JS::MutableHandle<JSObject*> aBackingObj,
+                               bool* aBackingObjCreated)
+{
+  JS::Rooted<JSObject*> reflector(aCx);
+  reflector = IsDOMObject(aObj) ? aObj : js::UncheckedUnwrap(aObj,
+                                                             /* stopAtOuter = */ false);
+
+  // Retrieve the backing object from the reserved slot on the maplike/setlike
+  // object. If it doesn't exist yet, create it.
+  JS::Rooted<JS::Value> slotValue(aCx);
+  slotValue = js::GetReservedSlot(reflector, aSlotIndex);
+  if (slotValue.isUndefined()) {
+    // Since backing object access can happen in non-originating compartments,
+    // make sure to create the backing object in reflector compartment.
+    {
+      JSAutoCompartment ac(aCx, reflector);
+      JS::Rooted<JSObject*> newBackingObj(aCx);
+      newBackingObj.set(Method(aCx));
+      if (NS_WARN_IF(!newBackingObj)) {
+        return false;
+      }
+      js::SetReservedSlot(reflector, aSlotIndex, JS::ObjectValue(*newBackingObj));
+    }
+    slotValue = js::GetReservedSlot(reflector, aSlotIndex);
+    *aBackingObjCreated = true;
+  } else {
+    *aBackingObjCreated = false;
+  }
+  if (!MaybeWrapNonDOMObjectValue(aCx, &slotValue)) {
+    return false;
+  }
+  aBackingObj.set(&slotValue.toObject());
+  return true;
+}
+
+bool
+GetMaplikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                        size_t aSlotIndex,
+                        JS::MutableHandle<JSObject*> aBackingObj,
+                        bool* aBackingObjCreated)
+{
+  return GetMaplikeSetlikeBackingObject<JS::NewMapObject>(aCx, aObj, aSlotIndex,
+                                                          aBackingObj,
+                                                          aBackingObjCreated);
+}
+
+bool
+GetSetlikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                        size_t aSlotIndex,
+                        JS::MutableHandle<JSObject*> aBackingObj,
+                        bool* aBackingObjCreated)
+{
+  return GetMaplikeSetlikeBackingObject<JS::NewSetObject>(aCx, aObj, aSlotIndex,
+                                                          aBackingObj,
+                                                          aBackingObjCreated);
+}
+
+bool
+ForEachHandler(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
+{
+  JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
+  // Unpack callback and object from slots
+  JS::Rooted<JS::Value>
+    callbackFn(aCx, js::GetFunctionNativeReserved(&args.callee(),
+                                                  FOREACH_CALLBACK_SLOT));
+  JS::Rooted<JS::Value>
+    maplikeOrSetlikeObj(aCx,
+                        js::GetFunctionNativeReserved(&args.callee(),
+                                                      FOREACH_MAPLIKEORSETLIKEOBJ_SLOT));
+  MOZ_ASSERT(aArgc == 3);
+  JS::AutoValueVector newArgs(aCx);
+  // Arguments are passed in as value, key, object. Keep value and key, replace
+  // object with the maplike/setlike object.
+  newArgs.append(args.get(0));
+  newArgs.append(args.get(1));
+  newArgs.append(maplikeOrSetlikeObj);
+  JS::Rooted<JS::Value> rval(aCx, JS::UndefinedValue());
+  // Now actually call the user specified callback
+  return JS::Call(aCx, args.thisv(), callbackFn, newArgs, &rval);
+}
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -3243,13 +3243,36 @@ GetErrorPrototype(JSContext* aCx, JS::Ha
 bool SystemGlobalResolve(JSContext* cx, JS::Handle<JSObject*> obj,
                          JS::Handle<jsid> id, bool* resolvedp);
 
 // Enumerate all ids on the given global object that wants to be included in
 // Exposed=System webidl annotations.  False return value means exception
 // thrown.
 bool SystemGlobalEnumerate(JSContext* cx, JS::Handle<JSObject*> obj);
 
+// Slot indexes for maplike/setlike forEach functions
+#define FOREACH_CALLBACK_SLOT 0
+#define FOREACH_MAPLIKEORSETLIKEOBJ_SLOT 1
+
+// Backing function for running .forEach() on maplike/setlike interfaces.
+// Unpacks callback and maplike/setlike object from reserved slots, then runs
+// callback for each key (and value, for maplikes)
+bool ForEachHandler(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
+
+// Unpacks backing object (ES6 map/set) from the reserved slot of a reflector
+// for a maplike/setlike interface. If backing object does not exist, creates
+// backing object in the compartment of the reflector involved, making this safe
+// to use across compartments/via xrays. Return values of these methods will
+// always be in the context compartment.
+bool GetMaplikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                             size_t aSlotIndex,
+                             JS::MutableHandle<JSObject*> aBackingObj,
+                             bool* aBackingObjCreated);
+bool GetSetlikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
+                             size_t aSlotIndex,
+                             JS::MutableHandle<JSObject*> aBackingObj,
+                             bool* aBackingObjCreated);
+
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_BindingUtils_h__ */
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1303,22 +1303,19 @@ DOMInterfaces = {
 'TreeWalker': {
     'wrapperCache': False,
 },
 
 'UndoManager': {
     'implicitJSContext' : [ 'undo', 'redo', 'transact' ],
 },
 
-'URL' : [{
-    'wrapperCache': False,
-},
+'URL' : [{},
 {
     'workers': True,
-    'wrapperCache': False,
 }],
 
 'VRDevice': {
     'concrete': False
 },
 
 'VTTCue': {
     'nativeType': 'mozilla::dom::TextTrackCue'
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1138,16 +1138,28 @@ class CGHeaders(CGWrapper):
 
             for m in desc.interface.members:
                 addHeaderForFunc(PropertyDefiner.getStringAttr(m, "Func"))
             # getExtendedAttribute() returns a list, extract the entry.
             funcList = desc.interface.getExtendedAttribute("Func")
             if funcList is not None:
                 addHeaderForFunc(funcList[0])
 
+        for desc in descriptors:
+            if desc.interface.maplikeOrSetlike:
+                # We need ToJSValue.h for maplike/setlike type conversions
+                bindingHeaders.add("mozilla/dom/ToJSValue.h")
+                # Add headers for the key and value types of the maplike, since
+                # they'll be needed for convenience functions
+                addHeadersForType((desc.interface.maplikeOrSetlike.keyType,
+                                   desc, None))
+                if desc.interface.maplikeOrSetlike.valueType:
+                    addHeadersForType((desc.interface.maplikeOrSetlike.valueType,
+                                       desc, None))
+
         for d in dictionaries:
             if d.parent:
                 declareIncludes.add(self.getDeclarationFilename(d.parent))
             bindingHeaders.add(self.getDeclarationFilename(d))
 
         for c in callbacks:
             bindingHeaders.add(self.getDeclarationFilename(c))
 
@@ -2159,39 +2171,78 @@ class MethodDefiner(PropertyDefiner):
                     "condition": MemberCondition(None, condition)
                 })
                 continue
 
             method = {
                 "name": m.identifier.name,
                 "methodInfo": not m.isStatic(),
                 "length": methodLength(m),
-                "flags": "JSPROP_ENUMERATE",
+                # Methods generated for a maplike/setlike declaration are not
+                # enumerable.
+                "flags": "JSPROP_ENUMERATE" if not m.isMaplikeOrSetlikeMethod() else "0",
                 "condition": PropertyDefiner.getControllingCondition(m, descriptor),
                 "allowCrossOriginThis": m.getExtendedAttribute("CrossOriginCallable"),
                 "returnsPromise": m.returnsPromise(),
                 "hasIteratorAlias": "@@iterator" in m.aliases
             }
             if isChromeOnly(m):
                 self.chrome.append(method)
             else:
                 self.regular.append(method)
 
-        # FIXME Check for an existing iterator on the interface first.
-        if (any(m.isGetter() and m.isIndexed() for m in methods) and
-            not any("@@iterator" in m.aliases for m in methods)):
+        # TODO: Once iterable is implemented, use tiebreak rules instead of
+        # failing. Also, may be more tiebreak rules to implement once spec bug
+        # is resolved.
+        # https://www.w3.org/Bugs/Public/show_bug.cgi?id=28592
+        def hasIterator(methods, regular):
+            return (any("@@iterator" in m.aliases for m in methods) or
+                    any("@@iterator" == r["name"] for r in regular))
+
+        if (any(m.isGetter() and m.isIndexed() for m in methods)):
+            if hasIterator(methods, self.regular):
+                raise TypeError("Cannot have indexed getter/attr on "
+                                "interface %s with other members "
+                                "that generate @@iterator, such as "
+                                "maplike/setlike or aliased functions." %
+                                self.descriptor.interface.identifier.name)
             self.regular.append({
                 "name": "@@iterator",
                 "methodInfo": False,
                 "selfHostedName": "ArrayValues",
                 "length": 0,
                 "flags": "JSPROP_ENUMERATE",
                 "condition": MemberCondition(None, None)
             })
 
+        # Generate the maplike/setlike iterator, if one wasn't already
+        # generated by a method. If we already have an @@iterator symbol, fail.
+        if descriptor.interface.maplikeOrSetlike:
+            if hasIterator(methods, self.regular):
+                raise TypeError("Cannot have maplike/setlike interface with "
+                                "other members that generate @@iterator "
+                                "on interface %s, such as indexed getters "
+                                "or aliased functions." %
+                                self.descriptor.interface.identifier.name)
+            for m in methods:
+                if (m.isMaplikeOrSetlikeMethod() and
+                    ((m.maplikeOrSetlike.isMaplike() and
+                      m.identifier.name == "entries") or
+                     (m.maplikeOrSetlike.isSetlike() and
+                      m.identifier.name == "values"))):
+                    self.regular.append({
+                        "name": "@@iterator",
+                        "methodName": m.identifier.name,
+                        "length": methodLength(m),
+                        "flags": "0",
+                        "condition": PropertyDefiner.getControllingCondition(m,
+                                                                             descriptor),
+                    })
+                    break
+
         if not static:
             stringifier = descriptor.operations['Stringifier']
             if (stringifier and
                 unforgeable == MemberIsUnforgeable(stringifier, descriptor) and
                 isMaybeExposedIn(stringifier, descriptor)):
                 toStringDesc = {
                     "name": "toString",
                     "nativeName": stringifier.identifier.name,
@@ -2279,17 +2330,19 @@ class MethodDefiner(PropertyDefiner):
         def specData(m):
             if "selfHostedName" in m:
                 selfHostedName = '"%s"' % m["selfHostedName"]
                 assert not m.get("methodInfo", True)
                 accessor = "nullptr"
                 jitinfo = "nullptr"
             else:
                 selfHostedName = "nullptr"
-                accessor = m.get("nativeName", IDLToCIdentifier(m["name"]))
+                # When defining symbols, function name may not match symbol name
+                methodName = m.get("methodName", m["name"])
+                accessor = m.get("nativeName", IDLToCIdentifier(methodName))
                 if m.get("methodInfo", True):
                     # Cast this in case the methodInfo is a
                     # JSTypedMethodJitInfo.
                     jitinfo = ("reinterpret_cast<const JSJitInfo*>(&%s_methodinfo)" % accessor)
                     if m.get("allowCrossOriginThis", False):
                         if m.get("returnsPromise", False):
                             raise TypeError("%s returns a Promise but should "
                                             "be allowed cross-origin?" %
@@ -2372,18 +2425,20 @@ class AttrDefiner(PropertyDefiner):
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
 
     def generateArray(self, array, name, doIdArrays):
         if len(array) == 0:
             return ""
 
         def flags(attr):
             unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
-            return ("JSPROP_SHARED | JSPROP_ENUMERATE" +
-                    unforgeable)
+            # Attributes generated as part of a maplike/setlike declaration are
+            # not enumerable.
+            enumerable = " | JSPROP_ENUMERATE" if not attr.isMaplikeOrSetlikeAttr() else ""
+            return ("JSPROP_SHARED" + enumerable + unforgeable)
 
         def getter(attr):
             if self.static:
                 accessor = 'get_' + IDLToCIdentifier(attr.identifier.name)
                 jitinfo = "nullptr"
             else:
                 if attr.hasLenientThis():
                     accessor = "genericLenientGetter"
@@ -5534,35 +5589,43 @@ class CGArgumentConverter(CGThing):
     right native type.
 
     argDescription is a description of the argument for error-reporting
     purposes.  Callers should assume that it might get placed in the middle of a
     sentence.  If it ends up at the beginning of a sentence, its first character
     will be automatically uppercased.
     """
     def __init__(self, argument, index, descriptorProvider,
-                 argDescription,
+                 argDescription, member,
                  invalidEnumValueFatal=True, lenientFloatCode=None):
         CGThing.__init__(self)
         self.argument = argument
         self.argDescription = argDescription
         assert(not argument.defaultValue or argument.optional)
 
         replacer = {
             "index": index,
             "argc": "args.length()"
         }
         self.replacementVariables = {
             "declName": "arg%d" % index,
             "holderName": ("arg%d" % index) + "_holder",
             "obj": "obj",
             "passedToJSImpl": toStringBool(isJSImplementedDescriptor(descriptorProvider))
         }
-        self.replacementVariables["val"] = string.Template(
-            "args[${index}]").substitute(replacer)
+        # If we have a method generated by the maplike/setlike portion of an
+        # interface, arguments can possibly be undefined, but will need to be
+        # converted to the key/value type of the backing object. In this case,
+        # use .get() instead of direct access to the argument.
+        if member.isMethod() and member.isMaplikeOrSetlikeMethod():
+            self.replacementVariables["val"] = string.Template(
+                "args.get(${index})").substitute(replacer)
+        else:
+            self.replacementVariables["val"] = string.Template(
+                "args[${index}]").substitute(replacer)
         haveValueCheck = string.Template(
             "args.hasDefined(${index})").substitute(replacer)
         self.replacementVariables["haveValue"] = haveValueCheck
         self.descriptorProvider = descriptorProvider
         if self.argument.canHaveMissingValue():
             self.argcAndIndex = replacer
         else:
             self.argcAndIndex = None
@@ -6790,17 +6853,17 @@ class CGPerSignatureCall(CGThing):
                 cgThings.append(CGIfWrapper(
                     CGGeneric("unwrappedObj.emplace(cx, obj);\n"),
                     "objIsXray"))
 
         for i in range(argConversionStartsAt, self.argCount):
             cgThings.append(
                 CGArgumentConverter(arguments[i], i, self.descriptor,
                                     argDescription % {"index": i + 1},
-                                    invalidEnumValueFatal=not setter,
+                                    idlNode, invalidEnumValueFatal=not setter,
                                     lenientFloatCode=lenientFloatCode))
 
         if needsUnwrap:
             # Something depends on having the unwrapped object, so unwrap it now.
             xraySteps = []
             # XXXkhuey we should be able to MOZ_ASSERT that ${obj} is
             # not null.
             xraySteps.append(
@@ -6827,21 +6890,29 @@ class CGPerSignatureCall(CGThing):
                 xraySteps.extend(
                     wrapArgIntoCurrentCompartment(arg, argname, isMember=False)
                     for arg, argname in self.getArguments())
 
             cgThings.append(
                 CGIfWrapper(CGList(xraySteps),
                             "objIsXray"))
 
-        cgThings.append(CGCallGenerator(
-            self.getErrorReport() if self.isFallible() else None,
-            self.getArguments(), argsPre, returnType,
-            self.extendedAttributes, descriptor, nativeMethodName,
-            static, argsPost=argsPost, resultVar=resultVar))
+        # If this is a method that was generated by a maplike/setlike
+        # interface, use the maplike/setlike generator to fill in the body.
+        # Otherwise, use CGCallGenerator to call the native method.
+        if idlNode.isMethod() and idlNode.isMaplikeOrSetlikeMethod():
+            cgThings.append(CGMaplikeOrSetlikeMethodGenerator(descriptor,
+                                                              idlNode.maplikeOrSetlike,
+                                                              idlNode.identifier.name))
+        else:
+            cgThings.append(CGCallGenerator(
+                self.getErrorReport() if self.isFallible() else None,
+                self.getArguments(), argsPre, returnType,
+                self.extendedAttributes, descriptor, nativeMethodName,
+                static, argsPost=argsPost, resultVar=resultVar))
         self.cgRoot = CGList(cgThings)
 
     def getArguments(self):
         return [(a, "arg" + str(i)) for i, a in enumerate(self.arguments)]
 
     def isFallible(self):
         return 'infallible' not in self.extendedAttributes
 
@@ -7046,17 +7117,20 @@ class CGMethodCall(CGThing):
         if len(signatures) == 1:
             # Special case: we can just do a per-signature method call
             # here for our one signature and not worry about switching
             # on anything.
             signature = signatures[0]
             self.cgRoot = CGList([getPerSignatureCall(signature)])
             requiredArgs = requiredArgCount(signature)
 
-            if requiredArgs > 0:
+            # Skip required arguments check for maplike/setlike interfaces, as
+            # they can have arguments which are not passed, and are treated as
+            # if undefined had been explicitly passed.
+            if requiredArgs > 0 and not method.isMaplikeOrSetlikeMethod():
                 code = fill(
                     """
                     if (MOZ_UNLIKELY(args.length() < ${requiredArgs})) {
                       return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "${methodName}");
                     }
                     """,
                     requiredArgs=requiredArgs,
                     methodName=methodName)
@@ -7141,17 +7215,17 @@ class CGMethodCall(CGThing):
                                     distinguishingArgument(sig).location)
 
             # Convert all our arguments up to the distinguishing index.
             # Doesn't matter which of the possible signatures we use, since
             # they all have the same types up to that point; just use
             # possibleSignatures[0]
             caseBody = [CGArgumentConverter(possibleSignatures[0][1][i],
                                             i, descriptor,
-                                            argDesc % (i + 1))
+                                            argDesc % (i + 1), method)
                         for i in range(0, distinguishingIndex)]
 
             # Select the right overload from our set.
             distinguishingArg = "args[%d]" % distinguishingIndex
 
             def tryCall(signature, indent, isDefinitelyObject=False,
                         isNullOrUndefined=False):
                 assert not isDefinitelyObject or not isNullOrUndefined
@@ -7433,17 +7507,22 @@ class FakeArgument():
     setters look like method calls or for special operations.
     """
     def __init__(self, type, interfaceMember, name="arg", allowTreatNonCallableAsNull=False):
         self.type = type
         self.optional = False
         self.variadic = False
         self.defaultValue = None
         self._allowTreatNonCallableAsNull = allowTreatNonCallableAsNull
-        self.treatNullAs = interfaceMember.treatNullAs
+        # For FakeArguments generated by maplike/setlike convenience functions,
+        # we won't have an interfaceMember to pass in.
+        if interfaceMember:
+            self.treatNullAs = interfaceMember.treatNullAs
+        else:
+            self.treatNullAs = "Default"
         if isinstance(interfaceMember, IDLAttribute):
             self.enforceRange = interfaceMember.enforceRange
             self.clamp = interfaceMember.clamp
         else:
             self.enforceRange = False
             self.clamp = False
 
         self.identifier = FakeIdentifier(name)
@@ -8003,16 +8082,22 @@ class CGSpecializedGetter(CGAbstractStat
             Argument('JSContext*', 'cx'),
             Argument('JS::Handle<JSObject*>', 'obj'),
             Argument('%s*' % descriptor.nativeType, 'self'),
             Argument('JSJitGetterCallArgs', 'args')
         ]
         CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
 
     def definition_body(self):
+        if self.attr.maplikeOrSetlike:
+            # If the interface is maplike/setlike, there will be one getter
+            # method for the size property of the backing object. Due to having
+            # to unpack the backing object from the slot, this requires its own
+            # generator.
+            return getMaplikeOrSetlikeSizeGetterBody(self.descriptor, self.attr)
         nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
                                                         self.attr)
         if self.attr.slotIndex is not None:
             if self.descriptor.hasXPConnectImpls:
                 raise TypeError("Interface '%s' has XPConnect impls, so we "
                                 "can't use our slot for property '%s'!" %
                                 (self.descriptor.interface.identifier.name,
                                  self.attr.identifier.name))
@@ -11258,16 +11343,20 @@ class CGDescriptor(CGThing):
                         cgThings.append(specializedMethod)
                         if m.returnsPromise():
                             cgThings.append(CGMethodPromiseWrapper(descriptor, specializedMethod))
                         cgThings.append(CGMemberJITInfo(descriptor, m))
                         if props.isCrossOriginMethod:
                             crossOriginMethods.add(m.identifier.name)
                         if m.getExtendedAttribute("MethodIdentityTestable"):
                             cgThings.append(CGMethodIdentityTest(descriptor, m))
+            # If we've hit the maplike/setlike member itself, go ahead and
+            # generate its convenience functions.
+            elif m.isMaplikeOrSetlike():
+                cgThings.append(CGMaplikeOrSetlikeHelperGenerator(descriptor, m))
             elif m.isAttr():
                 if m.stringifier:
                     raise TypeError("Stringifier attributes not supported yet. "
                                     "See bug 824857.\n"
                                     "%s" % m.location)
                 if m.isStatic():
                     assert descriptor.interface.hasInterfaceObject()
                     cgThings.append(CGStaticGetter(descriptor, m))
@@ -12433,16 +12522,25 @@ class CGForwardDeclarations(CGWrapper):
             elif t.isMozMap():
                 forwardDeclareForType(t.inner, workerness)
             # Don't need to do anything for void, primitive, string, any or object.
             # There may be some other cases we are missing.
 
         # Needed for at least Wrap.
         for d in descriptors:
             builder.add(d.nativeType)
+            # If we're an interface and we have a maplike/setlike declaration,
+            # we'll have helper functions exposed to the native side of our
+            # bindings, which will need to show up in the header. If either of
+            # our key/value types are interfaces, they'll be passed as
+            # arguments to helper functions, and they'll need to be forward
+            # declared in the header.
+            if d.interface.maplikeOrSetlike:
+                forwardDeclareForType(d.interface.maplikeOrSetlike.keyType)
+                forwardDeclareForType(d.interface.maplikeOrSetlike.valueType)
 
         # We just about always need NativePropertyHooks
         builder.addInMozillaDom("NativePropertyHooks", isStruct=True)
         builder.addInMozillaDom("ProtoAndIfaceCache")
         # Add the atoms cache type, even if we don't need it.
         for d in descriptors:
             builder.add(d.nativeType + "Atoms", isStruct=True)
 
@@ -14065,18 +14163,22 @@ class FakeMember():
         # Claim to be a [NewObject] so we can avoid the "return a raw pointer"
         # comments CGNativeMember codegen would otherwise stick in.
         if name == "NewObject":
             return True
         return None
 
 
 class CallbackMember(CGNativeMember):
+    # XXXbz It's OK to use CallbackPreserveColor for wrapScope because
+    # CallSetup already handled the unmark-gray bits for us. we don't have
+    # anything better to use for 'obj', really...
     def __init__(self, sig, name, descriptorProvider, needThisHandling,
-                 rethrowContentException=False, typedArraysAreStructs=False):
+                 rethrowContentException=False, typedArraysAreStructs=False,
+                 wrapScope='CallbackPreserveColor()'):
         """
         needThisHandling is True if we need to be able to accept a specified
         thisObj, False otherwise.
         """
         assert not rethrowContentException or not needThisHandling
 
         self.retvalType = sig[0]
         self.originalSig = sig
@@ -14090,16 +14192,18 @@ class CallbackMember(CGNativeMember):
                                     (self.argCount, lastArg.identifier.name))
             else:
                 self.argCountStr = "%d" % self.argCount
         self.needThisHandling = needThisHandling
         # If needThisHandling, we generate ourselves as private and the caller
         # will handle generating public versions that handle the "this" stuff.
         visibility = "private" if needThisHandling else "public"
         self.rethrowContentException = rethrowContentException
+
+        self.wrapScope = wrapScope
         # We don't care, for callback codegen, whether our original member was
         # a method or attribute or whatnot.  Just always pass FakeMember()
         # here.
         CGNativeMember.__init__(self, descriptorProvider, FakeMember(),
                                 name, (self.retvalType, args),
                                 extendedAttrs={},
                                 passJSBitsAsNeeded=False,
                                 visibility=visibility,
@@ -14209,20 +14313,17 @@ class CallbackMember(CGNativeMember):
         try:
             conversion = prepend + wrapForType(
                 arg.type, self.descriptorProvider,
                 {
                     'result': result,
                     'successCode': "continue;\n" if arg.variadic else "break;\n",
                     'jsvalRef': "argv[%s]" % jsvalIndex,
                     'jsvalHandle': "argv[%s]" % jsvalIndex,
-                    # XXXbz we don't have anything better to use for 'obj',
-                    # really...  It's OK to use CallbackPreserveColor because
-                    # CallSetup already handled the unmark-gray bits for us.
-                    'obj': 'CallbackPreserveColor()',
+                    'obj': self.wrapScope,
                     'returnsNewObject': False,
                     'exceptionCode': self.exceptionCode,
                     'typedArraysAreStructs': self.typedArraysAreStructs
                 })
         except MethodNotNewObjectError as err:
             raise TypeError("%s being passed as an argument to %s but is not "
                             "wrapper cached, so can't be reliably converted to "
                             "a JS object." %
@@ -14541,16 +14642,507 @@ class CGJSImplInitOperation(CallbackOper
         assert sig in descriptor.interface.ctor().signatures()
         CallbackOperationBase.__init__(self, (BuiltinTypes[IDLBuiltinType.Types.void], sig[1]),
                                        "__init", "__Init", descriptor, False, True)
 
     def getPrettyName(self):
         return "__init"
 
 
+def getMaplikeOrSetlikeErrorReturn(helperImpl):
+    """
+    Generate return values based on whether a maplike or setlike generated
+    method is an interface method (which returns bool) or a helper function
+    (which uses ErrorResult).
+    """
+    if helperImpl:
+        return dedent(
+            """
+            aRv.Throw(NS_ERROR_UNEXPECTED);
+            return%s;
+            """ % helperImpl.getDefaultRetval())
+    return "return false;\n"
+
+
+def getMaplikeOrSetlikeBackingObject(descriptor, maplikeOrSetlike, helperImpl=None):
+    """
+    Generate code to get/create a JS backing object for a maplike/setlike
+    declaration from the declaration slot.
+    """
+    func_prefix = maplikeOrSetlike.maplikeOrSetlikeType.title()
+    ret = fill(
+        """
+        JS::Rooted<JSObject*> backingObj(cx);
+        bool created = false;
+        if (!Get${func_prefix}BackingObject(cx, obj, ${slot}, &backingObj, &created)) {
+          $*{errorReturn}
+        }
+        if (created) {
+          PreserveWrapper<${selfType}>(self);
+        }
+        """,
+        slot=memberReservedSlot(maplikeOrSetlike),
+        func_prefix=func_prefix,
+        errorReturn=getMaplikeOrSetlikeErrorReturn(helperImpl),
+        selfType=descriptor.nativeType)
+    return ret
+
+
+def getMaplikeOrSetlikeSizeGetterBody(descriptor, attr):
+    """
+    Creates the body for the size getter method of maplike/setlike interfaces.
+    """
+    # We should only have one declaration attribute currently
+    assert attr.identifier.name == "size"
+    assert attr.isMaplikeOrSetlikeAttr()
+    return fill(
+        """
+        $*{getBackingObj}
+        uint32_t result = JS::${funcPrefix}Size(cx, backingObj);
+        MOZ_ASSERT(!JS_IsExceptionPending(cx));
+        args.rval().setNumber(result);
+        return true;
+        """,
+        getBackingObj=getMaplikeOrSetlikeBackingObject(descriptor,
+                                                       attr.maplikeOrSetlike),
+        funcPrefix=attr.maplikeOrSetlike.prefix)
+
+
+class CGMaplikeOrSetlikeMethodGenerator(CGThing):
+    """
+    Creates methods for maplike/setlike interfaces. It is expected that all
+    methods will be have a maplike/setlike object attached. Unwrapping/wrapping
+    will be taken care of by the usual method generation machinery in
+    CGMethodCall/CGPerSignatureCall. Functionality is filled in here instead of
+    using CGCallGenerator.
+    """
+    def __init__(self, descriptor, maplikeOrSetlike, methodName,
+                 helperImpl=None):
+        CGThing.__init__(self)
+        # True if this will be the body of a C++ helper function.
+        self.helperImpl = helperImpl
+        self.descriptor = descriptor
+        self.maplikeOrSetlike = maplikeOrSetlike
+        self.cgRoot = CGList([])
+        impl_method_name = methodName
+        if impl_method_name[0] == "_":
+            # double underscore means this is a js-implemented chrome only rw
+            # function. Truncate the double underscore so calling the right
+            # underlying JSAPI function still works.
+            impl_method_name = impl_method_name[2:]
+        self.cgRoot.append(CGGeneric(
+            getMaplikeOrSetlikeBackingObject(self.descriptor,
+                                             self.maplikeOrSetlike,
+                                             self.helperImpl)))
+        self.returnStmt = getMaplikeOrSetlikeErrorReturn(self.helperImpl)
+
+        # Generates required code for the method. Method descriptions included
+        # in definitions below. Throw if we don't have a method to fill in what
+        # we're looking for.
+        try:
+            methodGenerator = getattr(self, impl_method_name)
+        except AttributeError:
+            raise TypeError("Missing %s method definition '%s'" %
+                            (self.maplikeOrSetlike.maplikeOrSetlikeType,
+                             methodName))
+        # Method generator returns tuple, containing:
+        #
+        # - a list of CGThings representing setup code for preparing to call
+        #   the JS API function
+        # - a list of arguments needed for the JS API function we're calling
+        # - list of code CGThings needed for return value conversion.
+        (setupCode, arguments, setResult) = methodGenerator()
+
+        # Create the actual method call, and then wrap it with the code to
+        # return the value if needed.
+        funcName = (self.maplikeOrSetlike.prefix +
+                    MakeNativeName(impl_method_name))
+        # Append the list of setup code CGThings
+        self.cgRoot.append(CGList(setupCode))
+        # Create the JS API call
+        self.cgRoot.append(CGWrapper(
+            CGGeneric(fill(
+                """
+                if (!JS::${funcName}(${args})) {
+                  $*{errorReturn}
+                }
+                """,
+                funcName=funcName,
+                args=", ".join(["cx", "backingObj"] + arguments),
+                errorReturn=self.returnStmt))))
+        # Append result conversion
+        self.cgRoot.append(CGList(setResult))
+
+    def mergeTuples(self, a, b):
+        """
+        Expecting to take 2 tuples were all elements are lists, append the lists in
+        the second tuple to the lists in the first.
+        """
+        return tuple([x + y for x, y in zip(a, b)])
+
+    def appendArgConversion(self, name):
+        """
+        Generate code to convert arguments to JS::Values, so they can be
+        passed into JSAPI functions.
+        """
+        return CGGeneric(fill(
+            """
+            JS::Rooted<JS::Value> ${name}Val(cx);
+            if (!ToJSValue(cx, ${name}, &${name}Val)) {
+              $*{errorReturn}
+            }
+            """,
+            name=name,
+            errorReturn=self.returnStmt))
+
+    def appendKeyArgConversion(self):
+        """
+        Generates the key argument for methods. Helper functions will use
+        an AutoValueVector, while interface methods have seperate JS::Values.
+        """
+        if self.helperImpl:
+            return ([], ["argv[0]"], [])
+        return ([self.appendArgConversion("arg0")], ["arg0Val"], [])
+
+    def appendKeyAndValueArgConversion(self):
+        """
+        Generates arguments for methods that require a key and value. Helper
+        functions will use an AutoValueVector, while interface methods have
+        seperate JS::Values.
+        """
+        r = self.appendKeyArgConversion()
+        if self.helperImpl:
+            return self.mergeTuples(r, ([], ["argv[1]"], []))
+        return self.mergeTuples(r, ([self.appendArgConversion("arg1")],
+                                    ["arg1Val"],
+                                    []))
+
+    def appendIteratorResult(self):
+        """
+        Generate code to output JSObject* return values, needed for functions that
+        return iterators. Iterators cannot currently be wrapped via Xrays. If
+        something that would return an iterator is called via Xray, fail early.
+        """
+        # TODO: Bug 1173651 - Remove check once bug 1023984 is fixed.
+        code = CGGeneric(dedent(
+            """
+            // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
+            // after bug 1023984 is fixed.
+            if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
+              JS_ReportError(cx, "Xray wrapping of iterators not supported.");
+              return false;
+            }
+            JS::Rooted<JSObject*> result(cx);
+            JS::Rooted<JS::Value> v(cx);
+            """))
+        arguments = "&v"
+        setResult = CGGeneric(dedent(
+            """
+            result = &v.toObject();
+            """))
+        return ([code], [arguments], [setResult])
+
+    def appendSelfResult(self):
+        """
+        Generate code to return the interface object itself.
+        """
+        code = CGGeneric(dedent(
+            """
+            JS::Rooted<JSObject*> result(cx);
+            """))
+        setResult = CGGeneric(dedent(
+            """
+            result = obj;
+            """))
+        return ([code], [], [setResult])
+
+    def appendBoolResult(self):
+        if self.helperImpl:
+            return ([CGGeneric()], ["&aRetVal"], [])
+        return ([CGGeneric("bool result;\n")], ["&result"], [])
+
+    def forEach(self):
+        """
+        void forEach(callback c, any thisval);
+
+        ForEach takes a callback, and a possible value to use as 'this'. The
+        callback needs to take value, key, and the interface object
+        implementing maplike/setlike. In order to make sure that the third arg
+        is our interface object instead of the map/set backing object, we
+        create a js function with the callback and original object in its
+        storage slots, then use a helper function in BindingUtils to make sure
+        the callback is called correctly.
+        """
+        assert(not self.helperImpl)
+        code = [CGGeneric(dedent(
+            """
+            // Create a wrapper function.
+            JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
+            if (!func) {
+              return false;
+            }
+            JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
+            JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
+            js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
+                                          JS::ObjectValue(*arg0));
+            js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
+                                          JS::ObjectValue(*obj));
+            """))]
+        arguments = ["funcVal", "arg1"]
+        return (code, arguments, [])
+
+    def set(self):
+        """
+        object set(key, value);
+
+        Maplike only function, takes key and sets value to it, returns
+        interface object unless being called from a C++ helper.
+        """
+        assert self.maplikeOrSetlike.isMaplike()
+        r = self.appendKeyAndValueArgConversion()
+        if self.helperImpl:
+            return r
+        return self.mergeTuples(r, self.appendSelfResult())
+
+    def add(self):
+        """
+        object add(value);
+
+        Setlike only function, adds value to set, returns interface object
+        unless being called from a C++ helper
+        """
+        assert self.maplikeOrSetlike.isSetlike()
+        r = self.appendKeyArgConversion()
+        if self.helperImpl:
+            return r
+        return self.mergeTuples(r, self.appendSelfResult())
+
+    def get(self):
+        """
+        type? get(key);
+
+        Retrieves a value from a backing object based on the key. Returns value
+        if key is in backing object, undefined otherwise.
+        """
+        assert self.maplikeOrSetlike.isMaplike()
+        r = self.appendKeyArgConversion()
+        code = [CGGeneric(dedent(
+             """
+             JS::Rooted<JS::Value> result(cx);
+             """))]
+        arguments = ["&result"]
+        return self.mergeTuples(r, (code, arguments, []))
+
+    def has(self):
+        """
+        bool has(key);
+
+        Check if an entry exists in the backing object. Returns true if value
+        exists in backing object, false otherwise.
+        """
+        return self.mergeTuples(self.appendKeyArgConversion(),
+                                self.appendBoolResult())
+
+    def keys(self):
+        """
+        object keys();
+
+        Returns new object iterator with all keys from backing object.
+        """
+        return self.appendIteratorResult()
+
+    def values(self):
+        """
+        object values();
+
+        Returns new object iterator with all values from backing object.
+        """
+        return self.appendIteratorResult()
+
+    def entries(self):
+        """
+        object entries();
+
+        Returns new object iterator with all keys and values from backing
+        object. Keys will be null for set.
+        """
+        return self.appendIteratorResult()
+
+    def clear(self):
+        """
+        void clear();
+
+        Removes all entries from map/set.
+        """
+        return ([], [], [])
+
+    def delete(self):
+        """
+        bool delete(key);
+
+        Deletes an entry from the backing object. Returns true if value existed
+        in backing object, false otherwise.
+        """
+        return self.mergeTuples(self.appendKeyArgConversion(),
+                                self.appendBoolResult())
+
+    def define(self):
+        return self.cgRoot.define()
+
+
+class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
+    """
+    Generates code to allow C++ to perform operations on backing objects. Gets
+    a context from the binding wrapper, turns arguments into JS::Values (via
+    CallbackMember/CGNativeMember argument conversion), then uses
+    CGMaplikeOrSetlikeMethodGenerator to generate the body.
+
+    """
+
+    class HelperFunction(CGAbstractMethod):
+        """
+        Generates context retrieval code and rooted JSObject for interface for
+        CGMaplikeOrSetlikeMethodGenerator to use
+        """
+        def __init__(self, descriptor, name, args, code, needsBoolReturn=False):
+            self.code = code
+            CGAbstractMethod.__init__(self, descriptor, name,
+                                      "bool" if needsBoolReturn else "void",
+                                      args)
+
+        def definition_body(self):
+            return self.code
+
+    def __init__(self, descriptor, maplikeOrSetlike, name, needsKeyArg=False,
+                 needsValueArg=False, needsBoolReturn=False):
+        args = []
+        self.maplikeOrSetlike = maplikeOrSetlike
+        self.needsBoolReturn = needsBoolReturn
+        if needsKeyArg:
+            args.append(FakeArgument(maplikeOrSetlike.keyType, None, 'aKey'))
+        if needsValueArg:
+            assert needsKeyArg
+            args.append(FakeArgument(maplikeOrSetlike.valueType, None, 'aValue'))
+        # Run CallbackMember init function to generate argument conversion code.
+        # wrapScope is set to 'obj' when generating maplike or setlike helper
+        # functions, as we don't have access to the CallbackPreserveColor
+        # method.
+        CallbackMember.__init__(self,
+                                [BuiltinTypes[IDLBuiltinType.Types.void], args],
+                                name, descriptor, False,
+                                wrapScope='obj')
+        # Wrap CallbackMember body code into a CGAbstractMethod to make
+        # generation easier.
+        self.implMethod = CGMaplikeOrSetlikeHelperFunctionGenerator.HelperFunction(
+            descriptor, name, self.args, self.body, needsBoolReturn)
+
+    def getCallSetup(self):
+        return dedent(
+            """
+            MOZ_ASSERT(self);
+            AutoJSAPI jsapi;
+            jsapi.Init();
+            jsapi.TakeOwnershipOfErrorReporting();
+            JSContext* cx = jsapi.cx();
+            JSAutoCompartment tempCompartment(cx, xpc::UnprivilegedJunkScope());
+            JS::Rooted<JS::Value> v(cx);
+            if(!ToJSValue(cx, self, &v)) {
+              aRv.Throw(NS_ERROR_UNEXPECTED);
+              return%s;
+            }
+            // This is a reflector, but due to trying to name things
+            // similarly across method generators, it's called obj here.
+            JS::Rooted<JSObject*> obj(cx);
+            obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtOuter = */ false);
+            JSAutoCompartment reflectorCompartment(cx, obj);
+            """ % self.getDefaultRetval())
+
+    def getArgs(self, returnType, argList):
+        # We don't need the context or the value. We'll generate those instead.
+        args = CGNativeMember.getArgs(self, returnType, argList)
+        # Prepend a pointer to the binding object onto the arguments
+        return [Argument(self.descriptorProvider.nativeType + "*", "self")] + args
+
+    def getResultConversion(self):
+        if self.needsBoolReturn:
+            return "return aRetVal;\n"
+        return "return;\n"
+
+    def getRvalDecl(self):
+        if self.needsBoolReturn:
+            return "bool aRetVal;\n"
+        return ""
+
+    def getArgcDecl(self):
+        # Don't need argc for anything.
+        return None
+
+    def getDefaultRetval(self):
+        if self.needsBoolReturn:
+            return " false"
+        return ""
+
+
+    def getCall(self):
+        return CGMaplikeOrSetlikeMethodGenerator(self.descriptorProvider,
+                                                 self.maplikeOrSetlike,
+                                                 self.name.lower(),
+                                                 helperImpl=self).define()
+
+    def getPrettyName(self):
+        return self.name
+
+    def declare(self):
+        return self.implMethod.declare()
+
+    def define(self):
+        return self.implMethod.define()
+
+
+class CGMaplikeOrSetlikeHelperGenerator(CGNamespace):
+    """
+    Declares and defines convenience methods for accessing backing objects on
+    setlike/maplike interface. Generates function signatures, un/packs
+    backing objects from slot, etc.
+    """
+    def __init__(self, descriptor, maplikeOrSetlike):
+        self.descriptor = descriptor
+        self.maplikeOrSetlike = maplikeOrSetlike
+        self.namespace = "%sHelpers" % (self.maplikeOrSetlike.maplikeOrSetlikeType.title())
+        self.helpers = [
+            CGMaplikeOrSetlikeHelperFunctionGenerator(descriptor,
+                                                      maplikeOrSetlike,
+                                                      "Clear"),
+            CGMaplikeOrSetlikeHelperFunctionGenerator(descriptor,
+                                                      maplikeOrSetlike,
+                                                      "Delete",
+                                                      needsKeyArg=True,
+                                                      needsBoolReturn=True),
+            CGMaplikeOrSetlikeHelperFunctionGenerator(descriptor,
+                                                      maplikeOrSetlike,
+                                                      "Has",
+                                                      needsKeyArg=True,
+                                                      needsBoolReturn=True)]
+        if self.maplikeOrSetlike.isMaplike():
+            self.helpers.append(
+                CGMaplikeOrSetlikeHelperFunctionGenerator(descriptor,
+                                                          maplikeOrSetlike,
+                                                          "Set",
+                                                          needsKeyArg=True,
+                                                          needsValueArg=True))
+        else:
+            assert(self.maplikeOrSetlike.isSetlike())
+            self.helpers.append(
+                CGMaplikeOrSetlikeHelperFunctionGenerator(descriptor,
+                                                          maplikeOrSetlike,
+                                                          "Add",
+                                                          needsKeyArg=True))
+        CGNamespace.__init__(self, self.namespace, CGList(self.helpers))
+
+
 class GlobalGenRoots():
     """
     Roots for global codegen.
 
     To generate code, call the method associated with the target, and then
     call the appropriate define/declare method.
     """
 
--- a/dom/bindings/ToJSValue.h
+++ b/dom/bindings/ToJSValue.h
@@ -204,16 +204,25 @@ template <typename T>
 MOZ_WARN_UNUSED_RESULT bool
 ToJSValue(JSContext* aCx,
           const nsRefPtr<T>& aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
   return ToJSValue(aCx, *aArgument.get(), aValue);
 }
 
+template <typename T>
+MOZ_WARN_UNUSED_RESULT bool
+ToJSValue(JSContext* aCx,
+          const NonNull<T>& aArgument,
+          JS::MutableHandle<JS::Value> aValue)
+{
+  return ToJSValue(aCx, *aArgument.get(), aValue);
+}
+
 // Accept WebIDL dictionaries
 template <class T>
 MOZ_WARN_UNUSED_RESULT
 typename EnableIf<IsBaseOf<DictionaryBase, T>::value, bool>::Type
 ToJSValue(JSContext* aCx,
           const T& aArgument,
           JS::MutableHandle<JS::Value> aValue)
 {
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -79,16 +79,35 @@ UNIFIED_SOURCES += [
     'Exceptions.cpp',
     'ToJSValue.cpp',
 ]
 
 SOURCES += [
     'StructuredClone.cpp',
 ]
 
+# Tests for maplike and setlike require bindings to be built, which means they
+# must be included in libxul. This breaks the "no test classes are exported"
+# rule stated in the test/ directory, but it's the only way this will work.
+# Test classes are only built in debug mode, and all tests requiring use of
+# them are only run in debug mode.
+if CONFIG['MOZ_DEBUG']:
+    EXPORTS.mozilla.dom += [
+        "test/TestInterfaceMaplike.h",
+        "test/TestInterfaceMaplikeObject.h",
+        "test/TestInterfaceSetlike.h",
+        "test/TestInterfaceSetlikeNode.h"
+        ]
+    UNIFIED_SOURCES += [
+        "test/TestInterfaceMaplike.cpp",
+        "test/TestInterfaceMaplikeObject.cpp",
+        "test/TestInterfaceSetlike.cpp",
+        "test/TestInterfaceSetlikeNode.cpp",
+        ]
+
 include('/ipc/chromium/chromium-config.mozbuild')
 
 if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']:
     LOCAL_INCLUDES += [
         '/dom/system/gonk',
     ]
 
 if CONFIG['MOZ_B2G_BT_API_V1']:
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -614,16 +614,17 @@ class IDLInterface(IDLObjectWithScope, I
         assert isinstance(name, IDLUnresolvedIdentifier)
         assert isKnownNonPartial or not parent
         assert isKnownNonPartial or len(members) == 0
 
         self.parent = None
         self._callback = False
         self._finished = False
         self.members = []
+        self.maplikeOrSetlike = None
         self._partialInterfaces = []
         self._extendedAttrDict = {}
         # namedConstructors needs deterministic ordering because bindings code
         # outputs the constructs in the order that namedConstructors enumerates
         # them.
         self.namedConstructors = list()
         self.implementedInterfaces = set()
         self._consequential = False
@@ -687,16 +688,37 @@ class IDLInterface(IDLObjectWithScope, I
         IDLExposureMixins.finish(self, scope)
 
         # Now go ahead and merge in our partial interfaces.
         for partial in self._partialInterfaces:
             partial.finish(scope)
             self.addExtendedAttributes(partial.propagatedExtendedAttrs)
             self.members.extend(partial.members)
 
+        # Generate maplike/setlike interface members. Since generated members
+        # need to be treated like regular interface members, do this before
+        # things like exposure setting.
+        for member in self.members:
+            if member.isMaplikeOrSetlike():
+                # Check that we only have one interface declaration (currently
+                # there can only be one maplike/setlike declaration per
+                # interface)
+                if self.maplikeOrSetlike:
+                    raise WebIDLError("%s declaration used on "
+                                      "interface that already has %s "
+                                      "declaration" %
+                                      (member.maplikeOrSetlikeType,
+                                       self.maplikeOrSetlike.maplikeOrSetlikeType),
+                                      [self.maplikeOrSetlike.location,
+                                       member.location])
+                self.maplikeOrSetlike = member
+                # If we've got a maplike or setlike declaration, we'll be building all of
+                # our required methods in Codegen. Generate members now.
+                self.maplikeOrSetlike.expand(self.members, self.isJSImplemented())
+
         # Now that we've merged in our partial interfaces, set the
         # _exposureGlobalNames on any members that don't have it set yet.  Note
         # that any partial interfaces that had [Exposed] set have already set up
         # _exposureGlobalNames on all the members coming from them, so this is
         # just implementing the "members default to interface that defined them"
         # and "partial interfaces default to interface they're a partial for"
         # rules from the spec.
         for m in self.members:
@@ -716,17 +738,16 @@ class IDLInterface(IDLObjectWithScope, I
         assert not parent or isinstance(parent, IDLInterface)
 
         self.parent = parent
 
         assert iter(self.members)
 
         if self.parent:
             self.parent.finish(scope)
-
             self.parent._hasChildInterfaces = True
 
             self.totalMembersInSlots = self.parent.totalMembersInSlots
 
             # Interfaces with [Global] or [PrimaryGlobal] must not
             # have anything inherit from them
             if (self.parent.getExtendedAttribute("Global") or
                 self.parent.getExtendedAttribute("PrimaryGlobal")):
@@ -834,29 +855,49 @@ class IDLInterface(IDLObjectWithScope, I
             # Flag the interface as being someone's consequential interface
             iface.setIsConsequentialInterfaceOf(self)
             # Verify that we're not exposed somewhere where iface is not exposed
             if not self.exposureSet.issubset(iface.exposureSet):
                 raise WebIDLError("Interface %s is exposed in globals where its "
                                   "consequential interface %s is not exposed." %
                                   (self.identifier.name, iface.identifier.name),
                                   [self.location, iface.location])
+
+            # If we have a maplike or setlike, and the consequential interface
+            # also does, throw an error.
+            if iface.maplikeOrSetlike and self.maplikeOrSetlike:
+                raise WebIDLError("Maplike/setlike interface %s cannot have "
+                                  "maplike/setlike interface %s as a "
+                                  "consequential interface" %
+                                  (self.identifier.name,
+                                   iface.identifier.name),
+                                  [self.maplikeOrSetlike.location,
+                                   iface.maplikeOrSetlike.location])
             additionalMembers = iface.originalMembers;
             for additionalMember in additionalMembers:
                 for member in self.members:
                     if additionalMember.identifier.name == member.identifier.name:
                         raise WebIDLError(
                             "Multiple definitions of %s on %s coming from 'implements' statements" %
                             (member.identifier.name, self),
                             [additionalMember.location, member.location])
             self.members.extend(additionalMembers)
             iface.interfacesImplementingSelf.add(self)
 
         for ancestor in self.getInheritedInterfaces():
             ancestor.interfacesBasedOnSelf.add(self)
+            if (ancestor.maplikeOrSetlike is not None and
+                self.maplikeOrSetlike is not None):
+                raise WebIDLError("Cannot have maplike/setlike on %s that "
+                                  "inherits %s, which is already "
+                                  "maplike/setlike" %
+                                  (self.identifier.name,
+                                   ancestor.identifier.name),
+                                  [self.maplikeOrSetlike.location,
+                                   ancestor.maplikeOrSetlike.location])
             for ancestorConsequential in ancestor.getConsequentialInterfaces():
                 ancestorConsequential.interfacesBasedOnSelf.add(self)
 
         # Deal with interfaces marked [Unforgeable], now that we have our full
         # member list, except unforgeables pulled in from parents.  We want to
         # do this before we set "originatingInterface" on our unforgeable
         # members.
         if self.getExtendedAttribute("Unforgeable"):
@@ -883,22 +924,24 @@ class IDLInterface(IDLObjectWithScope, I
                                       [self.location, m.location])
 
         for member in self.members:
             if ((member.isAttr() or member.isMethod()) and
                 member.isUnforgeable() and
                 not hasattr(member, "originatingInterface")):
                 member.originatingInterface = self
 
-        # Compute slot indices for our members before we pull in
-        # unforgeable members from our parent.
+        # Compute slot indices for our members before we pull in unforgeable
+        # members from our parent. Also, maplike/setlike declarations get a
+        # slot to hold their backing object.
         for member in self.members:
-            if (member.isAttr() and
-                (member.getExtendedAttribute("StoreInSlot") or
-                 member.getExtendedAttribute("Cached"))):
+            if ((member.isAttr() and
+                 (member.getExtendedAttribute("StoreInSlot") or
+                  member.getExtendedAttribute("Cached"))) or
+                member.isMaplikeOrSetlike()):
                 member.slotIndex = self.totalMembersInSlots
                 self.totalMembersInSlots += 1
                 if member.getExtendedAttribute("StoreInSlot"):
                     self._ownMembersInSlots += 1
 
         if self.parent:
             # Make sure we don't shadow any of the [Unforgeable] attributes on
             # our ancestor interfaces.  We don't have to worry about
@@ -925,16 +968,28 @@ class IDLInterface(IDLObjectWithScope, I
                 # And now just stick it in our members, since we won't be
                 # inheriting this down the proto chain.  If we really cared we
                 # could try to do something where we set up the unforgeable
                 # attributes/methods of ancestor interfaces, with their
                 # corresponding getters, on our interface, but that gets pretty
                 # complicated and seems unnecessary.
                 self.members.append(unforgeableMember)
 
+        # At this point, we have all of our members. If the current interface
+        # uses maplike/setlike, check for collisions anywhere in the current
+        # interface or higher in the inheritance chain.
+        if self.maplikeOrSetlike:
+            testInterface = self
+            isAncestor = False
+            while testInterface:
+                self.maplikeOrSetlike.checkCollisions(testInterface.members,
+                                                      isAncestor)
+                isAncestor = True
+                testInterface = testInterface.parent
+
         # Ensure that there's at most one of each {named,indexed}
         # {getter,setter,creator,deleter}, at most one stringifier,
         # and at most one legacycaller.  Note that this last is not
         # quite per spec, but in practice no one overloads
         # legacycallers.
         specialMembersSeen = {}
         for member in self.members:
             if not member.isMethod():
@@ -3237,17 +3292,18 @@ class IDLUndefinedValue(IDLObject):
     def _getDependentObjects(self):
         return set()
 
 class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
 
     Tags = enum(
         'Const',
         'Attr',
-        'Method'
+        'Method',
+        'MaplikeOrSetlike'
     )
 
     Special = enum(
         'Static',
         'Stringifier'
     )
 
     AffectsValues = ("Nothing", "Everything")
@@ -3263,16 +3319,19 @@ class IDLInterfaceMember(IDLObjectWithId
         return self.tag == IDLInterfaceMember.Tags.Method
 
     def isAttr(self):
         return self.tag == IDLInterfaceMember.Tags.Attr
 
     def isConst(self):
         return self.tag == IDLInterfaceMember.Tags.Const
 
+    def isMaplikeOrSetlike(self):
+        return self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike
+
     def addExtendedAttributes(self, attrs):
         for attr in attrs:
             self.handleExtendedAttribute(attr)
             attrlist = attr.listValue()
             self._extendedAttrDict[attr.identifier()] = attrlist if len(attrlist) else True
 
     def handleExtendedAttribute(self, attr):
         pass
@@ -3335,16 +3394,266 @@ class IDLInterfaceMember(IDLObjectWithId
         self.affects = affects
 
     def _addAlias(self, alias):
         if alias in self.aliases:
             raise WebIDLError("Duplicate [Alias=%s] on attribute" % alias,
                               [self.location])
         self.aliases.append(alias)
 
+
+# MaplikeOrSetlike adds a trait to an interface, like map or iteration
+# functions. To handle them while still getting all of the generated binding
+# code taken care of, we treat them as macros that are expanded into members
+# based on parsed values.
+class IDLMaplikeOrSetlike(IDLInterfaceMember):
+
+    MaplikeOrSetlikeTypes = enum(
+        'maplike',
+        'setlike'
+    )
+
+    def __init__(self, location, identifier, maplikeOrSetlikeType,
+                 readonly, keyType, valueType):
+        IDLInterfaceMember.__init__(self, location, identifier,
+                                    IDLInterfaceMember.Tags.MaplikeOrSetlike)
+
+        assert isinstance(keyType, IDLType)
+        assert isinstance(valueType, IDLType)
+        self.maplikeOrSetlikeType = maplikeOrSetlikeType
+        self.readonly = readonly
+        self.keyType = keyType
+        self.valueType = valueType
+        self.slotIndex = None
+        self.disallowedMemberNames = []
+        self.disallowedNonMethodNames = []
+
+        # When generating JSAPI access code, we need to know the backing object
+        # type prefix to create the correct function. Generate here for reuse.
+        if self.isMaplike():
+            self.prefix = 'Map'
+        elif self.isSetlike():
+            self.prefix = 'Set'
+
+    def __str__(self):
+        return "declared '%s' with key '%s'" % (self.maplikeOrSetlikeType, self.keyType)
+
+    def isMaplike(self):
+        return self.maplikeOrSetlikeType == "maplike"
+
+    def isSetlike(self):
+        return self.maplikeOrSetlikeType == "setlike"
+
+    def checkCollisions(self, members, isAncestor):
+        for member in members:
+            # Check that there are no disallowed members
+            if (member.identifier.name in self.disallowedMemberNames and
+                not ((member.isMethod() and member.isMaplikeOrSetlikeMethod()) or
+                     (member.isAttr() and member.isMaplikeOrSetlikeAttr()))):
+                raise WebIDLError("Member '%s' conflicts "
+                                  "with reserved %s name." %
+                                  (member.identifier.name,
+                                   self.maplikeOrSetlikeType),
+                                  [self.location, member.location])
+            # Check that there are no disallowed non-method members
+            if (isAncestor or (member.isAttr() or member.isConst()) and
+                member.identifier.name in self.disallowedNonMethodNames):
+                raise WebIDLError("Member '%s' conflicts "
+                                  "with reserved %s method." %
+                                  (member.identifier.name,
+                                   self.maplikeOrSetlikeType),
+                                  [self.location, member.location])
+
+    def expand(self, members, isJSImplemented):
+        """
+        In order to take advantage of all of the method machinery in Codegen,
+        we generate our functions as if they were part of the interface
+        specification during parsing.
+        """
+        def addMethod(name, allowExistingOperations, returnType, args=[],
+                      chromeOnly=False, isPure=False, affectsNothing=False):
+            """
+            Create an IDLMethod based on the parameters passed in. chromeOnly is only
+            True for read-only js implemented classes, to implement underscore
+            prefixed convenience functions would otherwise not be available,
+            unlike the case of C++ bindings. isPure is only True for
+            idempotent functions, so it is not valid for things like keys,
+            values, etc. that return a new object every time.
+
+            """
+
+            # Only add name to lists for collision checks if it's not chrome
+            # only.
+            if chromeOnly:
+                name = "__" + name
+            else:
+                if not allowExistingOperations:
+                    self.disallowedMemberNames.append(name)
+                else:
+                    self.disallowedNonMethodNames.append(name)
+
+            # If allowExistingOperations is True, and another operation exists
+            # with the same name as the one we're trying to add, don't add the
+            # maplike/setlike operation. However, if the operation is static,
+            # then fail by way of creating the function, which will cause a
+            # naming conflict, per the spec.
+            if allowExistingOperations:
+                for m in members:
+                    if m.identifier.name == name and m.isMethod() and not m.isStatic():
+                        return
+
+            method = IDLMethod(self.location,
+                               IDLUnresolvedIdentifier(self.location, name, allowDoubleUnderscore=chromeOnly),
+                               returnType, args, maplikeOrSetlike=self)
+
+            # We need to be able to throw from declaration methods
+            method.addExtendedAttributes(
+                [IDLExtendedAttribute(self.location, ("Throws",))])
+            if chromeOnly:
+                method.addExtendedAttributes(
+                    [IDLExtendedAttribute(self.location, ("ChromeOnly",))])
+            if isPure:
+                method.addExtendedAttributes(
+                    [IDLExtendedAttribute(self.location, ("Pure",))])
+            # Following attributes are used for keys/values/entries. Can't mark
+            # them pure, since they return a new object each time they are run.
+            if affectsNothing:
+                method.addExtendedAttributes(
+                    [IDLExtendedAttribute(self.location, ("DependsOn", "Everything")),
+                     IDLExtendedAttribute(self.location, ("Affects", "Nothing"))])
+            members.append(method)
+
+        # Both maplike and setlike have a size attribute
+        members.append(IDLAttribute(self.location,
+                                    IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), "size"),
+                                    BuiltinTypes[IDLBuiltinType.Types.unsigned_long],
+                                    True,
+                                    maplikeOrSetlike=self))
+        self.reserved_ro_names = ["size"]
+
+        # object entries()
+        addMethod("entries", False, BuiltinTypes[IDLBuiltinType.Types.object],
+                  affectsNothing=True)
+        # object keys()
+        addMethod("keys", False, BuiltinTypes[IDLBuiltinType.Types.object],
+                  affectsNothing=True)
+        # object values()
+        addMethod("values", False, BuiltinTypes[IDLBuiltinType.Types.object],
+                  affectsNothing=True)
+
+        # void forEach(callback(valueType, keyType), thisVal)
+        foreachArguments = [IDLArgument(self.location,
+                                         IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+                                                                 "callback"),
+                                         BuiltinTypes[IDLBuiltinType.Types.object]),
+                             IDLArgument(self.location,
+                                         IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+                                                                 "thisArg"),
+                                         BuiltinTypes[IDLBuiltinType.Types.any],
+                                         optional=True)]
+        addMethod("forEach", False, BuiltinTypes[IDLBuiltinType.Types.void],
+                  foreachArguments)
+
+        def getKeyArg():
+            return IDLArgument(self.location,
+                               IDLUnresolvedIdentifier(self.location, "key"),
+                               self.keyType)
+
+        # boolean has(keyType key)
+        addMethod("has", False, BuiltinTypes[IDLBuiltinType.Types.boolean],
+                  [getKeyArg()], isPure=True)
+
+        if not self.readonly:
+            # void clear()
+            addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void],
+                      [])
+            # boolean delete(keyType key)
+            addMethod("delete", True,
+                      BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()])
+
+        # Always generate underscored functions (e.g. __add, __clear) for js
+        # implemented interfaces as convenience functions.
+        if isJSImplemented:
+            # void clear()
+            addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void],
+                      [], chromeOnly=True)
+            # boolean delete(keyType key)
+            addMethod("delete", True,
+                      BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()],
+                      chromeOnly=True)
+
+        if self.isSetlike():
+            if not self.readonly:
+                # Add returns the set object it just added to.
+                # object add(keyType key)
+
+                addMethod("add", True,
+                          BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()])
+            if isJSImplemented:
+                addMethod("add", True,
+                          BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()],
+                          chromeOnly=True)
+            return
+
+        # If we get this far, we're a maplike declaration.
+
+        # valueType get(keyType key)
+        #
+        # Note that instead of the value type, we're using any here. The
+        # validity checks should happen as things are inserted into the map,
+        # and using any as the return type makes code generation much simpler.
+        #
+        # TODO: Bug 1155340 may change this to use specific type to provide
+        # more info to JIT.
+        addMethod("get", False, BuiltinTypes[IDLBuiltinType.Types.any],
+                  [getKeyArg()], isPure=True)
+
+        def getValueArg():
+            return IDLArgument(self.location,
+                               IDLUnresolvedIdentifier(self.location, "value"),
+                               self.valueType)
+
+
+        if not self.readonly:
+            addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object],
+                      [getKeyArg(), getValueArg()])
+        if isJSImplemented:
+            addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object],
+                      [getKeyArg(), getValueArg()], chromeOnly=True)
+
+    def resolve(self, parentScope):
+        self.keyType.resolveType(parentScope)
+        self.valueType.resolveType(parentScope)
+
+    def finish(self, scope):
+        IDLInterfaceMember.finish(self, scope)
+        if not self.keyType.isComplete():
+            t = self.keyType.complete(scope)
+
+            assert not isinstance(t, IDLUnresolvedType)
+            assert not isinstance(t, IDLTypedefType)
+            assert not isinstance(t.name, IDLUnresolvedIdentifier)
+            self.keyType = t
+        if not self.valueType.isComplete():
+            t = self.valueType.complete(scope)
+
+            assert not isinstance(t, IDLUnresolvedType)
+            assert not isinstance(t, IDLTypedefType)
+            assert not isinstance(t.name, IDLUnresolvedIdentifier)
+            self.valueType = t
+
+    def validate(self):
+        IDLInterfaceMember.validate(self)
+
+    def handleExtendedAttribute(self, attr):
+        IDLInterfaceMember.handleExtendedAttribute(self, attr)
+
+    def _getDependentObjects(self):
+        return set([self.keyType, self.valueType])
+
 class IDLConst(IDLInterfaceMember):
     def __init__(self, location, identifier, type, value):
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Const)
 
         assert isinstance(type, IDLType)
         if type.isDictionary():
             raise WebIDLError("A constant cannot be of a dictionary type",
@@ -3398,31 +3707,33 @@ class IDLConst(IDLInterfaceMember):
                               [attr.location])
         IDLInterfaceMember.handleExtendedAttribute(self, attr)
 
     def _getDependentObjects(self):
         return set([self.type, self.value])
 
 class IDLAttribute(IDLInterfaceMember):
     def __init__(self, location, identifier, type, readonly, inherit=False,
-                 static=False, stringifier=False):
+                 static=False, stringifier=False, maplikeOrSetlike=None):
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Attr)
 
         assert isinstance(type, IDLType)
         self.type = type
         self.readonly = readonly
         self.inherit = inherit
         self.static = static
         self.lenientThis = False
         self._unforgeable = False
         self.stringifier = stringifier
         self.enforceRange = False
         self.clamp = False
         self.slotIndex = None
+        assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
+        self.maplikeOrSetlike = maplikeOrSetlike
         self.dependsOn = "Everything"
         self.affects = "Everything"
 
         if static and identifier.name == "prototype":
             raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
                               [location])
 
         if readonly and inherit:
@@ -3671,16 +3982,24 @@ class IDLAttribute(IDLInterfaceMember):
 
     def addExtendedAttributes(self, attrs):
         attrs = self.checkForStringHandlingExtendedAttributes(attrs)
         IDLInterfaceMember.addExtendedAttributes(self, attrs)
 
     def hasLenientThis(self):
         return self.lenientThis
 
+    def isMaplikeOrSetlikeAttr(self):
+        """
+        True if this attribute was generated from an interface with
+        maplike/setlike (e.g. this is the size attribute for
+        maplike/setlike)
+        """
+        return self.maplikeOrSetlike is not None
+
     def isUnforgeable(self):
         return self._unforgeable
 
     def _getDependentObjects(self):
         return set([self.type])
 
 class IDLArgument(IDLObjectWithIdentifier):
     def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
@@ -3909,17 +4228,18 @@ class IDLMethod(IDLInterfaceMember, IDLS
         'Neither',
         'Named',
         'Indexed'
     )
 
     def __init__(self, location, identifier, returnType, arguments,
                  static=False, getter=False, setter=False, creator=False,
                  deleter=False, specialType=NamedOrIndexed.Neither,
-                 legacycaller=False, stringifier=False, jsonifier=False):
+                 legacycaller=False, stringifier=False, jsonifier=False,
+                 maplikeOrSetlike=None):
         # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
         IDLInterfaceMember.__init__(self, location, identifier,
                                     IDLInterfaceMember.Tags.Method)
 
         self._hasOverloads = False
 
         assert isinstance(returnType, IDLType)
 
@@ -3937,16 +4257,18 @@ class IDLMethod(IDLInterfaceMember, IDLS
         assert isinstance(deleter, bool)
         self._deleter = deleter
         assert isinstance(legacycaller, bool)
         self._legacycaller = legacycaller
         assert isinstance(stringifier, bool)
         self._stringifier = stringifier
         assert isinstance(jsonifier, bool)
         self._jsonifier = jsonifier
+        assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
+        self.maplikeOrSetlike = maplikeOrSetlike
         self._specialType = specialType
         self._unforgeable = False
         self.dependsOn = "Everything"
         self.affects = "Everything"
         self.aliases = []
 
         if static and identifier.name == "prototype":
             raise WebIDLError("The identifier of a static operation must not be 'prototype'",
@@ -4018,21 +4340,36 @@ class IDLMethod(IDLInterfaceMember, IDLS
         return self._legacycaller
 
     def isStringifier(self):
         return self._stringifier
 
     def isJsonifier(self):
         return self._jsonifier
 
+    def isMaplikeOrSetlikeMethod(self):
+        """
+        True if this method was generated as part of a
+        maplike/setlike/etc interface (e.g. has/get methods)
+        """
+        return self.maplikeOrSetlike is not None
+
     def hasOverloads(self):
         return self._hasOverloads
 
     def isIdentifierLess(self):
-        return self.identifier.name[:2] == "__"
+        """
+        True if the method name started with __, and if the method is not a
+        maplike/setlike method. Interfaces with maplike/setlike will generate
+        methods starting with __ for chrome only backing object access in JS
+        implemented interfaces, so while these functions use what is considered
+        an non-identifier name, they actually DO have an identifier.
+        """
+        return (self.identifier.name[:2] == "__" and
+                not self.isMaplikeOrSetlikeMethod())
 
     def resolve(self, parentScope):
         assert isinstance(parentScope, IDLScope)
         IDLObjectWithIdentifier.resolve(self, parentScope)
         IDLScope.__init__(self, self.location, parentScope, self.identifier)
         for (returnType, arguments) in self.signatures():
             for argument in arguments:
                 argument.resolve(self)
@@ -4512,17 +4849,19 @@ class Tokenizer(object):
         "]": "RBRACKET",
         "?": "QUESTIONMARK",
         ",": "COMMA",
         "=": "EQUALS",
         "<": "LT",
         ">": "GT",
         "ArrayBuffer": "ARRAYBUFFER",
         "SharedArrayBuffer": "SHAREDARRAYBUFFER",
-        "or": "OR"
+        "or": "OR",
+        "maplike": "MAPLIKE",
+        "setlike": "SETLIKE"
         }
 
     tokens.extend(keywords.values())
 
     def t_error(self, t):
         raise WebIDLError("Unrecognized Input",
                [Location(lexer=self.lexer,
                          lineno=self.lexer.lineno,
@@ -4748,17 +5087,17 @@ class Parser(Tokenizer):
         """
             InterfaceMembers :
         """
         p[0] = []
 
     def p_InterfaceMember(self, p):
         """
             InterfaceMember : Const
-                            | AttributeOrOperation
+                            | AttributeOrOperationOrMaplikeOrSetlike
         """
         p[0] = p[1]
 
     def p_Dictionary(self, p):
         """
             Dictionary : DICTIONARY IDENTIFIER Inheritance LBRACE DictionaryMembers RBRACE SEMICOLON
         """
         location = self.getLocation(p, 1)
@@ -4963,39 +5302,76 @@ class Parser(Tokenizer):
         p[0] = True
 
     def p_BooleanLiteralFalse(self, p):
         """
             BooleanLiteral : FALSE
         """
         p[0] = False
 
-    def p_AttributeOrOperation(self, p):
-        """
-            AttributeOrOperation : Attribute
-                                 | Operation
+    def p_AttributeOrOperationOrMaplikeOrSetlike(self, p):
+        """
+            AttributeOrOperationOrMaplikeOrSetlike : Attribute
+                                                   | Maplike
+                                                   | Setlike
+                                                   | Operation
         """
         p[0] = p[1]
 
+    def p_Setlike(self, p):
+        """
+            Setlike : ReadOnly SETLIKE LT Type GT SEMICOLON
+        """
+        readonly = p[1]
+        maplikeOrSetlikeType = p[2]
+        location = self.getLocation(p, 2)
+        identifier = IDLUnresolvedIdentifier(location, "__setlike",
+                                             allowDoubleUnderscore=True)
+        keyType = p[4]
+        valueType = keyType
+        p[0] = IDLMaplikeOrSetlike(location, identifier, maplikeOrSetlikeType,
+                                   readonly, keyType, valueType)
+
+    def p_Maplike(self, p):
+        """
+            Maplike : ReadOnly MAPLIKE LT Type COMMA Type GT SEMICOLON
+        """
+        readonly = p[1]
+        maplikeOrSetlikeType = p[2]
+        location = self.getLocation(p, 2)
+        identifier = IDLUnresolvedIdentifier(location, "__maplike",
+                                             allowDoubleUnderscore=True)
+        keyType = p[4]
+        valueType = p[6]
+        p[0] = IDLMaplikeOrSetlike(location, identifier, maplikeOrSetlikeType,
+                                   readonly, keyType, valueType)
+
     def p_AttributeWithQualifier(self, p):
         """
             Attribute : Qualifier AttributeRest
         """
         static = IDLInterfaceMember.Special.Static in p[1]
         stringifier = IDLInterfaceMember.Special.Stringifier in p[1]
         (location, identifier, type, readonly) = p[2]
-        p[0] = IDLAttribute(location, identifier, type, readonly, static=static,
-                            stringifier=stringifier)
+        p[0] = IDLAttribute(location, identifier, type, readonly,
+                            static=static, stringifier=stringifier)
+
+    def p_AttributeInherited(self, p):
+        """
+            Attribute : INHERIT AttributeRest
+        """
+        (location, identifier, type, readonly) = p[2]
+        p[0] = IDLAttribute(location, identifier, type, readonly, inherit=True)
 
     def p_Attribute(self, p):
         """
-            Attribute : Inherit AttributeRest
-        """
-        (location, identifier, type, readonly) = p[2]
-        p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1])
+            Attribute : AttributeRest
+        """
+        (location, identifier, type, readonly) = p[1]
+        p[0] = IDLAttribute(location, identifier, type, readonly, inherit=False)
 
     def p_AttributeRest(self, p):
         """
             AttributeRest : ReadOnly ATTRIBUTE Type AttributeName SEMICOLON
         """
         location = self.getLocation(p, 2)
         readonly = p[1]
         t = p[3]
@@ -5009,28 +5385,16 @@ class Parser(Tokenizer):
         p[0] = True
 
     def p_ReadOnlyEmpty(self, p):
         """
             ReadOnly :
         """
         p[0] = False
 
-    def p_Inherit(self, p):
-        """
-            Inherit : INHERIT
-        """
-        p[0] = True
-
-    def p_InheritEmpty(self, p):
-        """
-            Inherit :
-        """
-        p[0] = False
-
     def p_Operation(self, p):
         """
             Operation : Qualifiers OperationRest
         """
         qualifiers = p[1]
 
         # Disallow duplicates in the qualifier set
         if not len(set(qualifiers)) == len(qualifiers):
@@ -5317,19 +5681,21 @@ class Parser(Tokenizer):
                          | DICTIONARY
                          | ENUM
                          | EXCEPTION
                          | GETTER
                          | IMPLEMENTS
                          | INHERIT
                          | INTERFACE
                          | LEGACYCALLER
+                         | MAPLIKE
                          | PARTIAL
                          | REQUIRED
                          | SERIALIZER
+                         | SETLIKE
                          | SETTER
                          | STATIC
                          | STRINGIFIER
                          | JSONIFIER
                          | TYPEDEF
                          | UNRESTRICTED
         """
         p[0] = p[1]
new file mode 100644
--- /dev/null
+++ b/dom/bindings/parser/tests/test_interface_maplikesetlike.py
@@ -0,0 +1,528 @@
+import WebIDL
+import traceback
+def WebIDLTest(parser, harness):
+
+    def shouldPass(prefix, iface, expectedMembers, numProductions=1):
+        p = parser.reset()
+        p.parse(iface)
+        results = p.finish()
+        harness.check(len(results), numProductions,
+                      "%s - Should have production count %d" % (prefix, numProductions))
+        harness.ok(isinstance(results[0], WebIDL.IDLInterface),
+                   "%s - Should be an IDLInterface" % (prefix))
+        harness.check(len(results[0].members), len(expectedMembers),
+                      "%s - Should be %d members" % (prefix,
+                                                     len(expectedMembers)))
+        for m in results[0].members:
+            name = m.identifier.name
+            if (name, type(m)) in expectedMembers:
+                harness.ok(True, "%s - %s - Should be a %s" % (prefix, name,
+                                                               type(m)))
+            elif isinstance(m, WebIDL.IDLMaplikeOrSetlike):
+                harness.ok(True, "%s - %s - Should be a MaplikeOrSetlike" %
+                           (prefix, name))
+            else:
+                harness.ok(False, "%s - %s - Unknown symbol of type %s" %
+                           (prefix, name, type(m)))
+        return results
+
+    def shouldFail(prefix, iface):
+        try:
+            p = parser.reset()
+            p.parse(iface)
+            p.finish()
+            harness.ok(False,
+                       prefix + " - Interface passed when should've failed")
+        except WebIDL.WebIDLError, e:
+            harness.ok(True,
+                       prefix + " - Interface failed as expected")
+        except Exception, e:
+            harness.ok(False,
+                       prefix + " - Interface failed but not as a WebIDLError exception")
+
+    iterableMembers = [(x, WebIDL.IDLMethod) for x in ["entries", "keys",
+                                                       "values", "forEach"]]
+    iterableMembers.extend([("size", WebIDL.IDLAttribute)])
+    setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has"]] +
+                    [("__setlike", WebIDL.IDLMaplikeOrSetlike)] +
+                    iterableMembers)
+    setRWMembers = ([(x, WebIDL.IDLMethod) for x in ["add",
+                                                     "clear",
+                                                     "delete"]] +
+                    setROMembers)
+    setROChromeMembers = ([(x, WebIDL.IDLMethod) for x in ["__add",
+                                                           "__clear",
+                                                           "__delete"]] +
+                          setROMembers)
+    setRWChromeMembers = ([(x, WebIDL.IDLMethod) for x in ["__add",
+                                                           "__clear",
+                                                           "__delete"]] +
+                          setRWMembers)
+    mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has"]] +
+                    [("__maplike", WebIDL.IDLMaplikeOrSetlike)] +
+                    iterableMembers)
+    mapRWMembers = ([(x, WebIDL.IDLMethod) for x in ["set",
+                                                     "clear",
+                                                     "delete"]] + mapROMembers)
+    mapRWChromeMembers = ([(x, WebIDL.IDLMethod) for x in ["__set",
+                                                           "__clear",
+                                                           "__delete"]] +
+                          mapRWMembers)
+
+    disallowedMemberNames = ["keys", "entries", "values", "forEach", "has",
+                             "size"]
+    mapDisallowedMemberNames = ["get"] + disallowedMemberNames
+    disallowedNonMethodNames = ["clear", "delete"]
+    mapDisallowedNonMethodNames = ["set"] + disallowedNonMethodNames
+    setDisallowedNonMethodNames = ["add"] + disallowedNonMethodNames
+
+    #
+    # Simple Usage Tests
+    #
+
+    shouldPass("Maplike (readwrite)",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               """, mapRWMembers)
+
+    shouldPass("Maplike (readonly)",
+               """
+               interface Foo1 {
+               readonly maplike<long, long>;
+               };
+               """, mapROMembers)
+
+    shouldPass("Setlike (readwrite)",
+               """
+               interface Foo1 {
+               setlike<long>;
+               };
+               """, setRWMembers)
+
+    shouldPass("Setlike (readonly)",
+               """
+               interface Foo1 {
+               readonly setlike<long>;
+               };
+               """, setROMembers)
+
+    shouldPass("Inheritance of maplike/setlike",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               };
+               """, mapRWMembers, numProductions=2)
+
+    shouldPass("Implements with maplike/setlike",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 {
+               };
+               Foo2 implements Foo1;
+               """, mapRWMembers, numProductions=3)
+
+    shouldPass("JS Implemented maplike interface",
+               """
+               [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
+               Constructor()]
+               interface Foo1 {
+               setlike<long>;
+               };
+               """, setRWChromeMembers)
+
+    shouldPass("JS Implemented maplike interface",
+               """
+               [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
+               Constructor()]
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               """, mapRWChromeMembers)
+
+    #
+    # Multiple maplike/setlike tests
+    #
+
+    shouldFail("Two maplike/setlikes on same interface",
+               """
+               interface Foo1 {
+               setlike<long>;
+               maplike<long, long>;
+               };
+               """)
+
+    shouldFail("Two maplike/setlikes in partials",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               partial interface Foo1 {
+               setlike<long>;
+               };
+               """)
+
+    shouldFail("Conflicting maplike/setlikes across inheritance",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               setlike<long>;
+               };
+               """)
+
+    shouldFail("Conflicting maplike/setlikes across multistep inheritance",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               };
+               interface Foo3 : Foo2 {
+               setlike<long>;
+               };
+               """)
+
+    shouldFail("Consequential interface with conflicting maplike/setlike",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 {
+               setlike<long>;
+               };
+               Foo2 implements Foo1;
+               """)
+
+    shouldFail("Consequential interfaces with conflicting maplike/setlike",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 {
+               setlike<long>;
+               };
+               interface Foo3 {
+               };
+               Foo3 implements Foo1;
+               Foo3 implements Foo2;
+               """)
+
+    #
+    # Member name collision tests
+    #
+
+    def testConflictingMembers(likeMember, conflictName, expectedMembers, methodPasses):
+        """
+        Tests for maplike/setlike member generation against conflicting member
+        names. If methodPasses is True, this means we expect the interface to
+        pass in the case of method shadowing, and expectedMembers should be the
+        list of interface members to check against on the passing interface.
+
+        """
+        if methodPasses:
+            shouldPass("Conflicting method: %s and %s" % (likeMember, conflictName),
+                       """
+                       interface Foo1 {
+                       %s;
+                       [Throws]
+                       void %s(long test1, double test2, double test3);
+                       };
+                       """ % (likeMember, conflictName), expectedMembers)
+        else:
+            shouldFail("Conflicting method: %s and %s" % (likeMember, conflictName),
+                       """
+                       interface Foo1 {
+                       %s;
+                       [Throws]
+                       void %s(long test1, double test2, double test3);
+                       };
+                       """ % (likeMember, conflictName))
+        # Inherited conflicting methods should ALWAYS fail
+        shouldFail("Conflicting inherited method: %s and %s" % (likeMember, conflictName),
+                   """
+                   interface Foo1 {
+                   void %s(long test1, double test2, double test3);
+                   };
+                   interface Foo2 : Foo1 {
+                   %s;
+                   };
+                   """ % (conflictName, likeMember))
+        shouldFail("Conflicting static method: %s and %s" % (likeMember, conflictName),
+                   """
+                   interface Foo1 {
+                   %s;
+                   static void %s(long test1, double test2, double test3);
+                   };
+                   """ % (likeMember, conflictName))
+        shouldFail("Conflicting attribute: %s and %s" % (likeMember, conflictName),
+                   """
+                   interface Foo1 {
+                   %s
+                   attribute double %s;
+                   };
+                   """ % (likeMember, conflictName))
+        shouldFail("Conflicting const: %s and %s" % (likeMember, conflictName),
+                   """
+                   interface Foo1 {
+                   %s;
+                   const double %s = 0;
+                   };
+                   """ % (likeMember, conflictName))
+        shouldFail("Conflicting static attribute: %s and %s" % (likeMember, conflictName),
+                   """
+                   interface Foo1 {
+                   %s;
+                   static attribute long %s;
+                   };
+                   """ % (likeMember, conflictName))
+
+    for member in mapDisallowedMemberNames:
+        testConflictingMembers("maplike<long, long>", member, mapRWMembers, False)
+    for member in disallowedMemberNames:
+        testConflictingMembers("setlike<long>", member, setRWMembers, False)
+    for member in mapDisallowedNonMethodNames:
+        testConflictingMembers("maplike<long, long>", member, mapRWMembers, True)
+    for member in setDisallowedNonMethodNames:
+        testConflictingMembers("setlike<long>", member, setRWMembers, True)
+
+    shouldPass("Inheritance of maplike/setlike with child member collision",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               void entries();
+               };
+               """, mapRWMembers, numProductions=2)
+
+    shouldPass("Inheritance of multi-level maplike/setlike with child member collision",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               };
+               interface Foo3 : Foo2 {
+               void entries();
+               };
+               """, mapRWMembers, numProductions=3)
+
+    shouldFail("Interface with consequential maplike/setlike interface member collision",
+               """
+               interface Foo1 {
+               void entries();
+               };
+               interface Foo2 {
+               maplike<long, long>;
+               };
+               Foo1 implements Foo2;
+               """)
+
+    shouldFail("Maplike interface with consequential interface member collision",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 {
+               void entries();
+               };
+               Foo1 implements Foo2;
+               """)
+
+    shouldPass("Consequential Maplike interface with inherited interface member collision",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 {
+               void entries();
+               };
+               interface Foo3 : Foo2 {
+               };
+               Foo3 implements Foo1;
+               """, mapRWMembers, numProductions=4)
+
+    shouldPass("Inherited Maplike interface with consequential interface member collision",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 {
+               void entries();
+               };
+               interface Foo3 : Foo1 {
+               };
+               Foo3 implements Foo2;
+               """, mapRWMembers, numProductions=4)
+
+    shouldFail("Inheritance of name collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               void entries();
+               };
+               interface Foo2 : Foo1 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldFail("Inheritance of multi-level name collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               void entries();
+               };
+               interface Foo2 : Foo1 {
+               };
+               interface Foo3 : Foo2 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldPass("Inheritance of attribute collision with parent maplike/setlike",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               attribute double size;
+               };
+               """, mapRWMembers, numProductions=2)
+
+    shouldPass("Inheritance of multi-level attribute collision with parent maplike/setlike",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               };
+               interface Foo3 : Foo2 {
+               attribute double size;
+               };
+               """, mapRWMembers, numProductions=3)
+
+    shouldFail("Inheritance of attribute collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               attribute double size;
+               };
+               interface Foo2 : Foo1 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldFail("Inheritance of multi-level attribute collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               attribute double size;
+               };
+               interface Foo2 : Foo1 {
+               };
+               interface Foo3 : Foo2 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldFail("Inheritance of attribute/rw function collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               attribute double set;
+               };
+               interface Foo2 : Foo1 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldFail("Inheritance of const/rw function collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               const double set = 0;
+               };
+               interface Foo2 : Foo1 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldPass("Inheritance of rw function with same name in child maplike/setlike",
+               """
+               interface Foo1 {
+               maplike<long, long>;
+               };
+               interface Foo2 : Foo1 {
+               void clear();
+               };
+               """, mapRWMembers, numProductions=2)
+
+    shouldFail("Inheritance of unforgeable attribute collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               [Unforgeable]
+               attribute double size;
+               };
+               interface Foo2 : Foo1 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldFail("Inheritance of multi-level unforgeable attribute collision with child maplike/setlike",
+               """
+               interface Foo1 {
+               [Unforgeable]
+               attribute double size;
+               };
+               interface Foo2 : Foo1 {
+               };
+               interface Foo3 : Foo2 {
+               maplike<long, long>;
+               };
+               """)
+
+    shouldPass("Implemented interface with readonly allowable overrides",
+               """
+               interface Foo1 {
+               readonly setlike<long>;
+               readonly attribute boolean clear;
+               };
+               """, setROMembers + [("clear", WebIDL.IDLAttribute)])
+
+    shouldPass("JS Implemented read-only interface with readonly allowable overrides",
+               """
+               [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
+               Constructor()]
+               interface Foo1 {
+               readonly setlike<long>;
+               readonly attribute boolean clear;
+               };
+               """, setROChromeMembers + [("clear", WebIDL.IDLAttribute)])
+
+    shouldFail("JS Implemented read-write interface with non-readwrite allowable overrides",
+               """
+               [JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
+               Constructor()]
+               interface Foo1 {
+               setlike<long>;
+               readonly attribute boolean clear;
+               };
+               """)
+
+    r = shouldPass("Check proper override of clear/delete/set",
+                   """
+                   interface Foo1 {
+                   maplike<long, long>;
+                   long clear(long a, long b, double c, double d);
+                   long set(long a, long b, double c, double d);
+                   long delete(long a, long b, double c, double d);
+                   };
+                   """, mapRWMembers)
+
+    for m in r[0].members:
+        if m.identifier.name in ["clear", "set", "delete"]:
+            harness.ok(m.isMethod(), "%s should be a method" % m.identifier.name)
+            harness.check(m.maxArgCount, 4, "%s should have 4 arguments" % m.identifier.name)
+            harness.ok(not m.isMaplikeOrSetlikeMethod(),
+                       "%s should not be a maplike/setlike function" % m.identifier.name)
--- a/dom/bindings/test/TestInterfaceJS.manifest
+++ b/dom/bindings/test/TestInterfaceJS.manifest
@@ -1,2 +1,4 @@
 component {2ac4e026-cf25-47d5-b067-78d553c3cad8} TestInterfaceJS.js
 contract @mozilla.org/dom/test-interface-js;1 {2ac4e026-cf25-47d5-b067-78d553c3cad8}
+component {4bc6f6f3-e005-4f0a-b42d-4d1663a9013a} TestInterfaceJSMaplike.js
+contract @mozilla.org/dom/test-interface-js-maplike;1 {4bc6f6f3-e005-4f0a-b42d-4d1663a9013a}
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceJSMaplike.js
@@ -0,0 +1,38 @@
+/* -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+function TestInterfaceJSMaplike() {}
+
+TestInterfaceJSMaplike.prototype = {
+  classID: Components.ID("{4bc6f6f3-e005-4f0a-b42d-4d1663a9013a}"),
+  contractID: "@mozilla.org/dom/test-interface-js-maplike;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer]),
+
+  init: function(win) { this._win = win; },
+
+  __init: function () {},
+
+  setInternal: function(aKey, aValue) {
+    return this.__DOM_IMPL__.__set(aKey, aValue);
+  },
+
+  deleteInternal: function(aKey) {
+    return this.__DOM_IMPL__.__delete(aKey);
+  },
+
+  clearInternal: function() {
+    return this.__DOM_IMPL__.__clear();
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestInterfaceJSMaplike])
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceMaplike.cpp
@@ -0,0 +1,84 @@
+/* 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/dom/TestInterfaceMaplike.h"
+#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
+#include "nsPIDOMWindow.h"
+#include "mozilla/dom/BindingUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceMaplike, mParent)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceMaplike)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceMaplike)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceMaplike)
+NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+TestInterfaceMaplike::TestInterfaceMaplike(nsPIDOMWindow* aParent)
+: mParent(aParent)
+{
+}
+
+//static
+already_AddRefed<TestInterfaceMaplike>
+TestInterfaceMaplike::Constructor(const GlobalObject& aGlobal,
+                                  ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!window) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<TestInterfaceMaplike> r = new TestInterfaceMaplike(window);
+  return r.forget();
+}
+
+JSObject*
+TestInterfaceMaplike::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return TestInterfaceMaplikeBinding::Wrap(aCx, this, aGivenProto);
+}
+
+nsPIDOMWindow*
+TestInterfaceMaplike::GetParentObject() const
+{
+  return mParent;
+}
+
+void
+TestInterfaceMaplike::SetInternal(const nsAString& aKey, int32_t aValue)
+{
+  ErrorResult rv;
+  TestInterfaceMaplikeBinding::MaplikeHelpers::Set(this, aKey, aValue, rv);
+}
+
+void
+TestInterfaceMaplike::ClearInternal()
+{
+  ErrorResult rv;
+  TestInterfaceMaplikeBinding::MaplikeHelpers::Clear(this, rv);
+}
+
+bool
+TestInterfaceMaplike::DeleteInternal(const nsAString& aKey)
+{
+  ErrorResult rv;
+  return TestInterfaceMaplikeBinding::MaplikeHelpers::Delete(this, aKey, rv);
+}
+
+bool
+TestInterfaceMaplike::HasInternal(const nsAString& aKey)
+{
+  ErrorResult rv;
+  return TestInterfaceMaplikeBinding::MaplikeHelpers::Has(this, aKey, rv);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceMaplike.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 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 mozilla_dom_TestInterfaceMaplike_h
+#define mozilla_dom_TestInterfaceMaplike_h
+
+#include "nsWrapperCache.h"
+#include "nsCOMPtr.h"
+
+class nsPIDOMWindow;
+
+namespace mozilla {
+
+class ErrorResult;
+
+namespace dom {
+
+class GlobalObject;
+
+// Implementation of test binding for webidl maplike interfaces, using
+// primitives for key and value types.
+class TestInterfaceMaplike final : public nsISupports,
+                                   public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceMaplike)
+
+  explicit TestInterfaceMaplike(nsPIDOMWindow* aParent);
+  nsPIDOMWindow* GetParentObject() const;
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+  static already_AddRefed<TestInterfaceMaplike>
+    Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
+
+  // External access for testing internal convenience functions.
+  void SetInternal(const nsAString& aKey, int32_t aValue);
+  void ClearInternal();
+  bool DeleteInternal(const nsAString& aKey);
+  bool HasInternal(const nsAString& aKey);
+private:
+  virtual ~TestInterfaceMaplike() {}
+  nsCOMPtr<nsPIDOMWindow> mParent;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TestInterfaceMaplike_h
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceMaplikeObject.cpp
@@ -0,0 +1,88 @@
+/* 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/dom/TestInterfaceMaplikeObject.h"
+#include "mozilla/dom/TestInterfaceMaplike.h"
+#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
+#include "nsPIDOMWindow.h"
+#include "mozilla/dom/BindingUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceMaplikeObject, mParent)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceMaplikeObject)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceMaplikeObject)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceMaplikeObject)
+NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+TestInterfaceMaplikeObject::TestInterfaceMaplikeObject(nsPIDOMWindow* aParent)
+: mParent(aParent)
+{
+}
+
+//static
+already_AddRefed<TestInterfaceMaplikeObject>
+TestInterfaceMaplikeObject::Constructor(const GlobalObject& aGlobal,
+                                        ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!window) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<TestInterfaceMaplikeObject> r =
+    new TestInterfaceMaplikeObject(window);
+  return r.forget();
+}
+
+JSObject*
+TestInterfaceMaplikeObject::WrapObject(JSContext* aCx,
+                                       JS::Handle<JSObject*> aGivenProto)
+{
+  return TestInterfaceMaplikeObjectBinding::Wrap(aCx, this, aGivenProto);
+}
+
+nsPIDOMWindow*
+TestInterfaceMaplikeObject::GetParentObject() const
+{
+  return mParent;
+}
+
+void
+TestInterfaceMaplikeObject::SetInternal(const nsAString& aKey)
+{
+  nsRefPtr<TestInterfaceMaplike> p(new TestInterfaceMaplike(mParent));
+  ErrorResult rv;
+  TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Set(this, aKey, *p, rv);
+}
+
+void
+TestInterfaceMaplikeObject::ClearInternal()
+{
+  ErrorResult rv;
+  TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Clear(this, rv);
+}
+
+bool
+TestInterfaceMaplikeObject::DeleteInternal(const nsAString& aKey)
+{
+  ErrorResult rv;
+  return TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Delete(this, aKey, rv);
+}
+
+bool
+TestInterfaceMaplikeObject::HasInternal(const nsAString& aKey)
+{
+  ErrorResult rv;
+  return TestInterfaceMaplikeObjectBinding::MaplikeHelpers::Has(this, aKey, rv);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceMaplikeObject.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 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 mozilla_dom_TestInterfaceMaplikeObject_h
+#define mozilla_dom_TestInterfaceMaplikeObject_h
+
+#include "nsWrapperCache.h"
+#include "nsCOMPtr.h"
+
+class nsPIDOMWindow;
+
+namespace mozilla {
+
+class ErrorResult;
+
+namespace dom {
+
+class GlobalObject;
+
+// Implementation of test binding for webidl maplike interfaces, using
+// primitives for key types and objects for value types.
+class TestInterfaceMaplikeObject final : public nsISupports,
+                                         public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceMaplikeObject)
+
+  explicit TestInterfaceMaplikeObject(nsPIDOMWindow* aParent);
+  nsPIDOMWindow* GetParentObject() const;
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+  static already_AddRefed<TestInterfaceMaplikeObject>
+    Constructor(const GlobalObject& aGlobal,ErrorResult& rv);
+
+  // External access for testing internal convenience functions.
+  void SetInternal(const nsAString& aKey);
+  void ClearInternal();
+  bool DeleteInternal(const nsAString& aKey);
+  bool HasInternal(const nsAString& aKey);
+private:
+  virtual ~TestInterfaceMaplikeObject() {}
+  nsCOMPtr<nsPIDOMWindow> mParent;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TestInterfaceMaplikeObject_h
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceSetlike.cpp
@@ -0,0 +1,58 @@
+/* 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/dom/TestInterfaceSetlike.h"
+#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
+#include "nsPIDOMWindow.h"
+#include "mozilla/dom/BindingUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceSetlike, mParent)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceSetlike)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceSetlike)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceSetlike)
+NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+TestInterfaceSetlike::TestInterfaceSetlike(JSContext* aCx,
+                                           nsPIDOMWindow* aParent)
+: mParent(aParent)
+{
+}
+
+//static
+already_AddRefed<TestInterfaceSetlike>
+TestInterfaceSetlike::Constructor(const GlobalObject& aGlobal,
+                                  ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!window) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<TestInterfaceSetlike> r = new TestInterfaceSetlike(nullptr, window);
+  return r.forget();
+}
+
+JSObject*
+TestInterfaceSetlike::WrapObject(JSContext* aCx,
+                                 JS::Handle<JSObject*> aGivenProto)
+{
+  return TestInterfaceSetlikeBinding::Wrap(aCx, this, aGivenProto);
+}
+
+nsPIDOMWindow*
+TestInterfaceSetlike::GetParentObject() const
+{
+  return mParent;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceSetlike.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 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 mozilla_dom_TestInterfaceSetlike_h
+#define mozilla_dom_TestInterfaceSetlike_h
+
+#include "nsWrapperCache.h"
+#include "nsCOMPtr.h"
+
+class nsPIDOMWindow;
+
+namespace mozilla {
+
+class ErrorResult;
+
+namespace dom {
+
+class GlobalObject;
+
+// Implementation of test binding for webidl setlike interfaces, using
+// primitives for key type.
+class TestInterfaceSetlike final : public nsISupports,
+                                   public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceSetlike)
+  explicit TestInterfaceSetlike(JSContext* aCx,
+                                nsPIDOMWindow* aParent);
+  nsPIDOMWindow* GetParentObject() const;
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+  static already_AddRefed<TestInterfaceSetlike>
+    Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
+private:
+  virtual ~TestInterfaceSetlike() {}
+  nsCOMPtr<nsPIDOMWindow> mParent;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TestInterfaceSetlike_h
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceSetlikeNode.cpp
@@ -0,0 +1,58 @@
+/* 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/dom/TestInterfaceSetlikeNode.h"
+#include "mozilla/dom/TestInterfaceJSMaplikeSetlikeBinding.h"
+#include "nsPIDOMWindow.h"
+#include "mozilla/dom/BindingUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceSetlikeNode, mParent)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceSetlikeNode)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceSetlikeNode)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceSetlikeNode)
+NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+TestInterfaceSetlikeNode::TestInterfaceSetlikeNode(JSContext* aCx,
+                                                   nsPIDOMWindow* aParent)
+: mParent(aParent)
+{
+}
+
+//static
+already_AddRefed<TestInterfaceSetlikeNode>
+TestInterfaceSetlikeNode::Constructor(const GlobalObject& aGlobal,
+                                      ErrorResult& aRv)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!window) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  nsRefPtr<TestInterfaceSetlikeNode> r = new TestInterfaceSetlikeNode(nullptr, window);
+  return r.forget();
+}
+
+JSObject*
+TestInterfaceSetlikeNode::WrapObject(JSContext* aCx,
+                                     JS::Handle<JSObject*> aGivenProto)
+{
+  return TestInterfaceSetlikeNodeBinding::Wrap(aCx, this, aGivenProto);
+}
+
+nsPIDOMWindow*
+TestInterfaceSetlikeNode::GetParentObject() const
+{
+  return mParent;
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/TestInterfaceSetlikeNode.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 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 mozilla_dom_TestInterfaceSetlikeNode_h
+#define mozilla_dom_TestInterfaceSetlikeNode_h
+
+#include "nsWrapperCache.h"
+#include "nsCOMPtr.h"
+
+class nsPIDOMWindow;
+
+namespace mozilla {
+
+class ErrorResult;
+
+namespace dom {
+
+class GlobalObject;
+
+// Implementation of test binding for webidl setlike interfaces, using
+// primitives for key type.
+class TestInterfaceSetlikeNode final : public nsISupports,
+                                       public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TestInterfaceSetlikeNode)
+  explicit TestInterfaceSetlikeNode(JSContext* aCx,
+                                    nsPIDOMWindow* aParent);
+  nsPIDOMWindow* GetParentObject() const;
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+  static already_AddRefed<TestInterfaceSetlikeNode>
+    Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
+private:
+  virtual ~TestInterfaceSetlikeNode() {}
+  nsCOMPtr<nsPIDOMWindow> mParent;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TestInterfaceSetlikeNode_h
--- a/dom/bindings/test/chrome.ini
+++ b/dom/bindings/test/chrome.ini
@@ -9,8 +9,10 @@ skip-if = buildapp == 'b2g'
 [test_document_location_via_xray_cached.html]
 [test_blacklisted_prerendering_function.xul]
 support-files =
   file_focuser.html
   file_fullScreenPropertyAccessor.html
 skip-if = e10s # prerendering doesn't work in e10s yet
 [test_kill_longrunning_prerendered_content.xul]
 skip-if = e10s # prerendering doesn't work in e10s yet
+[test_bug1123516_maplikesetlikechrome.xul]
+skip-if = debug == false
--- a/dom/bindings/test/mochitest.ini
+++ b/dom/bindings/test/mochitest.ini
@@ -56,8 +56,10 @@ skip-if = debug == false
 skip-if = debug == false
 [test_exception_options_from_jsimplemented.html]
 skip-if = debug == false
 [test_promise_rejections_from_jsimplemented.html]
 skip-if = debug == false
 [test_worker_UnwrapArg.html]
 [test_unforgeablesonexpando.html]
 [test_crossOriginWindowSymbolAccess.html]
+[test_bug1123516_maplikesetlike.html]
+skip-if = debug == false
\ No newline at end of file
--- a/dom/bindings/test/moz.build
+++ b/dom/bindings/test/moz.build
@@ -12,16 +12,17 @@ DEFINES.update({
 # Do NOT export this library.  We don't actually want our test code
 # being added to libxul or anything.
 
 Library('dombindings_test_s')
 
 EXTRA_COMPONENTS += [
     'TestInterfaceJS.js',
     'TestInterfaceJS.manifest',
+    'TestInterfaceJSMaplike.js'
 ]
 
 MOCHITEST_MANIFESTS += ['mochitest.ini']
 
 MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
 
 TEST_WEBIDL_FILES += [
     'TestDictionary.webidl',
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_bug1123516_maplikesetlike.html
@@ -0,0 +1,270 @@
+<!-- Any copyright is dedicated to the Public Domain.
+- http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!DOCTYPE HTML>
+<html>
+    <head>
+        <title>Test Maplike Interface</title>
+        <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+        <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+    </head>
+    <body>
+        <script class="testbody" type="application/javascript">
+         SimpleTest.waitForExplicitFinish();
+         SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, function() {
+
+             base_properties = [["has", "function", 1],
+                                ["entries", "function", 0],
+                                ["keys", "function", 0],
+                                ["values", "function", 0],
+                                ["forEach", "function", 1],
+                                ["size", "number"]];
+             maplike_properties = base_properties.concat([["set", "function", 2]]);
+             setlike_properties = base_properties;
+             rw_properties = [["clear", "function", 0],
+                              ["delete", "function", 1]];
+             setlike_rw_properties = base_properties.concat(rw_properties).concat([["add", "function", 1]]);
+             maplike_rw_properties = maplike_properties.concat(rw_properties).concat([["get", "function",1]]);
+             var testExistence = function testExistence(prefix, obj, properties) {
+                 for (var [name, type, args] of properties) {
+                     // Properties are somewhere up the proto chain, hasOwnProperty won't work
+                     isnot(obj[name], undefined,
+                        `${prefix} object has property ${name}`);
+
+                     is(typeof obj[name], type,
+                        `${prefix} object property ${name} is a ${type}`);
+                     // Check function length
+                     if (type == "function") {
+                         is(obj[name].length, args,
+                            `${prefix} object property ${name} is length ${args}`);
+                         is(obj[name].name, name,
+                            `${prefix} object method name is ${name}`);
+                     }
+
+                     // Find where property is on proto chain, check for enumerablility there.
+                     var owner = obj;
+                     while (owner) {
+                         var propDesc = Object.getOwnPropertyDescriptor(owner, name);
+                         if (propDesc) {
+                             ok(!propDesc.enumerable,
+                                `${prefix} object property ${name} is not enumerable`);
+                             break;
+                         }
+                         owner = Object.getPrototypeOf(owner);
+                     }
+                 }
+             }
+
+             var m;
+             var testSet;
+             var testIndex;
+             var iterable;
+             // Simple map creation and functionality test
+             info("SimpleMap: Testing simple map creation and functionality");
+             m = new TestInterfaceMaplike();
+             ok(m, "SimpleMap: got a TestInterfaceMaplike object");
+             testExistence("SimpleMap: ", m, maplike_rw_properties);
+             is(m.size, 0, "SimpleMap: size should be zero");
+             ok(!m.has("test"), "SimpleMap: maplike has should return false");
+             is(m.get("test"), undefined, "SimpleMap: maplike get should return undefined on bogus lookup");
+             m1 = m.set("test", 1);
+             is(m, m1, "SimpleMap: return from set should be map object");
+             is(m.size, 1, "SimpleMap: size should be 1");
+             ok(m.has("test"), "SimpleMap: maplike has should return true");
+             is(m.get("test"), 1, "SimpleMap: maplike get should return value entered");
+             m2 = m.set("test2", 2);
+             is(m.size, 2, "SimpleMap: size should be 2");
+             testSet = [["test", 1], ["test2", 2]];
+             testIndex = 0;
+             m.forEach(function(v, k, o) {
+                 "use strict";
+                 is(o, m, "SimpleMap: foreach obj is correct");
+                 is(k, testSet[testIndex][0], "SimpleMap: foreach map key: " + k + " = " + testSet[testIndex][0]);
+                 is(v, testSet[testIndex][1], "SimpleMap: foreach map value: " + v + " = " + testSet[testIndex][1]);
+                 testIndex += 1;
+             });
+             is(testIndex, 2, "SimpleMap: foreach ran correct number of times");
+             ok(m.has("test2"), "SimpleMap: maplike has should return true");
+             is(m.get("test2"), 2, "SimpleMap: maplike get should return value entered");
+             is(m.delete("test2"), true, "SimpleMap: maplike deletion should return boolean");
+             is(m.size, 1, "SimpleMap: size should be 1");
+             iterable = false;
+             for (var e of m) {
+                 iterable = true;
+                 is(e[0], "test", "SimpleMap: iterable first array element should be key");
+                 is(e[1], 1, "SimpleMap: iterable second array element should be value");
+             }
+             is(m[Symbol.iterator].length, 0, "SimpleMap: @@iterator symbol is correct length");
+             is(m[Symbol.iterator].name, "[Symbol.iterator]", "SimpleMap: @@iterator symbol has correct name");
+             ok(iterable, "SimpleMap: @@iterator symbol resolved correctly");
+             for (var k of m.keys()) {
+                 is(k, "test", "SimpleMap: first keys element should be 'test'");
+             }
+             for (var v of m.values()) {
+                 is(v, 1, "SimpleMap: first values elements should be 1");
+             }
+             for (var e of m.entries()) {
+                 is(e[0], "test", "SimpleMap: entries first array element should be 'test'");
+                 is(e[1], 1, "SimpleMap: entries second array element should be 1");
+             }
+             m.clear();
+             is(m.size, 0, "SimpleMap: size should be 0 after clear");
+
+             // Simple set creation and functionality test
+             info("SimpleSet: Testing simple set creation and functionality");
+             m = new TestInterfaceSetlike();
+             ok(m, "SimpleSet: got a TestInterfaceSetlike object");
+             testExistence("SimpleSet: ", m, setlike_rw_properties);
+             is(m.size, 0, "SimpleSet: size should be zero");
+             ok(!m.has("test"), "SimpleSet: maplike has should return false");
+             m1 = m.add("test");
+             is(m, m1, "SimpleSet: return from set should be map object");
+             is(m.size, 1, "SimpleSet: size should be 1");
+             ok(m.has("test"), "SimpleSet: maplike has should return true");
+             m2 = m.add("test2");
+             is(m.size, 2, "SimpleSet: size should be 2");
+             testSet = ["test", "test2"];
+             testIndex = 0;
+             m.forEach(function(v, k, o) {
+                 "use strict";
+                 is(o, m, "SimpleSet: foreach obj is correct");
+                 is(k, testSet[testIndex], "SimpleSet: foreach set key: " + k + " = " + testSet[testIndex]);
+                 testIndex += 1;
+             });
+             is(testIndex, 2, "SimpleSet: foreach ran correct number of times");
+             ok(m.has("test2"), "SimpleSet: maplike has should return true");
+             is(m.delete("test2"), true, "SimpleSet: maplike deletion should return true");
+             is(m.size, 1, "SimpleSet: size should be 1");
+             iterable = false;
+             for (var e of m) {
+                 iterable = true;
+                 is(e, "test", "SimpleSet: iterable first array element should be key");
+             }
+             is(m[Symbol.iterator].length, 0, "SimpleSet: @@iterator symbol is correct length");
+             is(m[Symbol.iterator].name, "[Symbol.iterator]", "SimpleSet: @@iterator symbol has correct name");
+             ok(iterable, "SimpleSet: @@iterator symbol resolved correctly");
+             for (var k of m.keys()) {
+                 is(k, "test", "SimpleSet: first keys element should be 'test'");
+             }
+             for (var v of m.values()) {
+                 is(v, "test", "SimpleSet: first values elements should be 'test'");
+             }
+             for (var e of m.entries()) {
+                 is(e[0], "test", "SimpleSet: Entries first array element should be 'test'");
+                 is(e[1], "test", "SimpleSet: Entries second array element should be 'test'");
+             }
+             m.clear();
+             is(m.size, 0, "SimpleSet: size should be 0 after clear");
+
+             // Map convenience function test
+             info("Testing map convenience functions");
+             m = new TestInterfaceMaplike();
+             ok(m, "MapConvenience: got a TestInterfaceMaplike object");
+             is(m.size, 0, "MapConvenience: size should be zero");
+             ok(!m.hasInternal("test"), "MapConvenience: maplike hasInternal should return false");
+             m.setInternal("test", 1);
+             is(m.size, 1, "MapConvenience: size should be 1");
+             ok(m.hasInternal("test"), "MapConvenience: maplike hasInternal should return true");
+             is(m.get("test"), 1, "MapConvenience: maplike get should return value entered");
+             m2 = m.setInternal("test2", 2);
+             is(m.size, 2, "size should be 2");
+             ok(m.hasInternal("test2"), "MapConvenience: maplike hasInternal should return true");
+             is(m.get("test2"), 2, "MapConvenience: maplike get should return value entered");
+             is(m.deleteInternal("test2"), true, "MapConvenience: maplike deleteInternal should return true");
+             is(m.size, 1, "MapConvenience: size should be 1");
+             m.clearInternal();
+             is(m.size, 0, "MapConvenience: size should be 0 after clearInternal");
+
+             // Map convenience function test using objects and readonly
+
+             info("Testing Map convenience function test using objects and readonly");
+             m = new TestInterfaceMaplikeObject();
+             ok(m, "ReadOnlyMapConvenience: got a TestInterfaceMaplikeObject object");
+             is(m.size, 0, "ReadOnlyMapConvenience: size should be zero");
+             is(m["set"], undefined, "ReadOnlyMapConvenience: readonly map, should be no set function");
+             is(m["clear"], undefined, "ReadOnlyMapConvenience: readonly map, should be no clear function");
+             is(m["delete"], undefined, "ReadOnlyMapConvenience: readonly map, should be no delete function");
+             ok(!m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return false");
+             m.setInternal("test");
+             is(m.size, 1, "size should be 1");
+             ok(m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return true");
+             m2 = m.setInternal("test2");
+             is(m.size, 2, "size should be 2");
+             ok(m.hasInternal("test2"), "ReadOnlyMapConvenience: maplike hasInternal should return true");
+             is(m.deleteInternal("test2"), true, "ReadOnlyMapConvenience: maplike deleteInternal should return true");
+             is(m.size, 1, "ReadOnlyMapConvenience: size should be 1");
+             m.clearInternal();
+             is(m.size, 0, "ReadOnlyMapConvenience: size should be 0 after clearInternal");
+
+             // JS implemented map creation convenience function test
+
+             info("JSMapConvenience: Testing JS implemented map creation convenience functions");
+             m = new TestInterfaceJSMaplike();
+             ok(m, "JSMapConvenience: got a TestInterfaceJSMaplike object");
+             is(m.size, 0, "JSMapConvenience: size should be zero");
+             ok(!m.has("test"), "JSMapConvenience: maplike has should return false");
+             m.setInternal("test", 1);
+             is(m.size, 1, "JSMapConvenience: size should be 1");
+             ok(m.has("test"), "JSMapConvenience: maplike has should return true");
+             is(m.get("test"), 1, "JSMapConvenience: maplike get should return value entered");
+             m2 = m.setInternal("test2", 2);
+             is(m.size, 2, "JSMapConvenience: size should be 2");
+             ok(m.has("test2"), "JSMapConvenience: maplike has should return true");
+             is(m.get("test2"), 2, "JSMapConvenience: maplike get should return value entered");
+             is(m.deleteInternal("test2"), true, "JSMapConvenience: maplike deleteInternal should return true");
+             is(m.size, 1, "JSMapConvenience: size should be 1");
+             for (var k of m.keys()) {
+                 is(k, "test", "JSMapConvenience: first keys element should be 'test'");
+             }
+             for (var v of m.values()) {
+                 is(v, 1, "JSMapConvenience: first values elements should be 1");
+             }
+             for (var e of m.entries()) {
+                 is(e[0], "test", "JSMapConvenience: entries first array element should be 'test'");
+                 is(e[1], 1, "JSMapConvenience: entries second array element should be 1");
+             }
+             m.clearInternal();
+             is(m.size, 0, "JSMapConvenience: size should be 0 after clearInternal");
+
+             // Test this override for forEach
+             info("ForEachThisOverride: Testing this override for forEach");
+             m = new TestInterfaceMaplike();
+             m.set("test", 1);
+             m.forEach(function(v, k, o) {
+                 "use strict";
+                 is(o, m, "ForEachThisOverride: foreach obj is correct");
+                 is(this, 5, "ForEachThisOverride: 'this' value should be correct");
+             }, 5);
+
+             // Test defaulting arguments on maplike to undefined
+             info("MapArgsDefault: Testing maplike defaulting arguments to undefined");
+             m = new TestInterfaceMaplike();
+             m.set();
+             is(m.size, 1, "MapArgsDefault: should have 1 entry");
+             m.forEach(function(v, k) {
+                 "use strict";
+                 is(typeof k, "string", "MapArgsDefault: key is a string");
+                 is(k, "undefined", "MapArgsDefault: key is the string undefined");
+                 is(v, 0, "MapArgsDefault: value is 0");
+             });
+             is(m.get(), 0, "MapArgsDefault: no argument to get() returns correct value");
+             m.delete();
+             is(m.size, 0, "MapArgsDefault: should have 0 entries");
+
+             // Test defaulting arguments on setlike to undefined
+             info("SetArgsDefault: Testing setlike defaulting arguments to undefined");
+             m = new TestInterfaceSetlike();
+             m.add();
+             is(m.size, 1, "SetArgsDefault: should have 1 entry");
+             m.forEach(function(v, k) {
+                 "use strict";
+                 is(typeof k, "string", "SetArgsDefault: key is a string");
+                 is(k, "undefined", "SetArgsDefault: key is the string undefined");
+             });
+             m.delete();
+             is(m.size, 0, "SetArgsDefault: should have 0 entries");
+
+             SimpleTest.finish();
+         });
+        </script>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_bug1123516_maplikesetlikechrome.xul
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1123516
+-->
+<window title="Mozilla Bug 1123516"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <iframe id="t"></iframe>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1123516"
+       target="_blank">Mozilla Bug 1123516</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+   <![CDATA[
+
+     /** Test for Bug 1123516 **/
+     const Cu = Components.utils;
+     function doTest() {
+       var win = $("t").contentWindow;
+       var sandbox = Components.utils.Sandbox(win, { sandboxPrototype: win });
+       is(sandbox._content, undefined, "_content does nothing over Xray");
+       // Test cross-compartment usage of maplike/setlike WebIDL structures.
+       SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, function() {
+         try {
+           var maplike = Components.utils.evalInSandbox("var m = new TestInterfaceMaplike(); m;", sandbox);
+           maplike.set("test2", 2);
+           is(maplike.get("test2"), 2, "Should be able to create and use maplike/setlike across compartments");
+           var test = Components.utils.evalInSandbox("m.get('test2');", sandbox);
+           is(test, 2, "Maplike/setlike should still work in original compartment");
+           is(maplike.size, 1, "Testing size retrieval across compartments");
+         } catch(e) {
+           ok(false, "Shouldn't throw when working with cross-compartment maplike/setlike interfaces " + e)
+         };
+         try {
+           var setlike = Components.utils.evalInSandbox("var m = new TestInterfaceSetlikeNode(); m.add(document.documentElement); m;", sandbox);
+           is(TestInterfaceSetlikeNode.prototype.has.call(setlike, win.document.documentElement), true,
+              "Cross-compartment unwrapping/comparison has works");
+           // TODO: Should throw until iterators are handled by Xrays, Bug 1023984
+           try {
+             var e = TestInterfaceSetlikeNode.prototype.keys.call(setlike);
+             ok(false, "Calling iterators via xrays should fail");
+           } catch(e) {
+             ok(true, "Calling iterators via xrays should fail");
+           }
+
+           setlike.forEach((v,k,t) => { is(v, win.document.documentElement, "Cross-compartment forEach works"); });
+           TestInterfaceSetlikeNode.prototype.forEach.call(setlike,
+                                                           (v,k,t) => { is(v, win.document.documentElement, "Cross-compartment forEach works"); });
+           is(TestInterfaceSetlikeNode.prototype.delete.call(setlike, win.document.documentElement), true,
+              "Cross-compartment unwrapping/comparison delete works");
+         } catch(e) {
+           ok(false, "Shouldn't throw when working with cross-compartment maplike/setlike interfaces " + e)
+         };
+         SimpleTest.finish();
+       });
+     }
+
+     SimpleTest.waitForExplicitFinish();
+     addLoadEvent(doTest);
+   ]]>
+  </script>
+</window>
--- a/dom/broadcastchannel/BroadcastChannel.h
+++ b/dom/broadcastchannel/BroadcastChannel.h
@@ -100,16 +100,21 @@ private:
 
   void PostMessageData(BroadcastChannelMessage* aData);
 
   void PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                            ErrorResult& aRv);
 
   void UpdateMustKeepAlive();
 
+  bool IsCertainlyAliveForCC() const override
+  {
+    return mIsKeptAlive;
+  }
+
   nsRefPtr<BroadcastChannelChild> mActor;
   nsTArray<nsRefPtr<BroadcastChannelMessage>> mPendingMessages;
 
   nsAutoPtr<workers::WorkerFeature> mWorkerFeature;
 
   nsAutoPtr<PrincipalInfo> mPrincipalInfo;
 
   nsString mOrigin;
--- a/dom/cache/test/mochitest/browser_cache_pb_window.js
+++ b/dom/cache/test/mochitest/browser_cache_pb_window.js
@@ -57,18 +57,17 @@ function testKeys(win) {
       is('SecurityError', err.name, 'caches.keys() should throw SecurityError');
       resolve();
     });
   });
 }
 
 function test() {
   waitForExplicitFinish();
-  SpecialPowers.pushPrefEnv({'set': [['browser.privatebrowing.autostart', true],
-                                     ['dom.caches.enabled', true],
+  SpecialPowers.pushPrefEnv({'set': [['dom.caches.enabled', true],
                                      ['dom.caches.testing.enabled', true]]},
                             function() {
     var privateWin = OpenBrowserWindow({private: true});
     privateWin.addEventListener('load', function() {
       Promise.all([
         testMatch(privateWin),
         testHas(privateWin),
         testOpen(privateWin),
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -1908,22 +1908,22 @@ InterfaceToJsval(nsPIDOMWindow* aWindow,
 
 JS::Value
 nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWindow);
 
   if (!aFile) {
-    return JSVAL_NULL;
+    return JS::NullValue();
   }
 
   if (aFile->mEditable) {
     // TODO - needs janv's file handle support.
-    return JSVAL_NULL;
+    return JS::NullValue();
   }
 
   nsString fullPath;
   aFile->GetFullPath(fullPath);
 
   // This check is useful to know if somewhere the DeviceStorageFile
   // has not been properly set. Mimetype is not checked because it can be
   // empty.
@@ -2526,17 +2526,17 @@ public:
   {
     MOZ_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsPIDOMWindow> window = mRequest->GetOwner();
     if (!window) {
       return NS_OK;
     }
 
     AutoJSContext cx;
-    JS::Rooted<JS::Value> result(cx, JSVAL_NULL);
+    JS::Rooted<JS::Value> result(cx, JS::NullValue());
 
     if (mFile) {
       result = nsIFileToJsval(window, mFile);
     } else if (mPath.Length()) {
       StringToJsval(window, mPath, &result);
     }
     else {
       result = JS_NumberValue(double(mValue));
--- a/dom/events/DOMEventTargetHelper.cpp
+++ b/dom/events/DOMEventTargetHelper.cpp
@@ -43,20 +43,24 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(DOMEventTargetHelper)
-  if (tmp->IsBlack()) {
+  if (tmp->IsBlack() || tmp->IsCertainlyAliveForCC()) {
     if (tmp->mListenerManager) {
       tmp->mListenerManager->MarkForCC();
     }
+    if (!tmp->IsBlack() && tmp->PreservingWrapper()) {
+      // This marks the wrapper black.
+      tmp->GetWrapper();
+    }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(DOMEventTargetHelper)
   return tmp->IsBlackAndDoesNotNeedTracing(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
--- a/dom/events/DOMEventTargetHelper.h
+++ b/dom/events/DOMEventTargetHelper.h
@@ -162,16 +162,24 @@ public:
 
   // Dispatch a trusted, non-cancellable and non-bubbling event to |this|.
   nsresult DispatchTrustedEvent(const nsAString& aEventName);
 protected:
   virtual ~DOMEventTargetHelper();
 
   nsresult WantsUntrusted(bool* aRetVal);
 
+  // If this method returns true your object is kept alive until it returns
+  // false. You can use this method instead using
+  // NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN macro.
+  virtual bool IsCertainlyAliveForCC() const
+  {
+    return false;
+  }
+
   nsRefPtr<EventListenerManager> mListenerManager;
   // Make |event| trusted and dispatch |aEvent| to |this|.
   nsresult DispatchTrustedEvent(nsIDOMEvent* aEvent);
 
   virtual void LastRelease() {}
 private:
   // Inner window or sandbox.
   nsWeakPtr                  mParentObject;
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -1538,22 +1538,22 @@ FetchBody<Derived>::ContinueConsumeBody(
         NS_NAMED_LITERAL_CSTRING(urlDataMimeType, "application/x-www-form-urlencoded");
         bool isValidUrlEncodedMimeType = StringBeginsWith(mMimeType, urlDataMimeType);
 
         if (isValidUrlEncodedMimeType && mMimeType.Length() > urlDataMimeType.Length()) {
           isValidUrlEncodedMimeType = mMimeType[urlDataMimeType.Length()] == ';';
         }
 
         if (isValidUrlEncodedMimeType) {
-          nsRefPtr<URLSearchParams> params = new URLSearchParams(nullptr);
-          params->ParseInput(data);
+          URLParams params;
+          params.ParseInput(data);
 
           nsRefPtr<nsFormData> fd = new nsFormData(DerivedClass()->GetParentObject());
           FillFormIterator iterator(fd);
-          DebugOnly<bool> status = params->ForEach(iterator);
+          DebugOnly<bool> status = params.ForEach(iterator);
           MOZ_ASSERT(status);
 
           localPromise->MaybeResolve(fd);
         } else {
           ErrorResult result;
           result.ThrowTypeError(MSG_BAD_FORMDATA);
           localPromise->MaybeReject(result);
         }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -498,17 +498,17 @@ TabChildBase::GetPresShell() const
   return result.forget();
 }
 
 void
 TabChildBase::DispatchMessageManagerMessage(const nsAString& aMessageName,
                                             const nsAString& aJSONData)
 {
     AutoSafeJSContext cx;
-    JS::Rooted<JS::Value> json(cx, JSVAL_NULL);
+    JS::Rooted<JS::Value> json(cx, JS::NullValue());
     StructuredCloneData cloneData;
     JSAutoStructuredCloneBuffer buffer;
     if (JS_ParseJSON(cx,
                       static_cast<const char16_t*>(aJSONData.BeginReading()),
                       aJSONData.Length(),
                       &json)) {
         WriteStructuredClone(cx, json, buffer, cloneData.mClosure);
         cloneData.mData = buffer.data();
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -95,22 +95,22 @@ IsTypeSupported(const nsAString& aType)
       if ((mimeType.EqualsASCII("video/mp4") ||
            mimeType.EqualsASCII("audio/mp4")) &&
           (!Preferences::GetBool("media.mediasource.mp4.enabled", false)
 #ifdef MOZ_WIDGET_ANDROID
           // MP4 won't work unless we have JellyBean+
           || AndroidBridge::Bridge()->GetAPIVersion() < 16
 #endif
           )) {
-        break;
+        return NS_ERROR_DOM_INVALID_STATE_ERR;
       }
       if ((mimeType.EqualsASCII("video/webm") ||
            mimeType.EqualsASCII("audio/webm")) &&
           !Preferences::GetBool("media.mediasource.webm.enabled", false)) {
-        break;
+        return NS_ERROR_DOM_INVALID_STATE_ERR;
       }
       found = true;
       break;
     }
   }
   if (!found) {
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
--- a/dom/messagechannel/MessagePort.cpp
+++ b/dom/messagechannel/MessagePort.cpp
@@ -187,39 +187,16 @@ MessagePortBase::MessagePortBase(nsPIDOM
 }
 
 MessagePortBase::MessagePortBase()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort)
 
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(MessagePort)
-  bool isBlack = tmp->IsBlack();
-  if (isBlack || tmp->mIsKeptAlive) {
-    if (tmp->mListenerManager) {
-      tmp->mListenerManager->MarkForCC();
-    }
-    if (!isBlack && tmp->PreservingWrapper()) {
-      // This marks the wrapper black.
-      tmp->GetWrapper();
-    }
-    return true;
-  }
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
-
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(MessagePort)
-  return tmp->
-    IsBlackAndDoesNotNeedTracing(static_cast<DOMEventTargetHelper*>(tmp));
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
-
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(MessagePort)
-  return tmp->IsBlack();
-NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
-
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort,
                                                 MessagePortBase)
   if (tmp->mDispatchRunnable) {
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDispatchRunnable->mPort);
   }
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessages);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagesForTheOtherPort);
@@ -230,20 +207,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                                                   MessagePortBase)
   if (tmp->mDispatchRunnable) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDispatchRunnable->mPort);
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUnshippedEntangledPort);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MessagePort,
-                                               MessagePortBase)
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort)
   NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END_INHERITING(MessagePortBase)
 
 NS_IMPL_ADDREF_INHERITED(MessagePort, MessagePortBase)
 NS_IMPL_RELEASE_INHERITED(MessagePort, MessagePortBase)
 
--- a/dom/messagechannel/MessagePort.h
+++ b/dom/messagechannel/MessagePort.h
@@ -70,18 +70,18 @@ class MessagePort final : public Message
                         , public nsIObserver
 {
   friend class DispatchEventRunnable;
 
 public:
   NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
   NS_DECL_NSIOBSERVER
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(MessagePort,
-                                                                   DOMEventTargetHelper)
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort,
+                                           MessagePortBase)
 
   static already_AddRefed<MessagePort>
   Create(nsPIDOMWindow* aWindow, const nsID& aUUID,
          const nsID& aDestinationUUID, ErrorResult& aRv);
 
   static already_AddRefed<MessagePort>
   Create(nsPIDOMWindow* aWindow, const MessagePortIdentifier& aIdentifier,
          ErrorResult& aRv);
@@ -172,16 +172,21 @@ private:
 
   void RemoveDocFromBFCache();
 
   // This method is meant to keep alive the MessagePort when this object is
   // creating the actor and until the actor is entangled.
   // We release the object when the port is closed or disentangled.
   void UpdateMustKeepAlive();
 
+  bool IsCertainlyAliveForCC() const override
+  {
+    return mIsKeptAlive;
+  }
+
   nsAutoPtr<workers::WorkerFeature> mWorkerFeature;
 
   nsRefPtr<DispatchEventRunnable> mDispatchRunnable;
 
   nsRefPtr<MessagePortChild> mActor;
 
   nsRefPtr<MessagePort> mUnshippedEntangledPort;
 
--- a/dom/mobilemessage/MobileMessageCallback.cpp
+++ b/dom/mobilemessage/MobileMessageCallback.cpp
@@ -200,17 +200,17 @@ MobileMessageCallback::NotifyGetMessageF
   return NotifyError(aError);
 }
 
 NS_IMETHODIMP
 MobileMessageCallback::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize)
 {
   if (aSize == 1) {
     AutoJSContext cx;
-    JS::Rooted<JS::Value> val(cx, aDeleted[0] ? JSVAL_TRUE : JSVAL_FALSE);
+    JS::Rooted<JS::Value> val(cx, JS::BooleanValue(*aDeleted));
     return NotifySuccess(val);
   }
 
   AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.Init(mDOMRequest->GetOwner()))) {
     return NS_ERROR_FAILURE;
   }
   JSContext* cx = jsapi.cx();
@@ -229,17 +229,17 @@ MobileMessageCallback::NotifyDeleteMessa
 {
   return NotifyError(aError);
 }
 
 NS_IMETHODIMP
 MobileMessageCallback::NotifyMessageMarkedRead(bool aRead)
 {
   AutoJSContext cx;
-  JS::Rooted<JS::Value> val(cx, aRead ? JSVAL_TRUE : JSVAL_FALSE);
+  JS::Rooted<JS::Value> val(cx, JS::BooleanValue(aRead));
   return NotifySuccess(val);
 }
 
 NS_IMETHODIMP
 MobileMessageCallback::NotifyMarkMessageReadFailed(int32_t aError)
 {
   return NotifyError(aError);
 }
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -482,17 +482,17 @@ LookupNPP(NPObject *npobj);
 
 static JS::Value
 NPVariantToJSVal(NPP npp, JSContext *cx, const NPVariant *variant)
 {
   switch (variant->type) {
   case NPVariantType_Void :
     return JS::UndefinedValue();
   case NPVariantType_Null :
-    return JSVAL_NULL;
+    return JS::NullValue();
   case NPVariantType_Bool :
     return BOOLEAN_TO_JSVAL(NPVARIANT_TO_BOOLEAN(*variant));
   case NPVariantType_Int32 :
     {
       // Don't use INT_TO_JSVAL directly to prevent bugs when dealing
       // with ints larger than what fits in a integer JS::Value.
       return ::JS_NumberValue(NPVARIANT_TO_INT32(*variant));
     }
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -910,17 +910,17 @@ bool DefineOSFileConstants(JSContext *cx
     JS::Rooted<JS::Value> valVersion(cx, STRING_TO_JSVAL(strVersion));
     if (!JS_SetProperty(cx, objSys, "Name", valVersion)) {
       return false;
     }
   }
 #endif // defined(MOZ_WIDGET_GONK)
 
 #if defined(DEBUG)
-  JS::Rooted<JS::Value> valDebug(cx, JSVAL_TRUE);
+  JS::Rooted<JS::Value> valDebug(cx, JS::TrueValue());
   if (!JS_SetProperty(cx, objSys, "DEBUG", valDebug)) {
     return false;
   }
 #endif
 
 #if defined(HAVE_64BIT_BUILD)
   JS::Rooted<JS::Value> valBits(cx, INT_TO_JSVAL(64));
 #else
--- a/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
+++ b/dom/tests/mochitest/chrome/test_sandbox_bindings.xul
@@ -2,17 +2,20 @@
 <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
 <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=741267
 -->
 <window title="Mozilla Bug 741267"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+   <script type="application/javascript">
 
+   
+</script>
   <iframe id="t"></iframe>
 
   <!-- test results are displayed in the html:body -->
   <body xmlns="http://www.w3.org/1999/xhtml">
   <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741267"
      target="_blank">Mozilla Bug 741267</a>
   </body>
 
new file mode 100644
--- /dev/null
+++ b/dom/webidl/TestInterfaceJSMaplikeSetlike.webidl
@@ -0,0 +1,47 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+[Constructor(),
+ Pref="dom.expose_test_interfaces"]
+interface TestInterfaceMaplike {
+  maplike<DOMString, long>;
+  void setInternal(DOMString aKey, long aValue);
+  void clearInternal();
+  boolean deleteInternal(DOMString aKey);
+  boolean hasInternal(DOMString aKey);
+};
+
+[Constructor(),
+ Pref="dom.expose_test_interfaces"]
+interface TestInterfaceMaplikeObject {
+  readonly maplike<DOMString, TestInterfaceMaplike>;
+  void setInternal(DOMString aKey);
+  void clearInternal();
+  boolean deleteInternal(DOMString aKey);
+  boolean hasInternal(DOMString aKey);
+};
+
+[Pref="dom.expose_test_interfaces",
+ JSImplementation="@mozilla.org/dom/test-interface-js-maplike;1",
+ Constructor()]
+interface TestInterfaceJSMaplike {
+  readonly maplike<DOMString, long>;
+  void setInternal(DOMString aKey, long aValue);
+  void clearInternal();
+  boolean deleteInternal(DOMString aKey);
+};
+
+[Constructor(),
+ Pref="dom.expose_test_interfaces"]
+interface TestInterfaceSetlike {
+  setlike<DOMString>;
+};
+
+[Constructor(),
+ Pref="dom.expose_test_interfaces"]
+interface TestInterfaceSetlikeNode {
+  setlike<Node>;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -638,17 +638,19 @@ WEBIDL_FILES += [
     'StyleRuleChangeEvent.webidl',
     'StyleSheetApplicableStateChangeEvent.webidl',
     'StyleSheetChangeEvent.webidl',
 ]
 
 # We only expose our prefable test interfaces in debug builds, just to be on
 # the safe side.
 if CONFIG['MOZ_DEBUG']:
-    WEBIDL_FILES += ['TestInterfaceJS.webidl', 'TestInterfaceJSDictionaries.webidl']
+    WEBIDL_FILES += ['TestInterfaceJS.webidl',
+                     'TestInterfaceJSDictionaries.webidl',
+                     'TestInterfaceJSMaplikeSetlike.webidl']
 
 if CONFIG['MOZ_B2G_BT']:
     if CONFIG['MOZ_B2G_BT_API_V1']:
         WEBIDL_FILES += [
             'BluetoothAdapter.webidl',
             'BluetoothDevice.webidl',
             'BluetoothManager.webidl',
         ]
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -254,21 +254,22 @@ public:
 
   bool
   MainThreadRun()
   {
     AssertIsOnMainThread();
 
     nsRefPtr<mozilla::dom::URL> url;
     if (mBaseProxy) {
-      url = mozilla::dom::URL::Constructor(mURL, mBaseProxy->URI(), mRv);
+      url = mozilla::dom::URL::Constructor(nullptr, mURL, mBaseProxy->URI(),
+                                           mRv);
     } else if (!mBase.IsVoid()) {
-      url = mozilla::dom::URL::Constructor(mURL, mBase, mRv);
+      url = mozilla::dom::URL::Constructor(nullptr, mURL, mBase, mRv);
     } else {
-      url = mozilla::dom::URL::Constructor(mURL, nullptr, mRv);
+      url = mozilla::dom::URL::Constructor(nullptr, mURL, nullptr, mRv);
     }
 
     if (mRv.Failed()) {
       return true;
     }
 
     mRetval = new URLProxy(url.forget());
     return true;
@@ -575,20 +576,20 @@ URL::~URL()
     mURLProxy = nullptr;
 
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       NS_ERROR("Failed to dispatch teardown runnable!");
     }
   }
 }
 
-bool
-URL::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
+JSObject*
+URL::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
-  return URLBinding_workers::Wrap(aCx, this, aGivenProto, aReflector);
+  return URLBinding_workers::Wrap(aCx, this, aGivenProto);
 }
 
 void
 URL::GetHref(nsAString& aHref, ErrorResult& aRv) const
 {
   nsRefPtr<GetterRunnable> runnable =
     new GetterRunnable(mWorkerPrivate, GetterRunnable::GetterHref, aHref,
                        mURLProxy);
@@ -947,14 +948,14 @@ URL::UpdateURLSearchParams()
     mSearchParams->ParseInput(NS_ConvertUTF16toUTF8(Substring(search, 1)));
   }
 }
 
 void
 URL::CreateSearchParamsIfNeeded()
 {
   if (!mSearchParams) {
-    mSearchParams = new URLSearchParams(this);
+    mSearchParams = new URLSearchParams(nullptr, this);
     UpdateURLSearchParams();
   }
 }
 
 END_WORKERS_NAMESPACE
--- a/dom/workers/URL.h
+++ b/dom/workers/URL.h
@@ -7,30 +7,32 @@
 #ifndef mozilla_dom_workers_url_h__
 #define mozilla_dom_workers_url_h__
 
 #include "Workers.h"
 
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/URLSearchParams.h"
+#include "nsWrapperCache.h"
 
 namespace mozilla {
 namespace dom {
 class Blob;
 struct objectURLOptions;
 }
 }
 
 BEGIN_WORKERS_NAMESPACE
 
 class URLProxy;
 class ConstructorRunnable;
 
 class URL final : public mozilla::dom::URLSearchParamsObserver
+                , public nsWrapperCache
 {
   typedef mozilla::dom::URLSearchParams URLSearchParams;
 
   ~URL();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(URL)
@@ -39,18 +41,18 @@ public:
 
   nsISupports*
   GetParentObject() const
   {
     // There's only one global on a worker, so we don't need to specify.
     return nullptr;
   }
 
-  bool
-  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector);
+  virtual JSObject*
+  WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // Methods for WebIDL
 
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
               URL& aBase, ErrorResult& aRv);
   static already_AddRefed<URL>
   Constructor(const GlobalObject& aGlobal, const nsAString& aUrl,
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -1182,17 +1182,17 @@ EventRunnable::PreDispatch(JSContext* aC
   if (NS_FAILED(xhr->GetResponseType(mResponseType))) {
     MOZ_ASSERT(false, "This should never fail!");
   }
 
   mResponseTextResult = xhr->GetResponseText(mResponseText);
   if (NS_SUCCEEDED(mResponseTextResult)) {
     mResponseResult = mResponseTextResult;
     if (mResponseText.IsVoid()) {
-      mResponse = JSVAL_NULL;
+      mResponse.setNull();
     }
   }
   else {
     JS::Rooted<JS::Value> response(aCx);
     mResponseResult = xhr->GetResponse(aCx, &response);
     if (NS_SUCCEEDED(mResponseResult)) {
       if (!response.isGCThing()) {
         mResponse = response;
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -246,17 +246,17 @@ public:
 
   void
   UpdateState(const StateData& aStateData, bool aUseCachedArrayBufferResponse);
 
   void
   NullResponseText()
   {
     mStateData.mResponseText.SetIsVoid(true);
-    mStateData.mResponse = JSVAL_NULL;
+    mStateData.mResponse.setNull();
   }
 
   bool MozAnon() const
   {
     return mMozAnon;
   }
 
   bool MozSystem() const
--- a/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.h
+++ b/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.h
@@ -11,17 +11,17 @@
 namespace mozilla {
 namespace _ipdltest {
 
 class IPDLUnitTestProcessChild : public mozilla::ipc::ProcessChild
 {
   typedef mozilla::ipc::ProcessChild ProcessChild;
 
 public:
-  IPDLUnitTestProcessChild(ProcessId aParentPid) :
+  explicit IPDLUnitTestProcessChild(ProcessId aParentPid) :
     ProcessChild(aParentPid)
   { }
 
   ~IPDLUnitTestProcessChild()
   { }
 
   virtual bool Init();
 };
--- a/ipc/ipdl/test/cxx/TestBridgeMain.h
+++ b/ipc/ipdl/test/cxx/TestBridgeMain.h
@@ -37,17 +37,17 @@ protected:
 
     virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 class TestBridgeMainSubParent :
     public PTestBridgeMainSubParent
 {
 public:
-    TestBridgeMainSubParent(Transport* aTransport)
+    explicit TestBridgeMainSubParent(Transport* aTransport)
         : mTransport(aTransport)
     {}
     virtual ~TestBridgeMainSubParent() {}
 
 protected:
     virtual bool RecvHello() override;
     virtual bool RecvHelloSync() override;
     virtual bool AnswerHelloRpc() override;
@@ -121,17 +121,17 @@ protected:
 
     virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 class TestBridgeMainSubChild :
     public PTestBridgeMainSubChild
 {
 public:
-    TestBridgeMainSubChild(Transport* aTransport)
+    explicit TestBridgeMainSubChild(Transport* aTransport)
         : mGotHi(false)
         , mTransport(aTransport)
     {}
     virtual ~TestBridgeMainSubChild() {}
 
 protected:
     virtual bool RecvHi() override;
     virtual bool AnswerHiRpc() override;
--- a/ipc/ipdl/test/cxx/TestDataStructures.h
+++ b/ipc/ipdl/test/cxx/TestDataStructures.h
@@ -15,17 +15,17 @@ namespace _ipdltest {
 //-----------------------------------------------------------------------------
 // Subprotocol actors
 
 class TestDataStructuresSub :
         public PTestDataStructuresSubParent,
         public PTestDataStructuresSubChild
 {
 public:
-    TestDataStructuresSub(uint32_t i) : mI(i)
+    explicit TestDataStructuresSub(uint32_t i) : mI(i)
     { }
     virtual ~TestDataStructuresSub()
     { }
     virtual void ActorDestroy(ActorDestroyReason why) override
     {
       if (Deletion != why)
         fail("unexpected destruction!");
     }
--- a/ipc/ipdl/test/cxx/TestOpens.h
+++ b/ipc/ipdl/test/cxx/TestOpens.h
@@ -35,17 +35,17 @@ protected:
 
 } // namespace _ipdltest
 
 namespace _ipdltest2 {
 
 class TestOpensOpenedParent : public PTestOpensOpenedParent
 {
 public:
-    TestOpensOpenedParent(Transport* aTransport)
+    explicit TestOpensOpenedParent(Transport* aTransport)
         : mTransport(aTransport)
     {}
     virtual ~TestOpensOpenedParent() {}
 
 protected:
     virtual bool RecvHello() override;
     virtual bool RecvHelloSync() override;
     virtual bool AnswerHelloRpc() override;
@@ -78,17 +78,17 @@ protected:
 
 } // namespace _ipdltest
 
 namespace _ipdltest2 {
 
 class TestOpensOpenedChild : public PTestOpensOpenedChild
 {
 public:
-    TestOpensOpenedChild(Transport* aTransport)
+    explicit TestOpensOpenedChild(Transport* aTransport)
         : mGotHi(false)
         , mTransport(aTransport)
     {}
     virtual ~TestOpensOpenedChild() {}
 
 protected:
     virtual bool RecvHi() override;
     virtual bool AnswerHiRpc() override;
--- a/ipc/ipdl/test/cxx/TestShutdown.h
+++ b/ipc/ipdl/test/cxx/TestShutdown.h
@@ -17,17 +17,17 @@ namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // Parent side
 
 class TestShutdownSubsubParent :
     public PTestShutdownSubsubParent
 {
 public:
-    TestShutdownSubsubParent(bool expectParentDeleted) :
+    explicit TestShutdownSubsubParent(bool expectParentDeleted) :
         mExpectParentDeleted(expectParentDeleted)
     {
     }
 
     virtual ~TestShutdownSubsubParent()
     {
     }
 
@@ -39,17 +39,17 @@ private:
     bool mExpectParentDeleted;
 };
 
 
 class TestShutdownSubParent :
     public PTestShutdownSubParent
 {
 public:
-    TestShutdownSubParent(bool expectCrash) :
+    explicit TestShutdownSubParent(bool expectCrash) :
         mExpectCrash(expectCrash),
         mDeletedCount(0)
     {
     }
 
     virtual ~TestShutdownSubParent()
     {
         if (2 != mDeletedCount)
@@ -126,17 +126,17 @@ protected:
 
 //-----------------------------------------------------------------------------
 // Child side
 
 class TestShutdownSubsubChild :
     public PTestShutdownSubsubChild
 {
 public:
-    TestShutdownSubsubChild(bool expectParentDeleted) :
+    explicit TestShutdownSubsubChild(bool expectParentDeleted) :
         mExpectParentDeleted(expectParentDeleted)
     {
     }
     virtual ~TestShutdownSubsubChild()
     {
     }
 
 protected:
@@ -147,17 +147,17 @@ private:
     bool mExpectParentDeleted;
 };
 
 
 class TestShutdownSubChild :
     public PTestShutdownSubChild
 {
 public:
-    TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash)
+    explicit TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash)
     {
     }
 
     virtual ~TestShutdownSubChild()
     {
     }
 
 protected:
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -362,17 +362,17 @@ XPCShellEnvironment::ProcessFile(JSConte
         JS_ClearPendingException(cx);
         JS::CompileOptions options(cx);
         options.setFileAndLine("typein", startline);
         JS::Rooted<JSScript*> script(cx);
         if (JS_CompileScript(cx, buffer, strlen(buffer), options, &script)) {
             JSErrorReporter older;
 
             ok = JS_ExecuteScript(cx, script, &result);
-            if (ok && result != JSVAL_VOID) {
+            if (ok && !result.isUndefined()) {
                 /* Suppress error reports from JS::ToString(). */
                 older = JS_SetErrorReporter(JS_GetRuntime(cx), nullptr);
                 str = JS::ToString(cx, result);
                 JSAutoByteString bytes;
                 if (str)
                     bytes.encodeLatin1(cx, str);
                 JS_SetErrorReporter(JS_GetRuntime(cx), older);
 
@@ -579,17 +579,17 @@ XPCShellEnvironment::EvaluateString(cons
   }
 
   if (aResult) {
       aResult->Truncate();
   }
 
   JS::Rooted<JS::Value> result(cx);
   bool ok = JS_ExecuteScript(cx, script, &result);
-  if (ok && result != JSVAL_VOID) {
+  if (ok && !result.isUndefined()) {
       JSErrorReporter old = JS_SetErrorReporter(JS_GetRuntime(cx), nullptr);
       JSString* str = JS::ToString(cx, result);
       nsAutoJSString autoStr;
       if (str)
           autoStr.init(cx, str);
       JS_SetErrorReporter(JS_GetRuntime(cx), old);
 
       if (!autoStr.IsEmpty() && aResult) {
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -265,17 +265,17 @@ JavaScriptShared::toVariant(JSContext* c
         *to = UndefinedVariant();
         return true;
 
       case JSTYPE_OBJECT:
       case JSTYPE_FUNCTION:
       {
         RootedObject obj(cx, from.toObjectOrNull());
         if (!obj) {
-            MOZ_ASSERT(from == JSVAL_NULL);
+            MOZ_ASSERT(from.isNull());
             *to = NullVariant();
             return true;
         }
 
         if (xpc_JSObjectIsID(cx, obj)) {
             JSIID iid;
             const nsID* id = xpc_JSObjectToID(cx, obj);
             ConvertID(*id, &iid);
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -1671,16 +1671,17 @@ class ValueOperations
   public:
     bool isUndefined() const { return value()->isUndefined(); }
     bool isNull() const { return value()->isNull(); }
     bool isBoolean() const { return value()->isBoolean(); }
     bool isTrue() const { return value()->isTrue(); }
     bool isFalse() const { return value()->isFalse(); }
     bool isNumber() const { return value()->isNumber(); }
     bool isInt32() const { return value()->isInt32(); }
+    bool isInt32(int32_t i32) const { return value()->isInt32(i32); }
     bool isDouble() const { return value()->isDouble(); }
     bool isString() const { return value()->isString(); }
     bool isSymbol() const { return value()->isSymbol(); }
     bool isObject() const { return value()->isObject(); }
     bool isMagic() const { return value()->isMagic(); }
     bool isMagic(JSWhyMagic why) const { return value()->isMagic(why); }
     bool isMarkable() const { return value()->isMarkable(); }
     bool isPrimitive() const { return value()->isPrimitive(); }
@@ -1993,27 +1994,16 @@ BOOLEAN_TO_JSVAL(bool b)
 /* To be GC-safe, privates are tagged as doubles. */
 
 static inline jsval
 PRIVATE_TO_JSVAL(void* ptr)
 {
     return IMPL_TO_JSVAL(PRIVATE_PTR_TO_JSVAL_IMPL(ptr));
 }
 
-// JS constants. For efficiency, prefer predicates (e.g. v.isNull()) and
-// constructing values from scratch (e.g. Int32Value(0)).  These constants are
-// stored in memory and initialized at startup, so testing against them and
-// using them requires memory loads and will be correspondingly slow.
-extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL;
-extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO;
-extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE;
-extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE;
-extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE;
-extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID;
-
 namespace JS {
 
 extern JS_PUBLIC_DATA(const HandleValue) NullHandleValue;
 extern JS_PUBLIC_DATA(const HandleValue) UndefinedHandleValue;
 extern JS_PUBLIC_DATA(const HandleValue) TrueHandleValue;
 extern JS_PUBLIC_DATA(const HandleValue) FalseHandleValue;
 
 }
--- a/js/src/asmjs/AsmJSFrameIterator.cpp
+++ b/js/src/asmjs/AsmJSFrameIterator.cpp
@@ -126,16 +126,21 @@ static const unsigned PostStorePrePopFP 
 # endif
 static const unsigned PushedFP = 8;
 static const unsigned StoredFP = 11;
 #elif defined(JS_CODEGEN_ARM)
 static const unsigned PushedRetAddr = 4;
 static const unsigned PushedFP = 16;
 static const unsigned StoredFP = 20;
 static const unsigned PostStorePrePopFP = 4;
+#elif defined(JS_CODEGEN_ARM64)
+static const unsigned PushedRetAddr = 0;
+static const unsigned PushedFP = 0;
+static const unsigned StoredFP = 0;
+static const unsigned PostStorePrePopFP = 0;
 #elif defined(JS_CODEGEN_MIPS)
 static const unsigned PushedRetAddr = 8;
 static const unsigned PushedFP = 24;
 static const unsigned StoredFP = 28;
 static const unsigned PostStorePrePopFP = 4;
 #elif defined(JS_CODEGEN_NONE)
 # if defined(DEBUG)
 static const unsigned PushedRetAddr = 0;
@@ -211,17 +216,17 @@ GenerateProfilingPrologue(MacroAssembler
 }
 
 // Generate the inverse of GenerateProfilingPrologue.
 static void
 GenerateProfilingEpilogue(MacroAssembler& masm, unsigned framePushed, AsmJSExit::Reason reason,
                           Label* profilingReturn)
 {
     Register scratch = ABIArgGenerator::NonReturn_VolatileReg0;
-#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
+#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS)
     Register scratch2 = ABIArgGenerator::NonReturn_VolatileReg1;
 #endif
 
     if (framePushed)
         masm.addToStackPtr(Imm32(framePushed));
 
     masm.loadAsmJSActivation(scratch);
 
@@ -235,21 +240,21 @@ GenerateProfilingEpilogue(MacroAssembler
 #if defined(JS_CODEGEN_ARM)
         AutoForbidPools afp(&masm, /* number of instructions in scope = */ 4);
 #endif
 
         // sp protects the stack from clobber via asynchronous signal handlers
         // and the async interrupt exit. Since activation.fp can be read at any
         // time and still points to the current frame, be careful to only update
         // sp after activation.fp has been repointed to the caller's frame.
-#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
+#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS)
         masm.loadPtr(Address(masm.getStackPointer(), 0), scratch2);
         masm.storePtr(scratch2, Address(scratch, AsmJSActivation::offsetOfFP()));
         DebugOnly<uint32_t> prePop = masm.currentOffset();
-        masm.add32(Imm32(4), masm.getStackPointer());
+        masm.addToStackPtr(Imm32(sizeof(void *)));
         MOZ_ASSERT(PostStorePrePopFP == masm.currentOffset() - prePop);
 #else
         masm.pop(Address(scratch, AsmJSActivation::offsetOfFP()));
         MOZ_ASSERT(PostStorePrePopFP == 0);
 #endif
 
         masm.bind(profilingReturn);
         masm.ret();
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -1782,16 +1782,19 @@ AsmJSModule::setProfilingEnabled(bool en
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
         void* callee = X86Encoding::GetRel32Target(callerRetAddr);
 #elif defined(JS_CODEGEN_ARM)
         uint8_t* caller = callerRetAddr - 4;
         Instruction* callerInsn = reinterpret_cast<Instruction*>(caller);
         BOffImm calleeOffset;
         callerInsn->as<InstBLImm>()->extractImm(&calleeOffset);
         void* callee = calleeOffset.getDest(callerInsn);
+#elif defined(JS_CODEGEN_ARM64)
+        MOZ_CRASH();
+        void* callee = nullptr;
 #elif defined(JS_CODEGEN_MIPS)
         Instruction* instr = (Instruction*)(callerRetAddr - 4 * sizeof(uint32_t));
         void* callee = (void*)Assembler::ExtractLuiOriValue(instr, instr->next());
 #elif defined(JS_CODEGEN_NONE)
         MOZ_CRASH();
         void* callee = nullptr;
 #else
 # error "Missing architecture"
@@ -1806,16 +1809,18 @@ AsmJSModule::setProfilingEnabled(bool en
         MOZ_ASSERT_IF(profilingEnabled_, callee == profilingEntry);
         MOZ_ASSERT_IF(!profilingEnabled_, callee == entry);
         uint8_t* newCallee = enabled ? profilingEntry : entry;
 
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
         X86Encoding::SetRel32(callerRetAddr, newCallee);
 #elif defined(JS_CODEGEN_ARM)
         new (caller) InstBLImm(BOffImm(newCallee - caller), Assembler::Always);
+#elif defined(JS_CODEGEN_ARM64)
+        MOZ_CRASH();
 #elif defined(JS_CODEGEN_MIPS)
         Assembler::WriteLuiOriInstructions(instr, instr->next(),
                                            ScratchRegister, (uint32_t)newCallee);
         instr[2] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr);
 #elif defined(JS_CODEGEN_NONE)
         MOZ_CRASH();
 #else
 # error "Missing architecture"
@@ -1869,16 +1874,18 @@ AsmJSModule::setProfilingEnabled(bool en
 #elif defined(JS_CODEGEN_ARM)
         if (enabled) {
             MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstNOP>());
             new (jump) InstBImm(BOffImm(profilingEpilogue - jump), Assembler::Always);
         } else {
             MOZ_ASSERT(reinterpret_cast<Instruction*>(jump)->is<InstBImm>());
             new (jump) InstNOP();
         }
+#elif defined(JS_CODEGEN_ARM64)
+        MOZ_CRASH();
 #elif defined(JS_CODEGEN_MIPS)
         Instruction* instr = (Instruction*)jump;
         if (enabled) {
             Assembler::WriteLuiOriInstructions(instr, instr->next(),
                                                ScratchRegister, (uint32_t)profilingEpilogue);
             instr[2] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr);
         } else {
             instr[0].makeNop();
--- a/js/src/asmjs/AsmJSSignalHandlers.cpp
+++ b/js/src/asmjs/AsmJSSignalHandlers.cpp
@@ -1159,18 +1159,18 @@ static bool
 RedirectJitCodeToInterruptCheck(JSRuntime* rt, CONTEXT* context)
 {
     RedirectIonBackedgesToInterruptCheck(rt);
 
     if (AsmJSActivation* activation = rt->asmJSActivationStack()) {
         const AsmJSModule& module = activation->module();
 
 #ifdef JS_SIMULATOR
-        if (module.containsFunctionPC((void*)rt->simulator()->get_pc()))
-            rt->simulator()->set_resume_pc(int32_t(module.interruptExit()));
+        if (module.containsFunctionPC(rt->simulator()->get_pc_as<void*>()))
+            rt->simulator()->set_resume_pc(module.interruptExit());
 #endif
 
         uint8_t** ppc = ContextToPC(context);
         uint8_t* pc = *ppc;
         if (module.containsFunctionPC(pc)) {
             activation->setResumePC(pc);
             *ppc = module.interruptExit();
             return true;
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -9107,17 +9107,18 @@ GenerateAsyncInterruptExit(ModuleCompile
     masm.transferReg(r8);
     masm.transferReg(r9);
     masm.transferReg(r10);
     masm.transferReg(r11);
     masm.transferReg(r12);
     masm.transferReg(lr);
     masm.finishDataTransfer();
     masm.ret();
-
+#elif defined(JS_CODEGEN_ARM64)
+    MOZ_CRASH();
 #elif defined (JS_CODEGEN_NONE)
     MOZ_CRASH();
 #else
 # error "Unknown architecture!"
 #endif
 
     return m.finishGeneratingInlineStub(&m.asyncInterruptLabel()) && !masm.oom();
 }
--- a/js/src/builtin/Intl.js
+++ b/js/src/builtin/Intl.js
@@ -432,54 +432,148 @@ function CanonicalizeLanguageTag(locale)
         else
             canonical = privateUse;
     }
 
     return canonical;
 }
 
 
-// mappings from some commonly used old-style language tags to current flavors
-// with script codes
+function localeContainsNoUnicodeExtensions(locale) {
+    // No "-u-", no possible Unicode extension.
+    if (callFunction(std_String_indexOf, locale, "-u-") === -1)
+        return true;
+
+    // "-u-" within privateuse also isn't one.
+    if (callFunction(std_String_indexOf, locale, "-u-") > callFunction(std_String_indexOf, locale, "-x-"))
+        return true;
+
+    // An entirely-privateuse tag doesn't contain extensions.
+    if (callFunction(std_String_startsWith, locale, "x-"))
+        return true;
+
+    // Otherwise, we have a Unicode extension sequence.
+    return false;
+}
+
+
+// The last-ditch locale is used if none of the available locales satisfies a
+// request. "en-GB" is used based on the assumptions that English is the most
+// common second language, that both en-GB and en-US are normally available in
+// an implementation, and that en-GB is more representative of the English used
+// in other locales.
+function lastDitchLocale() {
+    // Per bug 1177929, strings don't clone out of self-hosted code as atoms,
+    // breaking IonBuilder::constant.  Put this in a function for now.
+    return "en-GB";
+}
+
+
+// Certain old, commonly-used language tags that lack a script, are expected to
+// nonetheless imply one.  This object maps these old-style tags to modern
+// equivalents.
 var oldStyleLanguageTagMappings = {
     "pa-PK": "pa-Arab-PK",
     "zh-CN": "zh-Hans-CN",
     "zh-HK": "zh-Hant-HK",
     "zh-SG": "zh-Hans-SG",
-    "zh-TW": "zh-Hant-TW"
+    "zh-TW": "zh-Hant-TW",
+};
+
+
+var localeCandidateCache = {
+    runtimeDefaultLocale: undefined,
+    candidateDefaultLocale: undefined,
+};
+
+
+var localeCache = {
+    runtimeDefaultLocale: undefined,
+    defaultLocale: undefined,
 };
 
 
 /**
+ * Compute the candidate default locale: the locale *requested* to be used as
+ * the default locale.  We'll use it if and only if ICU provides support (maybe
+ * fallback support, e.g. supporting "de-ZA" through "de" support implied by a
+ * "de-DE" locale).
+ */
+function DefaultLocaleIgnoringAvailableLocales() {
+    const runtimeDefaultLocale = RuntimeDefaultLocale();
+    if (runtimeDefaultLocale === localeCandidateCache.runtimeDefaultLocale)
+        return localeCandidateCache.candidateDefaultLocale;
+
+    // If we didn't get a cache hit, compute the candidate default locale and
+    // cache it.  Fall back on the last-ditch locale when necessary.
+    var candidate;
+    if (!IsStructurallyValidLanguageTag(runtimeDefaultLocale)) {
+        candidate = lastDitchLocale();
+    } else {
+        candidate = CanonicalizeLanguageTag(runtimeDefaultLocale);
+
+        // The default locale must be in [[availableLocales]], and that list
+        // must not contain any locales with Unicode extension sequences, so
+        // remove any present in the candidate.
+        candidate = removeUnicodeExtensions(candidate);
+
+        if (callFunction(std_Object_hasOwnProperty, oldStyleLanguageTagMappings, candidate))
+            candidate = oldStyleLanguageTagMappings[candidate];
+    }
+
+    // Cache the candidate locale until the runtime default locale changes.
+    localeCandidateCache.runtimeDefaultLocale = runtimeDefaultLocale;
+    localeCandidateCache.candidateDefaultLocale = candidate;
+
+    assert(IsStructurallyValidLanguageTag(candidate),
+           "the candidate must be structurally valid");
+    assert(localeContainsNoUnicodeExtensions(candidate),
+           "the candidate must not contain a Unicode extension sequence");
+
+    return candidate;
+}
+
+
+/**
  * Returns the BCP 47 language tag for the host environment's current locale.
  *
  * Spec: ECMAScript Internationalization API Specification, 6.2.4.
  */
 function DefaultLocale() {
-    // The locale of last resort is used if none of the available locales
-    // satisfies a request. "en-GB" is used based on the assumptions that
-    // English is the most common second language, that both en-GB and en-US
-    // are normally available in an implementation, and that en-GB is more
-    // representative of the English used in other locales.
-    var localeOfLastResort = "en-GB";
-
-    var locale = RuntimeDefaultLocale();
-    if (!IsStructurallyValidLanguageTag(locale))
-        return localeOfLastResort;
-
-    locale = CanonicalizeLanguageTag(locale);
-    if (callFunction(std_Object_hasOwnProperty, oldStyleLanguageTagMappings, locale))
-        locale = oldStyleLanguageTagMappings[locale];
-
-    if (!(collatorInternalProperties.availableLocales()[locale] &&
-          numberFormatInternalProperties.availableLocales()[locale] &&
-          dateTimeFormatInternalProperties.availableLocales()[locale]))
+    const runtimeDefaultLocale = RuntimeDefaultLocale();
+    if (runtimeDefaultLocale === localeCache.runtimeDefaultLocale)
+        return localeCache.defaultLocale;
+
+    // If we didn't have a cache hit, compute the candidate default locale.
+    // Then use it as the actual default locale if ICU supports that locale
+    // (perhaps via fallback).  Otherwise use the last-ditch locale.
+    var candidate = DefaultLocaleIgnoringAvailableLocales();
+    var locale;
+    if (BestAvailableLocaleIgnoringDefault(collatorInternalProperties.availableLocales(),
+                                           candidate) &&
+        BestAvailableLocaleIgnoringDefault(numberFormatInternalProperties.availableLocales(),
+                                           candidate) &&
+        BestAvailableLocaleIgnoringDefault(dateTimeFormatInternalProperties.availableLocales(),
+                                           candidate))
     {
-        locale = localeOfLastResort;
+        locale = candidate;
+    } else {
+        locale = lastDitchLocale();
     }
+
+    assert(IsStructurallyValidLanguageTag(locale),
+           "the computed default locale must be structurally valid");
+    assert(locale === CanonicalizeLanguageTag(locale),
+           "the computed default locale must be canonical");
+    assert(localeContainsNoUnicodeExtensions(locale),
+           "the computed default locale must not contain a Unicode extension sequence");
+
+    localeCache.runtimeDefaultLocale = runtimeDefaultLocale;
+    localeCache.defaultLocale = locale;
+
     return locale;
 }
 
 
 /**
  * Verifies that the given string is a well-formed ISO 4217 currency code.
  *
  * Spec: ECMAScript Internationalization API Specification, 6.3.1.
@@ -495,32 +589,38 @@ function IsWellFormedCurrencyCode(curren
     if (normalized.length !== 3)
         return false;
     return !regexp_test_no_statics(getIsWellFormedCurrencyCodeRE(), normalized);
 }
 
 
 /********** Locale and Parameter Negotiation **********/
 
-
 /**
  * Add old-style language tags without script code for locales that in current
- * usage would include a script subtag. Returns the availableLocales argument
- * provided.
- *
- * Spec: ECMAScript Internationalization API Specification, 9.1.
+ * usage would include a script subtag.  Also add an entry for the last-ditch
+ * locale, in case ICU doesn't directly support it (but does support it through
+ * fallback, e.g. supporting "en-GB" indirectly using "en" support).
  */
-function addOldStyleLanguageTags(availableLocales) {
+function addSpecialMissingLanguageTags(availableLocales) {
+    // Certain old-style language tags lack a script code, but in current usage
+    // they *would* include a script code.  Map these over to modern forms.
     var oldStyleLocales = std_Object_getOwnPropertyNames(oldStyleLanguageTagMappings);
     for (var i = 0; i < oldStyleLocales.length; i++) {
         var oldStyleLocale = oldStyleLocales[i];
         if (availableLocales[oldStyleLanguageTagMappings[oldStyleLocale]])
             availableLocales[oldStyleLocale] = true;
     }
-    return availableLocales;
+
+    // Also forcibly provide the last-ditch locale.
+    var lastDitch = lastDitchLocale();
+    assert(lastDitch === "en-GB" && availableLocales["en"],
+           "shouldn't be a need to add every locale implied by the last-" +
+           "ditch locale, merely just the last-ditch locale");
+    availableLocales[lastDitch] = true;
 }
 
 
 /**
  * Canonicalizes a locale list.
  *
  * Spec: ECMAScript Internationalization API Specification, 9.2.1.
  */
@@ -548,40 +648,79 @@ function CanonicalizeLocaleList(locales)
                 seen.push(tag);
         }
         k++;
     }
     return seen;
 }
 
 
+function BestAvailableLocaleHelper(availableLocales, locale, considerDefaultLocale) {
+    assert(IsStructurallyValidLanguageTag(locale), "invalid BestAvailableLocale locale structure");
+    assert(locale === CanonicalizeLanguageTag(locale), "non-canonical BestAvailableLocale locale");
+    assert(localeContainsNoUnicodeExtensions(locale), "locale must contain no Unicode extensions");
+
+    // In the spec, [[availableLocales]] is formally a list of all available
+    // locales.  But in our implementation, it's an *incomplete* list, not
+    // necessarily including the default locale (and all locales implied by it,
+    // e.g. "de" implied by "de-CH"), if that locale isn't in every
+    // [[availableLocales]] list (because that locale is supported through
+    // fallback, e.g. "de-CH" supported through "de").
+    //
+    // If we're considering the default locale, augment the spec loop with
+    // additional checks to also test whether the current prefix is a prefix of
+    // the default locale.
+
+    var defaultLocale;
+    if (considerDefaultLocale)
+        defaultLocale = DefaultLocale();
+
+    var candidate = locale;
+    while (true) {
+        if (availableLocales[candidate])
+            return candidate;
+
+        if (considerDefaultLocale && candidate.length <= defaultLocale.length) {
+            if (candidate === defaultLocale)
+                return candidate;
+            if (callFunction(std_String_startsWith, defaultLocale, candidate + "-"))
+                return candidate;
+        }
+
+        var pos = callFunction(std_String_lastIndexOf, candidate, "-");
+        if (pos === -1)
+            return undefined;
+
+        if (pos >= 2 && candidate[pos - 2] === "-")
+            pos -= 2;
+
+        candidate = callFunction(std_String_substring, candidate, 0, pos);
+    }
+}
+
+
 /**
  * Compares a BCP 47 language tag against the locales in availableLocales
  * and returns the best available match. Uses the fallback
  * mechanism of RFC 4647, section 3.4.
  *
  * Spec: ECMAScript Internationalization API Specification, 9.2.2.
  * Spec: RFC 4647, section 3.4.
  */
 function BestAvailableLocale(availableLocales, locale) {
-    assert(IsStructurallyValidLanguageTag(locale), "invalid BestAvailableLocale locale structure");
-    assert(locale === CanonicalizeLanguageTag(locale), "non-canonical BestAvailableLocale locale");
-    assert(callFunction(std_String_indexOf, locale, "-u-") === -1, "locale shouldn't contain -u-");
-
-    var candidate = locale;
-    while (true) {
-        if (availableLocales[candidate])
-            return candidate;
-        var pos = callFunction(std_String_lastIndexOf, candidate, "-");
-        if (pos === -1)
-            return undefined;
-        if (pos >= 2 && candidate[pos - 2] === "-")
-            pos -= 2;
-        candidate = callFunction(std_String_substring, candidate, 0, pos);
-    }
+    return BestAvailableLocaleHelper(availableLocales, locale, true);
+}
+
+
+/**
+ * Identical to BestAvailableLocale, but does not consider the default locale
+ * during computation.
+ */
+function BestAvailableLocaleIgnoringDefault(availableLocales, locale) {
+    return BestAvailableLocaleHelper(availableLocales, locale, false);
 }
 
 
 /**
  * Compares a BCP 47 language priority list against the set of locales in
  * availableLocales and determines the best available language to meet the
  * request. Options specified through Unicode extension subsequences are
  * ignored in the lookup, but information about such subsequences is returned
@@ -1352,18 +1491,20 @@ var collatorInternalProperties = {
     sortLocaleData: collatorSortLocaleData,
     searchLocaleData: collatorSearchLocaleData,
     _availableLocales: null,
     availableLocales: function()
     {
         var locales = this._availableLocales;
         if (locales)
             return locales;
-        return (this._availableLocales =
-          addOldStyleLanguageTags(intl_Collator_availableLocales()));
+
+        locales = intl_Collator_availableLocales();
+        addSpecialMissingLanguageTags(locales);
+        return (this._availableLocales = locales);
     },
     relevantExtensionKeys: ["co", "kn"]
 };
 
 
 function collatorSortLocaleData(locale) {
     var collations = intl_availableCollations(locale);
     callFunction(std_Array_unshift, collations, null);
@@ -1466,18 +1607,20 @@ function Intl_Collator_resolvedOptions()
 var numberFormatInternalProperties = {
     localeData: numberFormatLocaleData,
     _availableLocales: null,
     availableLocales: function()
     {
         var locales = this._availableLocales;
         if (locales)
             return locales;
-        return (this._availableLocales =
-          addOldStyleLanguageTags(intl_NumberFormat_availableLocales()));
+
+        locales = intl_NumberFormat_availableLocales();
+        addSpecialMissingLanguageTags(locales);
+        return (this._availableLocales = locales);
     },
     relevantExtensionKeys: ["nu"]
 };
 
 
 /**
  * Compute an internal properties object from |lazyNumberFormatData|.
  */
@@ -2499,18 +2642,20 @@ function Intl_DateTimeFormat_supportedLo
 var dateTimeFormatInternalProperties = {
     localeData: dateTimeFormatLocaleData,
     _availableLocales: null,
     availableLocales: function()
     {
         var locales = this._availableLocales;
         if (locales)
             return locales;
-        return (this._availableLocales =
-          addOldStyleLanguageTags(intl_DateTimeFormat_availableLocales()));
+
+        locales = intl_DateTimeFormat_availableLocales();
+        addSpecialMissingLanguageTags(locales);
+        return (this._availableLocales = locales);
     },
     relevantExtensionKeys: ["ca", "nu"]
 };
 
 
 function dateTimeFormatLocaleData(locale) {
     return {
         ca: intl_availableCalendars(locale),
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1349,17 +1349,16 @@ MapObject::extract(CallReceiver call)
     MOZ_ASSERT(call.thisv().isObject());
     MOZ_ASSERT(call.thisv().toObject().hasClass(&MapObject::class_));
     return *call.thisv().toObject().as<MapObject>().getData();
 }
 
 uint32_t
 MapObject::size(JSContext* cx, HandleObject obj)
 {
-    MOZ_ASSERT(MapObject::is(obj));
     ValueMap& map = extract(obj);
     static_assert(sizeof(map.count()) <= sizeof(uint32_t),
                   "map count must be precisely representable as a JS number");
     return map.count();
 }
 
 bool
 MapObject::size_impl(JSContext* cx, CallArgs args)
@@ -1375,18 +1374,16 @@ MapObject::size(JSContext* cx, unsigned 
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::size_impl>(cx, args);
 }
 
 bool
 MapObject::get(JSContext* cx, HandleObject obj,
                HandleValue key, MutableHandleValue rval)
 {
-    MOZ_ASSERT(MapObject::is(obj));
-
     ValueMap& map = extract(obj);
     AutoHashableValueRooter k(cx);
 
     if (!k.setValue(cx, key))
         return false;
 
     if (ValueMap::Entry* p = map.get(k))
         rval.set(p->value);
@@ -1408,18 +1405,16 @@ MapObject::get(JSContext* cx, unsigned a
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::get_impl>(cx, args);
 }
 
 bool
 MapObject::has(JSContext* cx, HandleObject obj, HandleValue key, bool* rval)
 {
-    MOZ_ASSERT(MapObject::is(obj));
-
     ValueMap& map = extract(obj);
     AutoHashableValueRooter k(cx);
 
     if (!k.setValue(cx, key))
         return false;
 
     *rval = map.has(k);
     return true;
@@ -1464,17 +1459,33 @@ MapObject::set_impl(JSContext* cx, CallA
 bool
 MapObject::set(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::set_impl>(cx, args);
 }
 
 bool
-MapObject::delete_impl(JSContext* cx, CallArgs args)
+MapObject::delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
+{
+    ValueMap &map = extract(obj);
+    AutoHashableValueRooter k(cx);
+
+    if (!k.setValue(cx, key))
+        return false;
+
+    if (!map.remove(k, rval)) {
+        ReportOutOfMemory(cx);
+        return false;
+    }
+    return true;
+}
+
+bool
+MapObject::delete_impl(JSContext *cx, CallArgs args)
 {
     // MapObject::mark does not mark deleted entries. Incremental GC therefore
     // requires that no RelocatableValue objects pointing to heap values be
     // left alive in the ValueMap.
     //
     // OrderedHashMap::remove() doesn't destroy the removed entry. It merely
     // calls OrderedHashMap::MapOps::makeEmpty. But that is sufficient, because
     // makeEmpty clears the value by doing e->value = Value(), and in the case
@@ -1499,17 +1510,16 @@ MapObject::delete_(JSContext* cx, unsign
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<MapObject::is, MapObject::delete_impl>(cx, args);
 }
 
 bool
 MapObject::iterator(JSContext* cx, IteratorKind kind,
                     HandleObject obj, MutableHandleValue iter)
 {
-    MOZ_ASSERT(MapObject::is(obj));
     ValueMap& map = extract(obj);
     Rooted<JSObject*> iterobj(cx, MapIteratorObject::create(cx, obj, &map, kind));
     return iterobj && (iter.setObject(*iterobj), true);
 }
 
 bool
 MapObject::iterator_impl(JSContext* cx, CallArgs args, IteratorKind kind)
 {
@@ -1569,17 +1579,16 @@ MapObject::clear(JSContext* cx, unsigned
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, is, clear_impl, args);
 }
 
 bool
 MapObject::clear(JSContext* cx, HandleObject obj)
 {
-    MOZ_ASSERT(MapObject::is(obj));
     ValueMap& map = extract(obj);
     if (!map.clear()) {
         ReportOutOfMemory(cx);
         return false;
     }
     return true;
 }
 
@@ -1956,24 +1965,47 @@ SetObject::construct(JSContext* cx, unsi
 }
 
 bool
 SetObject::is(HandleValue v)
 {
     return v.isObject() && v.toObject().hasClass(&class_) && v.toObject().as<SetObject>().getPrivate();
 }
 
-ValueSet&
+bool
+SetObject::is(HandleObject o)
+{
+    return o->hasClass(&class_) && o->as<SetObject>().getPrivate();
+}
+
+ValueSet &
+SetObject::extract(HandleObject o)
+{
+    MOZ_ASSERT(o->hasClass(&SetObject::class_));
+    return *o->as<SetObject>().getData();
+}
+
+ValueSet &
 SetObject::extract(CallReceiver call)
 {
     MOZ_ASSERT(call.thisv().isObject());
     MOZ_ASSERT(call.thisv().toObject().hasClass(&SetObject::class_));
     return *static_cast<SetObject&>(call.thisv().toObject()).getData();
 }
 
+uint32_t
+SetObject::size(JSContext *cx, HandleObject obj)
+{
+    MOZ_ASSERT(SetObject::is(obj));
+    ValueSet &set = extract(obj);
+    static_assert(sizeof(set.count()) <= sizeof(uint32_t),
+                  "set count must be precisely representable as a JS number");
+    return set.count();
+}
+
 bool
 SetObject::size_impl(JSContext* cx, CallArgs args)
 {
     MOZ_ASSERT(is(args.thisv()));
 
     ValueSet& set = extract(args);
     static_assert(sizeof(set.count()) <= sizeof(uint32_t),
                   "set count must be precisely representable as a JS number");
@@ -1995,17 +2027,32 @@ SetObject::has_impl(JSContext* cx, CallA
 
     ValueSet& set = extract(args);
     ARG0_KEY(cx, args, key);
     args.rval().setBoolean(set.has(key));
     return true;
 }
 
 bool
-SetObject::has(JSContext* cx, unsigned argc, Value* vp)
+SetObject::has(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
+{
+    MOZ_ASSERT(SetObject::is(obj));
+
+    ValueSet &set = extract(obj);
+    AutoHashableValueRooter k(cx);
+
+    if (!k.setValue(cx, key))
+        return false;
+
+    *rval = set.has(k);
+    return true;
+}
+
+bool
+SetObject::has(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<SetObject::is, SetObject::has_impl>(cx, args);
 }
 
 bool
 SetObject::add_impl(JSContext* cx, CallArgs args)
 {
@@ -2025,17 +2072,35 @@ SetObject::add_impl(JSContext* cx, CallA
 bool
 SetObject::add(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<SetObject::is, SetObject::add_impl>(cx, args);
 }
 
 bool
-SetObject::delete_impl(JSContext* cx, CallArgs args)
+SetObject::delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
+{
+    MOZ_ASSERT(SetObject::is(obj));
+
+    ValueSet &set = extract(obj);
+    AutoHashableValueRooter k(cx);
+
+    if (!k.setValue(cx, key))
+        return false;
+
+    if (!set.remove(k, rval)) {
+        ReportOutOfMemory(cx);
+        return false;
+    }
+    return true;
+}
+
+bool
+SetObject::delete_impl(JSContext *cx, CallArgs args)
 {
     MOZ_ASSERT(is(args.thisv()));
 
     ValueSet& set = extract(args);
     ARG0_KEY(cx, args, key);
     bool found;
     if (!set.remove(key, &found)) {
         ReportOutOfMemory(cx);
@@ -2048,17 +2113,27 @@ SetObject::delete_impl(JSContext* cx, Ca
 bool
 SetObject::delete_(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<SetObject::is, SetObject::delete_impl>(cx, args);
 }
 
 bool
-SetObject::iterator_impl(JSContext* cx, CallArgs args, IteratorKind kind)
+SetObject::iterator(JSContext *cx, IteratorKind kind,
+                    HandleObject obj, MutableHandleValue iter)
+{
+    MOZ_ASSERT(SetObject::is(obj));
+    ValueSet &set = extract(obj);
+    Rooted<JSObject*> iterobj(cx, SetIteratorObject::create(cx, obj, &set, kind));
+    return iterobj && (iter.setObject(*iterobj), true);
+}
+
+bool
+SetObject::iterator_impl(JSContext *cx, CallArgs args, IteratorKind kind)
 {
     Rooted<SetObject*> setobj(cx, &args.thisv().toObject().as<SetObject>());
     ValueSet& set = *setobj->getData();
     Rooted<JSObject*> iterobj(cx, SetIteratorObject::create(cx, setobj, &set, kind));
     if (!iterobj)
         return false;
     args.rval().setObject(*iterobj);
     return true;
@@ -2086,17 +2161,29 @@ SetObject::entries_impl(JSContext* cx, C
 bool
 SetObject::entries(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod(cx, is, entries_impl, args);
 }
 
 bool
-SetObject::clear_impl(JSContext* cx, CallArgs args)
+SetObject::clear(JSContext *cx, HandleObject obj)
+{
+    MOZ_ASSERT(SetObject::is(obj));
+    ValueSet &set = extract(obj);
+    if (!set.clear()) {
+        ReportOutOfMemory(cx);
+        return false;
+    }
+    return true;
+}
+
+bool
+SetObject::clear_impl(JSContext *cx, CallArgs args)
 {
     Rooted<SetObject*> setobj(cx, &args.thisv().toObject().as<SetObject>());
     if (!setobj->getData()->clear()) {
         ReportOutOfMemory(cx);
         return false;
     }
     args.rval().setUndefined();
     return true;
@@ -2122,79 +2209,290 @@ const JSFunctionSpec selfhosting_collect
 };
 
 bool
 js::InitSelfHostingCollectionIteratorFunctions(JSContext* cx, HandleObject obj)
 {
     return JS_DefineFunctions(cx, obj, selfhosting_collection_iterator_methods);
 }
 
+/*** JS static utility functions *********************************************/
+
+static
+bool
+forEach(const char* funcName, JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisArg)
+{
+    CHECK_REQUEST(cx);
+    RootedId forEachId(cx, NameToId(cx->names().forEach));
+    RootedFunction forEachFunc(cx, JS::GetSelfHostedFunction(cx, funcName, forEachId, 2));
+    if (!forEachFunc)
+        return false;
+    InvokeArgs args(cx);
+    if (!args.init(2))
+        return false;
+    args.setCallee(JS::ObjectValue(*forEachFunc));
+    args.setThis(JS::ObjectValue(*obj));
+    args[0].set(callbackFn);
+    args[1].set(thisArg);
+    return Invoke(cx, args);
+}
+
+// Handles Clear/Size for public jsapi map/set access
+template<typename RetT>
+RetT
+CallObjFunc(RetT(*ObjFunc)(JSContext*, HandleObject), JSContext* cx, HandleObject obj)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj);
+
+    // Always unwrap, in case this is an xray or cross-compartment wrapper.
+    RootedObject unwrappedObj(cx);
+    unwrappedObj = UncheckedUnwrap(obj);
+
+    // Enter the compartment of the backing object before calling functions on
+    // it.
+    JSAutoCompartment ac(cx, unwrappedObj);
+    return ObjFunc(cx, unwrappedObj);
+}
+
+// Handles Has/Delete for public jsapi map/set access
+bool
+CallObjFunc(bool(*ObjFunc)(JSContext *cx, HandleObject obj, HandleValue key, bool *rval),
+            JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj, key);
+
+    // Always unwrap, in case this is an xray or cross-compartment wrapper.
+    RootedObject unwrappedObj(cx);
+    unwrappedObj = UncheckedUnwrap(obj);
+    JSAutoCompartment ac(cx, unwrappedObj);
+
+    // If we're working with a wrapped map/set, rewrap the key into the
+    // compartment of the unwrapped map/set.
+    RootedValue wrappedKey(cx, key);
+    if (obj != unwrappedObj) {
+        if (!JS_WrapValue(cx, &wrappedKey))
+            return false;
+    }
+    return ObjFunc(cx, unwrappedObj, wrappedKey, rval);
+}
+
+// Handles iterator generation for public jsapi map/set access
+template<typename Iter>
+bool
+CallObjFunc(bool(*ObjFunc)(JSContext* cx, Iter kind,
+                           HandleObject obj, MutableHandleValue iter),
+            JSContext *cx, Iter iterType, HandleObject obj, MutableHandleValue rval)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj);
+
+    // Always unwrap, in case this is an xray or cross-compartment wrapper.
+    RootedObject unwrappedObj(cx);
+    unwrappedObj = UncheckedUnwrap(obj);
+    {
+        // Retrieve the iterator while in the unwrapped map/set's compartment,
+        // otherwise we'll crash on a compartment assert.
+        JSAutoCompartment ac(cx, unwrappedObj);
+        if (!ObjFunc(cx, iterType, unwrappedObj, rval))
+            return false;
+    }
+
+    // If the caller is in a different compartment than the map/set, rewrap the
+    // iterator object into the caller's compartment.
+    if (obj != unwrappedObj) {
+        if (!JS_WrapValue(cx, rval))
+            return false;
+    }
+    return true;
+}
+
 /*** JS public APIs **********************************************************/
 
 JS_PUBLIC_API(JSObject*)
 JS::NewMapObject(JSContext* cx)
 {
     return MapObject::create(cx);
 }
 
 JS_PUBLIC_API(uint32_t)
 JS::MapSize(JSContext* cx, HandleObject obj)
 {
-    CHECK_REQUEST(cx);
-    return MapObject::size(cx, obj);
+    return CallObjFunc<uint32_t>(&MapObject::size, cx, obj);
 }
 
 JS_PUBLIC_API(bool)
-JS::MapGet(JSContext* cx, HandleObject obj,
-           HandleValue key, MutableHandleValue rval)
+JS::MapGet(JSContext* cx, HandleObject obj, HandleValue key, MutableHandleValue rval)
 {
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, key, rval);
-    return MapObject::get(cx, obj, key, rval);
+    assertSameCompartment(cx, obj, key, rval);
+
+    // Unwrap the object, and enter its compartment. If object isn't wrapped,
+    // this is essentially a noop.
+    RootedObject unwrappedObj(cx);
+    unwrappedObj = UncheckedUnwrap(obj);
+    {
+        JSAutoCompartment ac(cx, unwrappedObj);
+        RootedValue wrappedKey(cx, key);
+
+        // If we passed in a wrapper, wrap our key into its compartment now.
+        if (obj != unwrappedObj) {
+            if (!JS_WrapValue(cx, &wrappedKey))
+                return false;
+        }
+        if (!MapObject::get(cx, unwrappedObj, wrappedKey, rval))
+            return false;
+    }
+
+    // If we passed in a wrapper, wrap our return value on the way out.
+    if (obj != unwrappedObj) {
+        if (!JS_WrapValue(cx, rval))
+            return false;
+    }
+    return true;
+}
+
+JS_PUBLIC_API(bool)
+JS::MapSet(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, obj, key, val);
+
+    // Unwrap the object, and enter its compartment. If object isn't wrapped,
+    // this is essentially a noop.
+    RootedObject unwrappedObj(cx);
+    unwrappedObj = UncheckedUnwrap(obj);
+    {
+        JSAutoCompartment ac(cx, unwrappedObj);
+
+        // If we passed in a wrapper, wrap both key and value before adding to
+        // the map
+        RootedValue wrappedKey(cx, key);
+        RootedValue wrappedValue(cx, val);
+        if (obj != unwrappedObj) {
+            if (!JS_WrapValue(cx, &wrappedKey) ||
+                !JS_WrapValue(cx, &wrappedValue)) {
+                return false;
+            }
+        }
+        return MapObject::set(cx, unwrappedObj, wrappedKey, wrappedValue);
+    }
 }
 
 JS_PUBLIC_API(bool)
 JS::MapHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval)
 {
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, key);
-    return MapObject::has(cx, obj, key, rval);
+    return CallObjFunc(MapObject::has, cx, obj, key, rval);
 }
 
 JS_PUBLIC_API(bool)
-JS::MapSet(JSContext* cx, HandleObject obj,
-           HandleValue key, HandleValue val)
+JS::MapDelete(JSContext *cx, HandleObject obj, HandleValue key, bool* rval)
 {
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, key, val);
-    return MapObject::set(cx, obj, key, val);
+    return CallObjFunc(MapObject::delete_, cx, obj, key, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS::MapClear(JSContext* cx, HandleObject obj)
 {
-    CHECK_REQUEST(cx);
-    return MapObject::clear(cx, obj);
+    return CallObjFunc(&MapObject::clear, cx, obj);
 }
 
 JS_PUBLIC_API(bool)
 JS::MapKeys(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, rval);
-    return MapObject::iterator(cx, MapObject::Keys, obj, rval);
+    return CallObjFunc(&MapObject::iterator, cx, MapObject::Keys, obj, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS::MapValues(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, rval);
-    return MapObject::iterator(cx, MapObject::Values, obj, rval);
+    return CallObjFunc(&MapObject::iterator, cx, MapObject::Values, obj, rval);
 }
 
 JS_PUBLIC_API(bool)
 JS::MapEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval)
 {
+    return CallObjFunc(&MapObject::iterator, cx, MapObject::Entries, obj, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::MapForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal)
+{
+    return forEach("MapForEach", cx, obj, callbackFn, thisVal);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS::NewSetObject(JSContext *cx)
+{
+    return SetObject::create(cx);
+}
+
+JS_PUBLIC_API(uint32_t)
+JS::SetSize(JSContext *cx, HandleObject obj)
+{
+    return CallObjFunc<uint32_t>(&SetObject::size, cx, obj);
+}
+
+JS_PUBLIC_API(bool)
+JS::SetAdd(JSContext *cx, HandleObject obj, HandleValue key)
+{
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, rval);
-    return MapObject::iterator(cx, MapObject::Entries, obj, rval);
+    assertSameCompartment(cx, obj, key);
+
+    // Unwrap the object, and enter its compartment. If object isn't wrapped,
+    // this is essentially a noop.
+    RootedObject unwrappedObj(cx);
+    unwrappedObj = UncheckedUnwrap(obj);
+    {
+        JSAutoCompartment ac(cx, unwrappedObj);
+
+        // If we passed in a wrapper, wrap key before adding to the set
+        RootedValue wrappedKey(cx, key);
+        if (obj != unwrappedObj) {
+            if (!JS_WrapValue(cx, &wrappedKey))
+                return false;
+        }
+        return SetObject::add(cx, unwrappedObj, wrappedKey);
+    }
+}
+
+JS_PUBLIC_API(bool)
+JS::SetHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval)
+{
+    return CallObjFunc(SetObject::has, cx, obj, key, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::SetDelete(JSContext *cx, HandleObject obj, HandleValue key, bool *rval)
+{
+    return CallObjFunc(SetObject::delete_, cx, obj, key, rval);
 }
+
+JS_PUBLIC_API(bool)
+JS::SetClear(JSContext* cx, HandleObject obj)
+{
+    return CallObjFunc(&SetObject::clear, cx, obj);
+}
+
+JS_PUBLIC_API(bool)
+JS::SetKeys(JSContext* cx, HandleObject obj, MutableHandleValue rval)
+{
+    return SetValues(cx, obj, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::SetValues(JSContext* cx, HandleObject obj, MutableHandleValue rval)
+{
+    return CallObjFunc(&SetObject::iterator, cx, SetObject::Values, obj, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::SetEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval)
+{
+    return CallObjFunc(&SetObject::iterator, cx, SetObject::Entries, obj, rval);
+}
+
+JS_PUBLIC_API(bool)
+JS::SetForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal)
+{
+    return forEach("SetForEach", cx, obj, callbackFn, thisVal);
+}
--- a/js/src/builtin/MapObject.h
+++ b/js/src/builtin/MapObject.h
@@ -93,22 +93,29 @@ class MapObject : public NativeObject {
     static const Class class_;
 
     static bool getKeysAndValuesInterleaved(JSContext* cx, HandleObject obj,
                                             JS::AutoValueVector* entries);
     static bool entries(JSContext* cx, unsigned argc, Value* vp);
     static bool has(JSContext* cx, unsigned argc, Value* vp);
     static MapObject* create(JSContext* cx);
 
-    static uint32_t size(JSContext* cx, HandleObject obj);
-    static bool get(JSContext* cx, HandleObject obj, HandleValue key, MutableHandleValue rval);
-    static bool has(JSContext* cx, HandleObject obj, HandleValue key, bool* rval);
-    static bool set(JSContext* cx, HandleObject obj, HandleValue key, HandleValue val);
-    static bool clear(JSContext* cx, HandleObject obj);
-    static bool iterator(JSContext* cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
+    // Publicly exposed Map calls for JSAPI access (webidl maplike/setlike
+    // interfaces, etc.)
+    static uint32_t size(JSContext *cx, HandleObject obj);
+    static bool get(JSContext *cx, HandleObject obj, HandleValue key, MutableHandleValue rval);
+    static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
+    static bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
+
+    // Set call for public JSAPI exposure. Does not actually return map object
+    // as stated in spec, expects caller to return a value. for instance, with
+    // webidl maplike/setlike, should return interface object.
+    static bool set(JSContext *cx, HandleObject obj, HandleValue key, HandleValue val);
+    static bool clear(JSContext *cx, HandleObject obj);
+    static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
 
   private:
     static const JSPropertySpec properties[];
     static const JSFunctionSpec methods[];
     static const JSPropertySpec staticProperties[];
     ValueMap* getData() { return static_cast<ValueMap*>(getPrivate()); }
     static ValueMap & extract(HandleObject o);
     static ValueMap & extract(CallReceiver call);
@@ -140,33 +147,43 @@ class MapObject : public NativeObject {
 };
 
 class SetObject : public NativeObject {
   public:
     enum IteratorKind { Values, Entries };
     static JSObject* initClass(JSContext* cx, JSObject* obj);
     static const Class class_;
 
-    static bool keys(JSContext* cx, HandleObject obj, JS::AutoValueVector* keys);
-    static bool values(JSContext* cx, unsigned argc, Value* vp);
-    static bool add(JSContext* cx, HandleObject obj, HandleValue key);
-    static bool has(JSContext* cx, unsigned argc, Value* vp);
-    static SetObject* create(JSContext* cx);
+    static bool keys(JSContext *cx, HandleObject obj, JS::AutoValueVector *keys);
+    static bool values(JSContext *cx, unsigned argc, Value *vp);
+    static bool add(JSContext *cx, HandleObject obj, HandleValue key);
+    static bool has(JSContext *cx, unsigned argc, Value *vp);
+
+    // Publicly exposed Set calls for JSAPI access (webidl maplike/setlike
+    // interfaces, etc.)
+    static SetObject* create(JSContext *cx);
+    static uint32_t size(JSContext *cx, HandleObject obj);
+    static bool has(JSContext *cx, HandleObject obj, HandleValue key, bool* rval);
+    static bool clear(JSContext *cx, HandleObject obj);
+    static bool iterator(JSContext *cx, IteratorKind kind, HandleObject obj, MutableHandleValue iter);
+    static bool delete_(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
 
   private:
     static const JSPropertySpec properties[];
     static const JSFunctionSpec methods[];
     static const JSPropertySpec staticProperties[];
     ValueSet* getData() { return static_cast<ValueSet*>(getPrivate()); }
+    static ValueSet & extract(HandleObject o);
     static ValueSet & extract(CallReceiver call);
     static void mark(JSTracer* trc, JSObject* obj);
     static void finalize(FreeOp* fop, JSObject* obj);
     static bool construct(JSContext* cx, unsigned argc, Value* vp);
 
     static bool is(HandleValue v);
+    static bool is(HandleObject o);
 
     static bool iterator_impl(JSContext* cx, CallArgs args, IteratorKind kind);
 
     static bool size_impl(JSContext* cx, CallArgs args);
     static bool size(JSContext* cx, unsigned argc, Value* vp);
     static bool has_impl(JSContext* cx, CallArgs args);
     static bool add_impl(JSContext* cx, CallArgs args);
     static bool add(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -107,16 +107,24 @@ GetBuildConfiguration(JSContext* cx, uns
 #ifdef JS_SIMULATOR_ARM
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
     if (!JS_SetProperty(cx, info, "arm-simulator", value))
         return false;
 
+#ifdef JS_SIMULATOR_ARM64
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "arm64-simulator", value))
+        return false;
+
 #ifdef MOZ_ASAN
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
     if (!JS_SetProperty(cx, info, "asan", value))
         return false;
 
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2470,17 +2470,17 @@ if test "$ac_cv_clock_monotonic" != "no"
     AC_DEFINE(HAVE_CLOCK_MONOTONIC)
     AC_SUBST(HAVE_CLOCK_MONOTONIC)
     AC_SUBST_LIST(REALTIME_LIBS)
 fi
 
 dnl Checks for math functions.
 dnl ========================================================
 AC_CHECK_LIB(m, sin)
-AC_CHECK_FUNCS([log2 log1p expm1 sqrt1pm1 acosh asinh atanh trunc cbrt])
+AC_CHECK_FUNCS([log2 log1p expm1 sqrt1pm1 acosh asinh atanh cbrt])
 
 
 dnl check for wcrtomb/mbrtowc
 dnl =======================================================================
 if test -z "$MACOS_DEPLOYMENT_TARGET" || test "$MACOS_DEPLOYMENT_TARGET" -ge "100300"; then
 AC_LANG_SAVE
 AC_LANG_CPLUSPLUS
 AC_CACHE_CHECK(for wcrtomb,
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -1884,17 +1884,18 @@ InitTypeClasses(JSContext* cx, HandleObj
   // that are still using jschar (bug 1064935).
   if (!JS_DefineProperty(cx, ctypesObj, "jschar", typeObj_char16_t,
                          JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
     return false;
 
   // Create objects representing the special types void_t and voidptr_t.
   RootedObject typeObj(cx,
     CType::DefineBuiltin(cx, ctypesObj, "void_t", CTypeProto, CDataProto, "void",
-                         TYPE_void_t, JSVAL_VOID, JSVAL_VOID, &ffi_type_void));
+                         TYPE_void_t, JS::UndefinedValue(), JS::UndefinedValue(),
+                         &ffi_type_void));
   if (!typeObj)
     return false;
 
   typeObj = PointerType::CreateInternal(cx, typeObj);
   if (!typeObj)
     return false;
   if (!JS_DefineProperty(cx, ctypesObj, "voidptr_t", typeObj,
                          JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT))
@@ -4186,17 +4187,17 @@ CType::TypesEqual(JSObject* t1, JSObject
 
 bool
 CType::GetSafeSize(JSObject* obj, size_t* result)
 {
   MOZ_ASSERT(CType::IsCType(obj));
 
   jsval size = JS_GetReservedSlot(obj, SLOT_SIZE);
 
-  // The "size" property can be an int, a double, or JSVAL_VOID
+  // The "size" property can be an int, a double, or JS::UndefinedValue()
   // (for arrays of undefined length), and must always fit in a size_t.
   if (size.isInt32()) {
     *result = size.toInt32();
     return true;
   }
   if (size.isDouble()) {
     *result = Convert<size_t>(size.toDouble());
     return true;
@@ -4210,32 +4211,33 @@ size_t
 CType::GetSize(JSObject* obj)
 {
   MOZ_ASSERT(CType::IsCType(obj));
 
   jsval size = JS_GetReservedSlot(obj, SLOT_SIZE);
 
   MOZ_ASSERT(!size.isUndefined());
 
-  // The "size" property can be an int, a double, or JSVAL_VOID
+  // The "size" property can be an int, a double, or JS::UndefinedValue()
   // (for arrays of undefined length), and must always fit in a size_t.
-  // For callers who know it can never be JSVAL_VOID, return a size_t directly.
+  // For callers who know it can never be JS::UndefinedValue(), return a size_t
+  // directly.
   if (size.isInt32())
     return size.toInt32();
   return Convert<size_t>(size.toDouble());
 }
 
 bool
 CType::IsSizeDefined(JSObject* obj)
 {
   MOZ_ASSERT(CType::IsCType(obj));
 
   jsval size = JS_GetReservedSlot(obj, SLOT_SIZE);
 
-  // The "size" property can be an int, a double, or JSVAL_VOID
+  // The "size" property can be an int, a double, or JS::UndefinedValue()
   // (for arrays of undefined length), and must always fit in a size_t.
   MOZ_ASSERT(size.isInt32() || size.isDouble() || size.isUndefined());
   return !size.isUndefined();
 }
 
 size_t
 CType::GetAlignment(JSObject* obj)
 {
@@ -4704,17 +4706,17 @@ PointerType::ConstructData(JSContext* cx
     } else if (!JS_ValueToObject(cx, args[1], &thisObj)) {
       return false;
     }
   }
 
   // The third argument is an optional error sentinel that js-ctypes will return
   // if an exception is raised while executing the closure. The type must match
   // the return type of the callback.
-  jsval errVal = JSVAL_VOID;
+  Value errVal = JS::UndefinedValue();
   if (args.length() == 3)
     errVal = args[2];
 
   RootedObject fnObj(cx, &args[0].toObject());
   return FunctionType::ConstructData(cx, baseObj, result, fnObj, thisObj, errVal);
 }
 
 JSObject*
@@ -4925,18 +4927,18 @@ ArrayType::CreateInternal(JSContext* cx,
   // The size of the base type must be defined.
   // If our length is undefined, both our size and length will be undefined.
   size_t baseSize;
   if (!CType::GetSafeSize(baseType, &baseSize)) {
     JS_ReportError(cx, "base size must be defined");
     return nullptr;
   }
 
-  RootedValue sizeVal(cx, JSVAL_VOID);
-  RootedValue lengthVal(cx, JSVAL_VOID);
+  RootedValue sizeVal(cx, JS::UndefinedValue());
+  RootedValue lengthVal(cx, JS::UndefinedValue());
   if (lengthDefined) {
     // Check for overflow, and convert to an int or double as required.
     size_t size = length * baseSize;
     if (length > 0 && size / length != baseSize) {
       JS_ReportError(cx, "size overflow");
       return nullptr;
     }
     if (!SizeTojsval(cx, size, &sizeVal) ||
@@ -5079,17 +5081,17 @@ ArrayType::GetBaseType(JSObject* obj)
 bool
 ArrayType::GetSafeLength(JSObject* obj, size_t* result)
 {
   MOZ_ASSERT(CType::IsCType(obj));
   MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_array);
 
   jsval length = JS_GetReservedSlot(obj, SLOT_LENGTH);
 
-  // The "length" property can be an int, a double, or JSVAL_VOID
+  // The "length" property can be an int, a double, or JS::UndefinedValue()
   // (for arrays of undefined length), and must always fit in a size_t.
   if (length.isInt32()) {
     *result = length.toInt32();
     return true;
   }
   if (length.isDouble()) {
     *result = Convert<size_t>(length.toDouble());
     return true;
@@ -5104,19 +5106,20 @@ ArrayType::GetLength(JSObject* obj)
 {
   MOZ_ASSERT(CType::IsCType(obj));
   MOZ_ASSERT(CType::GetTypeCode(obj) == TYPE_array);
 
   jsval length = JS_GetReservedSlot(obj, SLOT_LENGTH);
 
   MOZ_ASSERT(!length.isUndefined());
 
-  // The "length" property can be an int, a double, or JSVAL_VOID
+  // The "length" property can be an int, a double, or JS::UndefinedValue()
   // (for arrays of undefined length), and must always fit in a size_t.
-  // For callers who know it can never be JSVAL_VOID, return a size_t directly.
+  // For callers who know it can never be JS::UndefinedValue(), return a size_t
+  // directly.
   if (length.isInt32())
     return length.toInt32();
   return Convert<size_t>(length.toDouble());
 }
 
 UniquePtrFFIType
 ArrayType::BuildFFIType(JSContext* cx, JSObject* obj)
 {
@@ -5436,17 +5439,18 @@ StructType::Create(JSContext* cx, unsign
 
   // Get ctypes.StructType.prototype from the ctypes.StructType constructor.
   RootedObject typeProto(cx, CType::GetProtoFromCtor(&args.callee(), SLOT_STRUCTPROTO));
 
   // Create a simple StructType with no defined fields. The result will be
   // non-instantiable as CData, will have no 'prototype' property, and will
   // have undefined size and alignment and no ffi_type.
   RootedObject result(cx, CType::Create(cx, typeProto, nullptr, TYPE_struct,
-                                        name.toString(), JSVAL_VOID, JSVAL_VOID, nullptr));
+                                        name.toString(), JS::UndefinedValue(),
+                                        JS::UndefinedValue(), nullptr));
   if (!result)
     return false;
 
   if (args.length() == 2) {
     RootedObject arr(cx, args[1].isPrimitive() ? nullptr : &args[1].toObject());
     if (!arr || !JS_IsArrayObject(cx, arr)) {
       return ArgumentTypeMismatch(cx, "second ", "StructType", "an array");
     }
@@ -6421,17 +6425,18 @@ FunctionType::CreateInternal(JSContext* 
   if (!typeProto)
     return nullptr;
   RootedObject dataProto(cx, CType::GetProtoFromType(cx, returnType, SLOT_FUNCTIONDATAPROTO));
   if (!dataProto)
     return nullptr;
 
   // Create a new CType object with the common properties and slots.
   RootedObject typeObj(cx, CType::Create(cx, typeProto, dataProto, TYPE_function,
-                                         nullptr, JSVAL_VOID, JSVAL_VOID, nullptr));
+                                         nullptr, JS::UndefinedValue(),
+                                         JS::UndefinedValue(), nullptr));
   if (!typeObj)
     return nullptr;
 
   // Determine and check the types, and prepare the function CIF.
   if (!CreateFunctionInfo(cx, typeObj, abi, returnType, args))
       return nullptr;
 
   return typeObj;
@@ -7946,17 +7951,17 @@ CDataFinalizer::Methods::Dispose(JSConte
   MOZ_ASSERT(valCodePtrType.isObject());
   JSObject* objCodePtrType = &valCodePtrType.toObject();
 
   JSObject* objCodeType = PointerType::GetBaseType(objCodePtrType);
   MOZ_ASSERT(objCodeType);
   MOZ_ASSERT(CType::GetTypeCode(objCodeType) == TYPE_function);
 
   RootedObject resultType(cx, FunctionType::GetFunctionInfo(objCodeType)->mReturnType);
-  RootedValue result(cx, JSVAL_VOID);
+  RootedValue result(cx, JS::UndefinedValue());
 
   int errnoStatus;
 #if defined(XP_WIN)
   int32_t lastErrorStatus;
   CDataFinalizer::CallFinalizer(p, &errnoStatus, &lastErrorStatus);
 #else
   CDataFinalizer::CallFinalizer(p, &errnoStatus, nullptr);
 #endif // defined(XP_WIN)
@@ -8024,17 +8029,17 @@ CDataFinalizer::Cleanup(CDataFinalizer::
   if (!obj) {
     return;  // No slots to clean up
   }
 
   MOZ_ASSERT(CDataFinalizer::IsCDataFinalizer(obj));
 
   JS_SetPrivate(obj, nullptr);
   for (int i = 0; i < CDATAFINALIZER_SLOTS; ++i) {
-    JS_SetReservedSlot(obj, i, JSVAL_NULL);
+    JS_SetReservedSlot(obj, i, JS::NullValue());
   }
 }
 
 
 /*******************************************************************************
 ** Int64 and UInt64 implementation
 *******************************************************************************/
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -3467,17 +3467,17 @@ Parser<FullParseHandler>::checkDestructu
             MOZ_ASSERT(member->isKind(PNK_COLON) || member->isKind(PNK_SHORTHAND));
             MOZ_ASSERT_IF(member->isKind(PNK_SHORTHAND),
                           member->pn_left->isKind(PNK_OBJECT_PROPERTY_NAME) &&
                           member->pn_right->isKind(PNK_NAME) &&
                           member->pn_left->pn_atom == member->pn_right->pn_atom);
 
             target = member->pn_right;
         }
-        if (target->isKind(PNK_ASSIGN))
+        if (handler.isUnparenthesizedAssignment(target))
             target = target->pn_left;
 
         if (handler.isUnparenthesizedDestructuringPattern(target)) {
             if (!checkDestructuringPattern(data, target))
                 return false;
         } else {
             if (!checkDestructuringName(data, target))
                 return false;
@@ -3505,17 +3505,17 @@ Parser<FullParseHandler>::checkDestructu
                 return false;
             }
             target = element->pn_kid;
 
             if (handler.isUnparenthesizedDestructuringPattern(target)) {
                 report(ParseError, false, target, JSMSG_BAD_DESTRUCT_TARGET);
                 return false;
             }
-        } else if (element->isKind(PNK_ASSIGN)) {
+        } else if (handler.isUnparenthesizedAssignment(element)) {
             target = element->pn_left;
         } else {
             target = element;
         }
 
         if (handler.isUnparenthesizedDestructuringPattern(target)) {
             if (!checkDestructuringPattern(data, target))
                 return false;
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -272,27 +272,27 @@ struct InternalGCMethods<Value>
         }
     }
 
     static void postBarrierRelocate(Value* vp) {
         MOZ_ASSERT(!CurrentThreadIsIonCompiling());
         if (vp->isObject()) {
             gc::StoreBuffer* sb = reinterpret_cast<gc::Cell*>(&vp->toObject())->storeBuffer();
             if (sb)
-                sb->putRelocatableValueFromAnyThread(vp);
+                sb->putValueFromAnyThread(vp);
         }
     }
 
     static void postBarrierRemove(Value* vp) {
         MOZ_ASSERT(vp);
         MOZ_ASSERT(vp->isMarkable());
         MOZ_ASSERT(!CurrentThreadIsIonCompiling());
         JSRuntime* rt = static_cast<js::gc::Cell*>(vp->toGCThing())->runtimeFromAnyThread();
         JS::shadow::Runtime* shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
-        shadowRuntime->gcStoreBufferPtr()->removeRelocatableValueFromAnyThread(vp);
+        shadowRuntime->gcStoreBufferPtr()->unputValueFromAnyThread(vp);
     }
 
     static void readBarrier(const Value& v) {
         DispatchValueTyped(ReadBarrierFunctor<Value>(), v);
     }
 };
 
 template <>
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -440,24 +440,16 @@ js::Nursery::collect(JSRuntime* rt, JS::
     TIME_START(traceSlots);
     sb.traceSlots(mover);
     TIME_END(traceSlots);
 
     TIME_START(traceWholeCells);
     sb.traceWholeCells(mover);
     TIME_END(traceWholeCells);
 
-    TIME_START(traceRelocatableValues);
-    sb.traceRelocatableValues(mover);
-    TIME_END(traceRelocatableValues);
-
-    TIME_START(traceRelocatableCells);
-    sb.traceRelocatableCells(mover);
-    TIME_END(traceRelocatableCells);
-
     TIME_START(traceGenericEntries);
     sb.traceGenericEntries(&mover);
     TIME_END(traceGenericEntries);
 
     TIME_START(markRuntime);
     rt->gc.markRuntime(&mover);
     TIME_END(markRuntime);
 
@@ -552,34 +544,32 @@ js::Nursery::collect(JSRuntime* rt, JS::
         rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON_LONG, reason);
 
     TraceMinorGCEnd();
 
     if (enableProfiling_ && totalTime >= profileThreshold_) {
         static bool printedHeader = false;
         if (!printedHeader) {
             fprintf(stderr,
-                    "MinorGC: Reason               PRate  Size Time   mkVals mkClls mkSlts mkWCll mkRVal mkRCll mkGnrc ckTbls mkRntm mkDbgr clrNOC collct swpABO updtIn runFin frSlts clrSB  sweep resize pretnr\n");
+                    "MinorGC: Reason               PRate  Size Time   mkVals mkClls mkSlts mkWCll mkGnrc ckTbls mkRntm mkDbgr clrNOC collct swpABO updtIn runFin frSlts clrSB  sweep resize pretnr\n");
             printedHeader = true;
         }
 
 #define FMT " %6" PRIu64
         fprintf(stderr,
-                "MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n",
+                "MinorGC: %20s %5.1f%% %4d" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n",
                 js::gcstats::ExplainReason(reason),
                 promotionRate * 100,
                 numActiveChunks_,
                 totalTime,
                 TIME_TOTAL(cancelIonCompilations),
                 TIME_TOTAL(traceValues),
                 TIME_TOTAL(traceCells),
                 TIME_TOTAL(traceSlots),
                 TIME_TOTAL(traceWholeCells),
-                TIME_TOTAL(traceRelocatableValues),
-                TIME_TOTAL(traceRelocatableCells),
                 TIME_TOTAL(traceGenericEntries),
                 TIME_TOTAL(checkHashTables),
                 TIME_TOTAL(markRuntime),
                 TIME_TOTAL(markDebugger),
                 TIME_TOTAL(clearNewObjectCache),
                 TIME_TOTAL(collectToFP),
                 TIME_TOTAL(sweepArrayBufferViewList),
                 TIME_TOTAL(updateJitActivations),
--- a/js/src/gc/StoreBuffer.cpp
+++ b/js/src/gc/StoreBuffer.cpp
@@ -39,18 +39,16 @@ StoreBuffer::enable()
 {
     if (enabled_)
         return true;
 
     if (!bufferVal.init() ||
         !bufferCell.init() ||
         !bufferSlot.init() ||
         !bufferWholeCell.init() ||
-        !bufferRelocVal.init() ||
-        !bufferRelocCell.init() ||
         !bufferGeneric.init())
     {
         return false;
     }
 
     enabled_ = true;
     return true;
 }
@@ -74,18 +72,16 @@ StoreBuffer::clear()
 
     aboutToOverflow_ = false;
     cancelIonCompilations_ = false;
 
     bufferVal.clear();
     bufferCell.clear();
     bufferSlot.clear();
     bufferWholeCell.clear();
-    bufferRelocVal.clear();
-    bufferRelocCell.clear();
     bufferGeneric.clear();
 
     return true;
 }
 
 void
 StoreBuffer::setAboutToOverflow()
 {
@@ -99,17 +95,15 @@ StoreBuffer::setAboutToOverflow()
 void
 StoreBuffer::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::GCSizes
 *sizes)
 {
     sizes->storeBufferVals       += bufferVal.sizeOfExcludingThis(mallocSizeOf);
     sizes->storeBufferCells      += bufferCell.sizeOfExcludingThis(mallocSizeOf);
     sizes->storeBufferSlots      += bufferSlot.sizeOfExcludingThis(mallocSizeOf);
     sizes->storeBufferWholeCells += bufferWholeCell.sizeOfExcludingThis(mallocSizeOf);
-    sizes->storeBufferRelocVals  += bufferRelocVal.sizeOfExcludingThis(mallocSizeOf);
-    sizes->storeBufferRelocCells += bufferRelocCell.sizeOfExcludingThis(mallocSizeOf);
     sizes->storeBufferGenerics   += bufferGeneric.sizeOfExcludingThis(mallocSizeOf);
 }
 
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::ValueEdge>;
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::CellPtrEdge>;
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::SlotsEdge>;
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::WholeCellEdges>;
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -376,73 +376,58 @@ class StoreBuffer
         if (edge.maybeInRememberedSet(nursery_))
             buffer.put(this, edge);
     }
 
     MonoTypeBuffer<ValueEdge> bufferVal;
     MonoTypeBuffer<CellPtrEdge> bufferCell;
     MonoTypeBuffer<SlotsEdge> bufferSlot;
     MonoTypeBuffer<WholeCellEdges> bufferWholeCell;
-    MonoTypeBuffer<ValueEdge> bufferRelocVal;
-    MonoTypeBuffer<CellPtrEdge> bufferRelocCell;
     GenericBuffer bufferGeneric;
     bool cancelIonCompilations_;
 
     JSRuntime* runtime_;
     const Nursery& nursery_;
 
     bool aboutToOverflow_;
     bool enabled_;
     mozilla::DebugOnly<bool> mEntered; /* For ReentrancyGuard. */
 
   public:
     explicit StoreBuffer(JSRuntime* rt, const Nursery& nursery)
-      : bufferVal(), bufferCell(), bufferSlot(), bufferWholeCell(),
-        bufferRelocVal(), bufferRelocCell(), bufferGeneric(), cancelIonCompilations_(false),
-        runtime_(rt), nursery_(nursery), aboutToOverflow_(false), enabled_(false),
-        mEntered(false)
+      : bufferVal(), bufferCell(), bufferSlot(), bufferWholeCell(), bufferGeneric(),
+        cancelIonCompilations_(false), runtime_(rt), nursery_(nursery), aboutToOverflow_(false),
+        enabled_(false), mEntered(false)
     {
     }
 
     bool enable();
     void disable();
     bool isEnabled() const { return enabled_; }
 
     bool clear();
 
     /* Get the overflowed status. */
     bool isAboutToOverflow() const { return aboutToOverflow_; }
 
     bool cancelIonCompilations() const { return cancelIonCompilations_; }
 
     /* Insert a single edge into the buffer/remembered set. */
-    void putValueFromAnyThread(JS::Value* valuep) { putFromAnyThread(bufferVal, ValueEdge(valuep)); }
+    void putValueFromAnyThread(JS::Value* vp) { putFromAnyThread(bufferVal, ValueEdge(vp)); }
+    void unputValueFromAnyThread(JS::Value* vp) { unputFromAnyThread(bufferVal, ValueEdge(vp)); }
     void putCellFromAnyThread(Cell** cellp) { putFromAnyThread(bufferCell, CellPtrEdge(cellp)); }
+    void unputCellFromAnyThread(Cell** cellp) { unputFromAnyThread(bufferCell, CellPtrEdge(cellp)); }
     void putSlotFromAnyThread(NativeObject* obj, int kind, int32_t start, int32_t count) {
         putFromAnyThread(bufferSlot, SlotsEdge(obj, kind, start, count));
     }
     void putWholeCellFromMainThread(Cell* cell) {
         MOZ_ASSERT(cell->isTenured());
         putFromMainThread(bufferWholeCell, WholeCellEdges(cell));
     }
 
-    /* Insert or update a single edge in the Relocatable buffer. */
-    void putRelocatableValueFromAnyThread(JS::Value* valuep) {
-        putFromAnyThread(bufferRelocVal, ValueEdge(valuep));
-    }
-    void removeRelocatableValueFromAnyThread(JS::Value* valuep) {
-        unputFromAnyThread(bufferRelocVal, ValueEdge(valuep));
-    }
-    void putRelocatableCellFromAnyThread(Cell** cellp) {
-        putFromAnyThread(bufferRelocCell, CellPtrEdge(cellp));
-    }
-    void removeRelocatableCellFromAnyThread(Cell** cellp) {
-        unputFromAnyThread(bufferRelocCell, CellPtrEdge(cellp));
-    }
-
     /* Insert an entry into the generic buffer. */
     template <typename T>
     void putGeneric(const T& t) { putFromAnyThread(bufferGeneric, t);}
 
     /* Insert or update a callback entry. */
     template <typename Key>
     void putCallback(void (*callback)(JSTracer* trc, Key* key, void* data), Key* key, void* data) {
         putFromAnyThread(bufferGeneric, CallbackRef<Key>(callback, key, data));
@@ -452,29 +437,20 @@ class StoreBuffer
         cancelIonCompilations_ = true;
     }
 
     /* Methods to trace the source of all edges in the store buffer. */
     void traceValues(TenuringTracer& mover)            { bufferVal.trace(this, mover); }
     void traceCells(TenuringTracer& mover)             { bufferCell.trace(this, mover); }
     void traceSlots(TenuringTracer& mover)             { bufferSlot.trace(this, mover); }
     void traceWholeCells(TenuringTracer& mover)        { bufferWholeCell.trace(this, mover); }
-    void traceRelocatableValues(TenuringTracer& mover) { bufferRelocVal.trace(this, mover); }
-    void traceRelocatableCells(TenuringTracer& mover)  { bufferRelocCell.trace(this, mover); }
     void traceGenericEntries(JSTracer *trc)            { bufferGeneric.trace(this, trc); }
 
     /* For use by our owned buffers and for testing. */
     void setAboutToOverflow();
 
-    /* For jit access to the raw buffer. */
-    void oolSinkStoresForWholeCellBuffer() { bufferWholeCell.sinkStores(this); }
-    void* addressOfWholeCellBufferPointer() const { return (void*)&bufferWholeCell.insert_; }
-    void* addressOfWholeCellBufferEnd() const {
-        return (void*)(bufferWholeCell.buffer_ + bufferWholeCell.NumBufferEntries);
-    }
-
     void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::GCSizes* sizes);
 };
 
 } /* namespace gc */
 } /* namespace js */
 
 #endif /* gc_StoreBuffer_h */
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
@@ -115,16 +115,22 @@ NativeRegExpMacroAssembler::GenerateCode
         num_registers_++;
 
     Label return_temp0;
 
     // Finalize code - write the entry point code now we know how many
     // registers we need.
     masm.bind(&entry_label_);
 
+#ifdef JS_CODEGEN_ARM64
+    // ARM64 communicates stack address via sp, but uses a pseudo-sp for addressing.
+    MOZ_ASSERT(!masm.GetStackPointer64().Is(sp));
+    masm.moveStackPtrTo(masm.getStackPointer());
+#endif
+
     // Push non-volatile registers which might be modified by jitcode.
     size_t pushedNonVolatileRegisters = 0;
     for (GeneralRegisterForwardIterator iter(savedNonVolatileRegisters); iter.more(); ++iter) {
         masm.Push(*iter);
         pushedNonVolatileRegisters++;
     }
 
 #ifndef JS_CODEGEN_X86
@@ -382,17 +388,17 @@ NativeRegExpMacroAssembler::GenerateCode
         masm.bind(&stack_overflow_label_);
 
         Label grow_failed;
 
         masm.movePtr(ImmPtr(runtime), temp1);
 
         // Save registers before calling C function
         LiveGeneralRegisterSet volatileRegs(GeneralRegisterSet::Volatile());
-#if defined(JS_CODEGEN_ARM)
+#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)
         volatileRegs.add(Register::FromCode(Registers::lr));
 #elif defined(JS_CODEGEN_MIPS)
         volatileRegs.add(Register::FromCode(Registers::ra));
 #endif
         volatileRegs.takeUnchecked(temp0);
         volatileRegs.takeUnchecked(temp1);
         masm.PushRegsInMask(volatileRegs);
 
--- a/js/src/jit-test/tests/debug/Frame-newTargetEval-01.js
+++ b/js/src/jit-test/tests/debug/Frame-newTargetEval-01.js
@@ -1,10 +1,12 @@
 // Test that new.target is acceptably usable in RematerializedFrames.
 
+gczeal(0);
+
 load(libdir + "jitopts.js");
 
 if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation))
   quit();
 
 withJitOptions(Opts_Ion2NoOffthreadCompilation, function () {
   var g = newGlobal();
   var dbg = new Debugger;
--- a/js/src/jit-test/tests/debug/Frame-newTargetEval-02.js
+++ b/js/src/jit-test/tests/debug/Frame-newTargetEval-02.js
@@ -1,10 +1,12 @@
 // Test that new.target is acceptably usable in RematerializedFrames.
 
+gczeal(0);
+
 load(libdir + "jitopts.js");
 
 if (!jitTogglesMatch(Opts_Ion2NoOffthreadCompilation))
   quit();
 
 withJitOptions(Opts_Ion2NoOffthreadCompilation, function () {
   var g = newGlobal();
   var dbg = new Debugger;
--- a/js/src/jit/AtomicOperations-inl.h
+++ b/js/src/jit/AtomicOperations-inl.h
@@ -4,19 +4,21 @@
  * 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 jit_AtomicOperations_inl_h
 #define jit_AtomicOperations_inl_h
 
 #if defined(JS_CODEGEN_ARM)
 # include "jit/arm/AtomicOperations-arm.h"
+#elif defined(JS_CODEGEN_ARM64)
+# include "jit/arm64/AtomicOperations-arm64.h"
 #elif defined(JS_CODEGEN_MIPS)
 # include "jit/mips/AtomicOperations-mips.h"
 #elif defined(JS_CODEGEN_NONE)
 # include "jit/none/AtomicOperations-none.h"
 #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
 # include "jit/x86-shared/AtomicOperations-x86-shared.h"
 #else
 # error "Atomic operations must be defined for this platform"
 #endif
 
-#endif //  jit_AtomicOperations_inl_h
+#endif // jit_AtomicOperations_inl_h
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -13,16 +13,18 @@
 #endif
 
 #if defined(JS_CODEGEN_X86)
 # include "jit/x86/CodeGenerator-x86.h"
 #elif defined(JS_CODEGEN_X64)
 # include "jit/x64/CodeGenerator-x64.h"
 #elif defined(JS_CODEGEN_ARM)
 # include "jit/arm/CodeGenerator-arm.h"
+#elif defined(JS_CODEGEN_ARM64)
+# include "jit/arm64/CodeGenerator-arm64.h"
 #elif defined(JS_CODEGEN_MIPS)
 # include "jit/mips/CodeGenerator-mips.h"
 #elif defined(JS_CODEGEN_NONE)
 # include "jit/none/CodeGenerator-none.h"
 #else
 #error "Unknown architecture!"
 #endif
 
--- a/js/src/jit/IonCaches.h
+++ b/js/src/jit/IonCaches.h
@@ -4,16 +4,18 @@
  * 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 jit_IonCaches_h
 #define jit_IonCaches_h
 
 #if defined(JS_CODEGEN_ARM)
 # include "jit/arm/Assembler-arm.h"
+#elif defined(JS_CODEGEN_ARM64)
+# include "jit/arm64/Assembler-arm64.h"
 #elif defined(JS_CODEGEN_MIPS)
 # include "jit/mips/Assembler-mips.h"
 #endif
 #include "jit/Registers.h"
 #include "jit/shared/Assembler-shared.h"
 #include "vm/TypedArrayCommon.h"
 
 namespace js {
--- a/js/src/jit/JitCommon.h
+++ b/js/src/jit/JitCommon.h
@@ -6,21 +6,23 @@
 
 #ifndef jit_JitCommon_h
 #define jit_JitCommon_h
 
 // Various macros used by all JITs.
 
 #if defined(JS_SIMULATOR_ARM)
 #include "jit/arm/Simulator-arm.h"
+#elif defined(JS_SIMULATOR_ARM64)
+# include "jit/arm64/vixl/Simulator-vixl.h"
 #elif defined(JS_SIMULATOR_MIPS)
 #include "jit/mips/Simulator-mips.h"
 #endif
 
-#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS)
+#ifdef JS_SIMULATOR
 // Call into cross-jitted code by following the ABI of the simulated architecture.
 #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4, p5, p6, p7)     \
     (js::jit::Simulator::Current()->call(                              \
         JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 8, p0, p1, p2, p3, p4, p5, p6, p7) & 0xffffffff)
 
 #define CALL_GENERATED_1(entry, p0)                     \
     (js::jit::Simulator::Current()->call(               \
         JS_FUNC_TO_DATA_PTR(uint8_t*, entry), 1, p0) & 0xffffffff)
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -2588,16 +2588,22 @@ MachineState::FromBailout(RegisterDump::
     }