Bug 1533872 - Add shims for some of the dependencies of the matrix-js-sdk. r=florian
authorPatrick Cloke <clokep@gmail.com>
Tue, 22 Oct 2019 12:07:16 -0400
changeset 36448 d31d845ea41e096fba0c805591e1a122c5c319ed
parent 36447 d296be7570aebc76856d3539c51a698ce199b1ef
child 36449 251e48e6fcd084a3ade7c5006cbb246c2666c685
push id2534
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:52:51 +0000
treeherdercomm-beta@055c50840778 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian
bugs1533872
Bug 1533872 - Add shims for some of the dependencies of the matrix-js-sdk. r=florian
chat/modules/imXPCOMUtils.jsm
chat/protocols/matrix/lib/moz.build
chat/protocols/matrix/lib/url/url.js
chat/protocols/matrix/matrix-sdk.jsm
chat/protocols/matrix/moz.build
chat/protocols/matrix/shims/loglevel.js
chat/protocols/matrix/shims/moz.build
chat/protocols/matrix/shims/safe-buffer.js
chat/protocols/matrix/shims/url.js
--- a/chat/modules/imXPCOMUtils.jsm
+++ b/chat/modules/imXPCOMUtils.jsm
@@ -7,16 +7,17 @@ this.EXPORTED_SYMBOLS = [
   "setTimeout",
   "clearTimeout",
   "executeSoon",
   "nsSimpleEnumerator",
   "EmptyEnumerator",
   "ClassInfo",
   "l10nHelper",
   "initLogModule",
+  "scriptError",
 ];
 
 const { XPCOMUtils } = ChromeUtils.import(
   "resource://gre/modules/XPCOMUtils.jsm"
 );
 const { Services } = ChromeUtils.import("resource:///modules/imServices.jsm");
 
 var kLogLevelPref = "purple.debug.loglevel";
--- a/chat/protocols/matrix/lib/moz.build
+++ b/chat/protocols/matrix/lib/moz.build
@@ -100,17 +100,16 @@ EXTRA_JS_MODULES.matrix.matrix_sdk.webrt
 # Dependencies of the Matrix SDK.
 
 # Single file dependencies (with good names) are just added to the top-level
 # matrix module.
 EXTRA_JS_MODULES.matrix += [
     'another-json/another-json.js',
     'events/events.js',
     'punycode/punycode.js',
-    'url/url.js',
 ]
 
 EXTRA_JS_MODULES.matrix.querystring += [
     'querystring/decode.js',
     'querystring/encode.js',
     'querystring/index.js',
 ]
 
