Backed out 2 changesets (bug 1314388) for timing out in dom/svg/test/test_zoom.xhtml. r=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sun, 02 Apr 2017 14:37:08 +0200
changeset 385029 89b885c2cb80f6f346205d986933fef47001738b
parent 385028 804d8199aecadaf1948044b1b4520963056fee67
child 385049 38894655c89e68bcd8f45d31a0d3005f2c2b53db
push id41
push userfmarier@mozilla.com
push dateTue, 04 Apr 2017 00:38:28 +0000
reviewersbackout
bugs1314388
milestone55.0a1
backs out804d8199aecadaf1948044b1b4520963056fee67
b7fab6a89c1d618d67e3a0b1f67e7c1bc09b9fd4
Backed out 2 changesets (bug 1314388) for timing out in dom/svg/test/test_zoom.xhtml. r=backout Backed out changeset 804d8199aeca (bug 1314388) Backed out changeset b7fab6a89c1d (bug 1314388)
devtools/client/debugger/new/debugger.js
dom/events/EventDispatcher.cpp
dom/events/EventNameList.h
dom/events/test/test_all_synthetic_events.html
dom/smil/test/test_smilTimeEvents.xhtml
dom/svg/SVGSVGElement.cpp
dom/svg/SVGSVGElement.h
dom/svg/SVGZoomEvent.cpp
dom/svg/SVGZoomEvent.h
dom/svg/moz.build
dom/tests/mochitest/general/test_interfaces.js
dom/webidl/SVGZoomEvent.webidl
dom/webidl/moz.build
testing/web-platform/meta/dom/nodes/Document-createEvent.html.ini
testing/web-platform/meta/svg/historical.html.ini
testing/web-platform/tests/svg/interfaces.html
widget/BasicEvents.h
widget/ContentEvents.h
widget/EventClassList.h
--- a/devtools/client/debugger/new/debugger.js
+++ b/devtools/client/debugger/new/debugger.js
@@ -2022,67 +2022,67 @@ return /******/ (function(modules) { // 
 
 	module.exports = __WEBPACK_EXTERNAL_MODULE_31__;
 
 /***/ },
 /* 32 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/* This Source Code Form is subject to the terms of the Mozilla Public
-	 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
-	 * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-	const React = __webpack_require__(2);
-	const ReactDOM = __webpack_require__(31);
-	const { DOM: dom, PropTypes } = React;
-
-	const Draggable = React.createClass({
-	  displayName: "Draggable",
-
-	  propTypes: {
-	    onMove: PropTypes.func.isRequired,
-	    onStart: PropTypes.func,
-	    onStop: PropTypes.func,
-	    style: PropTypes.object,
-	    className: PropTypes.string
-	  },
-
-	  startDragging(ev) {
-	    ev.preventDefault();
-	    const doc = ReactDOM.findDOMNode(this).ownerDocument;
-	    doc.addEventListener("mousemove", this.onMove);
-	    doc.addEventListener("mouseup", this.onUp);
-	    this.props.onStart && this.props.onStart();
-	  },
-
-	  onMove(ev) {
+	 * 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/. */
+
+	const React = __webpack_require__(2);
+	const ReactDOM = __webpack_require__(31);
+	const { DOM: dom, PropTypes } = React;
+
+	const Draggable = React.createClass({
+	  displayName: "Draggable",
+
+	  propTypes: {
+	    onMove: PropTypes.func.isRequired,
+	    onStart: PropTypes.func,
+	    onStop: PropTypes.func,
+	    style: PropTypes.object,
+	    className: PropTypes.string
+	  },
+
+	  startDragging(ev) {
+	    ev.preventDefault();
+	    const doc = ReactDOM.findDOMNode(this).ownerDocument;
+	    doc.addEventListener("mousemove", this.onMove);
+	    doc.addEventListener("mouseup", this.onUp);
+	    this.props.onStart && this.props.onStart();
+	  },
+
+	  onMove(ev) {
 	    ev.preventDefault();
 	    // We pass the whole event because we don't know which properties
 	    // the callee needs.
 	    this.props.onMove(ev);
-	  },
-
-	  onUp(ev) {
-	    ev.preventDefault();
-	    const doc = ReactDOM.findDOMNode(this).ownerDocument;
-	    doc.removeEventListener("mousemove", this.onMove);
-	    doc.removeEventListener("mouseup", this.onUp);
-	    this.props.onStop && this.props.onStop();
-	  },
-
-	  render() {
-	    return dom.div({
-	      style: this.props.style,
-	      className: this.props.className,
-	      onMouseDown: this.startDragging
-	    });
-	  }
-	});
-
-	module.exports = Draggable;
+	  },
+
+	  onUp(ev) {
+	    ev.preventDefault();
+	    const doc = ReactDOM.findDOMNode(this).ownerDocument;
+	    doc.removeEventListener("mousemove", this.onMove);
+	    doc.removeEventListener("mouseup", this.onUp);
+	    this.props.onStop && this.props.onStop();
+	  },
+
+	  render() {
+	    return dom.div({
+	      style: this.props.style,
+	      className: this.props.className,
+	      onMouseDown: this.startDragging
+	    });
+	  }
+	});
+
+	module.exports = Draggable;
 
 
 /***/ },
 /* 33 */
 /***/ function(module, exports, __webpack_require__) {
 
 	/**
 	 * Copyright (c) 2007-2016, Alexandru Marasteanu <hello [at) alexei (dot] ro>
@@ -10031,26 +10031,26 @@ return /******/ (function(modules) { // 
 	}(this));
 
 	/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(51)(module), (function() { return this; }())))
 
 /***/ },
 /* 51 */
 /***/ function(module, exports) {
 
-	module.exports = function(module) {
-		if(!module.webpackPolyfill) {
-			module.deprecate = function() {};
-			module.paths = [];
-			// module.parent = undefined by default
-			module.children = [];
-			module.webpackPolyfill = 1;
-		}
-		return module;
-	}
+	module.exports = function(module) {
+		if(!module.webpackPolyfill) {
+			module.deprecate = function() {};
+			module.paths = [];
+			// module.parent = undefined by default
+			module.children = [];
+			module.webpackPolyfill = 1;
+		}
+		return module;
+	}
 
 
 /***/ },
 /* 52 */
 /***/ function(module, exports, __webpack_require__) {
 
 	var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/utf8js v2.0.0 by @mathias */
 	;(function(root) {
@@ -32333,176 +32333,176 @@ return /******/ (function(modules) { // 
 	module.exports = {
 	  originalToGeneratedId, generatedToOriginalId, isOriginalId, isGeneratedId
 	};
 
 /***/ },
 /* 248 */
 /***/ function(module, exports, __webpack_require__) {
 
-	(function(){
-	  var crypt = __webpack_require__(249),
-	      utf8 = __webpack_require__(250).utf8,
-	      isBuffer = __webpack_require__(251),
-	      bin = __webpack_require__(250).bin,
-
-	  // The core
-	  md5 = function (message, options) {
-	    // Convert to byte array
-	    if (message.constructor == String)
-	      if (options && options.encoding === 'binary')
-	        message = bin.stringToBytes(message);
-	      else
-	        message = utf8.stringToBytes(message);
-	    else if (isBuffer(message))
-	      message = Array.prototype.slice.call(message, 0);
-	    else if (!Array.isArray(message))
-	      message = message.toString();
-	    // else, assume byte array already
-
-	    var m = crypt.bytesToWords(message),
-	        l = message.length * 8,
-	        a =  1732584193,
-	        b = -271733879,
-	        c = -1732584194,
-	        d =  271733878;
-
-	    // Swap endian
-	    for (var i = 0; i < m.length; i++) {
-	      m[i] = ((m[i] <<  8) | (m[i] >>> 24)) & 0x00FF00FF |
-	             ((m[i] << 24) | (m[i] >>>  8)) & 0xFF00FF00;
-	    }
-
-	    // Padding
-	    m[l >>> 5] |= 0x80 << (l % 32);
-	    m[(((l + 64) >>> 9) << 4) + 14] = l;
-
-	    // Method shortcuts
-	    var FF = md5._ff,
-	        GG = md5._gg,
-	        HH = md5._hh,
-	        II = md5._ii;
-
-	    for (var i = 0; i < m.length; i += 16) {
-
-	      var aa = a,
-	          bb = b,
-	          cc = c,
-	          dd = d;
-
-	      a = FF(a, b, c, d, m[i+ 0],  7, -680876936);
-	      d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
-	      c = FF(c, d, a, b, m[i+ 2], 17,  606105819);
-	      b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
-	      a = FF(a, b, c, d, m[i+ 4],  7, -176418897);
-	      d = FF(d, a, b, c, m[i+ 5], 12,  1200080426);
-	      c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
-	      b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
-	      a = FF(a, b, c, d, m[i+ 8],  7,  1770035416);
-	      d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
-	      c = FF(c, d, a, b, m[i+10], 17, -42063);
-	      b = FF(b, c, d, a, m[i+11], 22, -1990404162);
-	      a = FF(a, b, c, d, m[i+12],  7,  1804603682);
-	      d = FF(d, a, b, c, m[i+13], 12, -40341101);
-	      c = FF(c, d, a, b, m[i+14], 17, -1502002290);
-	      b = FF(b, c, d, a, m[i+15], 22,  1236535329);
-
-	      a = GG(a, b, c, d, m[i+ 1],  5, -165796510);
-	      d = GG(d, a, b, c, m[i+ 6],  9, -1069501632);
-	      c = GG(c, d, a, b, m[i+11], 14,  643717713);
-	      b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
-	      a = GG(a, b, c, d, m[i+ 5],  5, -701558691);
-	      d = GG(d, a, b, c, m[i+10],  9,  38016083);
-	      c = GG(c, d, a, b, m[i+15], 14, -660478335);
-	      b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
-	      a = GG(a, b, c, d, m[i+ 9],  5,  568446438);
-	      d = GG(d, a, b, c, m[i+14],  9, -1019803690);
-	      c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
-	      b = GG(b, c, d, a, m[i+ 8], 20,  1163531501);
-	      a = GG(a, b, c, d, m[i+13],  5, -1444681467);
-	      d = GG(d, a, b, c, m[i+ 2],  9, -51403784);
-	      c = GG(c, d, a, b, m[i+ 7], 14,  1735328473);
-	      b = GG(b, c, d, a, m[i+12], 20, -1926607734);
-
-	      a = HH(a, b, c, d, m[i+ 5],  4, -378558);
-	      d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
-	      c = HH(c, d, a, b, m[i+11], 16,  1839030562);
-	      b = HH(b, c, d, a, m[i+14], 23, -35309556);
-	      a = HH(a, b, c, d, m[i+ 1],  4, -1530992060);
-	      d = HH(d, a, b, c, m[i+ 4], 11,  1272893353);
-	      c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
-	      b = HH(b, c, d, a, m[i+10], 23, -1094730640);
-	      a = HH(a, b, c, d, m[i+13],  4,  681279174);
-	      d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
-	      c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
-	      b = HH(b, c, d, a, m[i+ 6], 23,  76029189);
-	      a = HH(a, b, c, d, m[i+ 9],  4, -640364487);
-	      d = HH(d, a, b, c, m[i+12], 11, -421815835);
-	      c = HH(c, d, a, b, m[i+15], 16,  530742520);
-	      b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
-
-	      a = II(a, b, c, d, m[i+ 0],  6, -198630844);
-	      d = II(d, a, b, c, m[i+ 7], 10,  1126891415);
-	      c = II(c, d, a, b, m[i+14], 15, -1416354905);
-	      b = II(b, c, d, a, m[i+ 5], 21, -57434055);
-	      a = II(a, b, c, d, m[i+12],  6,  1700485571);
-	      d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
-	      c = II(c, d, a, b, m[i+10], 15, -1051523);
-	      b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
-	      a = II(a, b, c, d, m[i+ 8],  6,  1873313359);
-	      d = II(d, a, b, c, m[i+15], 10, -30611744);
-	      c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
-	      b = II(b, c, d, a, m[i+13], 21,  1309151649);
-	      a = II(a, b, c, d, m[i+ 4],  6, -145523070);
-	      d = II(d, a, b, c, m[i+11], 10, -1120210379);
-	      c = II(c, d, a, b, m[i+ 2], 15,  718787259);
-	      b = II(b, c, d, a, m[i+ 9], 21, -343485551);
-
-	      a = (a + aa) >>> 0;
-	      b = (b + bb) >>> 0;
-	      c = (c + cc) >>> 0;
-	      d = (d + dd) >>> 0;
-	    }
-
-	    return crypt.endian([a, b, c, d]);
-	  };
-
-	  // Auxiliary functions
-	  md5._ff  = function (a, b, c, d, x, s, t) {
-	    var n = a + (b & c | ~b & d) + (x >>> 0) + t;
-	    return ((n << s) | (n >>> (32 - s))) + b;
-	  };
-	  md5._gg  = function (a, b, c, d, x, s, t) {
-	    var n = a + (b & d | c & ~d) + (x >>> 0) + t;
-	    return ((n << s) | (n >>> (32 - s))) + b;
-	  };
-	  md5._hh  = function (a, b, c, d, x, s, t) {
-	    var n = a + (b ^ c ^ d) + (x >>> 0) + t;
-	    return ((n << s) | (n >>> (32 - s))) + b;
-	  };
-	  md5._ii  = function (a, b, c, d, x, s, t) {
-	    var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
-	    return ((n << s) | (n >>> (32 - s))) + b;
-	  };
-
-	  // Package private blocksize
-	  md5._blocksize = 16;
-	  md5._digestsize = 16;
-
-	  module.exports = function (message, options) {
-	    if (message === undefined || message === null)
-	      throw new Error('Illegal argument ' + message);
-
-	    var digestbytes = crypt.wordsToBytes(md5(message, options));
-	    return options && options.asBytes ? digestbytes :
-	        options && options.asString ? bin.bytesToString(digestbytes) :
-	        crypt.bytesToHex(digestbytes);
-	  };
-
-	})();
+	(function(){
+	  var crypt = __webpack_require__(249),
+	      utf8 = __webpack_require__(250).utf8,
+	      isBuffer = __webpack_require__(251),
+	      bin = __webpack_require__(250).bin,
+
+	  // The core
+	  md5 = function (message, options) {
+	    // Convert to byte array
+	    if (message.constructor == String)
+	      if (options && options.encoding === 'binary')
+	        message = bin.stringToBytes(message);
+	      else
+	        message = utf8.stringToBytes(message);
+	    else if (isBuffer(message))
+	      message = Array.prototype.slice.call(message, 0);
+	    else if (!Array.isArray(message))
+	      message = message.toString();
+	    // else, assume byte array already
+
+	    var m = crypt.bytesToWords(message),
+	        l = message.length * 8,
+	        a =  1732584193,
+	        b = -271733879,
+	        c = -1732584194,
+	        d =  271733878;
+
+	    // Swap endian
+	    for (var i = 0; i < m.length; i++) {
+	      m[i] = ((m[i] <<  8) | (m[i] >>> 24)) & 0x00FF00FF |
+	             ((m[i] << 24) | (m[i] >>>  8)) & 0xFF00FF00;
+	    }
+
+	    // Padding
+	    m[l >>> 5] |= 0x80 << (l % 32);
+	    m[(((l + 64) >>> 9) << 4) + 14] = l;
+
+	    // Method shortcuts
+	    var FF = md5._ff,
+	        GG = md5._gg,
+	        HH = md5._hh,
+	        II = md5._ii;
+
+	    for (var i = 0; i < m.length; i += 16) {
+
+	      var aa = a,
+	          bb = b,
+	          cc = c,
+	          dd = d;
+
+	      a = FF(a, b, c, d, m[i+ 0],  7, -680876936);
+	      d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
+	      c = FF(c, d, a, b, m[i+ 2], 17,  606105819);
+	      b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
+	      a = FF(a, b, c, d, m[i+ 4],  7, -176418897);
+	      d = FF(d, a, b, c, m[i+ 5], 12,  1200080426);
+	      c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
+	      b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
+	      a = FF(a, b, c, d, m[i+ 8],  7,  1770035416);
+	      d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
+	      c = FF(c, d, a, b, m[i+10], 17, -42063);
+	      b = FF(b, c, d, a, m[i+11], 22, -1990404162);
+	      a = FF(a, b, c, d, m[i+12],  7,  1804603682);
+	      d = FF(d, a, b, c, m[i+13], 12, -40341101);
+	      c = FF(c, d, a, b, m[i+14], 17, -1502002290);
+	      b = FF(b, c, d, a, m[i+15], 22,  1236535329);
+
+	      a = GG(a, b, c, d, m[i+ 1],  5, -165796510);
+	      d = GG(d, a, b, c, m[i+ 6],  9, -1069501632);
+	      c = GG(c, d, a, b, m[i+11], 14,  643717713);
+	      b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
+	      a = GG(a, b, c, d, m[i+ 5],  5, -701558691);
+	      d = GG(d, a, b, c, m[i+10],  9,  38016083);
+	      c = GG(c, d, a, b, m[i+15], 14, -660478335);
+	      b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
+	      a = GG(a, b, c, d, m[i+ 9],  5,  568446438);
+	      d = GG(d, a, b, c, m[i+14],  9, -1019803690);
+	      c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
+	      b = GG(b, c, d, a, m[i+ 8], 20,  1163531501);
+	      a = GG(a, b, c, d, m[i+13],  5, -1444681467);
+	      d = GG(d, a, b, c, m[i+ 2],  9, -51403784);
+	      c = GG(c, d, a, b, m[i+ 7], 14,  1735328473);
+	      b = GG(b, c, d, a, m[i+12], 20, -1926607734);
+
+	      a = HH(a, b, c, d, m[i+ 5],  4, -378558);
+	      d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
+	      c = HH(c, d, a, b, m[i+11], 16,  1839030562);
+	      b = HH(b, c, d, a, m[i+14], 23, -35309556);
+	      a = HH(a, b, c, d, m[i+ 1],  4, -1530992060);
+	      d = HH(d, a, b, c, m[i+ 4], 11,  1272893353);
+	      c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
+	      b = HH(b, c, d, a, m[i+10], 23, -1094730640);
+	      a = HH(a, b, c, d, m[i+13],  4,  681279174);
+	      d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
+	      c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
+	      b = HH(b, c, d, a, m[i+ 6], 23,  76029189);
+	      a = HH(a, b, c, d, m[i+ 9],  4, -640364487);
+	      d = HH(d, a, b, c, m[i+12], 11, -421815835);
+	      c = HH(c, d, a, b, m[i+15], 16,  530742520);
+	      b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
+
+	      a = II(a, b, c, d, m[i+ 0],  6, -198630844);
+	      d = II(d, a, b, c, m[i+ 7], 10,  1126891415);
+	      c = II(c, d, a, b, m[i+14], 15, -1416354905);
+	      b = II(b, c, d, a, m[i+ 5], 21, -57434055);
+	      a = II(a, b, c, d, m[i+12],  6,  1700485571);
+	      d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
+	      c = II(c, d, a, b, m[i+10], 15, -1051523);
+	      b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
+	      a = II(a, b, c, d, m[i+ 8],  6,  1873313359);
+	      d = II(d, a, b, c, m[i+15], 10, -30611744);
+	      c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
+	      b = II(b, c, d, a, m[i+13], 21,  1309151649);
+	      a = II(a, b, c, d, m[i+ 4],  6, -145523070);
+	      d = II(d, a, b, c, m[i+11], 10, -1120210379);
+	      c = II(c, d, a, b, m[i+ 2], 15,  718787259);
+	      b = II(b, c, d, a, m[i+ 9], 21, -343485551);
+
+	      a = (a + aa) >>> 0;
+	      b = (b + bb) >>> 0;
+	      c = (c + cc) >>> 0;
+	      d = (d + dd) >>> 0;
+	    }
+
+	    return crypt.endian([a, b, c, d]);
+	  };
+
+	  // Auxiliary functions
+	  md5._ff  = function (a, b, c, d, x, s, t) {
+	    var n = a + (b & c | ~b & d) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+	  md5._gg  = function (a, b, c, d, x, s, t) {
+	    var n = a + (b & d | c & ~d) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+	  md5._hh  = function (a, b, c, d, x, s, t) {
+	    var n = a + (b ^ c ^ d) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+	  md5._ii  = function (a, b, c, d, x, s, t) {
+	    var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
+	    return ((n << s) | (n >>> (32 - s))) + b;
+	  };
+
+	  // Package private blocksize
+	  md5._blocksize = 16;
+	  md5._digestsize = 16;
+
+	  module.exports = function (message, options) {
+	    if (message === undefined || message === null)
+	      throw new Error('Illegal argument ' + message);
+
+	    var digestbytes = crypt.wordsToBytes(md5(message, options));
+	    return options && options.asBytes ? digestbytes :
+	        options && options.asString ? bin.bytesToString(digestbytes) :
+	        crypt.bytesToHex(digestbytes);
+	  };
+
+	})();
 
 
 /***/ },
 /* 249 */
 /***/ function(module, exports) {
 
 	(function() {
 	  var base64map
@@ -73510,16 +73510,17 @@ return /******/ (function(modules) { // 
 			"SVGTSpanElement": false,
 			"SVGUnitTypes": false,
 			"SVGURIReference": false,
 			"SVGUseElement": false,
 			"SVGViewElement": false,
 			"SVGViewSpec": false,
 			"SVGVKernElement": false,
 			"SVGZoomAndPan": false,
+			"SVGZoomEvent": false,
 			"Text": false,
 			"TextDecoder": false,
 			"TextEncoder": false,
 			"TextEvent": false,
 			"TextMetrics": false,
 			"TextTrack": false,
 			"TextTrackCue": false,
 			"TextTrackCueList": false,
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -38,16 +38,17 @@
 #include "mozilla/dom/PageTransitionEvent.h"
 #include "mozilla/dom/PointerEvent.h"
 #include "mozilla/dom/PopStateEvent.h"
 #include "mozilla/dom/RootedDictionary.h"
 #include "mozilla/dom/ScrollAreaEvent.h"
 #include "mozilla/dom/SimpleGestureEvent.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/StorageEvent.h"
+#include "mozilla/dom/SVGZoomEvent.h"
 #include "mozilla/dom/TimeEvent.h"
 #include "mozilla/dom/TouchEvent.h"
 #include "mozilla/dom/TransitionEvent.h"
 #include "mozilla/dom/WheelEvent.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/XULCommandEvent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventListenerManager.h"
@@ -934,16 +935,19 @@ EventDispatcher::CreateEvent(EventTarget
     case eEditorInputEventClass:
       return NS_NewDOMInputEvent(aOwner, aPresContext,
                                  aEvent->AsEditorInputEvent());
     case eDragEventClass:
       return NS_NewDOMDragEvent(aOwner, aPresContext, aEvent->AsDragEvent());
     case eClipboardEventClass:
       return NS_NewDOMClipboardEvent(aOwner, aPresContext,
                                      aEvent->AsClipboardEvent());
+    case eSVGZoomEventClass:
+      return NS_NewDOMSVGZoomEvent(aOwner, aPresContext,
+                                   aEvent->AsSVGZoomEvent());
     case eSMILTimeEventClass:
       return NS_NewDOMTimeEvent(aOwner, aPresContext,
                                 aEvent->AsSMILTimeEvent());
     case eCommandEventClass:
       return NS_NewDOMCommandEvent(aOwner, aPresContext,
                                    aEvent->AsCommandEvent());
     case eSimpleGestureEventClass:
       return NS_NewDOMSimpleGestureEvent(aOwner, aPresContext,
@@ -1057,16 +1061,24 @@ EventDispatcher::CreateEvent(EventTarget
   if (aEventType.LowerCaseEqualsLiteral("svgevent")) {
     LOG_EVENT_CREATION(SVGEVENT);
     return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
   }
   if (aEventType.LowerCaseEqualsLiteral("svgevents")) {
     LOG_EVENT_CREATION(SVGEVENTS);
     return NS_NewDOMEvent(aOwner, aPresContext, nullptr);
   }
+  if (aEventType.LowerCaseEqualsLiteral("svgzoomevent")) {
+    LOG_EVENT_CREATION(SVGZOOMEVENT);
+    return NS_NewDOMSVGZoomEvent(aOwner, aPresContext, nullptr);
+  }
+  if (aEventType.LowerCaseEqualsLiteral("svgzoomevents")) {
+    LOG_EVENT_CREATION(SVGZOOMEVENTS);
+    return NS_NewDOMSVGZoomEvent(aOwner, aPresContext, nullptr);
+  }
   if (aEventType.LowerCaseEqualsLiteral("timeevent")) {
     LOG_EVENT_CREATION(TIMEEVENT);
     return NS_NewDOMTimeEvent(aOwner, aPresContext, nullptr);
   }
   if (aEventType.LowerCaseEqualsLiteral("timeevents")) {
     LOG_EVENT_CREATION(TIMEEVENTS);
     return NS_NewDOMTimeEvent(aOwner, aPresContext, nullptr);
   }
--- a/dom/events/EventNameList.h
+++ b/dom/events/EventNameList.h
@@ -830,16 +830,29 @@ NON_IDL_EVENT(SVGResize,
               eSVGResize,
               EventNameType_None,
               eBasicEventClass)
 NON_IDL_EVENT(SVGScroll,
               eSVGScroll,
               EventNameType_None,
               eBasicEventClass)
 
+NON_IDL_EVENT(SVGZoom,
+              eSVGZoom,
+              EventNameType_None,
+              eSVGZoomEventClass)
+
+// Only map the ID to the real event name when MESSAGE_TO_EVENT is defined.
+#ifndef MESSAGE_TO_EVENT
+// This is a bit hackish, but SVG's event names are weird.
+NON_IDL_EVENT(zoom,
+              eSVGZoom,
+              EventNameType_SVGSVG,
+              eBasicEventClass)
+#endif
 // Only map the ID to the real event name when MESSAGE_TO_EVENT is defined.
 #ifndef MESSAGE_TO_EVENT
 NON_IDL_EVENT(begin,
               eSMILBeginEvent,
               EventNameType_SMIL,
               eBasicEventClass)
 #endif
 NON_IDL_EVENT(beginEvent,
--- a/dom/events/test/test_all_synthetic_events.html
+++ b/dom/events/test/test_all_synthetic_events.html
@@ -376,16 +376,23 @@ const kEventConstructors = {
                                                        },
                                                chromeOnly: true,
                                              },
   StyleSheetChangeEvent:                     { create: function (aName, aProps) {
                                                          return new StyleSheetChangeEvent(aName, aProps);
                                                        },
                                                chromeOnly: true,
                                              },
+  SVGZoomEvent:                              { create: function (aName, aProps) {
+                                                         var e = document.createEvent("svgzoomevent");
+                                                         e.initUIEvent(aName, aProps.bubbles, aProps.cancelable,
+                                                                       aProps.view, aProps.detail);
+                                                         return e;
+                                                       },
+                                             },
   TCPSocketErrorEvent:                       { create: function(aName, aProps) {
                                                          return new TCPSocketErrorEvent(aName, aProps);
                                                        },
                                              },
   TCPSocketEvent:                            { create: function(aName, aProps) {
                                                          return new TCPSocketEvent(aName, aProps);
                                                        },
                                              },
--- a/dom/smil/test/test_smilTimeEvents.xhtml
+++ b/dom/smil/test/test_smilTimeEvents.xhtml
@@ -317,13 +317,21 @@ for (var i = 0; i < timeEvents.length; +
 is(expectedEvents.length, 0, "Got all the expected events.");
 
 expectedEvents = ["zoom", "SVGZoom"];
 d.addEventListener("zoom", function(e) {
   is(e.type, expectedEvents[0]);
   expectedEvents.shift();
 });
 
+var zoomEvent = document.createEvent("svgzoomevent");
+zoomEvent.initEvent("zoom", true, true);
+d.dispatchEvent(zoomEvent);
+zoomEvent = document.createEvent("svgzoomevent");
+zoomEvent.initEvent("SVGZoom", true, true);
+d.dispatchEvent(zoomEvent);
+is(expectedEvents.length, 0, "Got all the expected events.");
+
 ]]>
 </script>
 </pre>
 </body>
 </html>
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -470,17 +470,17 @@ SVGSVGElement::SetZoomAndPan(uint16_t aZ
     mEnumAttributes[ZOOMANDPAN].SetBaseValue(aZoomAndPan, this);
     return;
   }
 
   rv.ThrowRangeError<MSG_INVALID_ZOOMANDPAN_VALUE_ERROR>();
 }
 
 //----------------------------------------------------------------------
-// helper method for implementing SetCurrentScale/Translate
+// helper methods for implementing SVGZoomEvent:
 
 void
 SVGSVGElement::SetCurrentScaleTranslate(float s, float x, float y)
 {
   if (s == mCurrentScale &&
       x == mCurrentTranslate.GetX() && y == mCurrentTranslate.GetY()) {
     return;
   }
@@ -494,32 +494,32 @@ SVGSVGElement::SetCurrentScaleTranslate(
   // IMPORTANT: If either mCurrentTranslate *or* mCurrentScale is changed then
   // mPreviousTranslate_x, mPreviousTranslate_y *and* mPreviousScale must all
   // be updated otherwise SVGZoomEvents will end up with invalid data. I.e. an
   // SVGZoomEvent's properties previousScale and previousTranslate must contain
   // the state of currentScale and currentTranslate immediately before the
   // change that caused the event's dispatch, which is *not* necessarily the
   // same thing as the values of currentScale and currentTranslate prior to
   // their own last change.
-  //
-  // XXX This comment is out-of-date due to removal of SVGZoomEvent.  Can we
-  // remove some of this code?
   mPreviousScale = mCurrentScale;
   mPreviousTranslate = mCurrentTranslate;
   
   mCurrentScale = s;
   mCurrentTranslate = SVGPoint(x, y);
 
   // now dispatch the appropriate event if we are the root element
   nsIDocument* doc = GetUncomposedDoc();
   if (doc) {
     nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
     if (presShell && IsRoot()) {
       nsEventStatus status = nsEventStatus_eIgnore;
-      if (mPreviousScale == mCurrentScale) {
+      if (mPreviousScale != mCurrentScale) {
+        InternalSVGZoomEvent svgZoomEvent(true, eSVGZoom);
+        presShell->HandleDOMEventWithTarget(this, &svgZoomEvent, &status);
+      } else {
         WidgetEvent svgScrollEvent(true, eSVGScroll);
         presShell->HandleDOMEventWithTarget(this, &svgScrollEvent, &status);
       }
       InvalidateTransformNotifyFrame();
     }
   }
 }
 
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -127,18 +127,16 @@ public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSVGElement, SVGSVGElementBase)
 
   /**
    * For use by zoom controls to allow currentScale, currentTranslate.x and
    * currentTranslate.y to be set by a single operation that dispatches a
    * single SVGZoom event (instead of one SVGZoom and two SVGScroll events).
-   *
-   * XXX SVGZoomEvent is no more, is this needed?
    */
   void SetCurrentScaleTranslate(float s, float x, float y);
 
   /**
    * Retrieve the value of currentScale and currentTranslate.
    */
   const SVGPoint& GetCurrentTranslate() { return mCurrentTranslate; }
   float GetCurrentScale() { return mCurrentScale; }
new file mode 100644
--- /dev/null
+++ b/dom/svg/SVGZoomEvent.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DOMSVGPoint.h"
+#include "mozilla/ContentEvents.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/SVGSVGElement.h"
+#include "mozilla/dom/SVGZoomEvent.h"
+#include "nsIDocument.h"
+#include "nsIPresShell.h"
+#include "prtime.h"
+
+namespace mozilla {
+namespace dom {
+
+//----------------------------------------------------------------------
+// Implementation
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(SVGZoomEvent, UIEvent, mPreviousTranslate, mNewTranslate)
+
+NS_IMPL_ADDREF_INHERITED(SVGZoomEvent, UIEvent)
+NS_IMPL_RELEASE_INHERITED(SVGZoomEvent, UIEvent)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SVGZoomEvent)
+NS_INTERFACE_MAP_END_INHERITING(UIEvent)
+
+SVGZoomEvent::SVGZoomEvent(EventTarget* aOwner,
+                           nsPresContext* aPresContext,
+                           InternalSVGZoomEvent* aEvent)
+  : UIEvent(aOwner, aPresContext,
+            aEvent ? aEvent : new InternalSVGZoomEvent(false, eSVGZoom))
+  , mPreviousScale(0)
+  , mNewScale(0)
+{
+  if (aEvent) {
+    mEventIsInternal = false;
+  }
+  else {
+    mEventIsInternal = true;
+    mEvent->mTime = PR_Now();
+  }
+
+  // We must store the "Previous" and "New" values before this event is
+  // dispatched. Reading the values from the root 'svg' element after we've
+  // been dispatched is not an option since event handler code may change
+  // currentScale and currentTranslate in response to this event.
+  nsIPresShell *presShell;
+  if (mPresContext && (presShell = mPresContext->GetPresShell())) {
+    nsIDocument *doc = presShell->GetDocument();
+    if (doc) {
+      Element *rootElement = doc->GetRootElement();
+      if (rootElement) {
+        // If the root element isn't an SVG 'svg' element
+        // (e.g. if this event was created by calling createEvent on a
+        // non-SVGDocument), then the "New" and "Previous"
+        // properties will be left null which is probably what we want.
+        if (rootElement->IsSVGElement(nsGkAtoms::svg)) {
+          SVGSVGElement *SVGSVGElem =
+            static_cast<SVGSVGElement*>(rootElement);
+
+          mNewScale = SVGSVGElem->GetCurrentScale();
+          mPreviousScale = SVGSVGElem->GetPreviousScale();
+
+          const SVGPoint& translate = SVGSVGElem->GetCurrentTranslate();
+          mNewTranslate =
+            new DOMSVGPoint(translate.GetX(), translate.GetY());
+          mNewTranslate->SetReadonly(true);
+
+          const SVGPoint& prevTranslate = SVGSVGElem->GetPreviousTranslate();
+          mPreviousTranslate =
+            new DOMSVGPoint(prevTranslate.GetX(), prevTranslate.GetY());
+          mPreviousTranslate->SetReadonly(true);
+        }
+      }
+    }
+  }
+}
+
+SVGZoomEvent::~SVGZoomEvent()
+{
+}
+
+} // namespace dom
+} // namespace mozilla
+
+
+////////////////////////////////////////////////////////////////////////
+// Exported creation functions:
+
+using namespace mozilla;
+using namespace mozilla::dom;
+
+already_AddRefed<SVGZoomEvent>
+NS_NewDOMSVGZoomEvent(EventTarget* aOwner,
+                      nsPresContext* aPresContext,
+                      mozilla::InternalSVGZoomEvent* aEvent)
+{
+  RefPtr<SVGZoomEvent> it = new SVGZoomEvent(aOwner, aPresContext, aEvent);
+  return it.forget();
+}
new file mode 100644
--- /dev/null
+++ b/dom/svg/SVGZoomEvent.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SVGZoomEvent_h
+#define mozilla_dom_SVGZoomEvent_h
+
+#include "DOMSVGPoint.h"
+#include "mozilla/dom/UIEvent.h"
+#include "mozilla/dom/SVGZoomEventBinding.h"
+#include "mozilla/EventForwards.h"
+
+class nsPresContext;
+
+namespace mozilla {
+
+class nsISVGPoint;
+
+namespace dom {
+
+class SVGZoomEvent final : public UIEvent
+{
+public:
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGZoomEvent, UIEvent)
+  NS_DECL_ISUPPORTS_INHERITED
+
+  SVGZoomEvent(EventTarget* aOwner, nsPresContext* aPresContext,
+               InternalSVGZoomEvent* aEvent);
+
+  // Forward to base class
+  NS_FORWARD_TO_UIEVENT
+
+  virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
+  {
+    return SVGZoomEventBinding::Wrap(aCx, this, aGivenProto);
+  }
+
+  float PreviousScale() const
+  {
+    return mPreviousScale;
+  }
+
+  nsISVGPoint* GetPreviousTranslate() const
+  {
+    return mPreviousTranslate;
+  }
+
+  float NewScale() const
+  {
+    return mNewScale;
+  }
+
+  nsISVGPoint* GetNewTranslate() const
+  {
+    return mNewTranslate;
+  }
+
+private:
+  ~SVGZoomEvent();
+
+  float mPreviousScale;
+  float mNewScale;
+  RefPtr<DOMSVGPoint> mPreviousTranslate;
+  RefPtr<DOMSVGPoint> mNewTranslate;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+already_AddRefed<mozilla::dom::SVGZoomEvent>
+NS_NewDOMSVGZoomEvent(mozilla::dom::EventTarget* aOwner,
+                      nsPresContext* aPresContext,
+                      mozilla::InternalSVGZoomEvent* aEvent);
+
+#endif // mozilla_dom_SVGZoomEvent_h
--- a/dom/svg/moz.build
+++ b/dom/svg/moz.build
@@ -97,16 +97,17 @@ EXPORTS.mozilla.dom += [
     'SVGTextPathElement.h',
     'SVGTextPositioningElement.h',
     'SVGTitleElement.h',
     'SVGTransform.h',
     'SVGTransformableElement.h',
     'SVGTSpanElement.h',
     'SVGUseElement.h',
     'SVGViewElement.h',
+    'SVGZoomEvent.h',
 ]
 
 UNIFIED_SOURCES += [
     'DOMSVGAnimatedLengthList.cpp',
     'DOMSVGAnimatedNumberList.cpp',
     'DOMSVGLength.cpp',
     'DOMSVGLengthList.cpp',
     'DOMSVGNumber.cpp',
@@ -243,16 +244,17 @@ UNIFIED_SOURCES += [
     'SVGTransformableElement.cpp',
     'SVGTransformList.cpp',
     'SVGTransformListParser.cpp',
     'SVGTransformListSMILType.cpp',
     'SVGTSpanElement.cpp',
     'SVGUseElement.cpp',
     'SVGViewBoxSMILType.cpp',
     'SVGViewElement.cpp',
+    'SVGZoomEvent.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom',
     '/dom/base',
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -1114,16 +1114,18 @@ var interfaceNamesInGlobalScope =
     "SVGUnitTypes",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGUseElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGViewElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGZoomAndPan",
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    "SVGZoomEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
     "Text",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextDecoder",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextEncoder",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextMetrics",
 // IMPORTANT: Do not change this list without review from a DOM peer!
new file mode 100644
--- /dev/null
+++ b/dom/webidl/SVGZoomEvent.webidl
@@ -0,0 +1,25 @@
+/* -*- 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/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/SVG2/
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+interface SVGZoomEvent : UIEvent {
+  // Not implemented
+  // readonly attribute SVGRect zoomRectScreen;
+
+  [Constant]
+  readonly attribute float previousScale;
+  [Constant]
+  readonly attribute SVGPoint? previousTranslate;
+  [Constant]
+  readonly attribute float newScale;
+  [Constant]
+  readonly attribute SVGPoint? newTranslate;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -895,16 +895,17 @@ WEBIDL_FILES = [
     'SVGTSpanElement.webidl',
     'SVGUnitTypes.webidl',
     'SVGUnitTypeValues.webidl',
     'SVGURIReference.webidl',
     'SVGUseElement.webidl',
     'SVGViewElement.webidl',
     'SVGZoomAndPan.webidl',
     'SVGZoomAndPanValues.webidl',
+    'SVGZoomEvent.webidl',
     'TCPServerSocket.webidl',
     'TCPServerSocketEvent.webidl',
     'TCPSocket.webidl',
     'TCPSocketErrorEvent.webidl',
     'TCPSocketEvent.webidl',
     'Text.webidl',
     'TextClause.webidl',
     'TextDecoder.webidl',
--- a/testing/web-platform/meta/dom/nodes/Document-createEvent.html.ini
+++ b/testing/web-platform/meta/dom/nodes/Document-createEvent.html.ini
@@ -143,16 +143,40 @@
   [PROGRESSEVENT should be an alias for ProgressEvent.]
     expected: FAIL
     bug: https://github.com/whatwg/dom/issues/362, 1314303
 
   [createEvent('PROGRESSEVENT') should be initialized correctly.]
     expected: FAIL
     bug: https://github.com/whatwg/dom/issues/362, 1314303
 
+  [createEvent('SVGZoomEvent') should be initialized correctly.]
+    expected: FAIL
+    bug: 1314388
+
+  [createEvent('svgzoomevent') should be initialized correctly.]
+    expected: FAIL
+    bug: 1314388
+
+  [createEvent('SVGZOOMEVENT') should be initialized correctly.]
+    expected: FAIL
+    bug: 1314388
+
+  [createEvent('SVGZoomEvents') should be initialized correctly.]
+    expected: FAIL
+    bug: 1314388
+
+  [createEvent('svgzoomevents') should be initialized correctly.]
+    expected: FAIL
+    bug: 1314388
+
+  [createEvent('SVGZOOMEVENTS') should be initialized correctly.]
+    expected: FAIL
+    bug: 1314388
+
   [Should throw NOT_SUPPORTED_ERR for pluralized legacy event interface "TextEvents"]
     expected: FAIL
     bug: 1251198
 
   [TrackEvent should be an alias for TrackEvent.]
     expected: FAIL
     bug: https://github.com/whatwg/dom/issues/362, 1314303
 
@@ -315,8 +339,14 @@
   [Should throw NOT_SUPPORTED_ERR for non-legacy event interface "XULCommandEvent"]
     expected: FAIL
     bug: 1251198
 
   [Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "XULCommandEvents"]
     expected: FAIL
     bug: 1251198
 
+  [Should throw NOT_SUPPORTED_ERR for non-legacy event interface "SVGZoomEvent"]
+    expected: FAIL
+
+  [Should throw NOT_SUPPORTED_ERR for pluralized non-legacy event interface "SVGZoomEvents"]
+    expected: FAIL
+
--- a/testing/web-platform/meta/svg/historical.html.ini
+++ b/testing/web-platform/meta/svg/historical.html.ini
@@ -1,13 +1,16 @@
 [historical.html]
   type: testharness
   [SVGPathSeg interface must be removed]
     expected: FAIL
 
+  [SVGZoomEvent interface must be removed]
+    expected: FAIL
+
   [SVGUnitTypes mixin interface must not be exposed]
     expected: FAIL
 
   [SVGZoomAndPan mixin interface must not be exposed]
     expected: FAIL
 
   [SVGGraphicsElement.prototype.getTransformToElement must be removed]
     expected: FAIL
--- a/testing/web-platform/tests/svg/interfaces.html
+++ b/testing/web-platform/tests/svg/interfaces.html
@@ -978,16 +978,24 @@ SVGCursorElement implements SVGURIRefere
 
 interface SVGScriptElement : SVGElement {
   attribute DOMString type;
   attribute DOMString crossOrigin;
 };
 
 SVGScriptElement implements SVGURIReference;
 
+interface SVGZoomEvent : UIEvent {
+  [SameObject] readonly attribute DOMRectReadOnly zoomRectScreen;
+  readonly attribute float previousScale;
+  [SameObject] readonly attribute DOMPointReadOnly previousTranslate;
+  readonly attribute float newScale;
+  [SameObject] readonly attribute DOMPointReadOnly newTranslate;
+};
+
 interface SVGAElement : SVGGraphicsElement {
   [SameObject] readonly attribute SVGAnimatedString target;
 };
 
 SVGAElement implements SVGURIReference;
 
 interface SVGViewElement : SVGElement {};
 
--- a/widget/BasicEvents.h
+++ b/widget/BasicEvents.h
@@ -319,16 +319,17 @@ private:
         mFlags.mBubbles = true;
         break;
       case eSMILTimeEventClass:
         mFlags.mCancelable = false;
         mFlags.mBubbles = false;
         break;
       case eTransitionEventClass:
       case eAnimationEventClass:
+      case eSVGZoomEventClass:
         mFlags.mCancelable = false;
         mFlags.mBubbles = true;
         break;
       case eCompositionEventClass:
         // XXX compositionstart is cancelable in draft of DOM3 Events.
         //     However, it doesn't make sense for us, we cannot cancel
         //     composition when we send compositionstart event.
         mFlags.mCancelable = false;
--- a/widget/ContentEvents.h
+++ b/widget/ContentEvents.h
@@ -312,16 +312,48 @@ public:
 
     mAnimationName = aEvent.mAnimationName;
     mElapsedTime = aEvent.mElapsedTime;
     mPseudoElement = aEvent.mPseudoElement;
   }
 };
 
 /******************************************************************************
+ * mozilla::InternalSVGZoomEvent
+ ******************************************************************************/
+
+class InternalSVGZoomEvent : public WidgetGUIEvent
+{
+public:
+  virtual InternalSVGZoomEvent* AsSVGZoomEvent() override { return this; }
+
+  InternalSVGZoomEvent(bool aIsTrusted, EventMessage aMessage)
+    : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eSVGZoomEventClass)
+  {
+  }
+
+  virtual WidgetEvent* Duplicate() const override
+  {
+    MOZ_ASSERT(mClass == eSVGZoomEventClass,
+               "Duplicate() must be overridden by sub class");
+    // Not copying widget, it is a weak reference.
+    InternalSVGZoomEvent* result = new InternalSVGZoomEvent(false, mMessage);
+    result->AssignSVGZoomEventData(*this, true);
+    result->mFlags = mFlags;
+    return result;
+  }
+
+  void AssignSVGZoomEventData(const InternalSVGZoomEvent& aEvent,
+                              bool aCopyTargets)
+  {
+    AssignGUIEventData(aEvent, aCopyTargets);
+  }
+};
+
+/******************************************************************************
  * mozilla::InternalSMILTimeEvent
  ******************************************************************************/
 
 class InternalSMILTimeEvent : public InternalUIEvent
 {
 public:
   virtual InternalSMILTimeEvent* AsSMILTimeEvent() override
   {
--- a/widget/EventClassList.h
+++ b/widget/EventClassList.h
@@ -43,16 +43,17 @@ NS_EVENT_CLASS(Widget, TouchEvent)
 // ContentEvents.h
 NS_EVENT_CLASS(Internal, ScrollPortEvent)
 NS_EVENT_CLASS(Internal, ScrollAreaEvent)
 NS_EVENT_CLASS(Internal, FormEvent)
 NS_EVENT_CLASS(Internal, ClipboardEvent)
 NS_EVENT_CLASS(Internal, FocusEvent)
 NS_EVENT_CLASS(Internal, TransitionEvent)
 NS_EVENT_CLASS(Internal, AnimationEvent)
+NS_EVENT_CLASS(Internal, SVGZoomEvent)
 NS_EVENT_CLASS(Internal, SMILTimeEvent)
 
 // MiscEvents.h
 NS_EVENT_CLASS(Widget, CommandEvent)
 NS_EVENT_CLASS(Widget, ContentCommandEvent)
 NS_EVENT_CLASS(Widget, PluginEvent)
 
 // InternalMutationEvent.h (dom/events)