deleted file mode 100644
--- a/chat/protocols/matrix/lib/url/url.js
+++ /dev/null
@@ -1,707 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-var punycode = require('punycode');
-
-exports.parse = urlParse;
-exports.resolve = urlResolve;
-exports.resolveObject = urlResolveObject;
-exports.format = urlFormat;
-
-exports.Url = Url;
-
-function Url() {
-  this.protocol = null;
-  this.slashes = null;
-  this.auth = null;
-  this.host = null;
-  this.port = null;
-  this.hostname = null;
-  this.hash = null;
-  this.search = null;
-  this.query = null;
-  this.pathname = null;
-  this.path = null;
-  this.href = null;
-}
-
-// Reference: RFC 3986, RFC 1808, RFC 2396
-
-// define these here so at least they only have to be
-// compiled once on the first module load.
-var protocolPattern = /^([a-z0-9.+-]+:)/i,
-    portPattern = /:[0-9]*$/,
-
-    // RFC 2396: characters reserved for delimiting URLs.
-    // We actually just auto-escape these.
-    delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
-
-    // RFC 2396: characters not allowed for various reasons.
-    unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
-
-    // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
-    autoEscape = ['\''].concat(unwise),
-    // Characters that are never ever allowed in a hostname.
-    // Note that any invalid chars are also handled, but these
-    // are the ones that are *expected* to be seen, so we fast-path
-    // them.
-    nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
-    hostEndingChars = ['/', '?', '#'],
-    hostnameMaxLen = 255,
-    hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/,
-    hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/,
-    // protocols that can allow "unsafe" and "unwise" chars.
-    unsafeProtocol = {
-      'javascript': true,
-      'javascript:': true
-    },
-    // protocols that never have a hostname.
-    hostlessProtocol = {
-      'javascript': true,
-      'javascript:': true
-    },
-    // protocols that always contain a // bit.
-    slashedProtocol = {
-      'http': true,
-      'https': true,
-      'ftp': true,
-      'gopher': true,
-      'file': true,
-      'http:': true,
-      'https:': true,
-      'ftp:': true,
-      'gopher:': true,
-      'file:': true
-    },
-    querystring = require('querystring');
-
-function urlParse(url, parseQueryString, slashesDenoteHost) {
-  if (url && isObject(url) && url instanceof Url) return url;
-
-  var u = new Url;
-  u.parse(url, parseQueryString, slashesDenoteHost);
-  return u;
-}
-
-Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
-  if (!isString(url)) {
-    throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
-  }
-
-  var rest = url;
-
-  // trim before proceeding.
-  // This is to support parse stuff like "  http://foo.com  \n"
-  rest = rest.trim();
-
-  var proto = protocolPattern.exec(rest);
-  if (proto) {
-    proto = proto[0];
-    var lowerProto = proto.toLowerCase();
-    this.protocol = lowerProto;
-    rest = rest.substr(proto.length);
-  }
-
-  // figure out if it's got a host
-  // user@server is *always* interpreted as a hostname, and url
-  // resolution will treat //foo/bar as host=foo,path=bar because that's
-  // how the browser resolves relative URLs.
-  if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
-    var slashes = rest.substr(0, 2) === '//';
-    if (slashes && !(proto && hostlessProtocol[proto])) {
-      rest = rest.substr(2);
-      this.slashes = true;
-    }
-  }
-
-  if (!hostlessProtocol[proto] &&
-      (slashes || (proto && !slashedProtocol[proto]))) {
-
-    // there's a hostname.
-    // the first instance of /, ?, ;, or # ends the host.
-    //
-    // If there is an @ in the hostname, then non-host chars *are* allowed
-    // to the left of the last @ sign, unless some host-ending character
-    // comes *before* the @-sign.
-    // URLs are obnoxious.
-    //
-    // ex:
-    // http://a@b@c/ => user:a@b host:c
-    // http://a@b?@c => user:a host:c path:/?@c
-
-    // v0.12 TODO(isaacs): This is not quite how Chrome does things.
-    // Review our test case against browsers more comprehensively.
-
-    // find the first instance of any hostEndingChars
-    var hostEnd = -1;
-    for (var i = 0; i < hostEndingChars.length; i++) {
-      var hec = rest.indexOf(hostEndingChars[i]);
-      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
-        hostEnd = hec;
-    }
-
-    // at this point, either we have an explicit point where the
-    // auth portion cannot go past, or the last @ char is the decider.
-    var auth, atSign;
-    if (hostEnd === -1) {
-      // atSign can be anywhere.
-      atSign = rest.lastIndexOf('@');
-    } else {
-      // atSign must be in auth portion.
-      // http://a@b/c@d => host:b auth:a path:/c@d
-      atSign = rest.lastIndexOf('@', hostEnd);
-    }
-
-    // Now we have a portion which is definitely the auth.
-    // Pull that off.
-    if (atSign !== -1) {
-      auth = rest.slice(0, atSign);
-      rest = rest.slice(atSign + 1);
-      this.auth = decodeURIComponent(auth);
-    }
-
-    // the host is the remaining to the left of the first non-host char
-    hostEnd = -1;
-    for (var i = 0; i < nonHostChars.length; i++) {
-      var hec = rest.indexOf(nonHostChars[i]);
-      if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
-        hostEnd = hec;
-    }
-    // if we still have not hit it, then the entire thing is a host.
-    if (hostEnd === -1)
-      hostEnd = rest.length;
-
-    this.host = rest.slice(0, hostEnd);
-    rest = rest.slice(hostEnd);
-
-    // pull out port.
-    this.parseHost();
-
-    // we've indicated that there is a hostname,
-    // so even if it's empty, it has to be present.
-    this.hostname = this.hostname || '';
-
-    // if hostname begins with [ and ends with ]
-    // assume that it's an IPv6 address.
-    var ipv6Hostname = this.hostname[0] === '[' &&
-        this.hostname[this.hostname.length - 1] === ']';
-
-    // validate a little.
-    if (!ipv6Hostname) {
-      var hostparts = this.hostname.split(/\./);
-      for (var i = 0, l = hostparts.length; i < l; i++) {
-        var part = hostparts[i];
-        if (!part) continue;
-        if (!part.match(hostnamePartPattern)) {
-          var newpart = '';
-          for (var j = 0, k = part.length; j < k; j++) {
-            if (part.charCodeAt(j) > 127) {
-              // we replace non-ASCII char with a temporary placeholder
-              // we need this to make sure size of hostname is not
-              // broken by replacing non-ASCII by nothing
-              newpart += 'x';
-            } else {
-              newpart += part[j];
-            }
-          }
-          // we test again with ASCII char only
-          if (!newpart.match(hostnamePartPattern)) {
-            var validParts = hostparts.slice(0, i);
-            var notHost = hostparts.slice(i + 1);
-            var bit = part.match(hostnamePartStart);
-            if (bit) {
-              validParts.push(bit[1]);
-              notHost.unshift(bit[2]);
-            }
-            if (notHost.length) {
-              rest = '/' + notHost.join('.') + rest;
-            }
-            this.hostname = validParts.join('.');
-            break;
-          }
-        }
-      }
-    }
-
-    if (this.hostname.length > hostnameMaxLen) {
-      this.hostname = '';
-    } else {
-      // hostnames are always lower case.
-      this.hostname = this.hostname.toLowerCase();
-    }
-
-    if (!ipv6Hostname) {
-      // IDNA Support: Returns a puny coded representation of "domain".
-      // It only converts the part of the domain name that
-      // has non ASCII characters. I.e. it dosent matter if
-      // you call it with a domain that already is in ASCII.
-      var domainArray = this.hostname.split('.');
-      var newOut = [];
-      for (var i = 0; i < domainArray.length; ++i) {
-        var s = domainArray[i];
-        newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
-            'xn--' + punycode.encode(s) : s);
-      }
-      this.hostname = newOut.join('.');
-    }
-
-    var p = this.port ? ':' + this.port : '';
-    var h = this.hostname || '';
-    this.host = h + p;
-    this.href += this.host;
-
-    // strip [ and ] from the hostname
-    // the host field still retains them, though
-    if (ipv6Hostname) {
-      this.hostname = this.hostname.substr(1, this.hostname.length - 2);
-      if (rest[0] !== '/') {
-        rest = '/' + rest;
-      }
-    }
-  }
-
-  // now rest is set to the post-host stuff.
-  // chop off any delim chars.
-  if (!unsafeProtocol[lowerProto]) {
-
-    // First, make 100% sure that any "autoEscape" chars get
-    // escaped, even if encodeURIComponent doesn't think they
-    // need to be.
-    for (var i = 0, l = autoEscape.length; i < l; i++) {
-      var ae = autoEscape[i];
-      var esc = encodeURIComponent(ae);
-      if (esc === ae) {
-        esc = escape(ae);
-      }
-      rest = rest.split(ae).join(esc);
-    }
-  }
-
-
-  // chop off from the tail first.
-  var hash = rest.indexOf('#');
-  if (hash !== -1) {
-    // got a fragment string.
-    this.hash = rest.substr(hash);
-    rest = rest.slice(0, hash);
-  }
-  var qm = rest.indexOf('?');
-  if (qm !== -1) {
-    this.search = rest.substr(qm);
-    this.query = rest.substr(qm + 1);
-    if (parseQueryString) {
-      this.query = querystring.parse(this.query);
-    }
-    rest = rest.slice(0, qm);
-  } else if (parseQueryString) {
-    // no query string, but parseQueryString still requested
-    this.search = '';
-    this.query = {};
-  }
-  if (rest) this.pathname = rest;
-  if (slashedProtocol[lowerProto] &&
-      this.hostname && !this.pathname) {
-    this.pathname = '/';
-  }
-
-  //to support http.request
-  if (this.pathname || this.search) {
-    var p = this.pathname || '';
-    var s = this.search || '';
-    this.path = p + s;
-  }
-
-  // finally, reconstruct the href based on what has been validated.
-  this.href = this.format();
-  return this;
-};
-
-// format a parsed object into a url string
-function urlFormat(obj) {
-  // ensure it's an object, and not a string url.
-  // If it's an obj, this is a no-op.
-  // this way, you can call url_format() on strings
-  // to clean up potentially wonky urls.
-  if (isString(obj)) obj = urlParse(obj);
-  if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
-  return obj.format();
-}
-
-Url.prototype.format = function() {
-  var auth = this.auth || '';
-  if (auth) {
-    auth = encodeURIComponent(auth);
-    auth = auth.replace(/%3A/i, ':');
-    auth += '@';
-  }
-
-  var protocol = this.protocol || '',
-      pathname = this.pathname || '',
-      hash = this.hash || '',
-      host = false,
-      query = '';
-
-  if (this.host) {
-    host = auth + this.host;
-  } else if (this.hostname) {
-    host = auth + (this.hostname.indexOf(':') === -1 ?
-        this.hostname :
-        '[' + this.hostname + ']');
-    if (this.port) {
-      host += ':' + this.port;
-    }
-  }
-
-  if (this.query &&
-      isObject(this.query) &&
-      Object.keys(this.query).length) {
-    query = querystring.stringify(this.query);
-  }
-
-  var search = this.search || (query && ('?' + query)) || '';
-
-  if (protocol && protocol.substr(-1) !== ':') protocol += ':';
-
-  // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
-  // unless they had them to begin with.
-  if (this.slashes ||
-      (!protocol || slashedProtocol[protocol]) && host !== false) {
-    host = '//' + (host || '');
-    if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
-  } else if (!host) {
-    host = '';
-  }
-
-  if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
-  if (search && search.charAt(0) !== '?') search = '?' + search;
-
-  pathname = pathname.replace(/[?#]/g, function(match) {
-    return encodeURIComponent(match);
-  });
-  search = search.replace('#', '%23');
-
-  return protocol + host + pathname + search + hash;
-};
-
-function urlResolve(source, relative) {
-  return urlParse(source, false, true).resolve(relative);
-}
-
-Url.prototype.resolve = function(relative) {
-  return this.resolveObject(urlParse(relative, false, true)).format();
-};
-
-function urlResolveObject(source, relative) {
-  if (!source) return relative;
-  return urlParse(source, false, true).resolveObject(relative);
-}
-
-Url.prototype.resolveObject = function(relative) {
-  if (isString(relative)) {
-    var rel = new Url();
-    rel.parse(relative, false, true);
-    relative = rel;
-  }
-
-  var result = new Url();
-  Object.keys(this).forEach(function(k) {
-    result[k] = this[k];
-  }, this);
-
-  // hash is always overridden, no matter what.
-  // even href="" will remove it.
-  result.hash = relative.hash;
-
-  // if the relative url is empty, then there's nothing left to do here.
-  if (relative.href === '') {
-    result.href = result.format();
-    return result;
-  }
-
-  // hrefs like //foo/bar always cut to the protocol.
-  if (relative.slashes && !relative.protocol) {
-    // take everything except the protocol from relative
-    Object.keys(relative).forEach(function(k) {
-      if (k !== 'protocol')
-        result[k] = relative[k];
-    });
-
-    //urlParse appends trailing / to urls like http://www.example.com
-    if (slashedProtocol[result.protocol] &&
-        result.hostname && !result.pathname) {
-      result.path = result.pathname = '/';
-    }
-
-    result.href = result.format();
-    return result;
-  }
-
-  if (relative.protocol && relative.protocol !== result.protocol) {
-    // if it's a known url protocol, then changing
-    // the protocol does weird things
-    // first, if it's not file:, then we MUST have a host,
-    // and if there was a path
-    // to begin with, then we MUST have a path.
-    // if it is file:, then the host is dropped,
-    // because that's known to be hostless.
-    // anything else is assumed to be absolute.
-    if (!slashedProtocol[relative.protocol]) {
-      Object.keys(relative).forEach(function(k) {
-        result[k] = relative[k];
-      });
-      result.href = result.format();
-      return result;
-    }
-
-    result.protocol = relative.protocol;
-    if (!relative.host && !hostlessProtocol[relative.protocol]) {
-      var relPath = (relative.pathname || '').split('/');
-      while (relPath.length && !(relative.host = relPath.shift()));
-      if (!relative.host) relative.host = '';
-      if (!relative.hostname) relative.hostname = '';
-      if (relPath[0] !== '') relPath.unshift('');
-      if (relPath.length < 2) relPath.unshift('');
-      result.pathname = relPath.join('/');
-    } else {
-      result.pathname = relative.pathname;
-    }
-    result.search = relative.search;
-    result.query = relative.query;
-    result.host = relative.host || '';
-    result.auth = relative.auth;
-    result.hostname = relative.hostname || relative.host;
-    result.port = relative.port;
-    // to support http.request
-    if (result.pathname || result.search) {
-      var p = result.pathname || '';
-      var s = result.search || '';
-      result.path = p + s;
-    }
-    result.slashes = result.slashes || relative.slashes;
-    result.href = result.format();
-    return result;
-  }
-
-  var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
-      isRelAbs = (
-          relative.host ||
-          relative.pathname && relative.pathname.charAt(0) === '/'
-      ),
-      mustEndAbs = (isRelAbs || isSourceAbs ||
-                    (result.host && relative.pathname)),
-      removeAllDots = mustEndAbs,
-      srcPath = result.pathname && result.pathname.split('/') || [],
-      relPath = relative.pathname && relative.pathname.split('/') || [],
-      psychotic = result.protocol && !slashedProtocol[result.protocol];
-
-  // if the url is a non-slashed url, then relative
-  // links like ../.. should be able
-  // to crawl up to the hostname, as well.  This is strange.
-  // result.protocol has already been set by now.
-  // Later on, put the first path part into the host field.
-  if (psychotic) {
-    result.hostname = '';
-    result.port = null;
-    if (result.host) {
-      if (srcPath[0] === '') srcPath[0] = result.host;
-      else srcPath.unshift(result.host);
-    }
-    result.host = '';
-    if (relative.protocol) {
-      relative.hostname = null;
-      relative.port = null;
-      if (relative.host) {
-        if (relPath[0] === '') relPath[0] = relative.host;
-        else relPath.unshift(relative.host);
-      }
-      relative.host = null;
-    }
-    mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
-  }
-
-  if (isRelAbs) {
-    // it's absolute.
-    result.host = (relative.host || relative.host === '') ?
-                  relative.host : result.host;
-    result.hostname = (relative.hostname || relative.hostname === '') ?
-                      relative.hostname : result.hostname;
-    result.search = relative.search;
-    result.query = relative.query;
-    srcPath = relPath;
-    // fall through to the dot-handling below.
-  } else if (relPath.length) {
-    // it's relative
-    // throw away the existing file, and take the new path instead.
-    if (!srcPath) srcPath = [];
-    srcPath.pop();
-    srcPath = srcPath.concat(relPath);
-    result.search = relative.search;
-    result.query = relative.query;
-  } else if (!isNullOrUndefined(relative.search)) {
-    // just pull out the search.
-    // like href='?foo'.
-    // Put this after the other two cases because it simplifies the booleans
-    if (psychotic) {
-      result.hostname = result.host = srcPath.shift();
-      //occationaly the auth can get stuck only in host
-      //this especialy happens in cases like
-      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
-      var authInHost = result.host && result.host.indexOf('@') > 0 ?
-                       result.host.split('@') : false;
-      if (authInHost) {
-        result.auth = authInHost.shift();
-        result.host = result.hostname = authInHost.shift();
-      }
-    }
-    result.search = relative.search;
-    result.query = relative.query;
-    //to support http.request
-    if (!isNull(result.pathname) || !isNull(result.search)) {
-      result.path = (result.pathname ? result.pathname : '') +
-                    (result.search ? result.search : '');
-    }
-    result.href = result.format();
-    return result;
-  }
-
-  if (!srcPath.length) {
-    // no path at all.  easy.
-    // we've already handled the other stuff above.
-    result.pathname = null;
-    //to support http.request
-    if (result.search) {
-      result.path = '/' + result.search;
-    } else {
-      result.path = null;
-    }
-    result.href = result.format();
-    return result;
-  }
-
-  // if a url ENDs in . or .., then it must get a trailing slash.
-  // however, if it ends in anything else non-slashy,
-  // then it must NOT get a trailing slash.
-  var last = srcPath.slice(-1)[0];
-  var hasTrailingSlash = (
-      (result.host || relative.host) && (last === '.' || last === '..') ||
-      last === '');
-
-  // strip single dots, resolve double dots to parent dir
-  // if the path tries to go above the root, `up` ends up > 0
-  var up = 0;
-  for (var i = srcPath.length; i >= 0; i--) {
-    last = srcPath[i];
-    if (last == '.') {
-      srcPath.splice(i, 1);
-    } else if (last === '..') {
-      srcPath.splice(i, 1);
-      up++;
-    } else if (up) {
-      srcPath.splice(i, 1);
-      up--;
-    }
-  }
-
-  // if the path is allowed to go above the root, restore leading ..s
-  if (!mustEndAbs && !removeAllDots) {
-    for (; up--; up) {
-      srcPath.unshift('..');
-    }
-  }
-
-  if (mustEndAbs && srcPath[0] !== '' &&
-      (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
-    srcPath.unshift('');
-  }
-
-  if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
-    srcPath.push('');
-  }
-
-  var isAbsolute = srcPath[0] === '' ||
-      (srcPath[0] && srcPath[0].charAt(0) === '/');
-
-  // put the host back
-  if (psychotic) {
-    result.hostname = result.host = isAbsolute ? '' :
-                                    srcPath.length ? srcPath.shift() : '';
-    //occationaly the auth can get stuck only in host
-    //this especialy happens in cases like
-    //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
-    var authInHost = result.host && result.host.indexOf('@') > 0 ?
-                     result.host.split('@') : false;
-    if (authInHost) {
-      result.auth = authInHost.shift();
-      result.host = result.hostname = authInHost.shift();
-    }
-  }
-
-  mustEndAbs = mustEndAbs || (result.host && srcPath.length);
-
-  if (mustEndAbs && !isAbsolute) {
-    srcPath.unshift('');
-  }
-
-  if (!srcPath.length) {
-    result.pathname = null;
-    result.path = null;
-  } else {
-    result.pathname = srcPath.join('/');
-  }
-
-  //to support request.http
-  if (!isNull(result.pathname) || !isNull(result.search)) {
-    result.path = (result.pathname ? result.pathname : '') +
-                  (result.search ? result.search : '');
-  }
-  result.auth = relative.auth || result.auth;
-  result.slashes = result.slashes || relative.slashes;
-  result.href = result.format();
-  return result;
-};
-
-Url.prototype.parseHost = function() {
-  var host = this.host;
-  var port = portPattern.exec(host);
-  if (port) {
-    port = port[0];
-    if (port !== ':') {
-      this.port = port.substr(1);
-    }
-    host = host.substr(0, host.length - port.length);
-  }
-  if (host) this.hostname = host;
-};
-
-function isString(arg) {
-  return typeof arg === "string";
-}
-
-function isObject(arg) {
-  return typeof arg === 'object' && arg !== null;
-}
-
-function isNull(arg) {
-  return arg === null;
-}
-function isNullOrUndefined(arg) {
-  return  arg == null;
-}
--- a/chat/protocols/matrix/matrix-sdk.jsm
+++ b/chat/protocols/matrix/matrix-sdk.jsm
@@ -4,16 +4,19 @@
 
 const { console } = ChromeUtils.import("resource://gre/modules/Console.jsm");
 const {
   clearInterval,
   clearTimeout,
   setInterval,
   setTimeout,
 } = ChromeUtils.import("resource://gre/modules/Timer.jsm");
+const { scriptError } = ChromeUtils.import(
+  "resource:///modules/imXPCOMUtils.jsm"
+);
 
 const { Loader, Require, Module } = ChromeUtils.import(
   "resource://devtools/shared/base-loader.js"
 );
 
 this.EXPORTED_SYMBOLS = ["MatrixSDK"];
 
 // Set-up loading so require works properly in CommonJS modules.
@@ -41,86 +44,103 @@ let loader = Loader({
     "../randomstring": matrixPath + "matrix_sdk/randomstring.js",
     "../ReEmitter": matrixPath + "matrix_sdk/ReEmitter.js",
     "../sync-accumulator": matrixPath + "matrix_sdk/sync-accumulator.js",
     "../utils": matrixPath + "matrix_sdk/utils.js",
     "../utils.js": matrixPath + "matrix_sdk/utils.js",
     "../../utils": matrixPath + "matrix_sdk/utils.js",
 
     // crypto
-    "crypto/backup_password": matrixPath + "matrix_sdk/crypto/backup_password.js",
+    "crypto/backup_password":
+      matrixPath + "matrix_sdk/crypto/backup_password.js",
     deviceinfo: matrixPath + "matrix_sdk/crypto/deviceinfo.js",
     "../deviceinfo": matrixPath + "matrix_sdk/crypto/deviceinfo.js",
     DeviceList: matrixPath + "matrix_sdk/crypto/DeviceList.js",
     "../DeviceList": matrixPath + "matrix_sdk/crypto/DeviceList.js",
     crypto: matrixPath + "matrix_sdk/crypto/index.js",
     olmlib: matrixPath + "matrix_sdk/crypto/olmlib.js",
     "../olmlib": matrixPath + "matrix_sdk/crypto/olmlib.js",
     "crypto/olmlib": matrixPath + "matrix_sdk/crypto/olmlib.js",
     OlmDevice: matrixPath + "matrix_sdk/crypto/OlmDevice.js",
     "crypto/recoverykey": matrixPath + "matrix_sdk/crypto/recoverykey.js",
-    OutgoingRoomKeyRequestManager: matrixPath + "matrix_sdk/crypto/OutgoingRoomKeyRequestManager.js",
+    OutgoingRoomKeyRequestManager:
+      matrixPath + "matrix_sdk/crypto/OutgoingRoomKeyRequestManager.js",
     "crypto/RoomList": matrixPath + "matrix_sdk/crypto/RoomList.js",
 
     // crypto/algorithms
     base: matrixPath + "matrix_sdk/crypto/algorithms/base.js",
     algorithms: matrixPath + "matrix_sdk/crypto/algorithms/index.js",
     megolm: matrixPath + "matrix_sdk/crypto/algorithms/megolm.js",
     olm: matrixPath + "matrix_sdk/crypto/algorithms/olm.js",
 
     // crypto/store
-    "store/indexeddb-crypto-store": matrixPath + "matrix_sdk/crypto/store/indexeddb-crypto-store.js",
-    "crypto/store/indexeddb-crypto-store": matrixPath + "matrix_sdk/crypto/store/indexeddb-crypto-store.js",
-    "crypto/store/indexeddb-crypto-store-backend": matrixPath + "matrix_sdk/crypto/store/indexeddb-crypto-store-backend.js",
-    "crypto/store/localStorage-crypto-store": matrixPath + "matrix_sdk/crypto/store/localStorage-crypto-store.js",
-    "crypto/store/memory-crypto-store": matrixPath + "matrix_sdk/crypto/store/memory-crypto-store.js",
+    "store/indexeddb-crypto-store":
+      matrixPath + "matrix_sdk/crypto/store/indexeddb-crypto-store.js",
+    "crypto/store/indexeddb-crypto-store":
+      matrixPath + "matrix_sdk/crypto/store/indexeddb-crypto-store.js",
+    "crypto/store/indexeddb-crypto-store-backend":
+      matrixPath + "matrix_sdk/crypto/store/indexeddb-crypto-store-backend.js",
+    "crypto/store/localStorage-crypto-store":
+      matrixPath + "matrix_sdk/crypto/store/localStorage-crypto-store.js",
+    "crypto/store/memory-crypto-store":
+      matrixPath + "matrix_sdk/crypto/store/memory-crypto-store.js",
 
     // crypto/verification
     Base: matrixPath + "matrix_sdk/crypto/verification/Base.js",
     Error: matrixPath + "matrix_sdk/crypto/verification/Error.js",
     "verification/Base": matrixPath + "matrix_sdk/crypto/verification/Base.js",
-    "verification/Error": matrixPath + "matrix_sdk/crypto/verification/Error.js",
-    "verification/QRCode": matrixPath + "matrix_sdk/crypto/verification/QRCode.js",
+    "verification/Error":
+      matrixPath + "matrix_sdk/crypto/verification/Error.js",
+    "verification/QRCode":
+      matrixPath + "matrix_sdk/crypto/verification/QRCode.js",
     "verification/SAS": matrixPath + "matrix_sdk/crypto/verification/SAS.js",
 
     // models
     "../models/event": matrixPath + "matrix_sdk/models/event.js",
     "../../models/event": matrixPath + "matrix_sdk/models/event.js",
     "../lib/models/event": matrixPath + "matrix_sdk/models/event.js",
     "../../lib/models/event": matrixPath + "matrix_sdk/models/event.js",
     "../models/user": matrixPath + "matrix_sdk/models/user.js",
 
     // Simple (one-file) dependencies.
     "another-json": matrixPath + "another-json.js",
     events: matrixPath + "events.js",
     punycode: matrixPath + "punycode.js",
-    url: matrixPath + "url.js",
 
     // Browser Request.
     "browser-request": matrixPath + "browser_request/index.js",
 
     // q
     q: matrixPath + "q/q.js",
 
     // querystring
     decode: matrixPath + "querystring/decode.js",
     encode: matrixPath + "querystring/encode.js",
     querystring: matrixPath + "querystring/index.js",
+
+    // Packages that are not included, but an alternate implementation is given.
+    loglevel: matrixPath + "loglevel.js",
+    "safe-buffer": matrixPath + "safe-buffer.js",
+    url: matrixPath + "url.js",
   },
   globals: {
     global: {
       setInterval,
       clearInterval,
       setTimeout,
       clearTimeout,
     },
     console,
     XMLHttpRequest,
     setTimeout,
     clearTimeout,
     location: { href: "" }, // workaround for browser-request's is_crossDomain
+
+    // Necessary for interacting with the logging framework.
+    scriptError,
+    imIDebugMessage: Ci.imIDebugMessage,
   },
 });
 
 let requirer = Module("matrix-module", "");
 let require = Require(loader, requirer);
 let MatrixSDK = require("matrix.js");
 MatrixSDK.request(require("browser-request"));
--- a/chat/protocols/matrix/moz.build
+++ b/chat/protocols/matrix/moz.build
@@ -2,16 +2,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # XPCSHELL_TESTS_MANIFESTS += []
 
 DIRS += [
     'lib',
+    'shims',
 ]
 
 EXTRA_COMPONENTS += [
     'matrix.js',
     'matrix.manifest',
 ]
 
 EXTRA_JS_MODULES += [
new file mode 100644
--- /dev/null
+++ b/chat/protocols/matrix/shims/loglevel.js
@@ -0,0 +1,73 @@
+/* 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";
+
+/* globals scriptError, imIDebugMessage, module */
+
+let _loggers = {};
+
+/*
+ * Implement a custom logger to to hook the Matrix logging up to the chat
+ * logging framework.
+ *
+ * This unfortunately does not enable account specific logging.
+ */
+function getLogger(loggerName) {
+  let moduleName = "prpl-matrix." + loggerName;
+
+  let logger = _loggers[moduleName];
+
+  // If the logger was previously created, return it.
+  if (logger) {
+    return logger;
+  }
+
+  // Otherwise, build a new logger.
+  logger = {};
+  logger.trace = scriptError.bind(
+    logger,
+    moduleName,
+    imIDebugMessage.LEVEL_DEBUG
+  );
+  logger.debug = scriptError.bind(
+    logger,
+    moduleName,
+    imIDebugMessage.LEVEL_DEBUG
+  );
+  logger.log = scriptError.bind(
+    logger,
+    moduleName,
+    imIDebugMessage.LEVEL_DEBUG
+  );
+  logger.info = scriptError.bind(logger, moduleName, imIDebugMessage.LEVEL_LOG);
+  logger.warn = scriptError.bind(
+    logger,
+    moduleName,
+    imIDebugMessage.LEVEL_WARNING
+  );
+  logger.error = scriptError.bind(
+    logger,
+    moduleName,
+    imIDebugMessage.LEVEL_ERROR
+  );
+
+  // This is a no-op since log levels are configured via preferences.
+  logger.setLevel = function(level) {};
+
+  _loggers[moduleName] = logger;
+
+  return logger;
+}
+
+module.exports = {
+  getLogger,
+  levels: {
+    TRACE: imIDebugMessage.LEVEL_DEBUG,
+    DEBUG: imIDebugMessage.LEVEL_DEBUG,
+    INFO: imIDebugMessage.LEVEL_LOG,
+    WARN: imIDebugMessage.LEVEL_WARNING,
+    ERROR: imIDebugMessage.LEVEL_ERROR,
+  },
+};
new file mode 100644
--- /dev/null
+++ b/chat/protocols/matrix/shims/moz.build
@@ -0,0 +1,13 @@
+# vim: set filetype=python:
+# 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/.
+
+# Shimmed dependencies of the matrix-js-sdk that we can provide through direct
+# implementation instead of through npm package.s
+
+EXTRA_JS_MODULES.matrix += [
+    'loglevel.js',
+    'safe-buffer.js',
+    'url.js',
+]
new file mode 100644
--- /dev/null
+++ b/chat/protocols/matrix/shims/safe-buffer.js
@@ -0,0 +1,33 @@
+/* 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";
+
+/* globals module */
+
+/*
+ * Per the Node.js documentation, a Buffer is an instance of Uint8Array, but
+ * additional class methods are missing for it.
+ *
+ * https://nodejs.org/docs/latest/api/buffer.html#buffer_buffers_and_typedarray
+ */
+var Buffer = {
+  isBuffer(obj) {
+    return obj.constructor == Uint8Array;
+  },
+
+  // Note that this doesn't fully implement allocate, only enough is implemented
+  // for the base-x package to function properly.
+  alloc(size, fill, encoding) {
+    return new Uint8Array(size);
+  },
+
+  allocUnsafe(size) {
+    return new Uint8Array(size);
+  },
+};
+
+module.exports = {
+  Buffer,
+};
new file mode 100644
--- /dev/null
+++ b/chat/protocols/matrix/shims/url.js
@@ -0,0 +1,15 @@
+/* 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";
+
+/* globals module */
+
+function parse(u) {
+  return new URL(u);
+}
+
+module.exports = {
+  parse,
+};