text: (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.activate = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
   /* eslint-env node */
  'use strict';
  
  // SDP helpers.
  var SDPUtils = {};
  
  // Generate an alphanumeric identifier for cname or mids.
  // TODO: use UUIDs instead? https://gist.github.com/jed/982883
  SDPUtils.generateIdentifier = function() {
    return Math.random().toString(36).substr(2, 10);
  };
  
  // The RTCP CNAME used by all peerconnections from the same JS.
  SDPUtils.localCName = SDPUtils.generateIdentifier();
  
  // Splits SDP into lines, dealing with both CRLF and LF.
  SDPUtils.splitLines = function(blob) {
    return blob.trim().split('\n').map(function(line) {
      return line.trim();
    });
  };
  // Splits SDP into sessionpart and mediasections. Ensures CRLF.
  SDPUtils.splitSections = function(blob) {
    var parts = blob.split('\nm=');
    return parts.map(function(part, index) {
      return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
    });
  };
  
  // Returns lines that start with a certain prefix.
  SDPUtils.matchPrefix = function(blob, prefix) {
    return SDPUtils.splitLines(blob).filter(function(line) {
      return line.indexOf(prefix) === 0;
    });
  };
  
  // Parses an ICE candidate line. Sample input:
  // candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
  // rport 55996"
  SDPUtils.parseCandidate = function(line) {
    var parts;
    // Parse both variants.
    if (line.indexOf('a=candidate:') === 0) {
      parts = line.substring(12).split(' ');
    } else {
      parts = line.substring(10).split(' ');
    }
  
    var candidate = {
      foundation: parts[0],
      component: parts[1],
      protocol: parts[2].toLowerCase(),
      priority: parseInt(parts[3], 10),
      ip: parts[4],
      port: parseInt(parts[5], 10),
      // skip parts[6] == 'typ'
      type: parts[7]
    };
  
    for (var i = 8; i < parts.length; i += 2) {
      switch (parts[i]) {
        case 'raddr':
          candidate.relatedAddress = parts[i + 1];
          break;
        case 'rport':
          candidate.relatedPort = parseInt(parts[i + 1], 10);
          break;
        case 'tcptype':
          candidate.tcpType = parts[i + 1];
          break;
        default: // Unknown extensions are silently ignored.
          break;
      }
    }
    return candidate;
  };
  
  // Translates a candidate object into SDP candidate attribute.
  SDPUtils.writeCandidate = function(candidate) {
    var sdp = [];
    sdp.push(candidate.foundation);
    sdp.push(candidate.component);
    sdp.push(candidate.protocol.toUpperCase());
    sdp.push(candidate.priority);
    sdp.push(candidate.ip);
    sdp.push(candidate.port);
  
    var type = candidate.type;
    sdp.push('typ');
    sdp.push(type);
    if (type !== 'host' && candidate.relatedAddress &&
        candidate.relatedPort) {
      sdp.push('raddr');
      sdp.push(candidate.relatedAddress); // was: relAddr
      sdp.push('rport');
      sdp.push(candidate.relatedPort); // was: relPort
    }
    if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
      sdp.push('tcptype');
      sdp.push(candidate.tcpType);
    }
    return 'candidate:' + sdp.join(' ');
  };
  
  // Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
  // a=rtpmap:111 opus/48000/2
  SDPUtils.parseRtpMap = function(line) {
    var parts = line.substr(9).split(' ');
    var parsed = {
      payloadType: parseInt(parts.shift(), 10) // was: id
    };
  
    parts = parts[0].split('/');
  
    parsed.name = parts[0];
    parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
    // was: channels
    parsed.numChannels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
    return parsed;
  };
  
  // Generate an a=rtpmap line from RTCRtpCodecCapability or
  // RTCRtpCodecParameters.
  SDPUtils.writeRtpMap = function(codec) {
    var pt = codec.payloadType;
    if (codec.preferredPayloadType !== undefined) {
      pt = codec.preferredPayloadType;
    }
    return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
        (codec.numChannels !== 1 ? '/' + codec.numChannels : '') + '\r\n';
  };
  
  // Parses an a=extmap line (headerextension from RFC 5285). Sample input:
  // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
  SDPUtils.parseExtmap = function(line) {
    var parts = line.substr(9).split(' ');
    return {
      id: parseInt(parts[0], 10),
      uri: parts[1]
    };
  };
  
  // Generates a=extmap line from RTCRtpHeaderExtensionParameters or
  // RTCRtpHeaderExtension.
  SDPUtils.writeExtmap = function(headerExtension) {
    return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
         ' ' + headerExtension.uri + '\r\n';
  };
  
  // Parses an ftmp line, returns dictionary. Sample input:
  // a=fmtp:96 vbr=on;cng=on
  // Also deals with vbr=on; cng=on
  SDPUtils.parseFmtp = function(line) {
    var parsed = {};
    var kv;
    var parts = line.substr(line.indexOf(' ') + 1).split(';');
    for (var j = 0; j < parts.length; j++) {
      kv = parts[j].trim().split('=');
      parsed[kv[0].trim()] = kv[1];
    }
    return parsed;
  };
  
  // Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
  SDPUtils.writeFmtp = function(codec) {
    var line = '';
    var pt = codec.payloadType;
    if (codec.preferredPayloadType !== undefined) {
      pt = codec.preferredPayloadType;
    }
    if (codec.parameters && Object.keys(codec.parameters).length) {
      var params = [];
      Object.keys(codec.parameters).forEach(function(param) {
        params.push(param + '=' + codec.parameters[param]);
      });
      line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
    }
    return line;
  };
  
  // Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
  // a=rtcp-fb:98 nack rpsi
  SDPUtils.parseRtcpFb = function(line) {
    var parts = line.substr(line.indexOf(' ') + 1).split(' ');
    return {
      type: parts.shift(),
      parameter: parts.join(' ')
    };
  };
  // Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
  SDPUtils.writeRtcpFb = function(codec) {
    var lines = '';
    var pt = codec.payloadType;
    if (codec.preferredPayloadType !== undefined) {
      pt = codec.preferredPayloadType;
    }
    if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
      // FIXME: special handling for trr-int?
      codec.rtcpFeedback.forEach(function(fb) {
        lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
        (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
            '\r\n';
      });
    }
    return lines;
  };
  
  // Parses an RFC 5576 ssrc media attribute. Sample input:
  // a=ssrc:3735928559 cname:something
  SDPUtils.parseSsrcMedia = function(line) {
    var sp = line.indexOf(' ');
    var parts = {
      ssrc: parseInt(line.substr(7, sp - 7), 10)
    };
    var colon = line.indexOf(':', sp);
    if (colon > -1) {
      parts.attribute = line.substr(sp + 1, colon - sp - 1);
      parts.value = line.substr(colon + 1);
    } else {
      parts.attribute = line.substr(sp + 1);
    }
    return parts;
  };
  
  // Extracts DTLS parameters from SDP media section or sessionpart.
  // FIXME: for consistency with other functions this should only
  //   get the fingerprint line as input. See also getIceParameters.
  SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
    var lines = SDPUtils.splitLines(mediaSection);
    // Search in session part, too.
    lines = lines.concat(SDPUtils.splitLines(sessionpart));
    var fpLine = lines.filter(function(line) {
      return line.indexOf('a=fingerprint:') === 0;
    })[0].substr(14);
    // Note: a=setup line is ignored since we use the 'auto' role.
    var dtlsParameters = {
      role: 'auto',
      fingerprints: [{
        algorithm: fpLine.split(' ')[0],
        value: fpLine.split(' ')[1]
      }]
    };
    return dtlsParameters;
  };
  
  // Serializes DTLS parameters to SDP.
  SDPUtils.writeDtlsParameters = function(params, setupType) {
    var sdp = 'a=setup:' + setupType + '\r\n';
    params.fingerprints.forEach(function(fp) {
      sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
    });
    return sdp;
  };
  // Parses ICE information from SDP media section or sessionpart.
  // FIXME: for consistency with other functions this should only
  //   get the ice-ufrag and ice-pwd lines as input.
  SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
    var lines = SDPUtils.splitLines(mediaSection);
    // Search in session part, too.
    lines = lines.concat(SDPUtils.splitLines(sessionpart));
    var iceParameters = {
      usernameFragment: lines.filter(function(line) {
        return line.indexOf('a=ice-ufrag:') === 0;
      })[0].substr(12),
      password: lines.filter(function(line) {
        return line.indexOf('a=ice-pwd:') === 0;
      })[0].substr(10)
    };
    return iceParameters;
  };
  
  // Serializes ICE parameters to SDP.
  SDPUtils.writeIceParameters = function(params) {
    return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
        'a=ice-pwd:' + params.password + '\r\n';
  };
  
  // Parses the SDP media section and returns RTCRtpParameters.
  SDPUtils.parseRtpParameters = function(mediaSection) {
    var description = {
      codecs: [],
      headerExtensions: [],
      fecMechanisms: [],
      rtcp: []
    };
    var lines = SDPUtils.splitLines(mediaSection);
    var mline = lines[0].split(' ');
    for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
      var pt = mline[i];
      var rtpmapline = SDPUtils.matchPrefix(
          mediaSection, 'a=rtpmap:' + pt + ' ')[0];
      if (rtpmapline) {
        var codec = SDPUtils.parseRtpMap(rtpmapline);
        var fmtps = SDPUtils.matchPrefix(
            mediaSection, 'a=fmtp:' + pt + ' ');
        // Only the first a=fmtp:<pt> is considered.
        codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
        codec.rtcpFeedback = SDPUtils.matchPrefix(
            mediaSection, 'a=rtcp-fb:' + pt + ' ')
          .map(SDPUtils.parseRtcpFb);
        description.codecs.push(codec);
        // parse FEC mechanisms from rtpmap lines.
        switch (codec.name.toUpperCase()) {
          case 'RED':
          case 'ULPFEC':
            description.fecMechanisms.push(codec.name.toUpperCase());
            break;
          default: // only RED and ULPFEC are recognized as FEC mechanisms.
            break;
        }
      }
    }
    SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
      description.headerExtensions.push(SDPUtils.parseExtmap(line));
    });
    // FIXME: parse rtcp.
    return description;
  };
  
  // Generates parts of the SDP media section describing the capabilities /
  // parameters.
  SDPUtils.writeRtpDescription = function(kind, caps) {
    var sdp = '';
  
    // Build the mline.
    sdp += 'm=' + kind + ' ';
    sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
    sdp += ' UDP/TLS/RTP/SAVPF ';
    sdp += caps.codecs.map(function(codec) {
      if (codec.preferredPayloadType !== undefined) {
        return codec.preferredPayloadType;
      }
      return codec.payloadType;
    }).join(' ') + '\r\n';
  
    sdp += 'c=IN IP4 0.0.0.0\r\n';
    sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
  
    // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
    caps.codecs.forEach(function(codec) {
      sdp += SDPUtils.writeRtpMap(codec);
      sdp += SDPUtils.writeFmtp(codec);
      sdp += SDPUtils.writeRtcpFb(codec);
    });
    var maxptime = 0;
    caps.codecs.forEach(function(codec) {
      if (codec.maxptime > maxptime) {
        maxptime = codec.maxptime;
      }
    });
    if (maxptime > 0) {
      sdp += 'a=maxptime:' + maxptime + '\r\n';
    }
    sdp += 'a=rtcp-mux\r\n';
  
    caps.headerExtensions.forEach(function(extension) {
      sdp += SDPUtils.writeExtmap(extension);
    });
    // FIXME: write fecMechanisms.
    return sdp;
  };
  
  // Parses the SDP media section and returns an array of
  // RTCRtpEncodingParameters.
  SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
    var encodingParameters = [];
    var description = SDPUtils.parseRtpParameters(mediaSection);
    var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
    var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
  
    // filter a=ssrc:... cname:, ignore PlanB-msid
    var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
    .map(function(line) {
      return SDPUtils.parseSsrcMedia(line);
    })
    .filter(function(parts) {
      return parts.attribute === 'cname';
    });
    var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
    var secondarySsrc;
  
    var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
    .map(function(line) {
      var parts = line.split(' ');
      parts.shift();
      return parts.map(function(part) {
        return parseInt(part, 10);
      });
    });
    if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
      secondarySsrc = flows[0][1];
    }
  
    description.codecs.forEach(function(codec) {
      if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
        var encParam = {
          ssrc: primarySsrc,
          codecPayloadType: parseInt(codec.parameters.apt, 10),
          rtx: {
            ssrc: secondarySsrc
          }
        };
        encodingParameters.push(encParam);
        if (hasRed) {
          encParam = JSON.parse(JSON.stringify(encParam));
          encParam.fec = {
            ssrc: secondarySsrc,
            mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
          };
          encodingParameters.push(encParam);
        }
      }
    });
    if (encodingParameters.length === 0 && primarySsrc) {
      encodingParameters.push({
        ssrc: primarySsrc
      });
    }
  
    // we support both b=AS and b=TIAS but interpret AS as TIAS.
    var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
    if (bandwidth.length) {
      if (bandwidth[0].indexOf('b=TIAS:') === 0) {
        bandwidth = parseInt(bandwidth[0].substr(7), 10);
      } else if (bandwidth[0].indexOf('b=AS:') === 0) {
        bandwidth = parseInt(bandwidth[0].substr(5), 10);
      }
      encodingParameters.forEach(function(params) {
        params.maxBitrate = bandwidth;
      });
    }
    return encodingParameters;
  };
  
  SDPUtils.writeSessionBoilerplate = function() {
    // FIXME: sess-id should be an NTP timestamp.
    return 'v=0\r\n' +
        'o=thisisadapterortc 8169639915646943137 2 IN IP4 127.0.0.1\r\n' +
        's=-\r\n' +
        't=0 0\r\n';
  };
  
  SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
    var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
  
    // Map ICE parameters (ufrag, pwd) to SDP.
    sdp += SDPUtils.writeIceParameters(
        transceiver.iceGatherer.getLocalParameters());
  
    // Map DTLS parameters to SDP.
    sdp += SDPUtils.writeDtlsParameters(
        transceiver.dtlsTransport.getLocalParameters(),
        type === 'offer' ? 'actpass' : 'active');
  
    sdp += 'a=mid:' + transceiver.mid + '\r\n';
  
    if (transceiver.rtpSender && transceiver.rtpReceiver) {
      sdp += 'a=sendrecv\r\n';
    } else if (transceiver.rtpSender) {
      sdp += 'a=sendonly\r\n';
    } else if (transceiver.rtpReceiver) {
      sdp += 'a=recvonly\r\n';
    } else {
      sdp += 'a=inactive\r\n';
    }
  
    // FIXME: for RTX there might be multiple SSRCs. Not implemented in Edge yet.
    if (transceiver.rtpSender) {
      var msid = 'msid:' + stream.id + ' ' +
          transceiver.rtpSender.track.id + '\r\n';
      sdp += 'a=' + msid;
      sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
          ' ' + msid;
      if (transceiver.sendEncodingParameters[0].rtx) {
        sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
            ' ' + msid;
        sdp += 'a=ssrc-group:FID ' +
            transceiver.sendEncodingParameters[0].ssrc + ' ' +
            transceiver.sendEncodingParameters[0].rtx.ssrc +
            '\r\n';
      }
    }
    // FIXME: this should be written by writeRtpDescription.
    sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
        ' cname:' + SDPUtils.localCName + '\r\n';
    if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
      sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
          ' cname:' + SDPUtils.localCName + '\r\n';
    }
    return sdp;
  };
  
  // Gets the direction from the mediaSection or the sessionpart.
  SDPUtils.getDirection = function(mediaSection, sessionpart) {
    // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
    var lines = SDPUtils.splitLines(mediaSection);
    for (var i = 0; i < lines.length; i++) {
      switch (lines[i]) {
        case 'a=sendrecv':
        case 'a=sendonly':
        case 'a=recvonly':
        case 'a=inactive':
          return lines[i].substr(2);
        default:
          // FIXME: What should happen here?
      }
    }
    if (sessionpart) {
      return SDPUtils.getDirection(sessionpart);
    }
    return 'sendrecv';
  };
  
  // Expose public methods.
  module.exports = SDPUtils;
  
  },{}],2:[function(require,module,exports){
  // version: 0.5.1
  // date: Tue Feb 07 2017 16:00:39 GMT+0000 (WET)
  // licence: 
  /**
  * Copyright 2016 PT Inovação e Sistemas SA
  * Copyright 2016 INESC-ID
  * Copyright 2016 QUOBIS NETWORKS SL
  * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
  * Copyright 2016 ORANGE SA
  * Copyright 2016 Deutsche Telekom AG
  * Copyright 2016 Apizee
  * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  **/
  
  
  (function webpackUniversalModuleDefinition(root, factory) {
  	if(typeof exports === 'object' && typeof module === 'object')
  		module.exports = factory();
  	else if(typeof define === 'function' && define.amd)
  		define("Syncher", [], factory);
  	else if(typeof exports === 'object')
  		exports["Syncher"] = factory();
  	else
  		root[""] = root[""] || {}, root[""]["Syncher"] = factory();
  })(this, function() {
  return /******/ (function(modules) { // webpackBootstrap
  /******/ 	// The module cache
  /******/ 	var installedModules = {};
  /******/
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  /******/
  /******/ 		// Check if module is in cache
  /******/ 		if(installedModules[moduleId])
  /******/ 			return installedModules[moduleId].exports;
  /******/
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = installedModules[moduleId] = {
  /******/ 			i: moduleId,
  /******/ 			l: false,
  /******/ 			exports: {}
  /******/ 		};
  /******/
  /******/ 		// Execute the module function
  /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  /******/
  /******/ 		// Flag the module as loaded
  /******/ 		module.l = true;
  /******/
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  /******/
  /******/
  /******/ 	// expose the modules object (__webpack_modules__)
  /******/ 	__webpack_require__.m = modules;
  /******/
  /******/ 	// expose the module cache
  /******/ 	__webpack_require__.c = installedModules;
  /******/
  /******/ 	// identity function for calling harmony imports with the correct context
  /******/ 	__webpack_require__.i = function(value) { return value; };
  /******/
  /******/ 	// define getter function for harmony exports
  /******/ 	__webpack_require__.d = function(exports, name, getter) {
  /******/ 		if(!__webpack_require__.o(exports, name)) {
  /******/ 			Object.defineProperty(exports, name, {
  /******/ 				configurable: false,
  /******/ 				enumerable: true,
  /******/ 				get: getter
  /******/ 			});
  /******/ 		}
  /******/ 	};
  /******/
  /******/ 	// getDefaultExport function for compatibility with non-harmony modules
  /******/ 	__webpack_require__.n = function(module) {
  /******/ 		var getter = module && module.__esModule ?
  /******/ 			function getDefault() { return module['default']; } :
  /******/ 			function getModuleExports() { return module; };
  /******/ 		__webpack_require__.d(getter, 'a', getter);
  /******/ 		return getter;
  /******/ 	};
  /******/
  /******/ 	// Object.prototype.hasOwnProperty.call
  /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  /******/
  /******/ 	// __webpack_public_path__
  /******/ 	__webpack_require__.p = "";
  /******/
  /******/ 	// Load entry module and return exports
  /******/ 	return __webpack_require__(__webpack_require__.s = 162);
  /******/ })
  /************************************************************************/
  /******/ ([
  /* 0 */
  /***/ (function(module, exports) {
  
  var core = module.exports = {version: '2.4.0'};
  if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
  
  /***/ }),
  /* 1 */
  /***/ (function(module, exports) {
  
  // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
  var global = module.exports = typeof window != 'undefined' && window.Math == Math
    ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
  if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef
  
  /***/ }),
  /* 2 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var store      = __webpack_require__(30)('wks')
    , uid        = __webpack_require__(23)
    , Symbol     = __webpack_require__(1).Symbol
    , USE_SYMBOL = typeof Symbol == 'function';
  
  var $exports = module.exports = function(name){
    return store[name] || (store[name] =
      USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name));
  };
  
  $exports.store = store;
  
  /***/ }),
  /* 3 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // Thank's IE8 for his funny defineProperty
  module.exports = !__webpack_require__(11)(function(){
    return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7;
  });
  
  /***/ }),
  /* 4 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var anObject       = __webpack_require__(5)
    , IE8_DOM_DEFINE = __webpack_require__(29)
    , toPrimitive    = __webpack_require__(22)
    , dP             = Object.defineProperty;
  
  exports.f = __webpack_require__(3) ? Object.defineProperty : function defineProperty(O, P, Attributes){
    anObject(O);
    P = toPrimitive(P, true);
    anObject(Attributes);
    if(IE8_DOM_DEFINE)try {
      return dP(O, P, Attributes);
    } catch(e){ /* empty */ }
    if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!');
    if('value' in Attributes)O[P] = Attributes.value;
    return O;
  };
  
  /***/ }),
  /* 5 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isObject = __webpack_require__(7);
  module.exports = function(it){
    if(!isObject(it))throw TypeError(it + ' is not an object!');
    return it;
  };
  
  /***/ }),
  /* 6 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var dP         = __webpack_require__(4)
    , createDesc = __webpack_require__(16);
  module.exports = __webpack_require__(3) ? function(object, key, value){
    return dP.f(object, key, createDesc(1, value));
  } : function(object, key, value){
    object[key] = value;
    return object;
  };
  
  /***/ }),
  /* 7 */
  /***/ (function(module, exports) {
  
  module.exports = function(it){
    return typeof it === 'object' ? it !== null : typeof it === 'function';
  };
  
  /***/ }),
  /* 8 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var global    = __webpack_require__(1)
    , core      = __webpack_require__(0)
    , ctx       = __webpack_require__(14)
    , hide      = __webpack_require__(6)
    , PROTOTYPE = 'prototype';
  
  var $export = function(type, name, source){
    var IS_FORCED = type & $export.F
      , IS_GLOBAL = type & $export.G
      , IS_STATIC = type & $export.S
      , IS_PROTO  = type & $export.P
      , IS_BIND   = type & $export.B
      , IS_WRAP   = type & $export.W
      , exports   = IS_GLOBAL ? core : core[name] || (core[name] = {})
      , expProto  = exports[PROTOTYPE]
      , target    = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]
      , key, own, out;
    if(IS_GLOBAL)source = name;
    for(key in source){
      // contains in native
      own = !IS_FORCED && target && target[key] !== undefined;
      if(own && key in exports)continue;
      // export native or passed
      out = own ? target[key] : source[key];
      // prevent global pollution for namespaces
      exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key]
      // bind timers to global for call from export context
      : IS_BIND && own ? ctx(out, global)
      // wrap global constructors for prevent change them in library
      : IS_WRAP && target[key] == out ? (function(C){
        var F = function(a, b, c){
          if(this instanceof C){
            switch(arguments.length){
              case 0: return new C;
              case 1: return new C(a);
              case 2: return new C(a, b);
            } return new C(a, b, c);
          } return C.apply(this, arguments);
        };
        F[PROTOTYPE] = C[PROTOTYPE];
        return F;
      // make static versions for prototype methods
      })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
      // export proto methods to core.%CONSTRUCTOR%.methods.%NAME%
      if(IS_PROTO){
        (exports.virtual || (exports.virtual = {}))[key] = out;
        // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME%
        if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out);
      }
    }
  };
  // type bitmap
  $export.F = 1;   // forced
  $export.G = 2;   // global
  $export.S = 4;   // static
  $export.P = 8;   // proto
  $export.B = 16;  // bind
  $export.W = 32;  // wrap
  $export.U = 64;  // safe
  $export.R = 128; // real proto method for `library` 
  module.exports = $export;
  
  /***/ }),
  /* 9 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.__esModule = true;
  
  exports.default = function (instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  };
  
  /***/ }),
  /* 10 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.__esModule = true;
  
  var _defineProperty = __webpack_require__(36);
  
  var _defineProperty2 = _interopRequireDefault(_defineProperty);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  exports.default = function () {
    function defineProperties(target, props) {
      for (var i = 0; i < props.length; i++) {
        var descriptor = props[i];
        descriptor.enumerable = descriptor.enumerable || false;
        descriptor.configurable = true;
        if ("value" in descriptor) descriptor.writable = true;
        (0, _defineProperty2.default)(target, descriptor.key, descriptor);
      }
    }
  
    return function (Constructor, protoProps, staticProps) {
      if (protoProps) defineProperties(Constructor.prototype, protoProps);
      if (staticProps) defineProperties(Constructor, staticProps);
      return Constructor;
    };
  }();
  
  /***/ }),
  /* 11 */
  /***/ (function(module, exports) {
  
  module.exports = function(exec){
    try {
      return !!exec();
    } catch(e){
      return true;
    }
  };
  
  /***/ }),
  /* 12 */
  /***/ (function(module, exports) {
  
  var hasOwnProperty = {}.hasOwnProperty;
  module.exports = function(it, key){
    return hasOwnProperty.call(it, key);
  };
  
  /***/ }),
  /* 13 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // to indexed object, toObject with fallback for non-array-like ES3 strings
  var IObject = __webpack_require__(56)
    , defined = __webpack_require__(24);
  module.exports = function(it){
    return IObject(defined(it));
  };
  
  /***/ }),
  /* 14 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // optional / simple context binding
  var aFunction = __webpack_require__(20);
  module.exports = function(fn, that, length){
    aFunction(fn);
    if(that === undefined)return fn;
    switch(length){
      case 1: return function(a){
        return fn.call(that, a);
      };
      case 2: return function(a, b){
        return fn.call(that, a, b);
      };
      case 3: return function(a, b, c){
        return fn.call(that, a, b, c);
      };
    }
    return function(/* ...args */){
      return fn.apply(that, arguments);
    };
  };
  
  /***/ }),
  /* 15 */
  /***/ (function(module, exports) {
  
  module.exports = {};
  
  /***/ }),
  /* 16 */
  /***/ (function(module, exports) {
  
  module.exports = function(bitmap, value){
    return {
      enumerable  : !(bitmap & 1),
      configurable: !(bitmap & 2),
      writable    : !(bitmap & 4),
      value       : value
    };
  };
  
  /***/ }),
  /* 17 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.2.14 / 15.2.3.14 Object.keys(O)
  var $keys       = __webpack_require__(44)
    , enumBugKeys = __webpack_require__(28);
  
  module.exports = Object.keys || function keys(O){
    return $keys(O, enumBugKeys);
  };
  
  /***/ }),
  /* 18 */
  /***/ (function(module, exports) {
  
  var toString = {}.toString;
  
  module.exports = function(it){
    return toString.call(it).slice(8, -1);
  };
  
  /***/ }),
  /* 19 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isObject = __webpack_require__(7)
    , document = __webpack_require__(1).document
    // in old IE typeof document.createElement is 'object'
    , is = isObject(document) && isObject(document.createElement);
  module.exports = function(it){
    return is ? document.createElement(it) : {};
  };
  
  /***/ }),
  /* 20 */
  /***/ (function(module, exports) {
  
  module.exports = function(it){
    if(typeof it != 'function')throw TypeError(it + ' is not a function!');
    return it;
  };
  
  /***/ }),
  /* 21 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var def = __webpack_require__(4).f
    , has = __webpack_require__(12)
    , TAG = __webpack_require__(2)('toStringTag');
  
  module.exports = function(it, tag, stat){
    if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag});
  };
  
  /***/ }),
  /* 22 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 7.1.1 ToPrimitive(input [, PreferredType])
  var isObject = __webpack_require__(7);
  // instead of the ES6 spec version, we didn't implement @@toPrimitive case
  // and the second argument - flag - preferred type is a string
  module.exports = function(it, S){
    if(!isObject(it))return it;
    var fn, val;
    if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val;
    if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val;
    if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val;
    throw TypeError("Can't convert object to primitive value");
  };
  
  /***/ }),
  /* 23 */
  /***/ (function(module, exports) {
  
  var id = 0
    , px = Math.random();
  module.exports = function(key){
    return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
  };
  
  /***/ }),
  /* 24 */
  /***/ (function(module, exports) {
  
  // 7.2.1 RequireObjectCoercible(argument)
  module.exports = function(it){
    if(it == undefined)throw TypeError("Can't call method on  " + it);
    return it;
  };
  
  /***/ }),
  /* 25 */
  /***/ (function(module, exports) {
  
  module.exports = true;
  
  /***/ }),
  /* 26 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var shared = __webpack_require__(30)('keys')
    , uid    = __webpack_require__(23);
  module.exports = function(key){
    return shared[key] || (shared[key] = uid(key));
  };
  
  /***/ }),
  /* 27 */
  /***/ (function(module, exports) {
  
  // 7.1.4 ToInteger
  var ceil  = Math.ceil
    , floor = Math.floor;
  module.exports = function(it){
    return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
  };
  
  /***/ }),
  /* 28 */
  /***/ (function(module, exports) {
  
  // IE 8- don't enum bug keys
  module.exports = (
    'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'
  ).split(',');
  
  /***/ }),
  /* 29 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = !__webpack_require__(3) && !__webpack_require__(11)(function(){
    return Object.defineProperty(__webpack_require__(19)('div'), 'a', {get: function(){ return 7; }}).a != 7;
  });
  
  /***/ }),
  /* 30 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var global = __webpack_require__(1)
    , SHARED = '__core-js_shared__'
    , store  = global[SHARED] || (global[SHARED] = {});
  module.exports = function(key){
    return store[key] || (store[key] = {});
  };
  
  /***/ }),
  /* 31 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(79), __esModule: true };
  
  /***/ }),
  /* 32 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 7.1.13 ToObject(argument)
  var defined = __webpack_require__(24);
  module.exports = function(it){
    return Object(defined(it));
  };
  
  /***/ }),
  /* 33 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.__esModule = true;
  
  var _setPrototypeOf = __webpack_require__(75);
  
  var _setPrototypeOf2 = _interopRequireDefault(_setPrototypeOf);
  
  var _create = __webpack_require__(74);
  
  var _create2 = _interopRequireDefault(_create);
  
  var _typeof2 = __webpack_require__(59);
  
  var _typeof3 = _interopRequireDefault(_typeof2);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  exports.default = function (subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function, not " + (typeof superClass === "undefined" ? "undefined" : (0, _typeof3.default)(superClass)));
    }
  
    subClass.prototype = (0, _create2.default)(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    if (superClass) _setPrototypeOf2.default ? (0, _setPrototypeOf2.default)(subClass, superClass) : subClass.__proto__ = superClass;
  };
  
  /***/ }),
  /* 34 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.__esModule = true;
  
  var _typeof2 = __webpack_require__(59);
  
  var _typeof3 = _interopRequireDefault(_typeof2);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  exports.default = function (self, call) {
    if (!self) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }
  
    return call && ((typeof call === "undefined" ? "undefined" : (0, _typeof3.default)(call)) === "object" || typeof call === "function") ? call : self;
  };
  
  /***/ }),
  /* 35 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
  var anObject    = __webpack_require__(5)
    , dPs         = __webpack_require__(64)
    , enumBugKeys = __webpack_require__(28)
    , IE_PROTO    = __webpack_require__(26)('IE_PROTO')
    , Empty       = function(){ /* empty */ }
    , PROTOTYPE   = 'prototype';
  
  // Create object with fake `null` prototype: use iframe Object with cleared prototype
  var createDict = function(){
    // Thrash, waste and sodomy: IE GC bug
    var iframe = __webpack_require__(19)('iframe')
      , i      = enumBugKeys.length
      , lt     = '<'
      , gt     = '>'
      , iframeDocument;
    iframe.style.display = 'none';
    __webpack_require__(42).appendChild(iframe);
    iframe.src = 'javascript:'; // eslint-disable-line no-script-url
    // createDict = iframe.contentWindow.Object;
    // html.removeChild(iframe);
    iframeDocument = iframe.contentWindow.document;
    iframeDocument.open();
    iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
    iframeDocument.close();
    createDict = iframeDocument.F;
    while(i--)delete createDict[PROTOTYPE][enumBugKeys[i]];
    return createDict();
  };
  
  module.exports = Object.create || function create(O, Properties){
    var result;
    if(O !== null){
      Empty[PROTOTYPE] = anObject(O);
      result = new Empty;
      Empty[PROTOTYPE] = null;
      // add "__proto__" for Object.getPrototypeOf polyfill
      result[IE_PROTO] = O;
    } else result = createDict();
    return Properties === undefined ? result : dPs(result, Properties);
  };
  
  
  /***/ }),
  /* 36 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(37), __esModule: true };
  
  /***/ }),
  /* 37 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(39);
  var $Object = __webpack_require__(0).Object;
  module.exports = function defineProperty(it, key, desc){
    return $Object.defineProperty(it, key, desc);
  };
  
  /***/ }),
  /* 38 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  var LIBRARY        = __webpack_require__(25)
    , $export        = __webpack_require__(8)
    , redefine       = __webpack_require__(46)
    , hide           = __webpack_require__(6)
    , has            = __webpack_require__(12)
    , Iterators      = __webpack_require__(15)
    , $iterCreate    = __webpack_require__(62)
    , setToStringTag = __webpack_require__(21)
    , getPrototypeOf = __webpack_require__(43)
    , ITERATOR       = __webpack_require__(2)('iterator')
    , BUGGY          = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next`
    , FF_ITERATOR    = '@@iterator'
    , KEYS           = 'keys'
    , VALUES         = 'values';
  
  var returnThis = function(){ return this; };
  
  module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){
    $iterCreate(Constructor, NAME, next);
    var getMethod = function(kind){
      if(!BUGGY && kind in proto)return proto[kind];
      switch(kind){
        case KEYS: return function keys(){ return new Constructor(this, kind); };
        case VALUES: return function values(){ return new Constructor(this, kind); };
      } return function entries(){ return new Constructor(this, kind); };
    };
    var TAG        = NAME + ' Iterator'
      , DEF_VALUES = DEFAULT == VALUES
      , VALUES_BUG = false
      , proto      = Base.prototype
      , $native    = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]
      , $default   = $native || getMethod(DEFAULT)
      , $entries   = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined
      , $anyNative = NAME == 'Array' ? proto.entries || $native : $native
      , methods, key, IteratorPrototype;
    // Fix native
    if($anyNative){
      IteratorPrototype = getPrototypeOf($anyNative.call(new Base));
      if(IteratorPrototype !== Object.prototype){
        // Set @@toStringTag to native iterators
        setToStringTag(IteratorPrototype, TAG, true);
        // fix for some old engines
        if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis);
      }
    }
    // fix Array#{values, @@iterator}.name in V8 / FF
    if(DEF_VALUES && $native && $native.name !== VALUES){
      VALUES_BUG = true;
      $default = function values(){ return $native.call(this); };
    }
    // Define iterator
    if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){
      hide(proto, ITERATOR, $default);
    }
    // Plug for library
    Iterators[NAME] = $default;
    Iterators[TAG]  = returnThis;
    if(DEFAULT){
      methods = {
        values:  DEF_VALUES ? $default : getMethod(VALUES),
        keys:    IS_SET     ? $default : getMethod(KEYS),
        entries: $entries
      };
      if(FORCED)for(key in methods){
        if(!(key in proto))redefine(proto, key, methods[key]);
      } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
    }
    return methods;
  };
  
  /***/ }),
  /* 39 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var $export = __webpack_require__(8);
  // 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes)
  $export($export.S + $export.F * !__webpack_require__(3), 'Object', {defineProperty: __webpack_require__(4).f});
  
  /***/ }),
  /* 40 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(53), __esModule: true };
  
  /***/ }),
  /* 41 */
  /***/ (function(module, exports) {
  
  exports.f = {}.propertyIsEnumerable;
  
  /***/ }),
  /* 42 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = __webpack_require__(1).document && document.documentElement;
  
  /***/ }),
  /* 43 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)
  var has         = __webpack_require__(12)
    , toObject    = __webpack_require__(32)
    , IE_PROTO    = __webpack_require__(26)('IE_PROTO')
    , ObjectProto = Object.prototype;
  
  module.exports = Object.getPrototypeOf || function(O){
    O = toObject(O);
    if(has(O, IE_PROTO))return O[IE_PROTO];
    if(typeof O.constructor == 'function' && O instanceof O.constructor){
      return O.constructor.prototype;
    } return O instanceof Object ? ObjectProto : null;
  };
  
  /***/ }),
  /* 44 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var has          = __webpack_require__(12)
    , toIObject    = __webpack_require__(13)
    , arrayIndexOf = __webpack_require__(61)(false)
    , IE_PROTO     = __webpack_require__(26)('IE_PROTO');
  
  module.exports = function(object, names){
    var O      = toIObject(object)
      , i      = 0
      , result = []
      , key;
    for(key in O)if(key != IE_PROTO)has(O, key) && result.push(key);
    // Don't enum bug & hidden keys
    while(names.length > i)if(has(O, key = names[i++])){
      ~arrayIndexOf(result, key) || result.push(key);
    }
    return result;
  };
  
  /***/ }),
  /* 45 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // most Object methods by ES6 should accept primitives
  var $export = __webpack_require__(8)
    , core    = __webpack_require__(0)
    , fails   = __webpack_require__(11);
  module.exports = function(KEY, exec){
    var fn  = (core.Object || {})[KEY] || Object[KEY]
      , exp = {};
    exp[KEY] = exec(fn);
    $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp);
  };
  
  /***/ }),
  /* 46 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = __webpack_require__(6);
  
  /***/ }),
  /* 47 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 7.1.15 ToLength
  var toInteger = __webpack_require__(27)
    , min       = Math.min;
  module.exports = function(it){
    return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
  };
  
  /***/ }),
  /* 48 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var global         = __webpack_require__(1)
    , core           = __webpack_require__(0)
    , LIBRARY        = __webpack_require__(25)
    , wksExt         = __webpack_require__(49)
    , defineProperty = __webpack_require__(4).f;
  module.exports = function(name){
    var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});
    if(name.charAt(0) != '_' && !(name in $Symbol))defineProperty($Symbol, name, {value: wksExt.f(name)});
  };
  
  /***/ }),
  /* 49 */
  /***/ (function(module, exports, __webpack_require__) {
  
  exports.f = __webpack_require__(2);
  
  /***/ }),
  /* 50 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  var $at  = __webpack_require__(66)(true);
  
  // 21.1.3.27 String.prototype[@@iterator]()
  __webpack_require__(38)(String, 'String', function(iterated){
    this._t = String(iterated); // target
    this._i = 0;                // next index
  // 21.1.5.2.1 %StringIteratorPrototype%.next()
  }, function(){
    var O     = this._t
      , index = this._i
      , point;
    if(index >= O.length)return {value: undefined, done: true};
    point = $at(O, index);
    this._i += point.length;
    return {value: point, done: false};
  });
  
  /***/ }),
  /* 51 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(69);
  var global        = __webpack_require__(1)
    , hide          = __webpack_require__(6)
    , Iterators     = __webpack_require__(15)
    , TO_STRING_TAG = __webpack_require__(2)('toStringTag');
  
  for(var collections = ['NodeList', 'DOMTokenList', 'MediaList', 'StyleSheetList', 'CSSRuleList'], i = 0; i < 5; i++){
    var NAME       = collections[i]
      , Collection = global[NAME]
      , proto      = Collection && Collection.prototype;
    if(proto && !proto[TO_STRING_TAG])hide(proto, TO_STRING_TAG, NAME);
    Iterators[NAME] = Iterators.Array;
  }
  
  /***/ }),
  /* 52 */,
  /* 53 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var core  = __webpack_require__(0)
    , $JSON = core.JSON || (core.JSON = {stringify: JSON.stringify});
  module.exports = function stringify(it){ // eslint-disable-line no-unused-vars
    return $JSON.stringify.apply($JSON, arguments);
  };
  
  /***/ }),
  /* 54 */
  /***/ (function(module, exports) {
  
  
  
  /***/ }),
  /* 55 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // getting tag from 19.1.3.6 Object.prototype.toString()
  var cof = __webpack_require__(18)
    , TAG = __webpack_require__(2)('toStringTag')
    // ES3 wrong here
    , ARG = cof(function(){ return arguments; }()) == 'Arguments';
  
  // fallback for IE11 Script Access Denied error
  var tryGet = function(it, key){
    try {
      return it[key];
    } catch(e){ /* empty */ }
  };
  
  module.exports = function(it){
    var O, T, B;
    return it === undefined ? 'Undefined' : it === null ? 'Null'
      // @@toStringTag case
      : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T
      // builtinTag case
      : ARG ? cof(O)
      // ES3 arguments fallback
      : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
  };
  
  /***/ }),
  /* 56 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // fallback for non-array-like ES3 and non-enumerable old V8 strings
  var cof = __webpack_require__(18);
  module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){
    return cof(it) == 'String' ? it.split('') : Object(it);
  };
  
  /***/ }),
  /* 57 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var pIE            = __webpack_require__(41)
    , createDesc     = __webpack_require__(16)
    , toIObject      = __webpack_require__(13)
    , toPrimitive    = __webpack_require__(22)
    , has            = __webpack_require__(12)
    , IE8_DOM_DEFINE = __webpack_require__(29)
    , gOPD           = Object.getOwnPropertyDescriptor;
  
  exports.f = __webpack_require__(3) ? gOPD : function getOwnPropertyDescriptor(O, P){
    O = toIObject(O);
    P = toPrimitive(P, true);
    if(IE8_DOM_DEFINE)try {
      return gOPD(O, P);
    } catch(e){ /* empty */ }
    if(has(O, P))return createDesc(!pIE.f.call(O, P), O[P]);
  };
  
  /***/ }),
  /* 58 */
  /***/ (function(module, exports) {
  
  exports.f = Object.getOwnPropertySymbols;
  
  /***/ }),
  /* 59 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.__esModule = true;
  
  var _iterator = __webpack_require__(77);
  
  var _iterator2 = _interopRequireDefault(_iterator);
  
  var _symbol = __webpack_require__(76);
  
  var _symbol2 = _interopRequireDefault(_symbol);
  
  var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj; };
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) {
    return typeof obj === "undefined" ? "undefined" : _typeof(obj);
  } : function (obj) {
    return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default && obj !== _symbol2.default.prototype ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj);
  };
  
  /***/ }),
  /* 60 */
  /***/ (function(module, exports) {
  
  module.exports = function(){ /* empty */ };
  
  /***/ }),
  /* 61 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // false -> Array#indexOf
  // true  -> Array#includes
  var toIObject = __webpack_require__(13)
    , toLength  = __webpack_require__(47)
    , toIndex   = __webpack_require__(68);
  module.exports = function(IS_INCLUDES){
    return function($this, el, fromIndex){
      var O      = toIObject($this)
        , length = toLength(O.length)
        , index  = toIndex(fromIndex, length)
        , value;
      // Array#includes uses SameValueZero equality algorithm
      if(IS_INCLUDES && el != el)while(length > index){
        value = O[index++];
        if(value != value)return true;
      // Array#toIndex ignores holes, Array#includes - not
      } else for(;length > index; index++)if(IS_INCLUDES || index in O){
        if(O[index] === el)return IS_INCLUDES || index || 0;
      } return !IS_INCLUDES && -1;
    };
  };
  
  /***/ }),
  /* 62 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  var create         = __webpack_require__(35)
    , descriptor     = __webpack_require__(16)
    , setToStringTag = __webpack_require__(21)
    , IteratorPrototype = {};
  
  // 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
  __webpack_require__(6)(IteratorPrototype, __webpack_require__(2)('iterator'), function(){ return this; });
  
  module.exports = function(Constructor, NAME, next){
    Constructor.prototype = create(IteratorPrototype, {next: descriptor(1, next)});
    setToStringTag(Constructor, NAME + ' Iterator');
  };
  
  /***/ }),
  /* 63 */
  /***/ (function(module, exports) {
  
  module.exports = function(done, value){
    return {value: value, done: !!done};
  };
  
  /***/ }),
  /* 64 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var dP       = __webpack_require__(4)
    , anObject = __webpack_require__(5)
    , getKeys  = __webpack_require__(17);
  
  module.exports = __webpack_require__(3) ? Object.defineProperties : function defineProperties(O, Properties){
    anObject(O);
    var keys   = getKeys(Properties)
      , length = keys.length
      , i = 0
      , P;
    while(length > i)dP.f(O, P = keys[i++], Properties[P]);
    return O;
  };
  
  /***/ }),
  /* 65 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.2.7 / 15.2.3.4 Object.getOwnPropertyNames(O)
  var $keys      = __webpack_require__(44)
    , hiddenKeys = __webpack_require__(28).concat('length', 'prototype');
  
  exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O){
    return $keys(O, hiddenKeys);
  };
  
  /***/ }),
  /* 66 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var toInteger = __webpack_require__(27)
    , defined   = __webpack_require__(24);
  // true  -> String#at
  // false -> String#codePointAt
  module.exports = function(TO_STRING){
    return function(that, pos){
      var s = String(defined(that))
        , i = toInteger(pos)
        , l = s.length
        , a, b;
      if(i < 0 || i >= l)return TO_STRING ? '' : undefined;
      a = s.charCodeAt(i);
      return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff
        ? TO_STRING ? s.charAt(i) : a
        : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
    };
  };
  
  /***/ }),
  /* 67 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var ctx                = __webpack_require__(14)
    , invoke             = __webpack_require__(88)
    , html               = __webpack_require__(42)
    , cel                = __webpack_require__(19)
    , global             = __webpack_require__(1)
    , process            = global.process
    , setTask            = global.setImmediate
    , clearTask          = global.clearImmediate
    , MessageChannel     = global.MessageChannel
    , counter            = 0
    , queue              = {}
    , ONREADYSTATECHANGE = 'onreadystatechange'
    , defer, channel, port;
  var run = function(){
    var id = +this;
    if(queue.hasOwnProperty(id)){
      var fn = queue[id];
      delete queue[id];
      fn();
    }
  };
  var listener = function(event){
    run.call(event.data);
  };
  // Node.js 0.9+ & IE10+ has setImmediate, otherwise:
  if(!setTask || !clearTask){
    setTask = function setImmediate(fn){
      var args = [], i = 1;
      while(arguments.length > i)args.push(arguments[i++]);
      queue[++counter] = function(){
        invoke(typeof fn == 'function' ? fn : Function(fn), args);
      };
      defer(counter);
      return counter;
    };
    clearTask = function clearImmediate(id){
      delete queue[id];
    };
    // Node.js 0.8-
    if(__webpack_require__(18)(process) == 'process'){
      defer = function(id){
        process.nextTick(ctx(run, id, 1));
      };
    // Browsers with MessageChannel, includes WebWorkers
    } else if(MessageChannel){
      channel = new MessageChannel;
      port    = channel.port2;
      channel.port1.onmessage = listener;
      defer = ctx(port.postMessage, port, 1);
    // Browsers with postMessage, skip WebWorkers
    // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
    } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){
      defer = function(id){
        global.postMessage(id + '', '*');
      };
      global.addEventListener('message', listener, false);
    // IE8-
    } else if(ONREADYSTATECHANGE in cel('script')){
      defer = function(id){
        html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){
          html.removeChild(this);
          run.call(id);
        };
      };
    // Rest old browsers
    } else {
      defer = function(id){
        setTimeout(ctx(run, id, 1), 0);
      };
    }
  }
  module.exports = {
    set:   setTask,
    clear: clearTask
  };
  
  /***/ }),
  /* 68 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var toInteger = __webpack_require__(27)
    , max       = Math.max
    , min       = Math.min;
  module.exports = function(index, length){
    index = toInteger(index);
    return index < 0 ? max(index + length, 0) : min(index, length);
  };
  
  /***/ }),
  /* 69 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  var addToUnscopables = __webpack_require__(60)
    , step             = __webpack_require__(63)
    , Iterators        = __webpack_require__(15)
    , toIObject        = __webpack_require__(13);
  
  // 22.1.3.4 Array.prototype.entries()
  // 22.1.3.13 Array.prototype.keys()
  // 22.1.3.29 Array.prototype.values()
  // 22.1.3.30 Array.prototype[@@iterator]()
  module.exports = __webpack_require__(38)(Array, 'Array', function(iterated, kind){
    this._t = toIObject(iterated); // target
    this._i = 0;                   // next index
    this._k = kind;                // kind
  // 22.1.5.2.1 %ArrayIteratorPrototype%.next()
  }, function(){
    var O     = this._t
      , kind  = this._k
      , index = this._i++;
    if(!O || index >= O.length){
      this._t = undefined;
      return step(1);
    }
    if(kind == 'keys'  )return step(0, index);
    if(kind == 'values')return step(0, O[index]);
    return step(0, [index, O[index]]);
  }, 'values');
  
  // argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
  Iterators.Arguments = Iterators.Array;
  
  addToUnscopables('keys');
  addToUnscopables('values');
  addToUnscopables('entries');
  
  /***/ }),
  /* 70 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(80), __esModule: true };
  
  /***/ }),
  /* 71 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(82), __esModule: true };
  
  /***/ }),
  /* 72 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var META     = __webpack_require__(23)('meta')
    , isObject = __webpack_require__(7)
    , has      = __webpack_require__(12)
    , setDesc  = __webpack_require__(4).f
    , id       = 0;
  var isExtensible = Object.isExtensible || function(){
    return true;
  };
  var FREEZE = !__webpack_require__(11)(function(){
    return isExtensible(Object.preventExtensions({}));
  });
  var setMeta = function(it){
    setDesc(it, META, {value: {
      i: 'O' + ++id, // object ID
      w: {}          // weak collections IDs
    }});
  };
  var fastKey = function(it, create){
    // return primitive with prefix
    if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
    if(!has(it, META)){
      // can't set metadata to uncaught frozen object
      if(!isExtensible(it))return 'F';
      // not necessary to add metadata
      if(!create)return 'E';
      // add missing metadata
      setMeta(it);
    // return object ID
    } return it[META].i;
  };
  var getWeak = function(it, create){
    if(!has(it, META)){
      // can't set metadata to uncaught frozen object
      if(!isExtensible(it))return true;
      // not necessary to add metadata
      if(!create)return false;
      // add missing metadata
      setMeta(it);
    // return hash weak collections IDs
    } return it[META].w;
  };
  // add metadata on freeze-family methods calling
  var onFreeze = function(it){
    if(FREEZE && meta.NEED && isExtensible(it) && !has(it, META))setMeta(it);
    return it;
  };
  var meta = module.exports = {
    KEY:      META,
    NEED:     false,
    fastKey:  fastKey,
    getWeak:  getWeak,
    onFreeze: onFreeze
  };
  
  /***/ }),
  /* 73 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var classof   = __webpack_require__(55)
    , ITERATOR  = __webpack_require__(2)('iterator')
    , Iterators = __webpack_require__(15);
  module.exports = __webpack_require__(0).getIteratorMethod = function(it){
    if(it != undefined)return it[ITERATOR]
      || it['@@iterator']
      || Iterators[classof(it)];
  };
  
  /***/ }),
  /* 74 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(78), __esModule: true };
  
  /***/ }),
  /* 75 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(81), __esModule: true };
  
  /***/ }),
  /* 76 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(83), __esModule: true };
  
  /***/ }),
  /* 77 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(84), __esModule: true };
  
  /***/ }),
  /* 78 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(100);
  var $Object = __webpack_require__(0).Object;
  module.exports = function create(P, D){
    return $Object.create(P, D);
  };
  
  /***/ }),
  /* 79 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(101);
  module.exports = __webpack_require__(0).Object.getPrototypeOf;
  
  /***/ }),
  /* 80 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(102);
  module.exports = __webpack_require__(0).Object.keys;
  
  /***/ }),
  /* 81 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(103);
  module.exports = __webpack_require__(0).Object.setPrototypeOf;
  
  /***/ }),
  /* 82 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(54);
  __webpack_require__(50);
  __webpack_require__(51);
  __webpack_require__(104);
  module.exports = __webpack_require__(0).Promise;
  
  /***/ }),
  /* 83 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(105);
  __webpack_require__(54);
  __webpack_require__(106);
  __webpack_require__(107);
  module.exports = __webpack_require__(0).Symbol;
  
  /***/ }),
  /* 84 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(50);
  __webpack_require__(51);
  module.exports = __webpack_require__(49).f('iterator');
  
  /***/ }),
  /* 85 */
  /***/ (function(module, exports) {
  
  module.exports = function(it, Constructor, name, forbiddenField){
    if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){
      throw TypeError(name + ': incorrect invocation!');
    } return it;
  };
  
  /***/ }),
  /* 86 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // all enumerable object keys, includes symbols
  var getKeys = __webpack_require__(17)
    , gOPS    = __webpack_require__(58)
    , pIE     = __webpack_require__(41);
  module.exports = function(it){
    var result     = getKeys(it)
      , getSymbols = gOPS.f;
    if(getSymbols){
      var symbols = getSymbols(it)
        , isEnum  = pIE.f
        , i       = 0
        , key;
      while(symbols.length > i)if(isEnum.call(it, key = symbols[i++]))result.push(key);
    } return result;
  };
  
  /***/ }),
  /* 87 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var ctx         = __webpack_require__(14)
    , call        = __webpack_require__(91)
    , isArrayIter = __webpack_require__(89)
    , anObject    = __webpack_require__(5)
    , toLength    = __webpack_require__(47)
    , getIterFn   = __webpack_require__(73)
    , BREAK       = {}
    , RETURN      = {};
  var exports = module.exports = function(iterable, entries, fn, that, ITERATOR){
    var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable)
      , f      = ctx(fn, that, entries ? 2 : 1)
      , index  = 0
      , length, step, iterator, result;
    if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!');
    // fast case for arrays with default iterator
    if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){
      result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
      if(result === BREAK || result === RETURN)return result;
    } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){
      result = call(iterator, f, step.value, entries);
      if(result === BREAK || result === RETURN)return result;
    }
  };
  exports.BREAK  = BREAK;
  exports.RETURN = RETURN;
  
  /***/ }),
  /* 88 */
  /***/ (function(module, exports) {
  
  // fast apply, http://jsperf.lnkit.com/fast-apply/5
  module.exports = function(fn, args, that){
    var un = that === undefined;
    switch(args.length){
      case 0: return un ? fn()
                        : fn.call(that);
      case 1: return un ? fn(args[0])
                        : fn.call(that, args[0]);
      case 2: return un ? fn(args[0], args[1])
                        : fn.call(that, args[0], args[1]);
      case 3: return un ? fn(args[0], args[1], args[2])
                        : fn.call(that, args[0], args[1], args[2]);
      case 4: return un ? fn(args[0], args[1], args[2], args[3])
                        : fn.call(that, args[0], args[1], args[2], args[3]);
    } return              fn.apply(that, args);
  };
  
  /***/ }),
  /* 89 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // check on default Array iterator
  var Iterators  = __webpack_require__(15)
    , ITERATOR   = __webpack_require__(2)('iterator')
    , ArrayProto = Array.prototype;
  
  module.exports = function(it){
    return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
  };
  
  /***/ }),
  /* 90 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 7.2.2 IsArray(argument)
  var cof = __webpack_require__(18);
  module.exports = Array.isArray || function isArray(arg){
    return cof(arg) == 'Array';
  };
  
  /***/ }),
  /* 91 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // call something on iterator step with safe closing on error
  var anObject = __webpack_require__(5);
  module.exports = function(iterator, fn, value, entries){
    try {
      return entries ? fn(anObject(value)[0], value[1]) : fn(value);
    // 7.4.6 IteratorClose(iterator, completion)
    } catch(e){
      var ret = iterator['return'];
      if(ret !== undefined)anObject(ret.call(iterator));
      throw e;
    }
  };
  
  /***/ }),
  /* 92 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var ITERATOR     = __webpack_require__(2)('iterator')
    , SAFE_CLOSING = false;
  
  try {
    var riter = [7][ITERATOR]();
    riter['return'] = function(){ SAFE_CLOSING = true; };
    Array.from(riter, function(){ throw 2; });
  } catch(e){ /* empty */ }
  
  module.exports = function(exec, skipClosing){
    if(!skipClosing && !SAFE_CLOSING)return false;
    var safe = false;
    try {
      var arr  = [7]
        , iter = arr[ITERATOR]();
      iter.next = function(){ return {done: safe = true}; };
      arr[ITERATOR] = function(){ return iter; };
      exec(arr);
    } catch(e){ /* empty */ }
    return safe;
  };
  
  /***/ }),
  /* 93 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getKeys   = __webpack_require__(17)
    , toIObject = __webpack_require__(13);
  module.exports = function(object, el){
    var O      = toIObject(object)
      , keys   = getKeys(O)
      , length = keys.length
      , index  = 0
      , key;
    while(length > index)if(O[key = keys[index++]] === el)return key;
  };
  
  /***/ }),
  /* 94 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var global    = __webpack_require__(1)
    , macrotask = __webpack_require__(67).set
    , Observer  = global.MutationObserver || global.WebKitMutationObserver
    , process   = global.process
    , Promise   = global.Promise
    , isNode    = __webpack_require__(18)(process) == 'process';
  
  module.exports = function(){
    var head, last, notify;
  
    var flush = function(){
      var parent, fn;
      if(isNode && (parent = process.domain))parent.exit();
      while(head){
        fn   = head.fn;
        head = head.next;
        try {
          fn();
        } catch(e){
          if(head)notify();
          else last = undefined;
          throw e;
        }
      } last = undefined;
      if(parent)parent.enter();
    };
  
    // Node.js
    if(isNode){
      notify = function(){
        process.nextTick(flush);
      };
    // browsers with MutationObserver
    } else if(Observer){
      var toggle = true
        , node   = document.createTextNode('');
      new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new
      notify = function(){
        node.data = toggle = !toggle;
      };
    // environments with maybe non-completely correct, but existent Promise
    } else if(Promise && Promise.resolve){
      var promise = Promise.resolve();
      notify = function(){
        promise.then(flush);
      };
    // for other environments - macrotask based on:
    // - setImmediate
    // - MessageChannel
    // - window.postMessag
    // - onreadystatechange
    // - setTimeout
    } else {
      notify = function(){
        // strange IE + webpack dev server bug - use .call(global)
        macrotask.call(global, flush);
      };
    }
  
    return function(fn){
      var task = {fn: fn, next: undefined};
      if(last)last.next = task;
      if(!head){
        head = task;
        notify();
      } last = task;
    };
  };
  
  /***/ }),
  /* 95 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
  var toIObject = __webpack_require__(13)
    , gOPN      = __webpack_require__(65).f
    , toString  = {}.toString;
  
  var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
    ? Object.getOwnPropertyNames(window) : [];
  
  var getWindowNames = function(it){
    try {
      return gOPN(it);
    } catch(e){
      return windowNames.slice();
    }
  };
  
  module.exports.f = function getOwnPropertyNames(it){
    return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));
  };
  
  
  /***/ }),
  /* 96 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var hide = __webpack_require__(6);
  module.exports = function(target, src, safe){
    for(var key in src){
      if(safe && target[key])target[key] = src[key];
      else hide(target, key, src[key]);
    } return target;
  };
  
  /***/ }),
  /* 97 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // Works with __proto__ only. Old v8 can't work with null proto objects.
  /* eslint-disable no-proto */
  var isObject = __webpack_require__(7)
    , anObject = __webpack_require__(5);
  var check = function(O, proto){
    anObject(O);
    if(!isObject(proto) && proto !== null)throw TypeError(proto + ": can't set as prototype!");
  };
  module.exports = {
    set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line
      function(test, buggy, set){
        try {
          set = __webpack_require__(14)(Function.call, __webpack_require__(57).f(Object.prototype, '__proto__').set, 2);
          set(test, []);
          buggy = !(test instanceof Array);
        } catch(e){ buggy = true; }
        return function setPrototypeOf(O, proto){
          check(O, proto);
          if(buggy)O.__proto__ = proto;
          else set(O, proto);
          return O;
        };
      }({}, false) : undefined),
    check: check
  };
  
  /***/ }),
  /* 98 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  var global      = __webpack_require__(1)
    , core        = __webpack_require__(0)
    , dP          = __webpack_require__(4)
    , DESCRIPTORS = __webpack_require__(3)
    , SPECIES     = __webpack_require__(2)('species');
  
  module.exports = function(KEY){
    var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY];
    if(DESCRIPTORS && C && !C[SPECIES])dP.f(C, SPECIES, {
      configurable: true,
      get: function(){ return this; }
    });
  };
  
  /***/ }),
  /* 99 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 7.3.20 SpeciesConstructor(O, defaultConstructor)
  var anObject  = __webpack_require__(5)
    , aFunction = __webpack_require__(20)
    , SPECIES   = __webpack_require__(2)('species');
  module.exports = function(O, D){
    var C = anObject(O).constructor, S;
    return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
  };
  
  /***/ }),
  /* 100 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var $export = __webpack_require__(8)
  // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
  $export($export.S, 'Object', {create: __webpack_require__(35)});
  
  /***/ }),
  /* 101 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.2.9 Object.getPrototypeOf(O)
  var toObject        = __webpack_require__(32)
    , $getPrototypeOf = __webpack_require__(43);
  
  __webpack_require__(45)('getPrototypeOf', function(){
    return function getPrototypeOf(it){
      return $getPrototypeOf(toObject(it));
    };
  });
  
  /***/ }),
  /* 102 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.2.14 Object.keys(O)
  var toObject = __webpack_require__(32)
    , $keys    = __webpack_require__(17);
  
  __webpack_require__(45)('keys', function(){
    return function keys(it){
      return $keys(toObject(it));
    };
  });
  
  /***/ }),
  /* 103 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.3.19 Object.setPrototypeOf(O, proto)
  var $export = __webpack_require__(8);
  $export($export.S, 'Object', {setPrototypeOf: __webpack_require__(97).set});
  
  /***/ }),
  /* 104 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  var LIBRARY            = __webpack_require__(25)
    , global             = __webpack_require__(1)
    , ctx                = __webpack_require__(14)
    , classof            = __webpack_require__(55)
    , $export            = __webpack_require__(8)
    , isObject           = __webpack_require__(7)
    , aFunction          = __webpack_require__(20)
    , anInstance         = __webpack_require__(85)
    , forOf              = __webpack_require__(87)
    , speciesConstructor = __webpack_require__(99)
    , task               = __webpack_require__(67).set
    , microtask          = __webpack_require__(94)()
    , PROMISE            = 'Promise'
    , TypeError          = global.TypeError
    , process            = global.process
    , $Promise           = global[PROMISE]
    , process            = global.process
    , isNode             = classof(process) == 'process'
    , empty              = function(){ /* empty */ }
    , Internal, GenericPromiseCapability, Wrapper;
  
  var USE_NATIVE = !!function(){
    try {
      // correct subclassing with @@species support
      var promise     = $Promise.resolve(1)
        , FakePromise = (promise.constructor = {})[__webpack_require__(2)('species')] = function(exec){ exec(empty, empty); };
      // unhandled rejections tracking support, NodeJS Promise without it fails @@species test
      return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;
    } catch(e){ /* empty */ }
  }();
  
  // helpers
  var sameConstructor = function(a, b){
    // with library wrapper special case
    return a === b || a === $Promise && b === Wrapper;
  };
  var isThenable = function(it){
    var then;
    return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
  };
  var newPromiseCapability = function(C){
    return sameConstructor($Promise, C)
      ? new PromiseCapability(C)
      : new GenericPromiseCapability(C);
  };
  var PromiseCapability = GenericPromiseCapability = function(C){
    var resolve, reject;
    this.promise = new C(function($$resolve, $$reject){
      if(resolve !== undefined || reject !== undefined)throw TypeError('Bad Promise constructor');
      resolve = $$resolve;
      reject  = $$reject;
    });
    this.resolve = aFunction(resolve);
    this.reject  = aFunction(reject);
  };
  var perform = function(exec){
    try {
      exec();
    } catch(e){
      return {error: e};
    }
  };
  var notify = function(promise, isReject){
    if(promise._n)return;
    promise._n = true;
    var chain = promise._c;
    microtask(function(){
      var value = promise._v
        , ok    = promise._s == 1
        , i     = 0;
      var run = function(reaction){
        var handler = ok ? reaction.ok : reaction.fail
          , resolve = reaction.resolve
          , reject  = reaction.reject
          , domain  = reaction.domain
          , result, then;
        try {
          if(handler){
            if(!ok){
              if(promise._h == 2)onHandleUnhandled(promise);
              promise._h = 1;
            }
            if(handler === true)result = value;
            else {
              if(domain)domain.enter();
              result = handler(value);
              if(domain)domain.exit();
            }
            if(result === reaction.promise){
              reject(TypeError('Promise-chain cycle'));
            } else if(then = isThenable(result)){
              then.call(result, resolve, reject);
            } else resolve(result);
          } else reject(value);
        } catch(e){
          reject(e);
        }
      };
      while(chain.length > i)run(chain[i++]); // variable length - can't use forEach
      promise._c = [];
      promise._n = false;
      if(isReject && !promise._h)onUnhandled(promise);
    });
  };
  var onUnhandled = function(promise){
    task.call(global, function(){
      var value = promise._v
        , abrupt, handler, console;
      if(isUnhandled(promise)){
        abrupt = perform(function(){
          if(isNode){
            process.emit('unhandledRejection', value, promise);
          } else if(handler = global.onunhandledrejection){
            handler({promise: promise, reason: value});
          } else if((console = global.console) && console.error){
            console.error('Unhandled promise rejection', value);
          }
        });
        // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
        promise._h = isNode || isUnhandled(promise) ? 2 : 1;
      } promise._a = undefined;
      if(abrupt)throw abrupt.error;
    });
  };
  var isUnhandled = function(promise){
    if(promise._h == 1)return false;
    var chain = promise._a || promise._c
      , i     = 0
      , reaction;
    while(chain.length > i){
      reaction = chain[i++];
      if(reaction.fail || !isUnhandled(reaction.promise))return false;
    } return true;
  };
  var onHandleUnhandled = function(promise){
    task.call(global, function(){
      var handler;
      if(isNode){
        process.emit('rejectionHandled', promise);
      } else if(handler = global.onrejectionhandled){
        handler({promise: promise, reason: promise._v});
      }
    });
  };
  var $reject = function(value){
    var promise = this;
    if(promise._d)return;
    promise._d = true;
    promise = promise._w || promise; // unwrap
    promise._v = value;
    promise._s = 2;
    if(!promise._a)promise._a = promise._c.slice();
    notify(promise, true);
  };
  var $resolve = function(value){
    var promise = this
      , then;
    if(promise._d)return;
    promise._d = true;
    promise = promise._w || promise; // unwrap
    try {
      if(promise === value)throw TypeError("Promise can't be resolved itself");
      if(then = isThenable(value)){
        microtask(function(){
          var wrapper = {_w: promise, _d: false}; // wrap
          try {
            then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
          } catch(e){
            $reject.call(wrapper, e);
          }
        });
      } else {
        promise._v = value;
        promise._s = 1;
        notify(promise, false);
      }
    } catch(e){
      $reject.call({_w: promise, _d: false}, e); // wrap
    }
  };
  
  // constructor polyfill
  if(!USE_NATIVE){
    // 25.4.3.1 Promise(executor)
    $Promise = function Promise(executor){
      anInstance(this, $Promise, PROMISE, '_h');
      aFunction(executor);
      Internal.call(this);
      try {
        executor(ctx($resolve, this, 1), ctx($reject, this, 1));
      } catch(err){
        $reject.call(this, err);
      }
    };
    Internal = function Promise(executor){
      this._c = [];             // <- awaiting reactions
      this._a = undefined;      // <- checked in isUnhandled reactions
      this._s = 0;              // <- state
      this._d = false;          // <- done
      this._v = undefined;      // <- value
      this._h = 0;              // <- rejection state, 0 - default, 1 - handled, 2 - unhandled
      this._n = false;          // <- notify
    };
    Internal.prototype = __webpack_require__(96)($Promise.prototype, {
      // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
      then: function then(onFulfilled, onRejected){
        var reaction    = newPromiseCapability(speciesConstructor(this, $Promise));
        reaction.ok     = typeof onFulfilled == 'function' ? onFulfilled : true;
        reaction.fail   = typeof onRejected == 'function' && onRejected;
        reaction.domain = isNode ? process.domain : undefined;
        this._c.push(reaction);
        if(this._a)this._a.push(reaction);
        if(this._s)notify(this, false);
        return reaction.promise;
      },
      // 25.4.5.1 Promise.prototype.catch(onRejected)
      'catch': function(onRejected){
        return this.then(undefined, onRejected);
      }
    });
    PromiseCapability = function(){
      var promise  = new Internal;
      this.promise = promise;
      this.resolve = ctx($resolve, promise, 1);
      this.reject  = ctx($reject, promise, 1);
    };
  }
  
  $export($export.G + $export.W + $export.F * !USE_NATIVE, {Promise: $Promise});
  __webpack_require__(21)($Promise, PROMISE);
  __webpack_require__(98)(PROMISE);
  Wrapper = __webpack_require__(0)[PROMISE];
  
  // statics
  $export($export.S + $export.F * !USE_NATIVE, PROMISE, {
    // 25.4.4.5 Promise.reject(r)
    reject: function reject(r){
      var capability = newPromiseCapability(this)
        , $$reject   = capability.reject;
      $$reject(r);
      return capability.promise;
    }
  });
  $export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
    // 25.4.4.6 Promise.resolve(x)
    resolve: function resolve(x){
      // instanceof instead of internal slot check because we should fix it without replacement native Promise core
      if(x instanceof $Promise && sameConstructor(x.constructor, this))return x;
      var capability = newPromiseCapability(this)
        , $$resolve  = capability.resolve;
      $$resolve(x);
      return capability.promise;
    }
  });
  $export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(92)(function(iter){
    $Promise.all(iter)['catch'](empty);
  })), PROMISE, {
    // 25.4.4.1 Promise.all(iterable)
    all: function all(iterable){
      var C          = this
        , capability = newPromiseCapability(C)
        , resolve    = capability.resolve
        , reject     = capability.reject;
      var abrupt = perform(function(){
        var values    = []
          , index     = 0
          , remaining = 1;
        forOf(iterable, false, function(promise){
          var $index        = index++
            , alreadyCalled = false;
          values.push(undefined);
          remaining++;
          C.resolve(promise).then(function(value){
            if(alreadyCalled)return;
            alreadyCalled  = true;
            values[$index] = value;
            --remaining || resolve(values);
          }, reject);
        });
        --remaining || resolve(values);
      });
      if(abrupt)reject(abrupt.error);
      return capability.promise;
    },
    // 25.4.4.4 Promise.race(iterable)
    race: function race(iterable){
      var C          = this
        , capability = newPromiseCapability(C)
        , reject     = capability.reject;
      var abrupt = perform(function(){
        forOf(iterable, false, function(promise){
          C.resolve(promise).then(capability.resolve, reject);
        });
      });
      if(abrupt)reject(abrupt.error);
      return capability.promise;
    }
  });
  
  /***/ }),
  /* 105 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  // ECMAScript 6 symbols shim
  var global         = __webpack_require__(1)
    , has            = __webpack_require__(12)
    , DESCRIPTORS    = __webpack_require__(3)
    , $export        = __webpack_require__(8)
    , redefine       = __webpack_require__(46)
    , META           = __webpack_require__(72).KEY
    , $fails         = __webpack_require__(11)
    , shared         = __webpack_require__(30)
    , setToStringTag = __webpack_require__(21)
    , uid            = __webpack_require__(23)
    , wks            = __webpack_require__(2)
    , wksExt         = __webpack_require__(49)
    , wksDefine      = __webpack_require__(48)
    , keyOf          = __webpack_require__(93)
    , enumKeys       = __webpack_require__(86)
    , isArray        = __webpack_require__(90)
    , anObject       = __webpack_require__(5)
    , toIObject      = __webpack_require__(13)
    , toPrimitive    = __webpack_require__(22)
    , createDesc     = __webpack_require__(16)
    , _create        = __webpack_require__(35)
    , gOPNExt        = __webpack_require__(95)
    , $GOPD          = __webpack_require__(57)
    , $DP            = __webpack_require__(4)
    , $keys          = __webpack_require__(17)
    , gOPD           = $GOPD.f
    , dP             = $DP.f
    , gOPN           = gOPNExt.f
    , $Symbol        = global.Symbol
    , $JSON          = global.JSON
    , _stringify     = $JSON && $JSON.stringify
    , PROTOTYPE      = 'prototype'
    , HIDDEN         = wks('_hidden')
    , TO_PRIMITIVE   = wks('toPrimitive')
    , isEnum         = {}.propertyIsEnumerable
    , SymbolRegistry = shared('symbol-registry')
    , AllSymbols     = shared('symbols')
    , OPSymbols      = shared('op-symbols')
    , ObjectProto    = Object[PROTOTYPE]
    , USE_NATIVE     = typeof $Symbol == 'function'
    , QObject        = global.QObject;
  // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
  var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;
  
  // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
  var setSymbolDesc = DESCRIPTORS && $fails(function(){
    return _create(dP({}, 'a', {
      get: function(){ return dP(this, 'a', {value: 7}).a; }
    })).a != 7;
  }) ? function(it, key, D){
    var protoDesc = gOPD(ObjectProto, key);
    if(protoDesc)delete ObjectProto[key];
    dP(it, key, D);
    if(protoDesc && it !== ObjectProto)dP(ObjectProto, key, protoDesc);
  } : dP;
  
  var wrap = function(tag){
    var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);
    sym._k = tag;
    return sym;
  };
  
  var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function(it){
    return typeof it == 'symbol';
  } : function(it){
    return it instanceof $Symbol;
  };
  
  var $defineProperty = function defineProperty(it, key, D){
    if(it === ObjectProto)$defineProperty(OPSymbols, key, D);
    anObject(it);
    key = toPrimitive(key, true);
    anObject(D);
    if(has(AllSymbols, key)){
      if(!D.enumerable){
        if(!has(it, HIDDEN))dP(it, HIDDEN, createDesc(1, {}));
        it[HIDDEN][key] = true;
      } else {
        if(has(it, HIDDEN) && it[HIDDEN][key])it[HIDDEN][key] = false;
        D = _create(D, {enumerable: createDesc(0, false)});
      } return setSymbolDesc(it, key, D);
    } return dP(it, key, D);
  };
  var $defineProperties = function defineProperties(it, P){
    anObject(it);
    var keys = enumKeys(P = toIObject(P))
      , i    = 0
      , l = keys.length
      , key;
    while(l > i)$defineProperty(it, key = keys[i++], P[key]);
    return it;
  };
  var $create = function create(it, P){
    return P === undefined ? _create(it) : $defineProperties(_create(it), P);
  };
  var $propertyIsEnumerable = function propertyIsEnumerable(key){
    var E = isEnum.call(this, key = toPrimitive(key, true));
    if(this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return false;
    return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
  };
  var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key){
    it  = toIObject(it);
    key = toPrimitive(key, true);
    if(it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return;
    var D = gOPD(it, key);
    if(D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key]))D.enumerable = true;
    return D;
  };
  var $getOwnPropertyNames = function getOwnPropertyNames(it){
    var names  = gOPN(toIObject(it))
      , result = []
      , i      = 0
      , key;
    while(names.length > i){
      if(!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META)result.push(key);
    } return result;
  };
  var $getOwnPropertySymbols = function getOwnPropertySymbols(it){
    var IS_OP  = it === ObjectProto
      , names  = gOPN(IS_OP ? OPSymbols : toIObject(it))
      , result = []
      , i      = 0
      , key;
    while(names.length > i){
      if(has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true))result.push(AllSymbols[key]);
    } return result;
  };
  
  // 19.4.1.1 Symbol([description])
  if(!USE_NATIVE){
    $Symbol = function Symbol(){
      if(this instanceof $Symbol)throw TypeError('Symbol is not a constructor!');
      var tag = uid(arguments.length > 0 ? arguments[0] : undefined);
      var $set = function(value){
        if(this === ObjectProto)$set.call(OPSymbols, value);
        if(has(this, HIDDEN) && has(this[HIDDEN], tag))this[HIDDEN][tag] = false;
        setSymbolDesc(this, tag, createDesc(1, value));
      };
      if(DESCRIPTORS && setter)setSymbolDesc(ObjectProto, tag, {configurable: true, set: $set});
      return wrap(tag);
    };
    redefine($Symbol[PROTOTYPE], 'toString', function toString(){
      return this._k;
    });
  
    $GOPD.f = $getOwnPropertyDescriptor;
    $DP.f   = $defineProperty;
    __webpack_require__(65).f = gOPNExt.f = $getOwnPropertyNames;
    __webpack_require__(41).f  = $propertyIsEnumerable;
    __webpack_require__(58).f = $getOwnPropertySymbols;
  
    if(DESCRIPTORS && !__webpack_require__(25)){
      redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
    }
  
    wksExt.f = function(name){
      return wrap(wks(name));
    }
  }
  
  $export($export.G + $export.W + $export.F * !USE_NATIVE, {Symbol: $Symbol});
  
  for(var symbols = (
    // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14
    'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'
  ).split(','), i = 0; symbols.length > i; )wks(symbols[i++]);
  
  for(var symbols = $keys(wks.store), i = 0; symbols.length > i; )wksDefine(symbols[i++]);
  
  $export($export.S + $export.F * !USE_NATIVE, 'Symbol', {
    // 19.4.2.1 Symbol.for(key)
    'for': function(key){
      return has(SymbolRegistry, key += '')
        ? SymbolRegistry[key]
        : SymbolRegistry[key] = $Symbol(key);
    },
    // 19.4.2.5 Symbol.keyFor(sym)
    keyFor: function keyFor(key){
      if(isSymbol(key))return keyOf(SymbolRegistry, key);
      throw TypeError(key + ' is not a symbol!');
    },
    useSetter: function(){ setter = true; },
    useSimple: function(){ setter = false; }
  });
  
  $export($export.S + $export.F * !USE_NATIVE, 'Object', {
    // 19.1.2.2 Object.create(O [, Properties])
    create: $create,
    // 19.1.2.4 Object.defineProperty(O, P, Attributes)
    defineProperty: $defineProperty,
    // 19.1.2.3 Object.defineProperties(O, Properties)
    defineProperties: $defineProperties,
    // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
    getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
    // 19.1.2.7 Object.getOwnPropertyNames(O)
    getOwnPropertyNames: $getOwnPropertyNames,
    // 19.1.2.8 Object.getOwnPropertySymbols(O)
    getOwnPropertySymbols: $getOwnPropertySymbols
  });
  
  // 24.3.2 JSON.stringify(value [, replacer [, space]])
  $JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function(){
    var S = $Symbol();
    // MS Edge converts symbol values to JSON as {}
    // WebKit converts symbol values to JSON as null
    // V8 throws on boxed symbols
    return _stringify([S]) != '[null]' || _stringify({a: S}) != '{}' || _stringify(Object(S)) != '{}';
  })), 'JSON', {
    stringify: function stringify(it){
      if(it === undefined || isSymbol(it))return; // IE8 returns string on undefined
      var args = [it]
        , i    = 1
        , replacer, $replacer;
      while(arguments.length > i)args.push(arguments[i++]);
      replacer = args[1];
      if(typeof replacer == 'function')$replacer = replacer;
      if($replacer || !isArray(replacer))replacer = function(key, value){
        if($replacer)value = $replacer.call(this, key, value);
        if(!isSymbol(value))return value;
      };
      args[1] = replacer;
      return _stringify.apply($JSON, args);
    }
  });
  
  // 19.4.3.4 Symbol.prototype[@@toPrimitive](hint)
  $Symbol[PROTOTYPE][TO_PRIMITIVE] || __webpack_require__(6)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);
  // 19.4.3.5 Symbol.prototype[@@toStringTag]
  setToStringTag($Symbol, 'Symbol');
  // 20.2.1.9 Math[@@toStringTag]
  setToStringTag(Math, 'Math', true);
  // 24.3.3 JSON[@@toStringTag]
  setToStringTag(global.JSON, 'JSON', true);
  
  /***/ }),
  /* 106 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(48)('asyncIterator');
  
  /***/ }),
  /* 107 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(48)('observable');
  
  /***/ }),
  /* 108 */,
  /* 109 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _stringify = __webpack_require__(40);
  
  var _stringify2 = _interopRequireDefault(_stringify);
  
  var _keys = __webpack_require__(70);
  
  var _keys2 = _interopRequireDefault(_keys);
  
  exports.divideURL = divideURL;
  exports.divideEmail = divideEmail;
  exports.emptyObject = emptyObject;
  exports.deepClone = deepClone;
  exports.getUserURLFromEmail = getUserURLFromEmail;
  exports.getUserEmailFromURL = getUserEmailFromURL;
  exports.convertToUserURL = convertToUserURL;
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
  * Copyright 2016 PT Inovação e Sistemas SA
  * Copyright 2016 INESC-ID
  * Copyright 2016 QUOBIS NETWORKS SL
  * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
  * Copyright 2016 ORANGE SA
  * Copyright 2016 Deutsche Telekom AG
  * Copyright 2016 Apizee
  * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  **/
  /**
   * Support module with some functions will be useful
   * @module utils
   */
  
  /**
   * @typedef divideURL
   * @type Object
   * @property {string} type The type of URL
   * @property {string} domain The domain of URL
   * @property {string} identity The identity of URL
   */
  
  /**
   * Divide an url in type, domain and identity
   * @param  {URL.URL} url - url address
   * @return {divideURL} the result of divideURL
   */
  function divideURL(url) {
  
    if (!url) throw Error('URL is needed to split');
  
    function recurse(value) {
      var regex = /([a-zA-Z-]*)(:\/\/(?:\.)?|:)([-a-zA-Z0-9@:%._\+~#=]{2,256})([-a-zA-Z0-9@:%._\+~#=\/]*)/gi;
      var subst = '$1,$3,$4';
      var parts = value.replace(regex, subst).split(',');
      return parts;
    }
  
    var parts = recurse(url);
  
    // If the url has no scheme
    if (parts[0] === url && !parts[0].includes('@')) {
  
      var _result = {
        type: "",
        domain: url,
        identity: ""
      };
  
      console.error('[DivideURL] DivideURL don\'t support url without scheme. Please review your url address', url);
  
      return _result;
    }
  
    // check if the url has the scheme and includes an @
    if (parts[0] === url && parts[0].includes('@')) {
      var scheme = parts[0] === url ? 'smtp' : parts[0];
      parts = recurse(scheme + '://' + parts[0]);
    }
  
    // if the domain includes an @, divide it to domain and identity respectively
    if (parts[1].includes('@')) {
      parts[2] = parts[0] + '://' + parts[1];
      parts[1] = parts[1].substr(parts[1].indexOf('@') + 1);
    } /*else if (parts[2].includes('/')) {
      parts[2] = parts[2].substr(parts[2].lastIndexOf('/')+1);
      }*/
  
    var result = {
      type: parts[0],
      domain: parts[1],
      identity: parts[2]
    };
  
    return result;
  }
  
  function divideEmail(email) {
    var indexOfAt = email.indexOf('@');
  
    var result = {
      username: email.substring(0, indexOfAt),
      domain: email.substring(indexOfAt + 1, email.length)
    };
  
    return result;
  }
  
  /**
   * Check if an Object is empty
   * @param  {Object} object Object to be checked
   * @return {Boolean}       status of Object, empty or not (true|false);
   */
  function emptyObject(object) {
    return (0, _keys2.default)(object).length > 0 ? false : true;
  }
  
  /**
   * Make a COPY of the original data
   * @param  {Object}  obj - object to be cloned
   * @return {Object}
   */
  function deepClone(obj) {
    //TODO: simple but inefficient JSON deep clone...
    if (obj) return JSON.parse((0, _stringify2.default)(obj));
  }
  
  /**
   * Obtains the user URL that corresponds to a given email
   * @param  {string} userEmail The user email
   * @return {URL.URL} userURL The user URL
   */
  function getUserURLFromEmail(userEmail) {
    var indexOfAt = userEmail.indexOf('@');
    return 'user://' + userEmail.substring(indexOfAt + 1, userEmail.length) + '/' + userEmail.substring(0, indexOfAt);
  }
  
  /**
   * Obtains the user email that corresponds to a given URL
   * @param  {URL.URL} userURL The user URL
   * @return {string} userEmail The user email
   */
  function getUserEmailFromURL(userURL) {
    var url = divideURL(userURL);
    return url.identity.replace('/', '') + '@' + url.domain; // identity field has '/exampleID' instead of 'exampleID'
  }
  
  /**
   * Check if the user identifier is already in the URL format, if not, convert to URL format
   * @param  {string}   identifier  user identifier
   * @return {string}   userURL    the user URL
   */
  function convertToUserURL(identifier) {
  
    // check if the identifier is already in the url format
    if (identifier.substring(0, 7) === 'user://') {
      var dividedURL = divideURL(identifier);
  
      //check if the url is well formated
      if (dividedURL.domain && dividedURL.identity) {
        return identifier;
      } else {
        throw 'userURL with wrong format';
      }
  
      //if not, convert the user email to URL format
    } else {
      return getUserURLFromEmail(identifier);
    }
  }
  
  /***/ }),
  /* 110 */,
  /* 111 */,
  /* 112 */,
  /* 113 */,
  /* 114 */,
  /* 115 */,
  /* 116 */,
  /* 117 */,
  /* 118 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _keys = __webpack_require__(70);
  
  var _keys2 = _interopRequireDefault(_keys);
  
  var _getPrototypeOf = __webpack_require__(31);
  
  var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
  
  var _classCallCheck2 = __webpack_require__(9);
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = __webpack_require__(10);
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  var _possibleConstructorReturn2 = __webpack_require__(34);
  
  var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
  
  var _get2 = __webpack_require__(123);
  
  var _get3 = _interopRequireDefault(_get2);
  
  var _inherits2 = __webpack_require__(33);
  
  var _inherits3 = _interopRequireDefault(_inherits2);
  
  var _DataObject2 = __webpack_require__(120);
  
  var _DataObject3 = _interopRequireDefault(_DataObject2);
  
  var _DataObjectChild = __webpack_require__(121);
  
  var _DataObjectChild2 = _interopRequireDefault(_DataObjectChild);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
  * Copyright 2016 PT Inovação e Sistemas SA
  * Copyright 2016 INESC-ID
  * Copyright 2016 QUOBIS NETWORKS SL
  * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
  * Copyright 2016 ORANGE SA
  * Copyright 2016 Deutsche Telekom AG
  * Copyright 2016 Apizee
  * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  **/
  
  var FilterType = { ANY: 'any', START: 'start', EXACT: 'exact' };
  
  /**
   * The class returned from the Syncher subscribe call.
   * To be used as an observation point from a DataObjectReporter change.
   */
  
  var DataObjectObserver = function (_DataObject) {
    (0, _inherits3.default)(DataObjectObserver, _DataObject);
  
    /* private
    _changeListener: MsgListener
     ----event handlers----
    _filters: {<filter>: {type: <start, exact>, callback: <function>} }
    */
  
    /**
     * @ignore
     * Should not be used directly by Hyperties. It's called by the Syncher.subscribe method
     */
  
    //TODO: For Further Study
    function DataObjectObserver(syncher, url, schema, initialStatus, initialData, childrens, initialVersion, mutual) {
      (0, _classCallCheck3.default)(this, DataObjectObserver);
  
      var _this2 = (0, _possibleConstructorReturn3.default)(this, (DataObjectObserver.__proto__ || (0, _getPrototypeOf2.default)(DataObjectObserver)).call(this, syncher, url, schema, initialStatus, initialData.data, childrens, mutual));
  
      var _this = _this2;
  
      _this._version = initialVersion;
      _this._filters = {};
  
      _this._syncObj.observe(function (event) {
        _this._onFilter(event);
      });
  
      //setup childrens data from subscription
      (0, _keys2.default)(initialData.childrens).forEach(function (childId) {
        var childData = initialData.childrens[childId];
        _this._childrenObjects[childId] = new _DataObjectChild2.default(_this, childId, childData);
      });
  
      _this._allocateListeners();
      return _this2;
    }
  
    (0, _createClass3.default)(DataObjectObserver, [{
      key: '_allocateListeners',
      value: function _allocateListeners() {
        (0, _get3.default)(DataObjectObserver.prototype.__proto__ || (0, _getPrototypeOf2.default)(DataObjectObserver.prototype), '_allocateListeners', this).call(this);
        var _this = this;
  
        _this._changeListener = _this._bus.addListener(_this._url + '/changes', function (msg) {
          if (msg.type === 'update') {
            console.log('DataObjectObserver-' + _this._url + '-RCV: ', msg);
            _this._changeObject(_this._syncObj, msg);
          }
        });
      }
    }, {
      key: '_releaseListeners',
      value: function _releaseListeners() {
        (0, _get3.default)(DataObjectObserver.prototype.__proto__ || (0, _getPrototypeOf2.default)(DataObjectObserver.prototype), '_releaseListeners', this).call(this);
        var _this = this;
  
        _this._changeListener.remove();
      }
  
      /**
       * Release and delete object data
       */
  
    }, {
      key: 'delete',
      value: function _delete() {
        var _this = this;
  
        _this._releaseListeners();
        delete _this._syncher._observers[_this._url];
      }
  
      /**
       * Release and delete object data
       */
  
    }, {
      key: 'unsubscribe',
      value: function unsubscribe() {
        var _this = this;
  
        //FLOW-OUT: this message will be sent to the runtime instance of SyncherManager -> _onLocalUnSubscribe
        var unSubscribeMsg = {
          type: 'unsubscribe', from: _this._owner, to: _this._syncher._subURL,
          body: { resource: _this._url }
        };
  
        _this._bus.postMessage(unSubscribeMsg, function (reply) {
          console.log('DataObjectObserver-UNSUBSCRIBE: ', reply);
          if (reply.body.code === 200) {
            _this._releaseListeners();
            delete _this._syncher._observers[_this._url];
          }
        });
      }
  
      /**
       * Register the change listeners sent by the reporter
       * @param {string} filter - Filter that identifies the field (separated dot path). Accepts * at the end for a more unrestricted filtering.
       * @param {function(event: MsgEvent)} callback
       */
  
    }, {
      key: 'onChange',
      value: function onChange(filter, callback) {
        var key = filter;
        var filterObj = {
          type: FilterType.EXACT,
          callback: callback
        };
  
        var idx = filter.indexOf('*');
        if (idx === filter.length - 1) {
          if (idx === 0) {
            filterObj.type = FilterType.ANY;
          } else {
            filterObj.type = FilterType.START;
            key = filter.substr(0, filter.length - 1);
          }
        }
  
        this._filters[key] = filterObj;
      }
    }, {
      key: '_onFilter',
      value: function _onFilter(event) {
        var _this = this;
  
        (0, _keys2.default)(_this._filters).forEach(function (key) {
          var filter = _this._filters[key];
          if (filter.type === FilterType.ANY) {
            //match anything
            filter.callback(event);
          } else if (filter.type === FilterType.START) {
            //if starts with filter...
            if (event.field.indexOf(key) === 0) {
              filter.callback(event);
            }
          } else if (filter.type === FilterType.EXACT) {
            //exact match
            if (event.field === key) {
              filter.callback(event);
            }
          }
        });
      }
    }]);
    return DataObjectObserver;
  }(_DataObject3.default /* implements SyncStatus */);
  
  exports.default = DataObjectObserver;
  module.exports = exports['default'];
  
  /***/ }),
  /* 119 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _keys = __webpack_require__(70);
  
  var _keys2 = _interopRequireDefault(_keys);
  
  var _getPrototypeOf = __webpack_require__(31);
  
  var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
  
  var _classCallCheck2 = __webpack_require__(9);
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = __webpack_require__(10);
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  var _possibleConstructorReturn2 = __webpack_require__(34);
  
  var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
  
  var _get2 = __webpack_require__(123);
  
  var _get3 = _interopRequireDefault(_get2);
  
  var _inherits2 = __webpack_require__(33);
  
  var _inherits3 = _interopRequireDefault(_inherits2);
  
  var _DataObject2 = __webpack_require__(120);
  
  var _DataObject3 = _interopRequireDefault(_DataObject2);
  
  var _utils = __webpack_require__(109);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * The class returned from the Syncher create call.
   * To be used as a reporter point, changes will be submited to DataObjectObserver instances.
   */
  /**
  * Copyright 2016 PT Inovação e Sistemas SA
  * Copyright 2016 INESC-ID
  * Copyright 2016 QUOBIS NETWORKS SL
  * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
  * Copyright 2016 ORANGE SA
  * Copyright 2016 Deutsche Telekom AG
  * Copyright 2016 Apizee
  * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  **/
  
  var DataObjectReporter = function (_DataObject) {
    (0, _inherits3.default)(DataObjectReporter, _DataObject);
  
    /* private
    _subscriptions: <hypertyUrl: { status: string } }>
     ----event handlers----
    _onSubscriptionHandler: (event) => void
    _onResponseHandler: (event) => void
    _onReadHandler: (event) => void
    */
  
    /**
     * @ignore
     * Should not be used directly by Hyperties. It's called by the Syncher.create method
     */
    function DataObjectReporter(syncher, url, schema, initialStatus, initialData, childrens) {
      (0, _classCallCheck3.default)(this, DataObjectReporter);
  
      var _this2 = (0, _possibleConstructorReturn3.default)(this, (DataObjectReporter.__proto__ || (0, _getPrototypeOf2.default)(DataObjectReporter)).call(this, syncher, url, schema, initialStatus, initialData, childrens));
  
      var _this = _this2;
  
      _this._subscriptions = {};
  
      _this._syncObj.observe(function (event) {
        console.log('DataObjectReporter-' + url + '-SEND: ', event);
        _this._onChange(event);
      });
  
      _this._allocateListeners();
      return _this2;
    }
  
    (0, _createClass3.default)(DataObjectReporter, [{
      key: '_allocateListeners',
      value: function _allocateListeners() {
        (0, _get3.default)(DataObjectReporter.prototype.__proto__ || (0, _getPrototypeOf2.default)(DataObjectReporter.prototype), '_allocateListeners', this).call(this);
        var _this = this;
  
        _this._objectListener = _this._bus.addListener(_this._url, function (msg) {
          console.log('DataObject-' + _this._url + '-RCV: ', msg);
          switch (msg.type) {
            case 'response':
              _this._onResponse(msg);break;
            case 'read':
              _this._onRead(msg);break;
          }
        });
      }
    }, {
      key: '_releaseListeners',
      value: function _releaseListeners() {
        (0, _get3.default)(DataObjectReporter.prototype.__proto__ || (0, _getPrototypeOf2.default)(DataObjectReporter.prototype), '_releaseListeners', this).call(this);
        var _this = this;
  
        _this._objectListener.remove();
      }
  
      /**
       * Send invitations (create messages) to hyperties, observers list.
       * @param  {HypertyURL[]} observers List of Hyperty URL's
       */
  
    }, {
      key: 'inviteObservers',
      value: function inviteObservers(observers) {
        var _this = this;
  
        //FLOW-OUT: this message will be sent to the runtime instance of SyncherManager -> _onCreate
        var inviteMsg = {
          type: 'create', from: _this._syncher._owner, to: _this._syncher._subURL,
          body: { resume: false, resource: _this._url, schema: _this._schema, value: _this._syncObj.data, authorise: observers }
        };
  
        _this._bus.postMessage(inviteMsg);
      }
  
      /**
       * Release and delete object data
       */
  
    }, {
      key: 'delete',
      value: function _delete() {
        var _this = this;
  
        //FLOW-OUT: this message will be sent to the runtime instance of SyncherManager -> _onDelete
        var deleteMsg = {
          type: 'delete', from: _this._owner, to: _this._syncher._subURL,
          body: { resource: _this._url }
        };
  
        _this._bus.postMessage(deleteMsg, function (reply) {
          console.log('DataObjectReporter-DELETE: ', reply);
          if (reply.body.code === 200) {
            _this._releaseListeners();
            delete _this._syncher._reporters[_this._url];
          }
        });
      }
  
      /**
       * Subscriptions requested and accepted to this reporter
       * @type {Object<HypertyURL, SyncSubscription>}
       */
  
    }, {
      key: 'onSubscription',
  
  
      /**
       * Setup the callback to process subscribe and unsubscribe notifications
       * @param {function(event: MsgEvent)} callback function to receive events
       */
      value: function onSubscription(callback) {
        this._onSubscriptionHandler = callback;
      }
  
      /**
       * Setup the callback to process response notifications of the create's
       * @param {function(event: MsgEvent)} callback function to receive events
       */
  
    }, {
      key: 'onResponse',
      value: function onResponse(callback) {
        this._onResponseHandler = callback;
      }
  
      /**
       * Setup the callback to process read notifications
       * @param {function(event: MsgEvent)} callback
       */
  
    }, {
      key: 'onRead',
      value: function onRead(callback) {
        this._onReadHandler = callback;
      }
  
      //FLOW-IN: message received from parent Syncher -> _onForward
  
    }, {
      key: '_onForward',
      value: function _onForward(msg) {
        var _this = this;
  
        console.log('DataObjectReporter-RCV: ', msg);
        switch (msg.body.type) {
          case 'subscribe':
            _this._onSubscribe(msg);break;
          case 'unsubscribe':
            _this._onUnSubscribe(msg);break;
        }
      }
  
      //FLOW-IN: message received from this -> _onForward: emitted by a remote Syncher -> subscribe
  
    }, {
      key: '_onSubscribe',
      value: function _onSubscribe(msg) {
        var _this3 = this;
  
        var _this = this;
        var hypertyUrl = msg.body.from;
        console.log('[DataObjectReporter._onSubscribe]', msg);
  
        var event = {
          type: msg.body.type,
          url: hypertyUrl,
  
          identity: msg.body.identity,
  
          accept: function accept() {
            //create new subscription
            var sub = { url: hypertyUrl, status: 'on' };
            _this._subscriptions[hypertyUrl] = sub;
  
            //process and send childrens data
            var childrenValues = {};
            (0, _keys2.default)(_this._childrenObjects).forEach(function (childId) {
              var childData = _this._childrenObjects[childId].data;
              childrenValues[childId] = (0, _utils.deepClone)(childData);
            });
  
            var sendMsg = {
              id: msg.id, type: 'response', from: msg.to, to: msg.from,
              body: { code: 200, schema: _this._schema, version: _this._version, value: { data: (0, _utils.deepClone)(_this.data), childrens: childrenValues } }
            };
  
            //TODO: For Further Study
            if (msg.body.hasOwnProperty('mutualAuthentication') && !msg.body.mutualAuthentication) {
              sendMsg.body.mutualAuthentication = _this3._mutualAuthentication;
              _this3._mutualAuthentication = msg.body.mutualAuthentication;
            }
  
            //send ok response message
            _this._bus.postMessage(sendMsg);
  
            return sub;
          },
  
          reject: function reject(reason) {
            //send reject response message
            _this._bus.postMessage({
              id: msg.id, type: 'response', from: msg.to, to: msg.from,
              body: { code: 403, desc: reason }
            });
          }
        };
  
        if (_this._onSubscriptionHandler) {
          console.log('SUBSCRIPTION-EVENT: ', event);
          _this._onSubscriptionHandler(event);
        }
      }
  
      //FLOW-IN: message received from this -> _onForward: emitted by a remote DataObjectObserver -> unsubscribe
  
    }, {
      key: '_onUnSubscribe',
      value: function _onUnSubscribe(msg) {
        var _this = this;
        var hypertyUrl = msg.body.from;
  
        var sub = _this._subscriptions[hypertyUrl];
        delete _this._subscriptions[hypertyUrl];
  
        var event = {
          type: msg.body.type,
          url: hypertyUrl,
          object: sub
        };
  
        if (_this._onSubscriptionHandler) {
          console.log('UN-SUBSCRIPTION-EVENT: ', event);
          _this._onSubscriptionHandler(event);
        }
      }
  
      //FLOW-IN: message received from ReporterURL address: emited by a remote Syncher -> _onRemoteCreate -> event.ack
  
    }, {
      key: '_onResponse',
      value: function _onResponse(msg) {
        var _this = this;
  
        var event = {
          type: msg.type,
          url: msg.from,
          code: msg.body.code
        };
  
        if (_this._onResponseHandler) {
          console.log('RESPONSE-EVENT: ', event);
          _this._onResponseHandler(event);
        }
      }
  
      //FLOW-IN: message received from ReporterURL address: emited by a remote Syncher -> read
  
    }, {
      key: '_onRead',
      value: function _onRead(msg) {
        var _this = this;
  
        var event = {
          type: msg.type,
          url: msg.from,
  
          accept: function accept() {
            _this._bus.postMessage({
              id: msg.id, type: 'response', from: msg.to, to: msg.from,
              body: { code: 200, value: (0, _utils.deepClone)(_this.data) }
            });
          },
  
          reject: function reject(reason) {
            _this._bus.postMessage({
              id: msg.id, type: 'response', from: msg.to, to: msg.from,
              body: { code: 401, desc: reason }
            });
          }
        };
  
        if (_this._onReadHandler) {
          console.log('READ-EVENT: ', event);
          _this._onReadHandler(event);
        }
      }
    }, {
      key: 'subscriptions',
      get: function get() {
        return this._subscriptions;
      }
    }]);
    return DataObjectReporter;
  }(_DataObject3.default /* implements SyncStatus */);
  
  exports.default = DataObjectReporter;
  module.exports = exports['default'];
  
  /***/ }),
  /* 120 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _promise = __webpack_require__(71);
  
  var _promise2 = _interopRequireDefault(_promise);
  
  var _keys = __webpack_require__(70);
  
  var _keys2 = _interopRequireDefault(_keys);
  
  var _classCallCheck2 = __webpack_require__(9);
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = __webpack_require__(10);
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  var _ProxyObject = __webpack_require__(122);
  
  var _ProxyObject2 = _interopRequireDefault(_ProxyObject);
  
  var _DataObjectChild = __webpack_require__(121);
  
  var _DataObjectChild2 = _interopRequireDefault(_DataObjectChild);
  
  var _utils = __webpack_require__(109);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * Main extension class for observers and reporters, with common properties and methods.
   * Children management is common for observers and reporters.
   */
  var DataObject = function () {
    /* private
    _version: number
     _owner: HypertyURL
    _url: ObjectURL
    _schema: Schema
    _bus: MiniBus
    _status: on | paused
    _syncObj: SyncData
     _children: { id: DataObjectChild }
    _childrenListeners: [MsgListener]
     ----event handlers----
    _onAddChildHandler: (event) => void
    */
  
    /**
     * @ignore
     * Should not be used directly by Hyperties. It's called by the Syncher create or subscribe method's
     */
    function DataObject(syncher, url, schema, initialStatus, initialData, childrens) {
      var mutual = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : true;
      (0, _classCallCheck3.default)(this, DataObject);
  
      var _this = this;
  
      _this._syncher = syncher;
      _this._url = url;
      _this._schema = schema;
      _this._status = initialStatus;
      _this._syncObj = new _ProxyObject2.default(initialData);
      _this._childrens = childrens;
  
      //TODO: For Further Study
      _this._mutualAuthentication = mutual;
  
      _this._version = 0;
      _this._childId = 0;
      _this._childrenObjects = {};
      _this._childrenListeners = [];
  
      _this._owner = syncher._owner;
      _this._bus = syncher._bus;
    }
  
    (0, _createClass3.default)(DataObject, [{
      key: '_allocateListeners',
      value: function _allocateListeners() {
        var _this2 = this;
  
        var _this = this;
  
        var childBaseURL = _this._url + '/children/';
        console.log('[Data Object - AllocateListeners] - ', _this._childrens);
        if (_this._childrens) {
          _this._childrens.forEach(function (child) {
            var childURL = childBaseURL + child;
            var listener = _this._bus.addListener(childURL, function (msg) {
              //ignore msg sent by himself
              if (msg.from !== _this2._owner) {
                console.log('DataObject-Children-RCV: ', msg);
                switch (msg.type) {
                  case 'create':
                    _this._onChildCreate(msg);break;
                  case 'delete':
                    console.log(msg);break;
                  default:
                    _this._changeChildren(msg);break;
                }
              }
            });
  
            _this._childrenListeners.push(listener);
          });
        }
      }
    }, {
      key: '_releaseListeners',
      value: function _releaseListeners() {
        var _this = this;
  
        _this._childrenListeners.forEach(function (listener) {
          listener.remove();
        });
  
        (0, _keys2.default)(_this._childrenObjects).forEach(function (key) {
          _this._childrenObjects[key]._releaseListeners();
        });
      }
  
      /**
       * Object URL of reporter or observer
       * @type {ObjectURL}
       */
  
    }, {
      key: 'pause',
  
  
      /**
       * @ignore
       */
      value: function pause() {
        //TODO: this feature needs more analise
        throw 'Not implemented';
      }
  
      /**
       * @ignore
       */
  
    }, {
      key: 'resume',
      value: function resume() {
        //TODO: this feature needs more analise
        throw 'Not implemented';
      }
  
      /**
       * @ignore
       */
  
    }, {
      key: 'stop',
      value: function stop() {
        //TODO: should remove the subscription and send message unsubscribe?
        throw 'Not implemented';
      }
  
      /**
       * Create and add a DataObjectChild to a children collection.
       * @param {String} children - Children name where the child is added.
       * @param {JSON} initialData - Initial data of the child
       * @return {Promise<DataObjectChild>} - Return Promise to a new DataObjectChild.
       */
  
    }, {
      key: 'addChild',
      value: function addChild(children, initialData) {
        var _this = this;
  
        //create new child unique ID, based on hypertyURL
        _this._childId++;
        var msgChildId = _this._owner + '#' + _this._childId;
        var msgChildPath = _this._url + '/children/' + children;
  
        //FLOW-OUT: this message will be sent directly to a resource child address: MessageBus
        var requestMsg = {
          type: 'create', from: _this._owner, to: msgChildPath,
          body: { resource: msgChildId, value: initialData }
        };
  
        //TODO: For Further Study
        if (!_this._mutualAuthentication) requestMsg.body.mutualAuthentication = _this._mutualAuthentication;
  
        //returns promise, in the future, the API may change to asynchronous call
        return new _promise2.default(function (resolve) {
          var msgId = _this._bus.postMessage(requestMsg);
  
          console.log('create-reporter-child( ' + _this._owner + ' ): ', requestMsg);
          var newChild = new _DataObjectChild2.default(_this, msgChildId, initialData, _this._owner, msgId);
          newChild.onChange(function (event) {
            _this._onChange(event, { path: msgChildPath, childId: msgChildId });
          });
  
          _this._childrenObjects[msgChildId] = newChild;
  
          resolve(newChild);
        });
      }
  
      /**
       * Setup the callback to process create and delete of childrens.
       * @param {function(event: MsgEvent)} callback
       */
  
    }, {
      key: 'onAddChild',
      value: function onAddChild(callback) {
        this._onAddChildrenHandler = callback;
      }
  
      //FLOW-IN: message received from a remote DataObject -> addChild
  
    }, {
      key: '_onChildCreate',
      value: function _onChildCreate(msg) {
        var _this = this;
        var msgChildId = msg.body.resource;
  
        console.log('create-observer-child( ' + _this._owner + ' ): ', msg);
        var newChild = new _DataObjectChild2.default(_this, msgChildId, msg.body.value);
        _this._childrenObjects[msgChildId] = newChild;
  
        setTimeout(function () {
          //FLOW-OUT: will flow to DataObjectChild -> _onResponse
          _this._bus.postMessage({
            id: msg.id, type: 'response', from: msg.to, to: msg.from,
            body: { code: 200, source: _this._owner }
          });
        });
  
        var event = {
          type: msg.type,
          from: msg.from,
          url: msg.to,
          value: msg.body.value,
          childId: msgChildId,
          identity: msg.body.identity
        };
  
        if (_this._onAddChildrenHandler) {
          console.log('ADD-CHILDREN-EVENT: ', event);
          _this._onAddChildrenHandler(event);
        }
      }
  
      //send delta messages to subscriptions
  
    }, {
      key: '_onChange',
      value: function _onChange(event, childInfo) {
        var _this = this;
  
        _this._version++;
  
        if (_this._status === 'on') {
          //FLOW-OUT: this message will be sent directly to a resource changes address: MessageBus
          var changeMsg = {
            type: 'update', from: _this._url, to: _this._url + '/changes',
            body: { version: _this._version, source: _this._owner, attribute: event.field }
          };
  
          console.log('[DataObject - _onChange] - ', event, childInfo, changeMsg);
  
          if (event.oType === _ProxyObject.ObjectType.OBJECT) {
            if (event.cType !== _ProxyObject.ChangeType.REMOVE) {
              changeMsg.body.value = event.data;
            }
          } else {
            changeMsg.body.attributeType = event.oType;
            changeMsg.body.value = event.data;
            if (event.cType !== _ProxyObject.ChangeType.UPDATE) {
              changeMsg.body.operation = event.cType;
            }
          }
  
          //childInfo must have (path, childId)
          if (childInfo) {
            changeMsg.to = childInfo.path;
            changeMsg.body.resource = childInfo.childId;
          }
  
          //TODO: For Further Study
          if (!_this._mutualAuthentication) changeMsg.body.mutualAuthentication = _this._mutualAuthentication;
  
          _this._bus.postMessage(changeMsg);
        }
      }
  
      //FLOW-IN: delta message received from a remote DataObjectReporter or DataObjectChild when changing data
  
    }, {
      key: '_changeObject',
      value: function _changeObject(syncObj, msg) {
        var _this = this;
  
        //TODO: update version ?
        //how to handle an incorrect version ? Example: receive a version 3 when the observer is in version 1, where is the version 2 ?
        //will we need to confirm the reception ?
        if (_this._version + 1 === msg.body.version) {
          _this._version++;
          var path = msg.body.attribute;
          var value = (0, _utils.deepClone)(msg.body.value);
          var findResult = syncObj.findBefore(path);
  
          if (msg.body.attributeType === _ProxyObject.ObjectType.ARRAY) {
            if (msg.body.operation === _ProxyObject.ChangeType.ADD) {
              var arr = findResult.obj;
              var index = findResult.last;
              Array.prototype.splice.apply(arr, [index, 0].concat(value));
            } else if (msg.body.operation === _ProxyObject.ChangeType.REMOVE) {
              var _arr = findResult.obj;
              var _index = findResult.last;
              _arr.splice(_index, value);
            } else {
              findResult.obj[findResult.last] = value; // UPDATE
            }
          } else {
            if (msg.body.value) {
              findResult.obj[findResult.last] = value; // UPDATE or ADD
            } else {
              delete findResult.obj[findResult.last]; // REMOVE
            }
          }
        } else {
          //TODO: how to handle unsynchronized versions?
          console.log('UNSYNCHRONIZED VERSION: (data => ' + _this._version + ', msg => ' + msg.body.version + ')');
        }
      }
  
      //FLOW-IN: message received from a remote DataObjectChild when changing data
  
    }, {
      key: '_changeChildren',
      value: function _changeChildren(msg) {
        var _this = this;
        console.log('Change children: ', _this._owner, msg);
  
        var childId = msg.body.resource;
        var children = _this._childrenObjects[childId];
  
        if (children) {
          _this._changeObject(children._syncObj, msg);
        } else {
          console.log('No children found for: ', childId);
        }
      }
    }, {
      key: 'url',
      get: function get() {
        return this._url;
      }
  
      /**
       * Object schema URL (this field is not yet stable, and is subsject to change)
       * @type {SchemaURL}
       */
  
    }, {
      key: 'schema',
      get: function get() {
        return this._schema;
      }
  
      /**
       * Status of the reporter or observer connection (this field is not yet stable, and is subsject to change)
       * @type {Status} - Enum of: on | paused
       */
  
    }, {
      key: 'status',
      get: function get() {
        return this._status;
      }
  
      /**
       * Data structure to be synchronized.
       * @type {JSON} - JSON structure that should follow the defined schema, if any.
       */
  
    }, {
      key: 'data',
      get: function get() {
        return this._syncObj.data;
      }
  
      /**
       * All created children's since the subscription, doesn't contain all children's since reporter creation.
       * @type {Object<ChildId, DataObjectChild>}
       */
  
    }, {
      key: 'childrens',
      get: function get() {
        return this._childrenObjects;
      }
    }]);
    return DataObject;
  }(); /**
       * Copyright 2016 PT Inovação e Sistemas SA
       * Copyright 2016 INESC-ID
       * Copyright 2016 QUOBIS NETWORKS SL
       * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
       * Copyright 2016 ORANGE SA
       * Copyright 2016 Deutsche Telekom AG
       * Copyright 2016 Apizee
       * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
       *
       * Licensed under the Apache License, Version 2.0 (the "License");
       * you may not use this file except in compliance with the License.
       * You may obtain a copy of the License at
       *
       *   http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       **/
  
  exports.default = DataObject;
  module.exports = exports['default'];
  
  /***/ }),
  /* 121 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _classCallCheck2 = __webpack_require__(9);
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = __webpack_require__(10);
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  var _ProxyObject = __webpack_require__(122);
  
  var _ProxyObject2 = _interopRequireDefault(_ProxyObject);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * The class returned from the DataObject addChildren call or from onAddChildren if remotely created.
   * Children object synchronization is a a fast forward mechanism, no need for direct subscriptions, it uses the already authorized subscription from the parent DataObject.
   */
  var DataObjectChild /* implements SyncStatus */ = function () {
    /* private
     ----event handlers----
    _onResponseHandler: (event) => void
    */
  
    /**
     * @ignore
     * Should not be used directly by Hyperties. It's called by the DataObject.addChildren
     */
    function DataObjectChild(parent, childId, initialData, owner, msgId) {
      (0, _classCallCheck3.default)(this, DataObjectChild);
  
      var _this = this;
  
      _this._parent = parent;
      _this._childId = childId;
      _this._owner = owner;
      _this._msgId = msgId;
  
      _this._syncObj = new _ProxyObject2.default(initialData);
  
      _this._bus = parent._bus;
      _this._allocateListeners();
    }
  
    (0, _createClass3.default)(DataObjectChild, [{
      key: '_allocateListeners',
      value: function _allocateListeners() {
        var _this = this;
  
        //this is only needed for children reporters
        if (_this._owner) {
          _this._listener = _this._bus.addListener(_this._owner, function (msg) {
            if (msg.type === 'response' && msg.id === _this._msgId) {
              console.log('DataObjectChild.onResponse:', msg);
              _this._onResponse(msg);
            }
          });
        }
      }
    }, {
      key: '_releaseListeners',
      value: function _releaseListeners() {
        var _this = this;
  
        if (_this._listener) {
          _this._listener.remove();
        }
      }
  
      /**
       * Release and delete object data
       */
  
    }, {
      key: 'delete',
      value: function _delete() {
        var _this = this;
  
        delete _this._parent._children[_this._childId];
  
        _this._releaseListeners();
  
        //TODO: send delete message ?
      }
  
      /**
       * Children ID generated on addChildren. Unique identifier
       * @type {URL} - URL of the format <HypertyURL>#<numeric-sequence>
       */
  
    }, {
      key: 'onChange',
  
  
      /**
       * Register the change listeners sent by the reporter child
       * @param {function(event: MsgEvent)} callback
       */
      value: function onChange(callback) {
        this._syncObj.observe(function (event) {
          callback(event);
        });
      }
  
      /**
       * Setup the callback to process response notifications of the creates
       * @param {function(event: MsgEvent)} callback
       */
  
    }, {
      key: 'onResponse',
      value: function onResponse(callback) {
        this._onResponseHandler = callback;
      }
  
      //FLOW-IN: message received from a remote DataObject -> _onChildCreate
  
    }, {
      key: '_onResponse',
      value: function _onResponse(msg) {
        var _this = this;
  
        var event = {
          type: msg.type,
          url: msg.body.source,
          code: msg.body.code
        };
  
        if (_this._onResponseHandler) {
          _this._onResponseHandler(event);
        }
      }
    }, {
      key: 'childId',
      get: function get() {
        return this._childId;
      }
  
      /**
       * Data Structure to be synchronized.
       * @type {JSON} - JSON structure that should follow the defined schema, if any.
       */
  
    }, {
      key: 'data',
      get: function get() {
        return this._syncObj.data;
      }
    }]);
    return DataObjectChild;
  }(); /**
       * Copyright 2016 PT Inovação e Sistemas SA
       * Copyright 2016 INESC-ID
       * Copyright 2016 QUOBIS NETWORKS SL
       * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
       * Copyright 2016 ORANGE SA
       * Copyright 2016 Deutsche Telekom AG
       * Copyright 2016 Apizee
       * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
       *
       * Licensed under the Apache License, Version 2.0 (the "License");
       * you may not use this file except in compliance with the License.
       * You may obtain a copy of the License at
       *
       *   http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       **/
  
  exports.default = DataObjectChild;
  module.exports = exports['default'];
  
  /***/ }),
  /* 122 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.ObjectType = exports.ChangeType = undefined;
  
  var _stringify = __webpack_require__(40);
  
  var _stringify2 = _interopRequireDefault(_stringify);
  
  var _classCallCheck2 = __webpack_require__(9);
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = __webpack_require__(10);
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  __webpack_require__(153);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var objectType = { ARRAY: '[object Array]', OBJECT: '[object Object]' };
  
  /**
   * @access private
   * Main class that maintains a JSON object, and observes changes in this object, recursively.
   * Internal objects and arrays are also observed.
   */
  
  var SyncObject = function () {
    function SyncObject(initialData) {
      (0, _classCallCheck3.default)(this, SyncObject);
  
      var _this = this;
  
      _this._observers = [];
      _this._filters = {};
  
      this._data = initialData || {};
  
      this._internalObserve(this._data);
    }
  
    (0, _createClass3.default)(SyncObject, [{
      key: 'observe',
      value: function observe(callback) {
        this._observers.push(callback);
      }
    }, {
      key: 'find',
      value: function find(path) {
        var list = path.split('.');
  
        return this._findWithSplit(list);
      }
    }, {
      key: 'findBefore',
      value: function findBefore(path) {
        var result = {};
        var list = path.split('.');
        result.last = list.pop();
        result.obj = this._findWithSplit(list);
  
        return result;
      }
    }, {
      key: '_findWithSplit',
      value: function _findWithSplit(list) {
        var obj = this._data;
        list.forEach(function (value) {
          obj = obj[value];
        });
  
        return obj;
      }
    }, {
      key: '_isObservable',
      value: function _isObservable(obj) {
        if (obj.constructor === Object || obj.constructor === Array) {
          return true;
        }
  
        return false;
      }
    }, {
      key: '_internalObserve',
      value: function _internalObserve(object) {
        var _this2 = this;
  
        var handler = function handler(changeset) {
  
          changeset.every(function (change) {
            _this2._onChanges(change);
          });
        };
  
        this._data = Object.deepObserve(object, handler);
      }
    }, {
      key: '_fireEvent',
      value: function _fireEvent(event) {
        this._observers.forEach(function (callback) {
          callback(event);
        });
      }
    }, {
      key: '_onChanges',
      value: function _onChanges(change) {
  
        var obj = change.object;
        var objType = void 0;
  
        if (obj.constructor === Object) {
          objType = ObjectType.OBJECT;
        }
  
        if (obj.constructor === Array) {
          objType = ObjectType.ARRAY;
        }
  
        var fieldString = change.keypath;
  
        // console.log('Field:', fieldString);
        // console.log('type:', change.type);
  
        //let oldValue = change.oldValue;
        var newValue = obj[change.name];
  
        console.info(change.type + ' | Field: ' + fieldString + ' | New Value:', (0, _stringify2.default)(newValue));
  
        if (change.type === 'update') {
          this._fireEvent({
            cType: ChangeType.UPDATE,
            oType: objType,
            field: fieldString,
            data: newValue
          });
        }
  
        if (change.type === 'add') {
          this._fireEvent({
            cType: ChangeType.ADD,
            oType: objType,
            field: fieldString,
            data: newValue
          });
        }
  
        if (change.type === 'delete') {
          this._fireEvent({
            cType: ChangeType.REMOVE,
            oType: objType,
            field: fieldString
          });
        }
      }
    }, {
      key: 'data',
      get: function get() {
        return this._data;
      }
    }]);
    return SyncObject;
  }();
  
  var ChangeType = exports.ChangeType = { UPDATE: 'update', ADD: 'add', REMOVE: 'remove' };
  var ObjectType = exports.ObjectType = { OBJECT: 'object', ARRAY: 'array' };
  exports.default = SyncObject;
  
  /***/ }),
  /* 123 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.__esModule = true;
  
  var _getPrototypeOf = __webpack_require__(31);
  
  var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
  
  var _getOwnPropertyDescriptor = __webpack_require__(138);
  
  var _getOwnPropertyDescriptor2 = _interopRequireDefault(_getOwnPropertyDescriptor);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  exports.default = function get(object, property, receiver) {
    if (object === null) object = Function.prototype;
    var desc = (0, _getOwnPropertyDescriptor2.default)(object, property);
  
    if (desc === undefined) {
      var parent = (0, _getPrototypeOf2.default)(object);
  
      if (parent === null) {
        return undefined;
      } else {
        return get(parent, property, receiver);
      }
    } else if ("value" in desc) {
      return desc.value;
    } else {
      var getter = desc.get;
  
      if (getter === undefined) {
        return undefined;
      }
  
      return getter.call(receiver);
    }
  };
  
  /***/ }),
  /* 124 */,
  /* 125 */,
  /* 126 */,
  /* 127 */,
  /* 128 */,
  /* 129 */,
  /* 130 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _promise = __webpack_require__(71);
  
  var _promise2 = _interopRequireDefault(_promise);
  
  var _assign = __webpack_require__(136);
  
  var _assign2 = _interopRequireDefault(_assign);
  
  var _classCallCheck2 = __webpack_require__(9);
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = __webpack_require__(10);
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  var _DataObjectReporter = __webpack_require__(119);
  
  var _DataObjectReporter2 = _interopRequireDefault(_DataObjectReporter);
  
  var _DataObjectObserver = __webpack_require__(118);
  
  var _DataObjectObserver2 = _interopRequireDefault(_DataObjectObserver);
  
  var _DataProvisional = __webpack_require__(133);
  
  var _DataProvisional2 = _interopRequireDefault(_DataProvisional);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
  * The main class for the syncher package.
  * The Syncher is a singleton class per Hyperty/URL and it is the owner of all created Data Sync Objects according to the Reporter - Observer pattern.
  * Main functionality is to create reporters and to subscribe to existing ones.
  */
  var Syncher = function () {
    /* private
    _owner: URL
    _bus: MiniBus
     _subURL: URL
     _reporters: <url: DataObjectReporter>
    _observers: <url: DataObjectObserver>
    _provisionals: <url: DataProvisional>
     ----event handlers----
    _onNotificationHandler: (event) => void
    _onResume: (event) => void
    */
  
    /**
    * Constructor that should be used by the Hyperty owner
    * @param {HypertyURL} owner - Hyperty URL owner. An URL allocated by the runtime that uniquely identifies the Hyperty.
    * @param {MiniBus} bus - An instance of the MiniBus provided in the sandbox. When an object (Reporter or Observed) is created, the SyncherManager will add a listener in the MiniBus to receive/send Messages of that object.
    * @param {JSON} config - Configuration data. The only required field for now is the runtimeURL.
    */
    function Syncher(owner, bus, config) {
      (0, _classCallCheck3.default)(this, Syncher);
  
      var _this = this;
  
      _this._owner = owner;
      _this._bus = bus;
  
      _this._subURL = config.runtimeURL + '/sm';
  
      _this._reporters = {};
      _this._observers = {};
      _this._provisionals = {};
  
      bus.addListener(owner, function (msg) {
        //ignore msg sent by himself
        if (msg.from !== owner) {
          console.info('[Syncher] Syncher-RCV: ', msg);
          switch (msg.type) {
            case 'forward':
              _this._onForward(msg);break;
            case 'create':
              _this._onRemoteCreate(msg);break;
            case 'delete':
              _this._onRemoteDelete(msg);break;
          }
        }
      });
    }
  
    /**
    * The owner of the Syncher and all created reporters.
    * @type {HypertyURL}
    */
  
  
    (0, _createClass3.default)(Syncher, [{
      key: 'create',
  
  
      /**
      * Request a DataObjectReporter creation. The URL will be be requested by the allocation mechanism.
      * @param  {SchemaURL} schema - Hyperty Catalogue URL address that can be used to retrieve the JSON-Schema describing the Data Object schema
      * @param  {HypertyURL[]} observers - List of hyperties that are pre-authorized for subscription
      * @param  {JSON} initialData - Initial data of the reporter
      * @param  {string} objectURL - reusable dataObject URL
      * @return {Promise<DataObjectReporter>} Return Promise to a new Reporter. The reporter can be accepted or rejected by the PEP
      */
      value: function create(schema, observers, initialData) {
        var store = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
        var p2p = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
  
        var _this = this;
        var criteria = {};
  
        criteria.p2p = p2p;
        criteria.store = store;
        criteria.schema = schema;
        criteria.observers = observers;
        criteria.initialData = initialData;
  
        console.log('[syncher - create] - create Reporter - criteria: ', criteria);
  
        (0, _assign2.default)(criteria, { resume: false });
  
        return _this._create(criteria);
      }
    }, {
      key: 'resumeReporters',
      value: function resumeReporters(criteria) {
        var _this = this;
        console.log('[syncher - create] - resume Reporter - criteria: ', criteria);
  
        (0, _assign2.default)(criteria, { resume: true });
  
        return _this._create(criteria);
      }
  
      /**
      * Request a subscription to an existent reporter object.
      * @param {SchemaURL} schema - Hyperty Catalogue URL address that can be used to retrieve the JSON-Schema describing the Data Object schema
      * @param {ObjectURL} objURL - Address of the existent reporter object to be observed
      * @param {Boolean} [store=false] - Save the subscription on the Syncher Manager for further resume (Default is false)
      * @param {Boolean} [p2p=false] - Info about if should use p2p connection (Default is false)
      * @param {Boolean} [mutual=true] - Info about if messages of this object should be encrypted (Default is true)
      * @return {Promise<DataObjectObserver>} Return Promise to a new observer. It's associated with the reporter.
      */
  
    }, {
      key: 'subscribe',
      value: function subscribe(schema, objURL) {
        var store = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
        var p2p = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
        var mutual = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
  
        var _this = this;
        var criteria = {};
  
        criteria.p2p = p2p;
        criteria.store = store;
        criteria.schema = schema;
        criteria.resource = objURL;
  
        //TODO: For Further Study
        criteria.mutual = mutual;
  
        console.log('[syncher - subscribe] - subscribe criteria: ', criteria);
  
        (0, _assign2.default)(criteria, { resume: false });
  
        return _this._subscribe(criteria);
      }
  
      /**
      * Request a subscription to an existent reporter object.
      * @param {criteria} criteria - Information to discovery the observer object
      * @return {Promise<DataObjectObserver>} Return Promise to a new observer. It's associated with the reporter.
      */
  
    }, {
      key: 'resumeObservers',
      value: function resumeObservers(criteria) {
        var _this = this;
        var _criteria = criteria || {};
  
        (0, _assign2.default)(_criteria, { resume: true });
  
        return _this._subscribe(_criteria);
      }
  
      /**
      * Request a read action on the reporter object
      * @param {ObjectURL} objURL - URL of the reporter object to be read
      * @return {Promise<Object>} Return Promise to last available data of the reporter
      */
  
    }, {
      key: 'read',
      value: function read(objURL) {
        var _this = this;
  
        //FLOW-OUT: this message will be sent directly to reporter object (maybe there is no listener available, so it will be resolved with MessageBus -> resolve)
        //will reach the remote object in DataObjectReporter -> _onRead
        var readMsg = {
          type: 'read', from: _this._owner, to: objURL
        };
  
        return new _promise2.default(function (resolve, reject) {
          _this._bus.postMessage(readMsg, function (reply) {
            console.log('read-response: ', reply);
            if (reply.body.code === 200) {
              resolve(reply.body.value);
            } else {
              reject(reply.body.desc);
            }
          });
        });
      }
  
      /**
      * Setup the callback to process create and delete events of remove Reporter objects.
      * This is releated to the messagens sent by create to the observers Hyperty array.
      * @param {function(event: MsgEvent)} callback
      */
  
    }, {
      key: 'onNotification',
      value: function onNotification(callback) {
        this._onNotificationHandler = callback;
      }
    }, {
      key: '_create',
      value: function _create(criteria) {
        var _this = this;
  
        return new _promise2.default(function (resolve, reject) {
          var resume = criteria.resume;
          var initialData = criteria.initialData || {};
          var schema = void 0;
  
          //FLOW-OUT: this message will be sent to the runtime instance of SyncherManager -> _onCreate
          var requestMsg = {
            type: 'create', from: _this._owner, to: _this._subURL,
            body: { resume: resume }
          };
  
          console.log('[syncher - create]: ', criteria, requestMsg);
  
          requestMsg.body.value = initialData;
          requestMsg.body.value.reporter = _this._owner;
  
          if (criteria.schema) {
            schema = criteria.schema;
            requestMsg.body.schema = criteria.schema;
          }
  
          if (criteria.p2p) requestMsg.body.p2p = criteria.p2p;
          if (criteria.store) requestMsg.body.store = criteria.store;
          if (criteria.observers) requestMsg.body.authorise = criteria.observers;
  
          if (resume) {
            console.log('[syncher - create] - resume message: ', requestMsg);
          } else {
            console.log('[syncher - create] - create message: ', requestMsg);
          }
  
          //request create to the allocation system. Can be rejected by the PolicyEngine.
          _this._bus.postMessage(requestMsg, function (reply) {
            console.log('[syncher - create] - create-response: ', reply);
            if (reply.body.code === 200) {
              //reporter creation accepted
              var objURL = reply.body.resource;
  
              if (resume) {
                schema = reply.body.schema;
                initialData = reply.body.value;
              }
  
              var newObj = new _DataObjectReporter2.default(_this, objURL, schema, 'on', initialData, reply.body.childrenResources);
              _this._reporters[objURL] = newObj;
  
              resolve(newObj);
            } else {
              //reporter creation rejected
              reject(reply.body.desc);
            }
          });
        });
      }
    }, {
      key: '_subscribe',
      value: function _subscribe(criteria) {
        var _this = this;
  
        return new _promise2.default(function (resolve, reject) {
  
          //FLOW-OUT: this message will be sent to the runtime instance of SyncherManager -> _onLocalSubscribe
          var subscribeMsg = {
            type: 'subscribe', from: _this._owner, to: _this._subURL,
            body: {}
          };
  
          // Hyperty request to be an Observer
          // https://github.com/reTHINK-project/specs/blob/master/messages/data-sync-messages.md#hyperty-request-to-be-an-observer
  
          // Resume Subscriptions for the same Hyperty URL
          // https://github.com/reTHINK-project/specs/blob/master/messages/data-sync-messages.md#resume-subscriptions-for-the-same-hyperty-url
  
          // Resume Subscriptions for a certain user and data schema independently of the Hyperty URL.
          // https://github.com/reTHINK-project/specs/blob/master/messages/data-sync-messages.md#resume-subscriptions-for-a-certain-user-and-data-schema-independently-of-the-hyperty-url
          if (criteria) {
            if (criteria.hasOwnProperty('p2p')) subscribeMsg.body.p2p = criteria.p2p;
            if (criteria.hasOwnProperty('store')) subscribeMsg.body.store = criteria.store;
            if (criteria.hasOwnProperty('schema')) subscribeMsg.body.schema = criteria.schema;
            if (criteria.hasOwnProperty('identity')) subscribeMsg.body.identity = criteria.identity;
            if (criteria.hasOwnProperty('resource')) subscribeMsg.body.resource = criteria.resource;
          }
  
          subscribeMsg.body.resume = criteria.resume;
  
          //TODO: For Further Study
          var mutualAuthentication = criteria.mutual;
          if (!mutualAuthentication) subscribeMsg.body.mutualAuthentication = mutualAuthentication;
  
          console.log('[syncher] - subscribe message: ', criteria, subscribeMsg);
  
          //request subscription
          //Provisional data is applied to the DataObjectObserver after confirmation. Or discarded if there is no confirmation.
          //for more info see the DataProvisional class documentation.
          _this._bus.postMessage(subscribeMsg, function (reply) {
            console.log('[syncher] - subscribe-response: ', reply);
  
            var schema = reply.body.schema;
            var objURL = reply.body.resource;
  
            var newProvisional = _this._provisionals[objURL];
            delete _this._provisionals[objURL];
            if (newProvisional) newProvisional._releaseListeners();
  
            if (reply.body.code < 200) {
              console.log('[syncher] - new DataProvisional: ', reply.body.childrenResources, objURL);
              newProvisional = new _DataProvisional2.default(_this._owner, objURL, _this._bus, reply.body.childrenResources);
              _this._provisionals[objURL] = newProvisional;
            } else if (reply.body.code === 200) {
              console.log('[syncher] - new Data Object Observer: ', reply, _this._provisionals);
  
              //TODO: For Further Study
              var newObj = new _DataObjectObserver2.default(_this, objURL, schema, 'on', reply.body.value, newProvisional.children, reply.body.version, mutualAuthentication);
              _this._observers[objURL] = newObj;
  
              resolve(newObj);
              newProvisional.apply(newObj);
            } else {
              reject(reply.body.desc);
            }
          });
        });
      }
  
      //FLOW-IN: message received from a local runtime ReporterObject -> _onRemoteSubscribe
  
    }, {
      key: '_onForward',
      value: function _onForward(msg) {
        var _this = this;
  
        var reporter = _this._reporters[msg.body.to];
        reporter._onForward(msg);
      }
  
      //FLOW-IN: message received from a remote Syncher -> create (this is actually an invitation to subscribe)
  
    }, {
      key: '_onRemoteCreate',
      value: function _onRemoteCreate(msg) {
        var _this = this;
  
        //remove "/subscription" from the URL
        var resource = msg.from.slice(0, -13);
  
        var event = {
          type: msg.type,
          from: msg.body.source,
          url: resource,
          schema: msg.body.schema,
          value: msg.body.value,
          identity: msg.body.identity,
  
          ack: function ack(type) {
            var lType = 200;
            if (type) {
              lType = type;
            }
  
            //send ack response message
            _this._bus.postMessage({
              id: msg.id, type: 'response', from: msg.to, to: msg.from,
              body: { code: lType }
            });
          }
        };
  
        if (_this._onNotificationHandler) {
          console.info('[Syncher] NOTIFICATION-EVENT: ', event);
          _this._onNotificationHandler(event);
        }
      }
  
      //FLOW-IN: message received from a remote DataObjectReporter -> delete
  
    }, {
      key: '_onRemoteDelete',
      value: function _onRemoteDelete(msg) {
        var _this = this;
  
        //remove "/subscription" from the URL
        var resource = msg.body.resource;
  
        var object = _this._observers[resource];
        if (object) {
          var event = {
            type: msg.type,
            url: resource,
            identity: msg.body.identity,
  
            ack: function ack(type) {
              var lType = 200;
              if (type) {
                lType = type;
              }
  
              //TODO: any other different options for the release process, like accept but nor release local?
              if (lType === 200) {
                object.delete();
              }
  
              //send ack response message
              _this._bus.postMessage({
                id: msg.id, type: 'response', from: msg.to, to: msg.from,
                body: { code: lType, source: _this._owner }
              });
            }
          };
  
          if (_this._onNotificationHandler) {
            console.log('NOTIFICATION-EVENT: ', event);
            _this._onNotificationHandler(event);
          }
        } else {
          _this._bus.postMessage({
            id: msg.id, type: 'response', from: msg.to, to: msg.from,
            body: { code: 404, source: _this._owner }
          });
        }
      }
    }, {
      key: 'owner',
      get: function get() {
        return this._owner;
      }
  
      /**
      * All owned reporters, the ones that were created by a create
      * @type {Object<URL, DataObjectReporter>}
      */
  
    }, {
      key: 'reporters',
      get: function get() {
        return this._reporters;
      }
  
      /**
      * All owned observers, the ones that were created by a local subscription
      * @type {Object<URL, DataObjectObserver>}
      */
  
    }, {
      key: 'observers',
      get: function get() {
        return this._observers;
      }
    }]);
    return Syncher;
  }(); /**
       * Copyright 2016 PT Inovação e Sistemas SA
       * Copyright 2016 INESC-ID
       * Copyright 2016 QUOBIS NETWORKS SL
       * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
       * Copyright 2016 ORANGE SA
       * Copyright 2016 Deutsche Telekom AG
       * Copyright 2016 Apizee
       * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
       *
       * Licensed under the Apache License, Version 2.0 (the "License");
       * you may not use this file except in compliance with the License.
       * You may obtain a copy of the License at
       *
       *   http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       **/
  
  exports.default = Syncher;
  module.exports = exports['default'];
  
  /***/ }),
  /* 131 */,
  /* 132 */,
  /* 133 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _classCallCheck2 = __webpack_require__(9);
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _createClass2 = __webpack_require__(10);
  
  var _createClass3 = _interopRequireDefault(_createClass2);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
  * Copyright 2016 PT Inovação e Sistemas SA
  * Copyright 2016 INESC-ID
  * Copyright 2016 QUOBIS NETWORKS SL
  * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
  * Copyright 2016 ORANGE SA
  * Copyright 2016 Deutsche Telekom AG
  * Copyright 2016 Apizee
  * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  **/
  
  /**
   * @access private
   * This class is responsible for collecting delta changes in remote objects, before the response of subscription reach the observer.
   * It's used in Syncher -> subscribe. The flow is defined as:
   * 1. (observer) --subscribe--> (reporter)
   * 2. (observer) <--delta updates-- (reporter)
   * 3. (observer) <--subscribe response-- (reporter)
   * This means that there could be delta updates transferred before the subscription confirmation.
   * Since there is no DataObjectObserver before the ubscription confirmation, there should be some other object collecting the updates.
   * Provisional data is applied to the DataObjectObserver after confirmation. Or discarded if there is no confirmation.
   */
  var DataProvisional = function () {
    /* private
    _childrenListeners: [MsgListener]
    _listener: MsgListener
     _changes: []
    */
  
    function DataProvisional(owner, url, bus, children) {
      (0, _classCallCheck3.default)(this, DataProvisional);
  
      var _this = this;
  
      _this._owner = owner;
      _this._url = url;
      _this._bus = bus;
      _this._children = children;
  
      _this._changes = [];
      _this._allocateListeners();
    }
  
    (0, _createClass3.default)(DataProvisional, [{
      key: '_allocateListeners',
      value: function _allocateListeners() {
        var _this = this;
  
        _this._listener = _this._bus.addListener(_this._url, function (msg) {
          console.log('DataProvisional-' + _this._url + '-RCV: ', msg);
          _this._changes.push(msg);
        });
  
        /*
        _this._childrenListeners = [];
        if (_this._children) {
          let childBaseURL = url + '/children/';
          _this._children.forEach((child) => {
            let childURL = childBaseURL + child;
            let listener = _this._bus.addListener(childURL, (msg) => {
              //ignore msg sent by himself
              if (msg.from !== owner) {
                console.log(msg);
              }
            });
             _this._childrenListeners.push(listener);
          });
        }*/
      }
    }, {
      key: '_releaseListeners',
      value: function _releaseListeners() {
        var _this = this;
  
        _this._listener.remove();
  
        /*_this._childrenListeners.forEach((listener) => {
          listener.remove();
        });*/
      }
    }, {
      key: 'apply',
      value: function apply(observer) {
        var _this = this;
        _this._changes.forEach(function (change) {
          observer._changeObject(observer._syncObj, change);
        });
      }
    }, {
      key: 'children',
      get: function get() {
        return this._children;
      }
    }]);
    return DataProvisional;
  }();
  
  exports.default = DataProvisional;
  module.exports = exports['default'];
  
  /***/ }),
  /* 134 */,
  /* 135 */,
  /* 136 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(143), __esModule: true };
  
  /***/ }),
  /* 137 */,
  /* 138 */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = { "default": __webpack_require__(145), __esModule: true };
  
  /***/ }),
  /* 139 */,
  /* 140 */,
  /* 141 */,
  /* 142 */,
  /* 143 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(149);
  module.exports = __webpack_require__(0).Object.assign;
  
  /***/ }),
  /* 144 */,
  /* 145 */
  /***/ (function(module, exports, __webpack_require__) {
  
  __webpack_require__(151);
  var $Object = __webpack_require__(0).Object;
  module.exports = function getOwnPropertyDescriptor(it, key){
    return $Object.getOwnPropertyDescriptor(it, key);
  };
  
  /***/ }),
  /* 146 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  // 19.1.2.1 Object.assign(target, source, ...)
  var getKeys  = __webpack_require__(17)
    , gOPS     = __webpack_require__(58)
    , pIE      = __webpack_require__(41)
    , toObject = __webpack_require__(32)
    , IObject  = __webpack_require__(56)
    , $assign  = Object.assign;
  
  // should work with symbols and should have deterministic property order (V8 bug)
  module.exports = !$assign || __webpack_require__(11)(function(){
    var A = {}
      , B = {}
      , S = Symbol()
      , K = 'abcdefghijklmnopqrst';
    A[S] = 7;
    K.split('').forEach(function(k){ B[k] = k; });
    return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
  }) ? function assign(target, source){ // eslint-disable-line no-unused-vars
    var T     = toObject(target)
      , aLen  = arguments.length
      , index = 1
      , getSymbols = gOPS.f
      , isEnum     = pIE.f;
    while(aLen > index){
      var S      = IObject(arguments[index++])
        , keys   = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S)
        , length = keys.length
        , j      = 0
        , key;
      while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key];
    } return T;
  } : $assign;
  
  /***/ }),
  /* 147 */,
  /* 148 */,
  /* 149 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.3.1 Object.assign(target, source)
  var $export = __webpack_require__(8);
  
  $export($export.S + $export.F, 'Object', {assign: __webpack_require__(146)});
  
  /***/ }),
  /* 150 */,
  /* 151 */
  /***/ (function(module, exports, __webpack_require__) {
  
  // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
  var toIObject                 = __webpack_require__(13)
    , $getOwnPropertyDescriptor = __webpack_require__(57).f;
  
  __webpack_require__(45)('getOwnPropertyDescriptor', function(){
    return function getOwnPropertyDescriptor(it, key){
      return $getOwnPropertyDescriptor(toIObject(it), key);
    };
  });
  
  /***/ }),
  /* 152 */,
  /* 153 */
  /***/ (function(module, exports) {
  
  //     proxy-observe v0.0.18
  //     Copyright (c) 2015, 2016 Simon Y. Blackwell, AnyWhichWay
  //     MIT License - http://opensource.org/licenses/mit-license.php
  (function() {
  	"use strict";
  	// Creates and returns a Proxy wrapping a target so that all changes can be trapped and forwarded to
  	// a callback. The callback takes an array of changes just like the traditional original Chrome Object.observe
  	// {object:<object changed>,name:<field changed>,type:add|update|delete|reconfigure|preventExtensions|setPrototype,oldValue:<old value if update | delete>}
  	// The acceptlist can be add|update|delete|reconfigure|preventExtensions|setPrototype.
  	// v 0.0.10 to support pausing and restarting observation two additional constructor arguments are available to Object.observe:
  	// pausable - create the Observer so it can be paused
  	// pause - create observer in paused state
  	// if pausable is true then an additional method deliver(ignorePrevious) is available to start delivery
  	// to pause delivery set a property called pause on the function deliver to true
  	// pausable is optional to reduce the chance of shadowing a property or method on any existing code called deliver
  	if(!Object.observe && typeof(Proxy)==="function") {
  		function Observer(target,callback,acceptlist,pausable,pause,delay) {
  	    	var me = this, proxy;
  	    	function deliver(ignorePrevious,delay) {
  	    		deliver.delay = delay;
  	    		if(!deliver.pause) {
  	        		if(me.changeset.length>0) {
  	        			if(!ignorePrevious) {
  		    	    		var changes = me.changeset.filter(function(change) { return !acceptlist || acceptlist.indexOf(change.type)>=0; });
  		        			if(changes.length>0) {
  		        				callback(changes);
  		        			}
  	        			}
  	        			me.changeset = [];
  	        		}
  	    		}
  	    	}
  	    	deliver.pause = pause;
  	    	deliver.delay = delay;
  		    me.get = function(target, property) {
  		    	if(property==="__observer__") {
  		    		return me;
  		    	}
  		    	if(property==="unobserve") {
  		    		return function() {
  		    			Object.unobserve(target);
  		    			return target;
  		    		};
  		    	}
  		    	if(property==="deliver") {
  		    		return deliver;
  		    	}
  		    	return target[property];
  		    }
  	    	me.target = target;
  	    	me.changeset = [];
  	    	if(!me.target.__observerCallbacks__) {
  	    		// __observerCallbacks__ is used as an index to get at the proxy which is the observer, so we can unobserve
  	    		Object.defineProperty(target,"__observerCallbacks__",{enumerable:false,configurable:true,writable:false,value:[]});
  	    		Object.defineProperty(target,"__observers__",{enumerable:false,configurable:true,writable:false,value:[]});
  	    	}
  	    	me.target.__observerCallbacks__.push(callback);
  	    	me.target.__observers__.push(this);
  	    	proxy = new Proxy(target,me);
  	    	deliver(false,delay);
  	    	return proxy;
  	    }
  		Observer.prototype.deliver = function() {
  			return this.get(null,"deliver");
  		}
  	    Observer.prototype.set = function(target, property, value) { // , receiver
  	    	var oldvalue = target[property];
  	    	var type = (oldvalue===undefined ? "add" : "update");
  	    	target[property] = value;
  	    	if(target.__observers__.indexOf(this)>=0 && (!this.acceptlist || this.acceptlist.indexOf(type)>=0)) {
  	        	var change = {object:target,name:property,type:type},
  	        		start = this.changeset.length === 0,
  	        		deliver = this.deliver();
  	        	if(type==="update") {
  	        		change.oldValue = oldvalue;
  	        	}
  	        	this.changeset.push(change);
  	        	if(start) {
  	        		deliver(false,(typeof(deliver.delay)==="number" ? deliver.delay : 10));
  	        	}
  	    	}
  	    	return true;
  	    };
  	    Observer.prototype.deleteProperty = function(target, property) {
  	    	var oldvalue = target[property];
  	    	//if(typeof(oldvalue)!=="undefined") {
  		    	delete target[property];
  		    	if(target.__observers__.indexOf(this)>=0 && !this.acceptlist || this.acceptlist.indexOf("delete")>=0) {
  		        	var change = {object:target,name:property,type:"delete",oldValue:oldvalue},
  		        		start = this.changeset.length === 0,
  		        		deliver = this.deliver();
  		        	this.changeset.push(change);
  		        	if(start) {
  		        		deliver(false,(typeof(deliver.delay)==="number" ? deliver.delay : 10));
  		        	}
  		    	}
  	    	//}
  	    	return true;
  	    };
  	    Observer.prototype.defineProperty = function(target, property, descriptor) {
  	    	Object.defineProperty(target, property, descriptor);
  	    	if(target.__observers__.indexOf(this)>=0 && !this.acceptlist || this.acceptlist.indexOf("reconfigure")>=0) {
  	        	var change = {object:target,name:property,type:"reconfigure"},
          			start = this.changeset.length === 0,
          			deliver = this.deliver();
  	        	this.changeset.push(change);
  	        	if(start) {
  	        		deliver(false,(typeof(deliver.delay)==="number" ? deliver.delay : 10));
  	        	}
  	    	}
  	    	return true;
  	    };
  	    Observer.prototype.setPrototypeOf = function(target, prototype) {
  	    	var oldvalue = Object.getPrototypeOf(target);
  	    	Object.setPrototypeOf(target, prototype);
  	    	if(target.__observers__.indexOf(this)>=0 && !this.acceptlist || this.acceptlist.indexOf("setPrototype")>=0) {
  	        	var change = {object:target,name:"__proto__",type:"setPrototype",oldValue:oldvalue},
      				start = this.changeset.length === 0,
      				deliver = this.deliver();
  	        	this.changeset.push(change);
  	        	if(start) {
  	        		deliver(false,(typeof(deliver.delay)==="number" ? deliver.delay : 10));
  	        	}
  	    	}
  	    	return true;
  	    };
  	    Observer.prototype.preventExtensions = function(target) {
  	        Object.preventExtensions(target);
  	    	if(target.__observers__.indexOf(this)>=0 && !this.acceptlist || this.acceptlist.indexOf("preventExtensions")>=0) {
  	        	var change = {object:target,type:"preventExtensions"},
  					start = this.changeset.length === 0,
  					deliver = this.deliver();
  	        	this.changeset.push(change);
  	        	if(start) {
  	        		deliver(false,(typeof(deliver.delay)==="number" ? deliver.delay : 10));
  	        	}
  	    	}
  	    	return true;
  	    };
  	    Object.observe = function(object,callback,acceptlist,pausable,pause,delay) {
  	    	return new Observer(object,callback,acceptlist,pausable,pause,delay);
  	    };
  	    Object.unobserve = function(object,callback) {
  	    	if(object.__observerCallbacks__) {
  	    		if(!callback) {
  	    			object.__observerCallbacks__.splice(0,object.__observerCallbacks__.length);
  	    			object.__observers__.splice(0,object.__observers__.length);
  	    			return;
  	    		}
  	    		object.__observerCallbacks__.forEach(function(observercallback,i) {
  	    			if(callback===observercallback) {
  	    				object.__observerCallbacks__.splice(i,1);
  	    				delete object.__observers__[i].callback;
  	    				object.__observers__.splice(i,1);
  	    			}
  	    		});
  	    	}
  	    };
  	    Array.observe = function(object,callback,acceptlist,pausable,pause,delay) {
  	    	if(!(object instanceof Array) && !Array.isArray(object)) {
  	    		throw new TypeError("First argument to Array.observer is not an Array");
  	    	}
              	acceptlist = acceptlist || ["add", "update", "delete", "splice"];
  	    	var arrayproxy = new Proxy(object,{get: function(target,property) {
  	    		if(property==="unobserve") {
  		    		return function(callback) {
  		    			if(callback) {
  		    				return Object.unobserve(target,callback);
  		    			}
  		    			return target.unobserve();
  		    		};
  		    	}
  	    		if(property==="splice") {
  	    			return function(start,end) {
  	    				if(typeof(start)!=="number" || typeof(end)!=="number") {
  	    					throw new TypeError("First two arguments to Array splice are not number, number");
  	    				}
  	    	    		var removed = this.slice(start,start+end),
  	    	    			addedCount = (arguments.length > 1 ? arguments.length-2 : 0),
  	    	    			change =  {object:object,type:"splice",index:start,removed:removed,addedCount:addedCount};
  	    	    		target.splice.apply(target,arguments);
  	    	    		if(acceptlist.indexOf("splice")>=0) {
  	    	    			var start = proxy.__observer__.changeset.length === 0,
  	    	        			deliver = proxy.__observer__.deliver();
  	    	    			proxy.__observer__.changeset.push(change);
  	    	    			if(start) {
  	    		        		deliver(false,(typeof(deliver.delay)==="number" ? deliver.delay : 10));
  	    		        	}
  	    	    		}
  	    	    	}
  	    		}
  	    		if(property==="push") {
  	    			 return function(item) {
  	    		    	return this.splice(this.length,0,item);
  	    		    }
  	    		}
  	    		if(property==="pop") {
  	    			 return function() {
  	    		    	return this.splice(this.length-1,1);
  	    		    }
  	    		}
  	    		if(property==="unshift") {
  	    			 return function(item) {
      		    		return this.splice(0,0,item);
      		    	}
  	    		}
  	    		if(property==="shift") {
  	    			return function() {
  	    	    		return this.splice(0,1);
  	    	    	}
  	    		}
  	    		return target[property];
  	    	}});
  	    	var proxy = Object.observe(arrayproxy,function(changeset) { 
  	    		var changes = changeset.filter(function(change) { return change.name!=="length" && change.name!=="add" && (!acceptlist || acceptlist.indexOf(change.type)>=0); });
  	    		if(changes.length>0) {
  	    			callback(changes);
  	    		}
  	    	},acceptlist,pausable,pause,delay);
  	    	return proxy;
  	    };
  	    Array.unobserve = function(object,callback) {
  		  return object.unobserve(callback);
  	    }
  	}
  	Object.deepObserve = function(object,callback,parts) {
  
  		parts = (parts ? parts : []);
  
  		var toTypeName = function(obj) {
  			return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
  		}
  
  		function reobserve(value, parts) {
  			var keys = Object.keys(value);
  			keys.forEach(function(key) {
  				if((toTypeName(value[key]) === 'object' || toTypeName(value[key]) === 'array') && !value[key].hasOwnProperty('__observers__')) {
  					var newparts = parts.slice(0);
  					newparts.push(key);
  					value[key] = Object.deepObserve(value[key],callback,newparts);
  				}
  			});
  		}
  
  		reobserve(object, parts);
  
  		var observed = Object.observe(object,function(changeset) {
  			var changes = [];
  			function recurse(name,rootObject,oldObject,newObject,path) {
  				if(newObject instanceof Object) {
  					var newkeys = Object.keys(newObject);
  					newkeys.forEach(function(key) {
  						if(!oldObject || (oldObject[key]!==newObject[key])) {
  							var oldvalue = (oldObject && oldObject[key]!==undefined ? oldObject[key] : undefined),
  								change = (oldvalue===undefined ? "add" : "update"),
  								keypath = path + "." + key;
  
  							changes.push({name:name,object:rootObject,type:change,oldValue:oldvalue,newValue:newObject[key],keypath:keypath});
  							recurse(name,rootObject,oldvalue,newObject[key],keypath);
  						}
  					});
  				} else if(oldObject instanceof Object) {
  					var oldkeys = Object.keys(oldObject);
  					oldkeys.forEach(function(key) {
  						var change = (newObject===null ? "update" : "delete"),
  							keypath = path + "." + key;
  							
  						changes.push({name:name,object:rootObject,type:change,oldValue:oldObject[key],newValue:newObject,keypath:keypath});
  						recurse(name,rootObject,oldObject[key],undefined,keypath);
  					});
  				}
  			}
  			changeset.forEach(function(change) {
  				var keypath = (parts.length>0 ? parts.join(".") + "." : "") + change.name;
  
  				if (change.type === "update" || change.type === "add") { 
  					reobserve(change.object, parts);
  				}
  
  				changes.push({name:change.name,object:change.object,type:change.type,oldValue:change.oldValue,newValue:change.object[change.name],keypath:keypath});
  				recurse(change.name,change.object,change.oldValue,change.object[change.name],keypath);
  			});
  			callback(changes);
  		});
  		return observed;
  	};
  })();
  
  
  /***/ }),
  /* 154 */,
  /* 155 */,
  /* 156 */,
  /* 157 */,
  /* 158 */,
  /* 159 */,
  /* 160 */,
  /* 161 */,
  /* 162 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.DataObjectObserver = exports.DataObjectReporter = exports.Syncher = undefined;
  
  var _Syncher = __webpack_require__(130);
  
  var _Syncher2 = _interopRequireDefault(_Syncher);
  
  var _DataObjectReporter = __webpack_require__(119);
  
  var _DataObjectReporter2 = _interopRequireDefault(_DataObjectReporter);
  
  var _DataObjectObserver = __webpack_require__(118);
  
  var _DataObjectObserver2 = _interopRequireDefault(_DataObjectObserver);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  exports.Syncher = _Syncher2.default;
  exports.DataObjectReporter = _DataObjectReporter2.default;
  exports.DataObjectObserver = _DataObjectObserver2.default;
  
  /***/ })
  /******/ ]);
  });
  
  },{}],3:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  
  'use strict';
  
  // Shimming starts here.
  (function() {
    // Utils.
    var utils = require('./utils');
    var logging = utils.log;
    var browserDetails = utils.browserDetails;
    // Export to the adapter global object visible in the browser.
    module.exports.browserDetails = browserDetails;
    module.exports.extractVersion = utils.extractVersion;
    module.exports.disableLog = utils.disableLog;
  
    // Uncomment the line below if you want logging to occur, including logging
    // for the switch statement below. Can also be turned on in the browser via
    // adapter.disableLog(false), but then logging from the switch statement below
    // will not appear.
    // require('./utils').disableLog(false);
  
    // Browser shims.
    var chromeShim = require('./chrome/chrome_shim') || null;
    var edgeShim = require('./edge/edge_shim') || null;
    var firefoxShim = require('./firefox/firefox_shim') || null;
    var safariShim = require('./safari/safari_shim') || null;
  
    // Shim browser if found.
    switch (browserDetails.browser) {
      case 'chrome':
        if (!chromeShim || !chromeShim.shimPeerConnection) {
          logging('Chrome shim is not included in this adapter release.');
          return;
        }
        logging('adapter.js shimming chrome.');
        // Export to the adapter global object visible in the browser.
        module.exports.browserShim = chromeShim;
  
        chromeShim.shimGetUserMedia();
        chromeShim.shimMediaStream();
        utils.shimCreateObjectURL();
        chromeShim.shimSourceObject();
        chromeShim.shimPeerConnection();
        chromeShim.shimOnTrack();
        break;
      case 'firefox':
        if (!firefoxShim || !firefoxShim.shimPeerConnection) {
          logging('Firefox shim is not included in this adapter release.');
          return;
        }
        logging('adapter.js shimming firefox.');
        // Export to the adapter global object visible in the browser.
        module.exports.browserShim = firefoxShim;
  
        firefoxShim.shimGetUserMedia();
        utils.shimCreateObjectURL();
        firefoxShim.shimSourceObject();
        firefoxShim.shimPeerConnection();
        firefoxShim.shimOnTrack();
        break;
      case 'edge':
        if (!edgeShim || !edgeShim.shimPeerConnection) {
          logging('MS edge shim is not included in this adapter release.');
          return;
        }
        logging('adapter.js shimming edge.');
        // Export to the adapter global object visible in the browser.
        module.exports.browserShim = edgeShim;
  
        edgeShim.shimGetUserMedia();
        utils.shimCreateObjectURL();
        edgeShim.shimPeerConnection();
        break;
      case 'safari':
        if (!safariShim) {
          logging('Safari shim is not included in this adapter release.');
          return;
        }
        logging('adapter.js shimming safari.');
        // Export to the adapter global object visible in the browser.
        module.exports.browserShim = safariShim;
  
        safariShim.shimGetUserMedia();
        break;
      default:
        logging('Unsupported browser!');
    }
  })();
  
  },{"./chrome/chrome_shim":4,"./edge/edge_shim":6,"./firefox/firefox_shim":8,"./safari/safari_shim":10,"./utils":11}],4:[function(require,module,exports){
  
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  'use strict';
  var logging = require('../utils.js').log;
  var browserDetails = require('../utils.js').browserDetails;
  
  var chromeShim = {
    shimMediaStream: function() {
      window.MediaStream = window.MediaStream || window.webkitMediaStream;
    },
  
    shimOnTrack: function() {
      if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
          window.RTCPeerConnection.prototype)) {
        Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
          get: function() {
            return this._ontrack;
          },
          set: function(f) {
            var self = this;
            if (this._ontrack) {
              this.removeEventListener('track', this._ontrack);
              this.removeEventListener('addstream', this._ontrackpoly);
            }
            this.addEventListener('track', this._ontrack = f);
            this.addEventListener('addstream', this._ontrackpoly = function(e) {
              // onaddstream does not fire when a track is added to an existing
              // stream. But stream.onaddtrack is implemented so we use that.
              e.stream.addEventListener('addtrack', function(te) {
                var event = new Event('track');
                event.track = te.track;
                event.receiver = {track: te.track};
                event.streams = [e.stream];
                self.dispatchEvent(event);
              });
              e.stream.getTracks().forEach(function(track) {
                var event = new Event('track');
                event.track = track;
                event.receiver = {track: track};
                event.streams = [e.stream];
                this.dispatchEvent(event);
              }.bind(this));
            }.bind(this));
          }
        });
      }
    },
  
    shimSourceObject: function() {
      if (typeof window === 'object') {
        if (window.HTMLMediaElement &&
          !('srcObject' in window.HTMLMediaElement.prototype)) {
          // Shim the srcObject property, once, when HTMLMediaElement is found.
          Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
            get: function() {
              return this._srcObject;
            },
            set: function(stream) {
              var self = this;
              // Use _srcObject as a private property for this shim
              this._srcObject = stream;
              if (this.src) {
                URL.revokeObjectURL(this.src);
              }
  
              if (!stream) {
                this.src = '';
                return undefined;
              }
              this.src = URL.createObjectURL(stream);
              // We need to recreate the blob url when a track is added or
              // removed. Doing it manually since we want to avoid a recursion.
              stream.addEventListener('addtrack', function() {
                if (self.src) {
                  URL.revokeObjectURL(self.src);
                }
                self.src = URL.createObjectURL(stream);
              });
              stream.addEventListener('removetrack', function() {
                if (self.src) {
                  URL.revokeObjectURL(self.src);
                }
                self.src = URL.createObjectURL(stream);
              });
            }
          });
        }
      }
    },
  
    shimPeerConnection: function() {
      // The RTCPeerConnection object.
      if (!window.RTCPeerConnection) {
        window.RTCPeerConnection = function(pcConfig, pcConstraints) {
          // Translate iceTransportPolicy to iceTransports,
          // see https://code.google.com/p/webrtc/issues/detail?id=4869
          // this was fixed in M56 along with unprefixing RTCPeerConnection.
          logging('PeerConnection');
          if (pcConfig && pcConfig.iceTransportPolicy) {
            pcConfig.iceTransports = pcConfig.iceTransportPolicy;
          }
  
          return new webkitRTCPeerConnection(pcConfig, pcConstraints);
        };
        window.RTCPeerConnection.prototype = webkitRTCPeerConnection.prototype;
        // wrap static methods. Currently just generateCertificate.
        if (webkitRTCPeerConnection.generateCertificate) {
          Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
            get: function() {
              return webkitRTCPeerConnection.generateCertificate;
            }
          });
        }
      }
  
      var origGetStats = RTCPeerConnection.prototype.getStats;
      RTCPeerConnection.prototype.getStats = function(selector,
          successCallback, errorCallback) {
        var self = this;
        var args = arguments;
  
        // If selector is a function then we are in the old style stats so just
        // pass back the original getStats format to avoid breaking old users.
        if (arguments.length > 0 && typeof selector === 'function') {
          return origGetStats.apply(this, arguments);
        }
  
        // When spec-style getStats is supported, return those when called with
        // either no arguments or the selector argument is null.
        if (origGetStats.length === 0 && (arguments.length === 0 ||
            typeof arguments[0] !== 'function')) {
          return origGetStats.apply(this, []);
        }
  
        var fixChromeStats_ = function(response) {
          var standardReport = {};
          var reports = response.result();
          reports.forEach(function(report) {
            var standardStats = {
              id: report.id,
              timestamp: report.timestamp,
              type: {
                localcandidate: 'local-candidate',
                remotecandidate: 'remote-candidate'
              }[report.type] || report.type
            };
            report.names().forEach(function(name) {
              standardStats[name] = report.stat(name);
            });
            standardReport[standardStats.id] = standardStats;
          });
  
          return standardReport;
        };
  
        // shim getStats with maplike support
        var makeMapStats = function(stats) {
          return new Map(Object.keys(stats).map(function(key) {
            return[key, stats[key]];
          }));
        };
  
        if (arguments.length >= 2) {
          var successCallbackWrapper_ = function(response) {
            args[1](makeMapStats(fixChromeStats_(response)));
          };
  
          return origGetStats.apply(this, [successCallbackWrapper_,
              arguments[0]]);
        }
  
        // promise-support
        return new Promise(function(resolve, reject) {
          origGetStats.apply(self, [
            function(response) {
              resolve(makeMapStats(fixChromeStats_(response)));
            }, reject]);
        }).then(successCallback, errorCallback);
      };
  
      // add promise support -- natively available in Chrome 51
      if (browserDetails.version < 51) {
        ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
            .forEach(function(method) {
              var nativeMethod = RTCPeerConnection.prototype[method];
              RTCPeerConnection.prototype[method] = function() {
                var args = arguments;
                var self = this;
                var promise = new Promise(function(resolve, reject) {
                  nativeMethod.apply(self, [args[0], resolve, reject]);
                });
                if (args.length < 2) {
                  return promise;
                }
                return promise.then(function() {
                  args[1].apply(null, []);
                },
                function(err) {
                  if (args.length >= 3) {
                    args[2].apply(null, [err]);
                  }
                });
              };
            });
      }
  
      // promise support for createOffer and createAnswer. Available (without
      // bugs) since M52: crbug/619289
      if (browserDetails.version < 52) {
        ['createOffer', 'createAnswer'].forEach(function(method) {
          var nativeMethod = RTCPeerConnection.prototype[method];
          RTCPeerConnection.prototype[method] = function() {
            var self = this;
            if (arguments.length < 1 || (arguments.length === 1 &&
                typeof arguments[0] === 'object')) {
              var opts = arguments.length === 1 ? arguments[0] : undefined;
              return new Promise(function(resolve, reject) {
                nativeMethod.apply(self, [resolve, reject, opts]);
              });
            }
            return nativeMethod.apply(this, arguments);
          };
        });
      }
  
      // shim implicit creation of RTCSessionDescription/RTCIceCandidate
      ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
          .forEach(function(method) {
            var nativeMethod = RTCPeerConnection.prototype[method];
            RTCPeerConnection.prototype[method] = function() {
              arguments[0] = new ((method === 'addIceCandidate') ?
                  RTCIceCandidate : RTCSessionDescription)(arguments[0]);
              return nativeMethod.apply(this, arguments);
            };
          });
  
      // support for addIceCandidate(null or undefined)
      var nativeAddIceCandidate =
          RTCPeerConnection.prototype.addIceCandidate;
      RTCPeerConnection.prototype.addIceCandidate = function() {
        if (!arguments[0]) {
          if (arguments[1]) {
            arguments[1].apply(null);
          }
          return Promise.resolve();
        }
        return nativeAddIceCandidate.apply(this, arguments);
      };
    }
  };
  
  
  // Expose public methods.
  module.exports = {
    shimMediaStream: chromeShim.shimMediaStream,
    shimOnTrack: chromeShim.shimOnTrack,
    shimSourceObject: chromeShim.shimSourceObject,
    shimPeerConnection: chromeShim.shimPeerConnection,
    shimGetUserMedia: require('./getusermedia')
  };
  
  },{"../utils.js":11,"./getusermedia":5}],5:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  'use strict';
  var logging = require('../utils.js').log;
  
  // Expose public methods.
  module.exports = function() {
    var constraintsToChrome_ = function(c) {
      if (typeof c !== 'object' || c.mandatory || c.optional) {
        return c;
      }
      var cc = {};
      Object.keys(c).forEach(function(key) {
        if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
          return;
        }
        var r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
        if (r.exact !== undefined && typeof r.exact === 'number') {
          r.min = r.max = r.exact;
        }
        var oldname_ = function(prefix, name) {
          if (prefix) {
            return prefix + name.charAt(0).toUpperCase() + name.slice(1);
          }
          return (name === 'deviceId') ? 'sourceId' : name;
        };
        if (r.ideal !== undefined) {
          cc.optional = cc.optional || [];
          var oc = {};
          if (typeof r.ideal === 'number') {
            oc[oldname_('min', key)] = r.ideal;
            cc.optional.push(oc);
            oc = {};
            oc[oldname_('max', key)] = r.ideal;
            cc.optional.push(oc);
          } else {
            oc[oldname_('', key)] = r.ideal;
            cc.optional.push(oc);
          }
        }
        if (r.exact !== undefined && typeof r.exact !== 'number') {
          cc.mandatory = cc.mandatory || {};
          cc.mandatory[oldname_('', key)] = r.exact;
        } else {
          ['min', 'max'].forEach(function(mix) {
            if (r[mix] !== undefined) {
              cc.mandatory = cc.mandatory || {};
              cc.mandatory[oldname_(mix, key)] = r[mix];
            }
          });
        }
      });
      if (c.advanced) {
        cc.optional = (cc.optional || []).concat(c.advanced);
      }
      return cc;
    };
  
    var shimConstraints_ = function(constraints, func) {
      constraints = JSON.parse(JSON.stringify(constraints));
      if (constraints && constraints.audio) {
        constraints.audio = constraintsToChrome_(constraints.audio);
      }
      if (constraints && typeof constraints.video === 'object') {
        // Shim facingMode for mobile, where it defaults to "user".
        var face = constraints.video.facingMode;
        face = face && ((typeof face === 'object') ? face : {ideal: face});
  
        if ((face && (face.exact === 'user' || face.exact === 'environment' ||
                      face.ideal === 'user' || face.ideal === 'environment')) &&
            !(navigator.mediaDevices.getSupportedConstraints &&
              navigator.mediaDevices.getSupportedConstraints().facingMode)) {
          delete constraints.video.facingMode;
          if (face.exact === 'environment' || face.ideal === 'environment') {
            // Look for "back" in label, or use last cam (typically back cam).
            return navigator.mediaDevices.enumerateDevices()
            .then(function(devices) {
              devices = devices.filter(function(d) {
                return d.kind === 'videoinput';
              });
              var back = devices.find(function(d) {
                return d.label.toLowerCase().indexOf('back') !== -1;
              }) || (devices.length && devices[devices.length - 1]);
              if (back) {
                constraints.video.deviceId = face.exact ? {exact: back.deviceId} :
                                                          {ideal: back.deviceId};
              }
              constraints.video = constraintsToChrome_(constraints.video);
              logging('chrome: ' + JSON.stringify(constraints));
              return func(constraints);
            });
          }
        }
        constraints.video = constraintsToChrome_(constraints.video);
      }
      logging('chrome: ' + JSON.stringify(constraints));
      return func(constraints);
    };
  
    var shimError_ = function(e) {
      return {
        name: {
          PermissionDeniedError: 'NotAllowedError',
          ConstraintNotSatisfiedError: 'OverconstrainedError'
        }[e.name] || e.name,
        message: e.message,
        constraint: e.constraintName,
        toString: function() {
          return this.name + (this.message && ': ') + this.message;
        }
      };
    };
  
    var getUserMedia_ = function(constraints, onSuccess, onError) {
      shimConstraints_(constraints, function(c) {
        navigator.webkitGetUserMedia(c, onSuccess, function(e) {
          onError(shimError_(e));
        });
      });
    };
  
    navigator.getUserMedia = getUserMedia_;
  
    // Returns the result of getUserMedia as a Promise.
    var getUserMediaPromise_ = function(constraints) {
      return new Promise(function(resolve, reject) {
        navigator.getUserMedia(constraints, resolve, reject);
      });
    };
  
    if (!navigator.mediaDevices) {
      navigator.mediaDevices = {
        getUserMedia: getUserMediaPromise_,
        enumerateDevices: function() {
          return new Promise(function(resolve) {
            var kinds = {audio: 'audioinput', video: 'videoinput'};
            return MediaStreamTrack.getSources(function(devices) {
              resolve(devices.map(function(device) {
                return {label: device.label,
                        kind: kinds[device.kind],
                        deviceId: device.id,
                        groupId: ''};
              }));
            });
          });
        }
      };
    }
  
    // A shim for getUserMedia method on the mediaDevices object.
    // TODO(KaptenJansson) remove once implemented in Chrome stable.
    if (!navigator.mediaDevices.getUserMedia) {
      navigator.mediaDevices.getUserMedia = function(constraints) {
        return getUserMediaPromise_(constraints);
      };
    } else {
      // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
      // function which returns a Promise, it does not accept spec-style
      // constraints.
      var origGetUserMedia = navigator.mediaDevices.getUserMedia.
          bind(navigator.mediaDevices);
      navigator.mediaDevices.getUserMedia = function(cs) {
        return shimConstraints_(cs, function(c) {
          return origGetUserMedia(c).then(function(stream) {
            if (c.audio && !stream.getAudioTracks().length ||
                c.video && !stream.getVideoTracks().length) {
              stream.getTracks().forEach(function(track) {
                track.stop();
              });
              throw new DOMException('', 'NotFoundError');
            }
            return stream;
          }, function(e) {
            return Promise.reject(shimError_(e));
          });
        });
      };
    }
  
    // Dummy devicechange event methods.
    // TODO(KaptenJansson) remove once implemented in Chrome stable.
    if (typeof navigator.mediaDevices.addEventListener === 'undefined') {
      navigator.mediaDevices.addEventListener = function() {
        logging('Dummy mediaDevices.addEventListener called.');
      };
    }
    if (typeof navigator.mediaDevices.removeEventListener === 'undefined') {
      navigator.mediaDevices.removeEventListener = function() {
        logging('Dummy mediaDevices.removeEventListener called.');
      };
    }
  };
  
  },{"../utils.js":11}],6:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  'use strict';
  
  var SDPUtils = require('sdp');
  var browserDetails = require('../utils').browserDetails;
  
  var edgeShim = {
    shimPeerConnection: function() {
      if (window.RTCIceGatherer) {
        // ORTC defines an RTCIceCandidate object but no constructor.
        // Not implemented in Edge.
        if (!window.RTCIceCandidate) {
          window.RTCIceCandidate = function(args) {
            return args;
          };
        }
        // ORTC does not have a session description object but
        // other browsers (i.e. Chrome) that will support both PC and ORTC
        // in the future might have this defined already.
        if (!window.RTCSessionDescription) {
          window.RTCSessionDescription = function(args) {
            return args;
          };
        }
        // this adds an additional event listener to MediaStrackTrack that signals
        // when a tracks enabled property was changed. Workaround for a bug in
        // addStream, see below. No longer required in 15025+
        if (browserDetails.version < 15025) {
          var origMSTEnabled = Object.getOwnPropertyDescriptor(
              MediaStreamTrack.prototype, 'enabled');
          Object.defineProperty(MediaStreamTrack.prototype, 'enabled', {
            set: function(value) {
              origMSTEnabled.set.call(this, value);
              var ev = new Event('enabled');
              ev.enabled = value;
              this.dispatchEvent(ev);
            }
          });
        }
      }
  
      window.RTCPeerConnection = function(config) {
        var self = this;
  
        var _eventTarget = document.createDocumentFragment();
        ['addEventListener', 'removeEventListener', 'dispatchEvent']
            .forEach(function(method) {
              self[method] = _eventTarget[method].bind(_eventTarget);
            });
  
        this.onicecandidate = null;
        this.onaddstream = null;
        this.ontrack = null;
        this.onremovestream = null;
        this.onsignalingstatechange = null;
        this.oniceconnectionstatechange = null;
        this.onicegatheringstatechange = null;
        this.onnegotiationneeded = null;
        this.ondatachannel = null;
  
        this.localStreams = [];
        this.remoteStreams = [];
        this.getLocalStreams = function() {
          return self.localStreams;
        };
        this.getRemoteStreams = function() {
          return self.remoteStreams;
        };
  
        this.localDescription = new RTCSessionDescription({
          type: '',
          sdp: ''
        });
        this.remoteDescription = new RTCSessionDescription({
          type: '',
          sdp: ''
        });
        this.signalingState = 'stable';
        this.iceConnectionState = 'new';
        this.iceGatheringState = 'new';
  
        this.iceOptions = {
          gatherPolicy: 'all',
          iceServers: []
        };
        if (config && config.iceTransportPolicy) {
          switch (config.iceTransportPolicy) {
            case 'all':
            case 'relay':
              this.iceOptions.gatherPolicy = config.iceTransportPolicy;
              break;
            case 'none':
              // FIXME: remove once implementation and spec have added this.
              throw new TypeError('iceTransportPolicy "none" not supported');
            default:
              // don't set iceTransportPolicy.
              break;
          }
        }
        this.usingBundle = config && config.bundlePolicy === 'max-bundle';
  
        if (config && config.iceServers) {
          // Edge does not like
          // 1) stun:
          // 2) turn: that does not have all of turn:host:port?transport=udp
          // 3) turn: with ipv6 addresses
          var iceServers = JSON.parse(JSON.stringify(config.iceServers));
          this.iceOptions.iceServers = iceServers.filter(function(server) {
            if (server && server.urls) {
              var urls = server.urls;
              if (typeof urls === 'string') {
                urls = [urls];
              }
              urls = urls.filter(function(url) {
                return (url.indexOf('turn:') === 0 &&
                    url.indexOf('transport=udp') !== -1 &&
                    url.indexOf('turn:[') === -1) ||
                    (url.indexOf('stun:') === 0 &&
                      browserDetails.version >= 14393);
              })[0];
              return !!urls;
            }
            return false;
          });
        }
        this._config = config;
  
        // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
        // everything that is needed to describe a SDP m-line.
        this.transceivers = [];
  
        // since the iceGatherer is currently created in createOffer but we
        // must not emit candidates until after setLocalDescription we buffer
        // them in this array.
        this._localIceCandidatesBuffer = [];
      };
  
      window.RTCPeerConnection.prototype._emitGatheringStateChange = function() {
        var event = new Event('icegatheringstatechange');
        this.dispatchEvent(event);
        if (this.onicegatheringstatechange !== null) {
          this.onicegatheringstatechange(event);
        }
      };
  
      window.RTCPeerConnection.prototype._emitBufferedCandidates = function() {
        var self = this;
        var sections = SDPUtils.splitSections(self.localDescription.sdp);
        // FIXME: need to apply ice candidates in a way which is async but
        // in-order
        this._localIceCandidatesBuffer.forEach(function(event) {
          var end = !event.candidate || Object.keys(event.candidate).length === 0;
          if (end) {
            for (var j = 1; j < sections.length; j++) {
              if (sections[j].indexOf('\r\na=end-of-candidates\r\n') === -1) {
                sections[j] += 'a=end-of-candidates\r\n';
              }
            }
          } else {
            sections[event.candidate.sdpMLineIndex + 1] +=
                'a=' + event.candidate.candidate + '\r\n';
          }
          self.localDescription.sdp = sections.join('');
          self.dispatchEvent(event);
          if (self.onicecandidate !== null) {
            self.onicecandidate(event);
          }
          if (!event.candidate && self.iceGatheringState !== 'complete') {
            var complete = self.transceivers.every(function(transceiver) {
              return transceiver.iceGatherer &&
                  transceiver.iceGatherer.state === 'completed';
            });
            if (complete && self.iceGatheringStateChange !== 'complete') {
              self.iceGatheringState = 'complete';
              self._emitGatheringStateChange();
            }
          }
        });
        this._localIceCandidatesBuffer = [];
      };
  
      window.RTCPeerConnection.prototype.getConfiguration = function() {
        return this._config;
      };
  
      window.RTCPeerConnection.prototype.addStream = function(stream) {
        if (browserDetails.version >= 15025) {
          this.localStreams.push(stream);
        } else {
          // Clone is necessary for local demos mostly, attaching directly
          // to two different senders does not work (build 10547).
          // Fixed in 15025 (or earlier)
          var clonedStream = stream.clone();
          stream.getTracks().forEach(function(track, idx) {
            var clonedTrack = clonedStream.getTracks()[idx];
            track.addEventListener('enabled', function(event) {
              clonedTrack.enabled = event.enabled;
            });
          });
          this.localStreams.push(clonedStream);
        }
        this._maybeFireNegotiationNeeded();
      };
  
      window.RTCPeerConnection.prototype.removeStream = function(stream) {
        var idx = this.localStreams.indexOf(stream);
        if (idx > -1) {
          this.localStreams.splice(idx, 1);
          this._maybeFireNegotiationNeeded();
        }
      };
  
      window.RTCPeerConnection.prototype.getSenders = function() {
        return this.transceivers.filter(function(transceiver) {
          return !!transceiver.rtpSender;
        })
        .map(function(transceiver) {
          return transceiver.rtpSender;
        });
      };
  
      window.RTCPeerConnection.prototype.getReceivers = function() {
        return this.transceivers.filter(function(transceiver) {
          return !!transceiver.rtpReceiver;
        })
        .map(function(transceiver) {
          return transceiver.rtpReceiver;
        });
      };
  
      // Determines the intersection of local and remote capabilities.
      window.RTCPeerConnection.prototype._getCommonCapabilities =
          function(localCapabilities, remoteCapabilities) {
            var commonCapabilities = {
              codecs: [],
              headerExtensions: [],
              fecMechanisms: []
            };
            localCapabilities.codecs.forEach(function(lCodec) {
              for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
                var rCodec = remoteCapabilities.codecs[i];
                if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
                    lCodec.clockRate === rCodec.clockRate) {
                  // number of channels is the highest common number of channels
                  rCodec.numChannels = Math.min(lCodec.numChannels,
                      rCodec.numChannels);
                  // push rCodec so we reply with offerer payload type
                  commonCapabilities.codecs.push(rCodec);
  
                  // determine common feedback mechanisms
                  rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
                    for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
                      if (lCodec.rtcpFeedback[j].type === fb.type &&
                          lCodec.rtcpFeedback[j].parameter === fb.parameter) {
                        return true;
                      }
                    }
                    return false;
                  });
                  // FIXME: also need to determine .parameters
                  //  see https://github.com/openpeer/ortc/issues/569
                  break;
                }
              }
            });
  
            localCapabilities.headerExtensions
                .forEach(function(lHeaderExtension) {
                  for (var i = 0; i < remoteCapabilities.headerExtensions.length;
                       i++) {
                    var rHeaderExtension = remoteCapabilities.headerExtensions[i];
                    if (lHeaderExtension.uri === rHeaderExtension.uri) {
                      commonCapabilities.headerExtensions.push(rHeaderExtension);
                      break;
                    }
                  }
                });
  
            // FIXME: fecMechanisms
            return commonCapabilities;
          };
  
      // Create ICE gatherer, ICE transport and DTLS transport.
      window.RTCPeerConnection.prototype._createIceAndDtlsTransports =
          function(mid, sdpMLineIndex) {
            var self = this;
            var iceGatherer = new RTCIceGatherer(self.iceOptions);
            var iceTransport = new RTCIceTransport(iceGatherer);
            iceGatherer.onlocalcandidate = function(evt) {
              var event = new Event('icecandidate');
              event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
  
              var cand = evt.candidate;
              var end = !cand || Object.keys(cand).length === 0;
              // Edge emits an empty object for RTCIceCandidateComplete‥
              if (end) {
                // polyfill since RTCIceGatherer.state is not implemented in
                // Edge 10547 yet.
                if (iceGatherer.state === undefined) {
                  iceGatherer.state = 'completed';
                }
              } else {
                // RTCIceCandidate doesn't have a component, needs to be added
                cand.component = iceTransport.component === 'RTCP' ? 2 : 1;
                event.candidate.candidate = SDPUtils.writeCandidate(cand);
              }
  
              // update local description.
              var sections = SDPUtils.splitSections(self.localDescription.sdp);
              if (!end) {
                sections[event.candidate.sdpMLineIndex + 1] +=
                    'a=' + event.candidate.candidate + '\r\n';
              } else {
                sections[event.candidate.sdpMLineIndex + 1] +=
                    'a=end-of-candidates\r\n';
              }
              self.localDescription.sdp = sections.join('');
              var transceivers = self._pendingOffer ? self._pendingOffer :
                  self.transceivers;
              var complete = transceivers.every(function(transceiver) {
                return transceiver.iceGatherer &&
                    transceiver.iceGatherer.state === 'completed';
              });
  
              // Emit candidate if localDescription is set.
              // Also emits null candidate when all gatherers are complete.
              switch (self.iceGatheringState) {
                case 'new':
                  if (!end) {
                    self._localIceCandidatesBuffer.push(event);
                  }
                  if (end && complete) {
                    self._localIceCandidatesBuffer.push(
                        new Event('icecandidate'));
                  }
                  break;
                case 'gathering':
                  self._emitBufferedCandidates();
                  if (!end) {
                    self.dispatchEvent(event);
                    if (self.onicecandidate !== null) {
                      self.onicecandidate(event);
                    }
                  }
                  if (complete) {
                    self.dispatchEvent(new Event('icecandidate'));
                    if (self.onicecandidate !== null) {
                      self.onicecandidate(new Event('icecandidate'));
                    }
                    self.iceGatheringState = 'complete';
                    self._emitGatheringStateChange();
                  }
                  break;
                case 'complete':
                  // should not happen... currently!
                  break;
                default: // no-op.
                  break;
              }
            };
            iceTransport.onicestatechange = function() {
              self._updateConnectionState();
            };
  
            var dtlsTransport = new RTCDtlsTransport(iceTransport);
            dtlsTransport.ondtlsstatechange = function() {
              self._updateConnectionState();
            };
            dtlsTransport.onerror = function() {
              // onerror does not set state to failed by itself.
              dtlsTransport.state = 'failed';
              self._updateConnectionState();
            };
  
            return {
              iceGatherer: iceGatherer,
              iceTransport: iceTransport,
              dtlsTransport: dtlsTransport
            };
          };
  
      // Start the RTP Sender and Receiver for a transceiver.
      window.RTCPeerConnection.prototype._transceive = function(transceiver,
          send, recv) {
        var params = this._getCommonCapabilities(transceiver.localCapabilities,
            transceiver.remoteCapabilities);
        if (send && transceiver.rtpSender) {
          params.encodings = transceiver.sendEncodingParameters;
          params.rtcp = {
            cname: SDPUtils.localCName
          };
          if (transceiver.recvEncodingParameters.length) {
            params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
          }
          transceiver.rtpSender.send(params);
        }
        if (recv && transceiver.rtpReceiver) {
          // remove RTX field in Edge 14942
          if (transceiver.kind === 'video'
              && transceiver.recvEncodingParameters) {
            transceiver.recvEncodingParameters.forEach(function(p) {
              delete p.rtx;
            });
          }
          params.encodings = transceiver.recvEncodingParameters;
          params.rtcp = {
            cname: transceiver.cname
          };
          if (transceiver.sendEncodingParameters.length) {
            params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
          }
          transceiver.rtpReceiver.receive(params);
        }
      };
  
      window.RTCPeerConnection.prototype.setLocalDescription =
          function(description) {
            var self = this;
            var sections;
            var sessionpart;
            if (description.type === 'offer') {
              // FIXME: What was the purpose of this empty if statement?
              // if (!this._pendingOffer) {
              // } else {
              if (this._pendingOffer) {
                // VERY limited support for SDP munging. Limited to:
                // * changing the order of codecs
                sections = SDPUtils.splitSections(description.sdp);
                sessionpart = sections.shift();
                sections.forEach(function(mediaSection, sdpMLineIndex) {
                  var caps = SDPUtils.parseRtpParameters(mediaSection);
                  self._pendingOffer[sdpMLineIndex].localCapabilities = caps;
                });
                this.transceivers = this._pendingOffer;
                delete this._pendingOffer;
              }
            } else if (description.type === 'answer') {
              sections = SDPUtils.splitSections(self.remoteDescription.sdp);
              sessionpart = sections.shift();
              var isIceLite = SDPUtils.matchPrefix(sessionpart,
                  'a=ice-lite').length > 0;
              sections.forEach(function(mediaSection, sdpMLineIndex) {
                var transceiver = self.transceivers[sdpMLineIndex];
                var iceGatherer = transceiver.iceGatherer;
                var iceTransport = transceiver.iceTransport;
                var dtlsTransport = transceiver.dtlsTransport;
                var localCapabilities = transceiver.localCapabilities;
                var remoteCapabilities = transceiver.remoteCapabilities;
  
                var rejected = mediaSection.split('\n', 1)[0]
                    .split(' ', 2)[1] === '0';
  
                if (!rejected && !transceiver.isDatachannel) {
                  var remoteIceParameters = SDPUtils.getIceParameters(
                      mediaSection, sessionpart);
                  var remoteDtlsParameters = SDPUtils.getDtlsParameters(
                      mediaSection, sessionpart);
                  if (isIceLite) {
                    remoteDtlsParameters.role = 'server';
                  }
  
                  if (!self.usingBundle || sdpMLineIndex === 0) {
                    iceTransport.start(iceGatherer, remoteIceParameters,
                        isIceLite ? 'controlling' : 'controlled');
                    dtlsTransport.start(remoteDtlsParameters);
                  }
  
                  // Calculate intersection of capabilities.
                  var params = self._getCommonCapabilities(localCapabilities,
                      remoteCapabilities);
  
                  // Start the RTCRtpSender. The RTCRtpReceiver for this
                  // transceiver has already been started in setRemoteDescription.
                  self._transceive(transceiver,
                      params.codecs.length > 0,
                      false);
                }
              });
            }
  
            this.localDescription = {
              type: description.type,
              sdp: description.sdp
            };
            switch (description.type) {
              case 'offer':
                this._updateSignalingState('have-local-offer');
                break;
              case 'answer':
                this._updateSignalingState('stable');
                break;
              default:
                throw new TypeError('unsupported type "' + description.type +
                    '"');
            }
  
            // If a success callback was provided, emit ICE candidates after it
            // has been executed. Otherwise, emit callback after the Promise is
            // resolved.
            var hasCallback = arguments.length > 1 &&
              typeof arguments[1] === 'function';
            if (hasCallback) {
              var cb = arguments[1];
              window.setTimeout(function() {
                cb();
                if (self.iceGatheringState === 'new') {
                  self.iceGatheringState = 'gathering';
                }
                self._emitBufferedCandidates();
              }, 0);
            }
            var p = Promise.resolve();
            p.then(function() {
              if (!hasCallback) {
                if (self.iceGatheringState === 'new') {
                  self.iceGatheringState = 'gathering';
                }
                // Usually candidates will be emitted earlier.
                window.setTimeout(self._emitBufferedCandidates.bind(self), 500);
              }
            });
            return p;
          };
  
      window.RTCPeerConnection.prototype.setRemoteDescription =
          function(description) {
            var self = this;
            var stream = new MediaStream();
            var receiverList = [];
            var sections = SDPUtils.splitSections(description.sdp);
            var sessionpart = sections.shift();
            var isIceLite = SDPUtils.matchPrefix(sessionpart,
                'a=ice-lite').length > 0;
            this.usingBundle = SDPUtils.matchPrefix(sessionpart,
                'a=group:BUNDLE ').length > 0;
            sections.forEach(function(mediaSection, sdpMLineIndex) {
              var lines = SDPUtils.splitLines(mediaSection);
              var mline = lines[0].substr(2).split(' ');
              var kind = mline[0];
              var rejected = mline[1] === '0';
              var direction = SDPUtils.getDirection(mediaSection, sessionpart);
  
              var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:');
              if (mid.length) {
                mid = mid[0].substr(6);
              } else {
                mid = SDPUtils.generateIdentifier();
              }
  
              // Reject datachannels which are not implemented yet.
              if (kind === 'application' && mline[2] === 'DTLS/SCTP') {
                self.transceivers[sdpMLineIndex] = {
                  mid: mid,
                  isDatachannel: true
                };
                return;
              }
  
              var transceiver;
              var iceGatherer;
              var iceTransport;
              var dtlsTransport;
              var rtpSender;
              var rtpReceiver;
              var sendEncodingParameters;
              var recvEncodingParameters;
              var localCapabilities;
  
              var track;
              // FIXME: ensure the mediaSection has rtcp-mux set.
              var remoteCapabilities = SDPUtils.parseRtpParameters(mediaSection);
              var remoteIceParameters;
              var remoteDtlsParameters;
              if (!rejected) {
                remoteIceParameters = SDPUtils.getIceParameters(mediaSection,
                    sessionpart);
                remoteDtlsParameters = SDPUtils.getDtlsParameters(mediaSection,
                    sessionpart);
                remoteDtlsParameters.role = 'client';
              }
              recvEncodingParameters =
                  SDPUtils.parseRtpEncodingParameters(mediaSection);
  
              var cname;
              // Gets the first SSRC. Note that with RTX there might be multiple
              // SSRCs.
              var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
                  .map(function(line) {
                    return SDPUtils.parseSsrcMedia(line);
                  })
                  .filter(function(obj) {
                    return obj.attribute === 'cname';
                  })[0];
              if (remoteSsrc) {
                cname = remoteSsrc.value;
              }
  
              var isComplete = SDPUtils.matchPrefix(mediaSection,
                  'a=end-of-candidates', sessionpart).length > 0;
              var cands = SDPUtils.matchPrefix(mediaSection, 'a=candidate:')
                  .map(function(cand) {
                    return SDPUtils.parseCandidate(cand);
                  })
                  .filter(function(cand) {
                    return cand.component === '1';
                  });
              if (description.type === 'offer' && !rejected) {
                var transports = self.usingBundle && sdpMLineIndex > 0 ? {
                  iceGatherer: self.transceivers[0].iceGatherer,
                  iceTransport: self.transceivers[0].iceTransport,
                  dtlsTransport: self.transceivers[0].dtlsTransport
                } : self._createIceAndDtlsTransports(mid, sdpMLineIndex);
  
                if (isComplete && (!self.usingBundle || sdpMLineIndex === 0)) {
                  transports.iceTransport.setRemoteCandidates(cands);
                }
  
                localCapabilities = RTCRtpReceiver.getCapabilities(kind);
  
                // filter RTX until additional stuff needed for RTX is implemented
                // in adapter.js
                localCapabilities.codecs = localCapabilities.codecs.filter(
                    function(codec) {
                      return codec.name !== 'rtx';
                    });
  
                sendEncodingParameters = [{
                  ssrc: (2 * sdpMLineIndex + 2) * 1001
                }];
  
                rtpReceiver = new RTCRtpReceiver(transports.dtlsTransport, kind);
  
                track = rtpReceiver.track;
                receiverList.push([track, rtpReceiver]);
                // FIXME: not correct when there are multiple streams but that is
                // not currently supported in this shim.
                stream.addTrack(track);
  
                // FIXME: look at direction.
                if (self.localStreams.length > 0 &&
                    self.localStreams[0].getTracks().length >= sdpMLineIndex) {
                  var localTrack;
                  if (kind === 'audio') {
                    localTrack = self.localStreams[0].getAudioTracks()[0];
                  } else if (kind === 'video') {
                    localTrack = self.localStreams[0].getVideoTracks()[0];
                  }
                  if (localTrack) {
                    rtpSender = new RTCRtpSender(localTrack,
                        transports.dtlsTransport);
                  }
                }
  
                self.transceivers[sdpMLineIndex] = {
                  iceGatherer: transports.iceGatherer,
                  iceTransport: transports.iceTransport,
                  dtlsTransport: transports.dtlsTransport,
                  localCapabilities: localCapabilities,
                  remoteCapabilities: remoteCapabilities,
                  rtpSender: rtpSender,
                  rtpReceiver: rtpReceiver,
                  kind: kind,
                  mid: mid,
                  cname: cname,
                  sendEncodingParameters: sendEncodingParameters,
                  recvEncodingParameters: recvEncodingParameters
                };
                // Start the RTCRtpReceiver now. The RTPSender is started in
                // setLocalDescription.
                self._transceive(self.transceivers[sdpMLineIndex],
                    false,
                    direction === 'sendrecv' || direction === 'sendonly');
              } else if (description.type === 'answer' && !rejected) {
                transceiver = self.transceivers[sdpMLineIndex];
                iceGatherer = transceiver.iceGatherer;
                iceTransport = transceiver.iceTransport;
                dtlsTransport = transceiver.dtlsTransport;
                rtpSender = transceiver.rtpSender;
                rtpReceiver = transceiver.rtpReceiver;
                sendEncodingParameters = transceiver.sendEncodingParameters;
                localCapabilities = transceiver.localCapabilities;
  
                self.transceivers[sdpMLineIndex].recvEncodingParameters =
                    recvEncodingParameters;
                self.transceivers[sdpMLineIndex].remoteCapabilities =
                    remoteCapabilities;
                self.transceivers[sdpMLineIndex].cname = cname;
  
                if ((isIceLite || isComplete) && cands.length) {
                  iceTransport.setRemoteCandidates(cands);
                }
                if (!self.usingBundle || sdpMLineIndex === 0) {
                  iceTransport.start(iceGatherer, remoteIceParameters,
                      'controlling');
                  dtlsTransport.start(remoteDtlsParameters);
                }
  
                self._transceive(transceiver,
                    direction === 'sendrecv' || direction === 'recvonly',
                    direction === 'sendrecv' || direction === 'sendonly');
  
                if (rtpReceiver &&
                    (direction === 'sendrecv' || direction === 'sendonly')) {
                  track = rtpReceiver.track;
                  receiverList.push([track, rtpReceiver]);
                  stream.addTrack(track);
                } else {
                  // FIXME: actually the receiver should be created later.
                  delete transceiver.rtpReceiver;
                }
              }
            });
  
            this.remoteDescription = {
              type: description.type,
              sdp: description.sdp
            };
            switch (description.type) {
              case 'offer':
                this._updateSignalingState('have-remote-offer');
                break;
              case 'answer':
                this._updateSignalingState('stable');
                break;
              default:
                throw new TypeError('unsupported type "' + description.type +
                    '"');
            }
            if (stream.getTracks().length) {
              self.remoteStreams.push(stream);
              window.setTimeout(function() {
                var event = new Event('addstream');
                event.stream = stream;
                self.dispatchEvent(event);
                if (self.onaddstream !== null) {
                  window.setTimeout(function() {
                    self.onaddstream(event);
                  }, 0);
                }
  
                receiverList.forEach(function(item) {
                  var track = item[0];
                  var receiver = item[1];
                  var trackEvent = new Event('track');
                  trackEvent.track = track;
                  trackEvent.receiver = receiver;
                  trackEvent.streams = [stream];
                  self.dispatchEvent(trackEvent);
                  if (self.ontrack !== null) {
                    window.setTimeout(function() {
                      self.ontrack(trackEvent);
                    }, 0);
                  }
                });
              }, 0);
            }
            if (arguments.length > 1 && typeof arguments[1] === 'function') {
              window.setTimeout(arguments[1], 0);
            }
            return Promise.resolve();
          };
  
      window.RTCPeerConnection.prototype.close = function() {
        this.transceivers.forEach(function(transceiver) {
          /* not yet
          if (transceiver.iceGatherer) {
            transceiver.iceGatherer.close();
          }
          */
          if (transceiver.iceTransport) {
            transceiver.iceTransport.stop();
          }
          if (transceiver.dtlsTransport) {
            transceiver.dtlsTransport.stop();
          }
          if (transceiver.rtpSender) {
            transceiver.rtpSender.stop();
          }
          if (transceiver.rtpReceiver) {
            transceiver.rtpReceiver.stop();
          }
        });
        // FIXME: clean up tracks, local streams, remote streams, etc
        this._updateSignalingState('closed');
      };
  
      // Update the signaling state.
      window.RTCPeerConnection.prototype._updateSignalingState =
          function(newState) {
            this.signalingState = newState;
            var event = new Event('signalingstatechange');
            this.dispatchEvent(event);
            if (this.onsignalingstatechange !== null) {
              this.onsignalingstatechange(event);
            }
          };
  
      // Determine whether to fire the negotiationneeded event.
      window.RTCPeerConnection.prototype._maybeFireNegotiationNeeded =
          function() {
            // Fire away (for now).
            var event = new Event('negotiationneeded');
            this.dispatchEvent(event);
            if (this.onnegotiationneeded !== null) {
              this.onnegotiationneeded(event);
            }
          };
  
      // Update the connection state.
      window.RTCPeerConnection.prototype._updateConnectionState = function() {
        var self = this;
        var newState;
        var states = {
          'new': 0,
          closed: 0,
          connecting: 0,
          checking: 0,
          connected: 0,
          completed: 0,
          failed: 0
        };
        this.transceivers.forEach(function(transceiver) {
          states[transceiver.iceTransport.state]++;
          states[transceiver.dtlsTransport.state]++;
        });
        // ICETransport.completed and connected are the same for this purpose.
        states.connected += states.completed;
  
        newState = 'new';
        if (states.failed > 0) {
          newState = 'failed';
        } else if (states.connecting > 0 || states.checking > 0) {
          newState = 'connecting';
        } else if (states.disconnected > 0) {
          newState = 'disconnected';
        } else if (states.new > 0) {
          newState = 'new';
        } else if (states.connected > 0 || states.completed > 0) {
          newState = 'connected';
        }
  
        if (newState !== self.iceConnectionState) {
          self.iceConnectionState = newState;
          var event = new Event('iceconnectionstatechange');
          this.dispatchEvent(event);
          if (this.oniceconnectionstatechange !== null) {
            this.oniceconnectionstatechange(event);
          }
        }
      };
  
      window.RTCPeerConnection.prototype.createOffer = function() {
        var self = this;
        if (this._pendingOffer) {
          throw new Error('createOffer called while there is a pending offer.');
        }
        var offerOptions;
        if (arguments.length === 1 && typeof arguments[0] !== 'function') {
          offerOptions = arguments[0];
        } else if (arguments.length === 3) {
          offerOptions = arguments[2];
        }
  
        var tracks = [];
        var numAudioTracks = 0;
        var numVideoTracks = 0;
        // Default to sendrecv.
        if (this.localStreams.length) {
          numAudioTracks = this.localStreams[0].getAudioTracks().length;
          numVideoTracks = this.localStreams[0].getVideoTracks().length;
        }
        // Determine number of audio and video tracks we need to send/recv.
        if (offerOptions) {
          // Reject Chrome legacy constraints.
          if (offerOptions.mandatory || offerOptions.optional) {
            throw new TypeError(
                'Legacy mandatory/optional constraints not supported.');
          }
          if (offerOptions.offerToReceiveAudio !== undefined) {
            numAudioTracks = offerOptions.offerToReceiveAudio;
          }
          if (offerOptions.offerToReceiveVideo !== undefined) {
            numVideoTracks = offerOptions.offerToReceiveVideo;
          }
        }
        if (this.localStreams.length) {
          // Push local streams.
          this.localStreams[0].getTracks().forEach(function(track) {
            tracks.push({
              kind: track.kind,
              track: track,
              wantReceive: track.kind === 'audio' ?
                  numAudioTracks > 0 : numVideoTracks > 0
            });
            if (track.kind === 'audio') {
              numAudioTracks--;
            } else if (track.kind === 'video') {
              numVideoTracks--;
            }
          });
        }
        // Create M-lines for recvonly streams.
        while (numAudioTracks > 0 || numVideoTracks > 0) {
          if (numAudioTracks > 0) {
            tracks.push({
              kind: 'audio',
              wantReceive: true
            });
            numAudioTracks--;
          }
          if (numVideoTracks > 0) {
            tracks.push({
              kind: 'video',
              wantReceive: true
            });
            numVideoTracks--;
          }
        }
  
        var sdp = SDPUtils.writeSessionBoilerplate();
        var transceivers = [];
        tracks.forEach(function(mline, sdpMLineIndex) {
          // For each track, create an ice gatherer, ice transport,
          // dtls transport, potentially rtpsender and rtpreceiver.
          var track = mline.track;
          var kind = mline.kind;
          var mid = SDPUtils.generateIdentifier();
  
          var transports = self.usingBundle && sdpMLineIndex > 0 ? {
            iceGatherer: transceivers[0].iceGatherer,
            iceTransport: transceivers[0].iceTransport,
            dtlsTransport: transceivers[0].dtlsTransport
          } : self._createIceAndDtlsTransports(mid, sdpMLineIndex);
  
          var localCapabilities = RTCRtpSender.getCapabilities(kind);
          // filter RTX until additional stuff needed for RTX is implemented
          // in adapter.js
          localCapabilities.codecs = localCapabilities.codecs.filter(
              function(codec) {
                return codec.name !== 'rtx';
              });
          localCapabilities.codecs.forEach(function(codec) {
            // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
            // by adding level-asymmetry-allowed=1
            if (codec.name === 'H264' &&
                codec.parameters['level-asymmetry-allowed'] === undefined) {
              codec.parameters['level-asymmetry-allowed'] = '1';
            }
          });
  
          var rtpSender;
          var rtpReceiver;
  
          // generate an ssrc now, to be used later in rtpSender.send
          var sendEncodingParameters = [{
            ssrc: (2 * sdpMLineIndex + 1) * 1001
          }];
          if (track) {
            rtpSender = new RTCRtpSender(track, transports.dtlsTransport);
          }
  
          if (mline.wantReceive) {
            rtpReceiver = new RTCRtpReceiver(transports.dtlsTransport, kind);
          }
  
          transceivers[sdpMLineIndex] = {
            iceGatherer: transports.iceGatherer,
            iceTransport: transports.iceTransport,
            dtlsTransport: transports.dtlsTransport,
            localCapabilities: localCapabilities,
            remoteCapabilities: null,
            rtpSender: rtpSender,
            rtpReceiver: rtpReceiver,
            kind: kind,
            mid: mid,
            sendEncodingParameters: sendEncodingParameters,
            recvEncodingParameters: null
          };
        });
        if (this.usingBundle) {
          sdp += 'a=group:BUNDLE ' + transceivers.map(function(t) {
            return t.mid;
          }).join(' ') + '\r\n';
        }
        tracks.forEach(function(mline, sdpMLineIndex) {
          var transceiver = transceivers[sdpMLineIndex];
          sdp += SDPUtils.writeMediaSection(transceiver,
              transceiver.localCapabilities, 'offer', self.localStreams[0]);
        });
  
        this._pendingOffer = transceivers;
        var desc = new RTCSessionDescription({
          type: 'offer',
          sdp: sdp
        });
        if (arguments.length && typeof arguments[0] === 'function') {
          window.setTimeout(arguments[0], 0, desc);
        }
        return Promise.resolve(desc);
      };
  
      window.RTCPeerConnection.prototype.createAnswer = function() {
        var self = this;
  
        var sdp = SDPUtils.writeSessionBoilerplate();
        if (this.usingBundle) {
          sdp += 'a=group:BUNDLE ' + this.transceivers.map(function(t) {
            return t.mid;
          }).join(' ') + '\r\n';
        }
        this.transceivers.forEach(function(transceiver) {
          if (transceiver.isDatachannel) {
            sdp += 'm=application 0 DTLS/SCTP 5000\r\n' +
                'c=IN IP4 0.0.0.0\r\n' +
                'a=mid:' + transceiver.mid + '\r\n';
            return;
          }
          // Calculate intersection of capabilities.
          var commonCapabilities = self._getCommonCapabilities(
              transceiver.localCapabilities,
              transceiver.remoteCapabilities);
  
          sdp += SDPUtils.writeMediaSection(transceiver, commonCapabilities,
              'answer', self.localStreams[0]);
        });
  
        var desc = new RTCSessionDescription({
          type: 'answer',
          sdp: sdp
        });
        if (arguments.length && typeof arguments[0] === 'function') {
          window.setTimeout(arguments[0], 0, desc);
        }
        return Promise.resolve(desc);
      };
  
      window.RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
        if (!candidate) {
          for (var j = 0; j < this.transceivers.length; j++) {
            this.transceivers[j].iceTransport.addRemoteCandidate({});
            if (this.usingBundle) {
              return Promise.resolve();
            }
          }
        } else {
          var mLineIndex = candidate.sdpMLineIndex;
          if (candidate.sdpMid) {
            for (var i = 0; i < this.transceivers.length; i++) {
              if (this.transceivers[i].mid === candidate.sdpMid) {
                mLineIndex = i;
                break;
              }
            }
          }
          var transceiver = this.transceivers[mLineIndex];
          if (transceiver) {
            var cand = Object.keys(candidate.candidate).length > 0 ?
                SDPUtils.parseCandidate(candidate.candidate) : {};
            // Ignore Chrome's invalid candidates since Edge does not like them.
            if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
              return Promise.resolve();
            }
            // Ignore RTCP candidates, we assume RTCP-MUX.
            if (cand.component !== '1') {
              return Promise.resolve();
            }
            transceiver.iceTransport.addRemoteCandidate(cand);
  
            // update the remoteDescription.
            var sections = SDPUtils.splitSections(this.remoteDescription.sdp);
            sections[mLineIndex + 1] += (cand.type ? candidate.candidate.trim()
                : 'a=end-of-candidates') + '\r\n';
            this.remoteDescription.sdp = sections.join('');
          }
        }
        if (arguments.length > 1 && typeof arguments[1] === 'function') {
          window.setTimeout(arguments[1], 0);
        }
        return Promise.resolve();
      };
  
      window.RTCPeerConnection.prototype.getStats = function() {
        var promises = [];
        this.transceivers.forEach(function(transceiver) {
          ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
              'dtlsTransport'].forEach(function(method) {
                if (transceiver[method]) {
                  promises.push(transceiver[method].getStats());
                }
              });
        });
        var cb = arguments.length > 1 && typeof arguments[1] === 'function' &&
            arguments[1];
        var fixStatsType = function(stat) {
          stat.type = {
            inboundrtp: 'inbound-rtp',
            outboundrtp: 'outbound-rtp',
            candidatepair: 'candidate-pair',
            localcandidate: 'local-candidate',
            remotecandidate: 'remote-candidate'
          }[stat.type] || stat.type;
          return stat;
        };
        return new Promise(function(resolve) {
          // shim getStats with maplike support
          var results = new Map();
          Promise.all(promises).then(function(res) {
            res.forEach(function(result) {
              Object.keys(result).forEach(function(id) {
                result[id].type = fixStatsType(result[id]);
                results.set(id, result[id]);
              });
            });
            if (cb) {
              window.setTimeout(cb, 0, results);
            }
            resolve(results);
          });
        });
      };
    }
  };
  
  // Expose public methods.
  module.exports = {
    shimPeerConnection: edgeShim.shimPeerConnection,
    shimGetUserMedia: require('./getusermedia')
  };
  
  },{"../utils":11,"./getusermedia":7,"sdp":1}],7:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  'use strict';
  
  // Expose public methods.
  module.exports = function() {
    var shimError_ = function(e) {
      return {
        name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
        message: e.message,
        constraint: e.constraint,
        toString: function() {
          return this.name;
        }
      };
    };
  
    // getUserMedia error shim.
    var origGetUserMedia = navigator.mediaDevices.getUserMedia.
        bind(navigator.mediaDevices);
    navigator.mediaDevices.getUserMedia = function(c) {
      return origGetUserMedia(c).catch(function(e) {
        return Promise.reject(shimError_(e));
      });
    };
  };
  
  },{}],8:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  'use strict';
  
  var browserDetails = require('../utils').browserDetails;
  
  var firefoxShim = {
    shimOnTrack: function() {
      if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
          window.RTCPeerConnection.prototype)) {
        Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
          get: function() {
            return this._ontrack;
          },
          set: function(f) {
            if (this._ontrack) {
              this.removeEventListener('track', this._ontrack);
              this.removeEventListener('addstream', this._ontrackpoly);
            }
            this.addEventListener('track', this._ontrack = f);
            this.addEventListener('addstream', this._ontrackpoly = function(e) {
              e.stream.getTracks().forEach(function(track) {
                var event = new Event('track');
                event.track = track;
                event.receiver = {track: track};
                event.streams = [e.stream];
                this.dispatchEvent(event);
              }.bind(this));
            }.bind(this));
          }
        });
      }
    },
  
    shimSourceObject: function() {
      // Firefox has supported mozSrcObject since FF22, unprefixed in 42.
      if (typeof window === 'object') {
        if (window.HTMLMediaElement &&
          !('srcObject' in window.HTMLMediaElement.prototype)) {
          // Shim the srcObject property, once, when HTMLMediaElement is found.
          Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
            get: function() {
              return this.mozSrcObject;
            },
            set: function(stream) {
              this.mozSrcObject = stream;
            }
          });
        }
      }
    },
  
    shimPeerConnection: function() {
      if (typeof window !== 'object' || !(window.RTCPeerConnection ||
          window.mozRTCPeerConnection)) {
        return; // probably media.peerconnection.enabled=false in about:config
      }
      // The RTCPeerConnection object.
      if (!window.RTCPeerConnection) {
        window.RTCPeerConnection = function(pcConfig, pcConstraints) {
          if (browserDetails.version < 38) {
            // .urls is not supported in FF < 38.
            // create RTCIceServers with a single url.
            if (pcConfig && pcConfig.iceServers) {
              var newIceServers = [];
              for (var i = 0; i < pcConfig.iceServers.length; i++) {
                var server = pcConfig.iceServers[i];
                if (server.hasOwnProperty('urls')) {
                  for (var j = 0; j < server.urls.length; j++) {
                    var newServer = {
                      url: server.urls[j]
                    };
                    if (server.urls[j].indexOf('turn') === 0) {
                      newServer.username = server.username;
                      newServer.credential = server.credential;
                    }
                    newIceServers.push(newServer);
                  }
                } else {
                  newIceServers.push(pcConfig.iceServers[i]);
                }
              }
              pcConfig.iceServers = newIceServers;
            }
          }
          return new mozRTCPeerConnection(pcConfig, pcConstraints);
        };
        window.RTCPeerConnection.prototype = mozRTCPeerConnection.prototype;
  
        // wrap static methods. Currently just generateCertificate.
        if (mozRTCPeerConnection.generateCertificate) {
          Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
            get: function() {
              return mozRTCPeerConnection.generateCertificate;
            }
          });
        }
  
        window.RTCSessionDescription = mozRTCSessionDescription;
        window.RTCIceCandidate = mozRTCIceCandidate;
      }
  
      // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
      ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
          .forEach(function(method) {
            var nativeMethod = RTCPeerConnection.prototype[method];
            RTCPeerConnection.prototype[method] = function() {
              arguments[0] = new ((method === 'addIceCandidate') ?
                  RTCIceCandidate : RTCSessionDescription)(arguments[0]);
              return nativeMethod.apply(this, arguments);
            };
          });
  
      // support for addIceCandidate(null or undefined)
      var nativeAddIceCandidate =
          RTCPeerConnection.prototype.addIceCandidate;
      RTCPeerConnection.prototype.addIceCandidate = function() {
        if (!arguments[0]) {
          if (arguments[1]) {
            arguments[1].apply(null);
          }
          return Promise.resolve();
        }
        return nativeAddIceCandidate.apply(this, arguments);
      };
  
      // shim getStats with maplike support
      var makeMapStats = function(stats) {
        var map = new Map();
        Object.keys(stats).forEach(function(key) {
          map.set(key, stats[key]);
          map[key] = stats[key];
        });
        return map;
      };
  
      var modernStatsTypes = {
        inboundrtp: 'inbound-rtp',
        outboundrtp: 'outbound-rtp',
        candidatepair: 'candidate-pair',
        localcandidate: 'local-candidate',
        remotecandidate: 'remote-candidate'
      };
  
      var nativeGetStats = RTCPeerConnection.prototype.getStats;
      RTCPeerConnection.prototype.getStats = function(selector, onSucc, onErr) {
        return nativeGetStats.apply(this, [selector || null])
          .then(function(stats) {
            if (browserDetails.version < 48) {
              stats = makeMapStats(stats);
            }
            if (browserDetails.version < 53 && !onSucc) {
              // Shim only promise getStats with spec-hyphens in type names
              // Leave callback version alone; misc old uses of forEach before Map
              try {
                stats.forEach(function(stat) {
                  stat.type = modernStatsTypes[stat.type] || stat.type;
                });
              } catch (e) {
                if (e.name !== 'TypeError') {
                  throw e;
                }
                // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
                stats.forEach(function(stat, i) {
                  stats.set(i, Object.assign({}, stat, {
                    type: modernStatsTypes[stat.type] || stat.type
                  }));
                });
              }
            }
            return stats;
          })
          .then(onSucc, onErr);
      };
    }
  };
  
  // Expose public methods.
  module.exports = {
    shimOnTrack: firefoxShim.shimOnTrack,
    shimSourceObject: firefoxShim.shimSourceObject,
    shimPeerConnection: firefoxShim.shimPeerConnection,
    shimGetUserMedia: require('./getusermedia')
  };
  
  },{"../utils":11,"./getusermedia":9}],9:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  'use strict';
  
  var logging = require('../utils').log;
  var browserDetails = require('../utils').browserDetails;
  
  // Expose public methods.
  module.exports = function() {
    var shimError_ = function(e) {
      return {
        name: {
          SecurityError: 'NotAllowedError',
          PermissionDeniedError: 'NotAllowedError'
        }[e.name] || e.name,
        message: {
          'The operation is insecure.': 'The request is not allowed by the ' +
          'user agent or the platform in the current context.'
        }[e.message] || e.message,
        constraint: e.constraint,
        toString: function() {
          return this.name + (this.message && ': ') + this.message;
        }
      };
    };
  
    // getUserMedia constraints shim.
    var getUserMedia_ = function(constraints, onSuccess, onError) {
      var constraintsToFF37_ = function(c) {
        if (typeof c !== 'object' || c.require) {
          return c;
        }
        var require = [];
        Object.keys(c).forEach(function(key) {
          if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
            return;
          }
          var r = c[key] = (typeof c[key] === 'object') ?
              c[key] : {ideal: c[key]};
          if (r.min !== undefined ||
              r.max !== undefined || r.exact !== undefined) {
            require.push(key);
          }
          if (r.exact !== undefined) {
            if (typeof r.exact === 'number') {
              r. min = r.max = r.exact;
            } else {
              c[key] = r.exact;
            }
            delete r.exact;
          }
          if (r.ideal !== undefined) {
            c.advanced = c.advanced || [];
            var oc = {};
            if (typeof r.ideal === 'number') {
              oc[key] = {min: r.ideal, max: r.ideal};
            } else {
              oc[key] = r.ideal;
            }
            c.advanced.push(oc);
            delete r.ideal;
            if (!Object.keys(r).length) {
              delete c[key];
            }
          }
        });
        if (require.length) {
          c.require = require;
        }
        return c;
      };
      constraints = JSON.parse(JSON.stringify(constraints));
      if (browserDetails.version < 38) {
        logging('spec: ' + JSON.stringify(constraints));
        if (constraints.audio) {
          constraints.audio = constraintsToFF37_(constraints.audio);
        }
        if (constraints.video) {
          constraints.video = constraintsToFF37_(constraints.video);
        }
        logging('ff37: ' + JSON.stringify(constraints));
      }
      return navigator.mozGetUserMedia(constraints, onSuccess, function(e) {
        onError(shimError_(e));
      });
    };
  
    // Returns the result of getUserMedia as a Promise.
    var getUserMediaPromise_ = function(constraints) {
      return new Promise(function(resolve, reject) {
        getUserMedia_(constraints, resolve, reject);
      });
    };
  
    // Shim for mediaDevices on older versions.
    if (!navigator.mediaDevices) {
      navigator.mediaDevices = {getUserMedia: getUserMediaPromise_,
        addEventListener: function() { },
        removeEventListener: function() { }
      };
    }
    navigator.mediaDevices.enumerateDevices =
        navigator.mediaDevices.enumerateDevices || function() {
          return new Promise(function(resolve) {
            var infos = [
              {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
              {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
            ];
            resolve(infos);
          });
        };
  
    if (browserDetails.version < 41) {
      // Work around http://bugzil.la/1169665
      var orgEnumerateDevices =
          navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
      navigator.mediaDevices.enumerateDevices = function() {
        return orgEnumerateDevices().then(undefined, function(e) {
          if (e.name === 'NotFoundError') {
            return [];
          }
          throw e;
        });
      };
    }
    if (browserDetails.version < 49) {
      var origGetUserMedia = navigator.mediaDevices.getUserMedia.
          bind(navigator.mediaDevices);
      navigator.mediaDevices.getUserMedia = function(c) {
        return origGetUserMedia(c).then(function(stream) {
          // Work around https://bugzil.la/802326
          if (c.audio && !stream.getAudioTracks().length ||
              c.video && !stream.getVideoTracks().length) {
            stream.getTracks().forEach(function(track) {
              track.stop();
            });
            throw new DOMException('The object can not be found here.',
                                   'NotFoundError');
          }
          return stream;
        }, function(e) {
          return Promise.reject(shimError_(e));
        });
      };
    }
    navigator.getUserMedia = function(constraints, onSuccess, onError) {
      if (browserDetails.version < 44) {
        return getUserMedia_(constraints, onSuccess, onError);
      }
      // Replace Firefox 44+'s deprecation warning with unprefixed version.
      console.warn('navigator.getUserMedia has been replaced by ' +
                   'navigator.mediaDevices.getUserMedia');
      navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
    };
  };
  
  },{"../utils":11}],10:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
  'use strict';
  var safariShim = {
    // TODO: DrAlex, should be here, double check against LayoutTests
    // shimOnTrack: function() { },
  
    // TODO: once the back-end for the mac port is done, add.
    // TODO: check for webkitGTK+
    // shimPeerConnection: function() { },
  
    shimGetUserMedia: function() {
      navigator.getUserMedia = navigator.webkitGetUserMedia;
    }
  };
  
  // Expose public methods.
  module.exports = {
    shimGetUserMedia: safariShim.shimGetUserMedia
    // TODO
    // shimOnTrack: safariShim.shimOnTrack,
    // shimPeerConnection: safariShim.shimPeerConnection
  };
  
  },{}],11:[function(require,module,exports){
  /*
   *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree.
   */
   /* eslint-env node */
  'use strict';
  
  var logDisabled_ = true;
  
  // Utility methods.
  var utils = {
    disableLog: function(bool) {
      if (typeof bool !== 'boolean') {
        return new Error('Argument type: ' + typeof bool +
            '. Please use a boolean.');
      }
      logDisabled_ = bool;
      return (bool) ? 'adapter.js logging disabled' :
          'adapter.js logging enabled';
    },
  
    log: function() {
      if (typeof window === 'object') {
        if (logDisabled_) {
          return;
        }
        if (typeof console !== 'undefined' && typeof console.log === 'function') {
          console.log.apply(console, arguments);
        }
      }
    },
  
    /**
     * Extract browser version out of the provided user agent string.
     *
     * @param {!string} uastring userAgent string.
     * @param {!string} expr Regular expression used as match criteria.
     * @param {!number} pos position in the version string to be returned.
     * @return {!number} browser version.
     */
    extractVersion: function(uastring, expr, pos) {
      var match = uastring.match(expr);
      return match && match.length >= pos && parseInt(match[pos], 10);
    },
  
    /**
     * Browser detector.
     *
     * @return {object} result containing browser and version
     *     properties.
     */
    detectBrowser: function() {
      // Returned result object.
      var result = {};
      result.browser = null;
      result.version = null;
  
      // Fail early if it's not a browser
      if (typeof window === 'undefined' || !window.navigator) {
        result.browser = 'Not a browser.';
        return result;
      }
  
      // Firefox.
      if (navigator.mozGetUserMedia) {
        result.browser = 'firefox';
        result.version = this.extractVersion(navigator.userAgent,
            /Firefox\/([0-9]+)\./, 1);
  
      // all webkit-based browsers
      } else if (navigator.webkitGetUserMedia) {
        // Chrome, Chromium, Webview, Opera, all use the chrome shim for now
        if (window.webkitRTCPeerConnection) {
          result.browser = 'chrome';
          result.version = this.extractVersion(navigator.userAgent,
            /Chrom(e|ium)\/([0-9]+)\./, 2);
  
        // Safari or unknown webkit-based
        // for the time being Safari has support for MediaStreams but not webRTC
        } else {
          // Safari UA substrings of interest for reference:
          // - webkit version:           AppleWebKit/602.1.25 (also used in Op,Cr)
          // - safari UI version:        Version/9.0.3 (unique to Safari)
          // - safari UI webkit version: Safari/601.4.4 (also used in Op,Cr)
          //
          // if the webkit version and safari UI webkit versions are equals,
          // ... this is a stable version.
          //
          // only the internal webkit version is important today to know if
          // media streams are supported
          //
          if (navigator.userAgent.match(/Version\/(\d+).(\d+)/)) {
            result.browser = 'safari';
            result.version = this.extractVersion(navigator.userAgent,
              /AppleWebKit\/([0-9]+)\./, 1);
  
          // unknown webkit-based browser
          } else {
            result.browser = 'Unsupported webkit-based browser ' +
                'with GUM support but no WebRTC support.';
            return result;
          }
        }
  
      // Edge.
      } else if (navigator.mediaDevices &&
          navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) {
        result.browser = 'edge';
        result.version = this.extractVersion(navigator.userAgent,
            /Edge\/(\d+).(\d+)$/, 2);
  
      // Default fallthrough: not supported.
      } else {
        result.browser = 'Not a supported browser.';
        return result;
      }
  
      return result;
    },
  
    // shimCreateObjectURL must be called before shimSourceObject to avoid loop.
  
    shimCreateObjectURL: function() {
      if (!(typeof window === 'object' && window.HTMLMediaElement &&
            'srcObject' in window.HTMLMediaElement.prototype)) {
        // Only shim CreateObjectURL using srcObject if srcObject exists.
        return undefined;
      }
  
      var nativeCreateObjectURL = URL.createObjectURL.bind(URL);
      var nativeRevokeObjectURL = URL.revokeObjectURL.bind(URL);
      var streams = new Map(), newId = 0;
  
      URL.createObjectURL = function(stream) {
        if ('getTracks' in stream) {
          var url = 'polyblob:' + (++newId);
          streams.set(url, stream);
          console.log('URL.createObjectURL(stream) is deprecated! ' +
                      'Use elem.srcObject = stream instead!');
          return url;
        }
        return nativeCreateObjectURL(stream);
      };
      URL.revokeObjectURL = function(url) {
        nativeRevokeObjectURL(url);
        streams.delete(url);
      };
  
      var dsc = Object.getOwnPropertyDescriptor(window.HTMLMediaElement.prototype,
                                                'src');
      Object.defineProperty(window.HTMLMediaElement.prototype, 'src', {
        get: function() {
          return dsc.get.apply(this);
        },
        set: function(url) {
          this.srcObject = streams.get(url) || null;
          return dsc.set.apply(this, [url]);
        }
      });
    }
  };
  
  // Export.
  module.exports = {
    log: utils.log,
    disableLog: utils.disableLog,
    browserDetails: utils.detectBrowser(),
    extractVersion: utils.extractVersion,
    shimCreateObjectURL: utils.shimCreateObjectURL
  };
  
  },{}],12:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 PT Inovação e Sistemas SA
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 INESC-ID
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 QUOBIS NETWORKS SL
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 ORANGE SA
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 Deutsche Telekom AG
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 Apizee
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Licensed under the Apache License, Version 2.0 (the "License");
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * you may not use this file except in compliance with the License.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * You may obtain a copy of the License at
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        *   http://www.apache.org/licenses/LICENSE-2.0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        *
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * Unless required by applicable law or agreed to in writing, software
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * distributed under the License is distributed on an "AS IS" BASIS,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * See the License for the specific language governing permissions and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        * limitations under the License.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        **/
  
  require('webrtc-adapter');
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  /**
    The ConnectionController has a generic design so that it can be used in both stubs.
    It manages a single DataChannel, it is not requesting access to media input, i.e.
    does not have audio/video streams.
  **/
  var ConnectionController = function () {
    function ConnectionController(myUrl, syncher, configuration, caller) {
      _classCallCheck(this, ConnectionController);
  
      if (!myUrl) throw new Error('The own url (myUrl) is a needed parameter');
      if (!syncher) throw new Error('The syncher is a needed parameter');
      if (!configuration) throw new Error('The configuration is a needed parameter');
  
      this._domain = this._divideURL(myUrl)["domain"];
      this._objectDescURL = 'hyperty-catalogue://catalogue.' + this._domain + '/.well-known/dataschema/Connection';
  
      this._myUrl = myUrl;
      this._syncher = syncher;
      this._configuration = configuration;
      this._caller = caller;
      this._dataObjectObserver;
      this._dataObjectReporter;
      this._peerUrl;
      this._dataChannel;
      this._onStatusUpdate;
      this._remoteRuntimeURL;
  
      this._peerConnection = this._createPeerConnection();
    }
  
    //create a peer connection with its event handlers
  
  
    _createClass(ConnectionController, [{
      key: '_createPeerConnection',
      value: function _createPeerConnection() {
        var _this = this;
  
        var pc = this._peerConnection;
        if (!pc) {
          pc = new RTCPeerConnection(this._configuration);
          console.log("[P2P-ConnectionController]: created PeerConnection");
  
          // add handler for datachannel creation from peer side
          pc.ondatachannel = function (event) {
            console.log("[P2P-ConnectionController]: ondatachannel -> remote side has created a datachannel");
            _this._dataChannel = event.channel;
            _this._addDataChannelListeners();
          };
  
          // event handler for local ice candidates
          pc.onicecandidate = function (e) {
            console.log("[P2P-ConnectionController]: icecandidateevent occured: ", e);
            if (!e.candidate) return;
            var icecandidate = {
              type: 'candidate',
              candidate: e.candidate.candidate,
              sdpMid: e.candidate.sdpMid,
              sdpMLineIndex: e.candidate.sdpMLineIndex
            };
            // send candidate to remote peer by pushing it to the reporter object
            _this._dataObjectReporter.data.iceCandidates.push(icecandidate);
          };
        }
        return pc;
      }
  
      /**
      React to the given invitation event by subscribing to the provided invitationEvent.url.
      **/
  
    }, {
      key: 'observe',
      value: function observe(invitationEvent) {
        var _this2 = this;
  
        this._peerUrl = invitationEvent.from;
        this._remoteRuntimeURL = invitationEvent.value.runtimeURL;
  
        return new Promise(function (resolve, reject) {
  
          _this2._syncher.subscribe(_this2._objectDescURL, invitationEvent.url).then(function (dataObjectObserver) {
            console.info('+[P2P-ConnectionController] got Data Object Observer', dataObjectObserver);
            _this2._setupObserver(dataObjectObserver);
            resolve();
          }).catch(function (reason) {
            console.error(reason);
            reject();
          });
        });
      }
  
      /**
      Creates a syncher object and invite the given peerUrl to subscribe for it.
      Also creates the local offer, performs setLocalDescription and publishes the offer via the reporter object.
      **/
  
    }, {
      key: 'report',
      value: function report(peerUrl, ownRuntimeUrl) {
        var _this3 = this;
  
        if (!this._peerUrl) this._peerUrl = peerUrl;
        return new Promise(function (resolve, reject) {
  
          //  if we are the caller (i.e. no reporter object present yet, initalize the creation of the DataChannel)
          if (_this3._caller) {
            console.log("[P2P-ConnectionController]: we are in caller role --> createDataChannel ...");
            _this3._dataChannel = _this3._peerConnection.createDataChannel("P2PChannel", { reliable: false });
            console.log("P2P: datachannel object", _this3._dataChannel);
            _this3._addDataChannelListeners();
          }
  
          // initial data for reporter sync object
          var dataObject = {
            name: "P2PConnection",
            status: "",
            owner: _this3._myUrl,
            runtimeURL: ownRuntimeUrl, // put the own runtimeURL to the dataObject (as discussed with Paulo)
            connectionDescription: {},
            iceCandidates: []
          };
          // ensure this the objReporter object is created before we create the offer
          _this3._syncher.create(_this3._objectDescURL, [_this3._peerUrl], dataObject).then(function (objReporter) {
            console.info('[P2P-ConnectionController] Created WebRTC Object Reporter', objReporter);
  
            _this3._dataObjectReporter = objReporter;
            _this3._dataObjectReporter.onSubscription(function (event) {
              event.accept(); // all subscription requested are accepted
            });
  
            var constraints = {
              offerToReceiveAudio: false,
              offerToReceiveVideo: false
            };
            // either invoke createOffer or createAnswer, depending on the roles
            var sdpPromise = _this3._caller ? _this3._peerConnection.createOffer(constraints) : _this3._peerConnection.createAnswer();
            sdpPromise.then(function (sdp) {
              console.log("[P2P-ConnectionController] SDP created", sdp);
              _this3._peerConnection.setLocalDescription(new RTCSessionDescription(sdp), function () {
                console.info('[P2P-ConnectionController] localDescription set successfully');
                _this3._dataObjectReporter.data.connectionDescription = sdp;
                resolve();
              }).catch(function (e) {
                reject("setting of localDescription failed: ", e);
              });
            }).catch(function (reason) {
              console.error(reason);
              reject(reason);
            });
          });
        });
      }
    }, {
      key: 'onMessage',
      value: function onMessage(callback) {
        // add the message callback
        this._onDataChannelMessage = callback;
      }
    }, {
      key: 'onStatusUpdate',
      value: function onStatusUpdate(callback) {
        // add a connection status update callback
        this._onStatusUpdate = callback;
      }
    }, {
      key: 'sendMessage',
      value: function sendMessage(m) {
        // todo: only send if data channel is connected
        console.log("[P2P-ConnectionController] --> outgoing msg: ", m);
        this._dataChannel.send(m);
      }
    }, {
      key: 'cleanup',
      value: function cleanup() {
        delete this._dataObjectReporter;
        delete this._dataObjectObserver;
        if (this._dataChannel) this._dataChannel.close();
        if (this._peerConnection) this._peerConnection.close();
        this._dataChannel = null;
        this._peerConnection = null;
      }
    }, {
      key: '_addDataChannelListeners',
      value: function _addDataChannelListeners() {
        var _this4 = this;
  
        this._dataChannel.onopen = function () {
          _this4._onDataChannelOpen();
        };
        this._dataChannel.onerror = function (e) {
          _this4._onDataChannelError(e);
        };
        this._dataChannel.onmessage = function (m) {
          console.log("[P2P-ConnectionController] <-- incoming msg: ", m);
          if (_this4._onDataChannelMessage) _this4._onDataChannelMessage(m);
        };
        this._dataChannel.onclose = function () {
          _this4._onDataChannelClose();
        };
      }
    }, {
      key: '_setupObserver',
      value: function _setupObserver(dataObjectObserver) {
        var _this5 = this;
  
        this._dataObjectObserver = dataObjectObserver;
  
        var peerData = this._dataObjectObserver.data;
        console.info("[P2P-ConnectionController]: _setupObserver Peer Data:", peerData);
  
        if (peerData.hasOwnProperty('connectionDescription')) {
          this._processPeerInformation(peerData.connectionDescription);
        }
  
        if (peerData.hasOwnProperty('iceCandidates')) {
          peerData.iceCandidates.forEach(function (ice) {
            console.log("[P2P-ConnectionController]: handleObserverObject for ice", ice);
            _this5._processPeerInformation(ice);
          });
        }
  
        // setup listener for future changes on the observed data object
        dataObjectObserver.onChange('*', function (event) {
          console.debug('[P2P-ConnectionController]: Observer on change message: ', event);
          // we need to process the answer from event.data and the candidates which might trickle
          // from event.data[0]
          if (event.data[0]) {
            // [0] this does the trick when ice candidates are trickling ;)
            console.log('>>event.data[0]', event.data[0]);
            _this5._processPeerInformation(event.data[0]);
          } else {
            console.log('[P2P-ConnectionController]: >>event', event);
            _this5._processPeerInformation(event.data);
          }
        });
      }
    }, {
      key: '_processPeerInformation',
      value: function _processPeerInformation(data) {
        console.info("[P2P-ConnectionController]: processPeerInformation: ", JSON.stringify(data));
        if (!this._peerConnection) {
          console.info("[P2P-ConnectionController]: processPeerInformation: no PeerConnection existing --> maybe in disconnecting process. --> ignoring this update");
          return;
        }
  
        if (data.type === 'offer' || data.type === 'answer') {
          console.info('[P2P-ConnectionController]: Process Connection Description: ', data);
          this._peerConnection.setRemoteDescription(new RTCSessionDescription(data)).then(function () {
            console.log("[P2P-ConnectionController]: remote success");
          }).catch(function (e) {
            console.log("[P2P-ConnectionController]: remote error: ", e);
          });
        }
  
        if (data.candidate) {
          console.info('Process Ice Candidate: ', data);
          this._peerConnection.addIceCandidate(new RTCIceCandidate({
            candidate: data.candidate
          }));
        }
      }
    }, {
      key: '_onDataChannelOpen',
      value: function _onDataChannelOpen() {
        console.log('[P2P-ConnectionController] DataChannel opened');
        if (this._onStatusUpdate) this._onStatusUpdate("live", undefined, this._remoteRuntimeURL);
      }
    }, {
      key: '_onDataChannelError',
      value: function _onDataChannelError(e) {
        console.log('[P2P-ConnectionController] DataChannel error: ', e);
        if (this._onStatusUpdate) this._onStatusUpdate("disconnected", "" + e);
      }
    }, {
      key: '_onDataChannelClose',
      value: function _onDataChannelClose() {
        console.log('[P2P-ConnectionController] DataChannel closed: ');
        if (this._onStatusUpdate) this._onStatusUpdate("disconnected", "closed");
      }
  
      /**
       * Divide an url in type, domain and identity
       * @param  {URL.URL} url - url address
       * @return {divideURL} the result of divideURL
       */
  
    }, {
      key: '_divideURL',
      value: function _divideURL(url) {
  
        // let re = /([a-zA-Z-]*)?:\/\/(?:\.)?([-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b)*(\/[\/\d\w\.-]*)*(?:[\?])*(.+)*/gi;
        var re = /([a-zA-Z-]*):\/\/(?:\.)?([-a-zA-Z0-9@:%._\+~#=]{2,256})([-a-zA-Z0-9@:%._\+~#=\/]*)/gi;
        var subst = '$1,$2,$3';
        var parts = url.replace(re, subst).split(',');
  
        // If the url has no protocol, the default protocol set is https
        if (parts[0] === url) {
          parts[0] = 'https';
          parts[1] = url;
        }
  
        var result = {
          type: parts[0],
          domain: parts[1],
          identity: parts[2]
        };
  
        return result;
      }
    }]);
  
    return ConnectionController;
  }();
  
  exports.default = ConnectionController;
  module.exports = exports['default'];
  
  },{"webrtc-adapter":3}],13:[function(require,module,exports){
  'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  /**
  * Copyright 2016 PT Inovação e Sistemas SA
  * Copyright 2016 INESC-ID
  * Copyright 2016 QUOBIS NETWORKS SL
  * Copyright 2016 FRAUNHOFER-GESELLSCHAFT ZUR FOERDERUNG DER ANGEWANDTEN FORSCHUNG E.V
  * Copyright 2016 ORANGE SA
  * Copyright 2016 Deutsche Telekom AG
  * Copyright 2016 Apizee
  * Copyright 2016 TECHNISCHE UNIVERSITAT BERLIN
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *   http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  **/
  
  exports.default = activate;
  
  var _Syncher = require('service-framework/dist/Syncher');
  
  var _ConnectionController = require('./ConnectionController');
  
  var _ConnectionController2 = _interopRequireDefault(_ConnectionController);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  // TODO: integrate the status eventing
  
  /**
   * ProtoStub Interface
   */
  var P2PRequesterStub = function () {
  
    /**
     * Initialise the protocol stub including as input parameters its allocated
     * component runtime url, the runtime BUS postMessage function to be invoked
     * on messages received by the protocol stub and required configuration retrieved from protocolStub descriptor.
     * @param  {URL.runtimeProtoStubURL}                   runtimeProtoStubURL runtimeProtoSubURL
     * @param  {Message.Message}                           busPostMessage     configuration
     * @param  {ProtoStubDescriptor.ConfigurationDataList} configuration      configuration
     */
    function P2PRequesterStub(runtimeProtoStubURL, miniBus, configuration) {
      var _this = this;
  
      _classCallCheck(this, P2PRequesterStub);
  
      if (!runtimeProtoStubURL) throw new Error('The runtimeProtoStubURL is a required parameter');
      if (!miniBus) throw new Error('The bus is a required parameter');
      if (!configuration) throw new Error('The configuration is a required parameter');
      // if (!configuration.p2pHandler) throw new Error('The p2pHandler is a required attribute in the configuration parameter');
  
      console.log('+[P2PRequesterStub.constructor] config is: ', configuration);
      this._runtimeProtoStubURL = runtimeProtoStubURL;
      this._runtimeURL = configuration.runtimeURL;
      this._remoteRuntimeURL = configuration.remoteRuntimeURL; // required for status events
      this._configuration = configuration;
      this._bus = miniBus;
      this._bus.addListener('*', function (msg) {
        _this._sendChannelMsg(msg);
      });
  
      this._syncher = new _Syncher.Syncher(runtimeProtoStubURL, miniBus, configuration);
      this._connectionController = new _ConnectionController2.default(this._runtimeProtoStubURL, this._syncher, this._configuration, true);
      this._connectionController.onStatusUpdate(function (status, reason) {
        _this._sendStatus(status, reason);
      });
  
      this._syncher.onNotification(function (event) {
        console.log('+[P2PRequesterStub] On Syncher Notification: ', event);
        event.ack(200);
  
        switch (event.type) {
  
          case 'create':
            // incoming observe invitation from peer
            if (_this._connectionController) {
              _this._connectionController.observe(event).then(function () {
                console.log("+[P2PRequesterStub] observer created ");
              });
            }
            break;
  
          case 'delete':
            // TODO: question regarding code in Connector: --> there it deletes all controllers --> why?
            console.log("+[P2PRequesterStub] deleting connection handler for " + event.from);
  
            disconnect();
            break;
  
          default:
        }
      });
  
      this._sendStatus("create");
  
      // the target handler stub url must be present in the configuration as "p2pHandler" attribute
      if (this._configuration.p2pHandler) this.connect(this._configuration.p2pHandler);
    }
  
    _createClass(P2PRequesterStub, [{
      key: 'connect',
      value: function connect(handlerURL) {
        var _this2 = this;
  
        this._connectionController.report(handlerURL, this._runtimeURL).then(function () {
          // send "in-progress" event, if the syncher.create was done
          _this2._sendStatus("in-progress");
          _this2._connectionController.onMessage(function (m) {
            console.log("+[P2PRequesterStub] onMessage: ", m);
            _this2._deliver(m);
          });
          console.log("+[P2PRequesterStub] setup reporter object successfully");
        });
      }
  
      /**
       * To disconnect the protocol stub.
       */
  
    }, {
      key: 'disconnect',
      value: function disconnect() {
        if (this._connectionController) {
          this._connectionController.cleanup();
          this._connectionController = null;
        }
      }
    }, {
      key: '_sendChannelMsg',
      value: function _sendChannelMsg(msg) {
        if (this._filter(msg)) {
          if (this._connectionController) {
            this._connectionController.sendMessage(JSON.stringify(msg));
          }
        }
      }
    }, {
      key: '_sendStatus',
      value: function _sendStatus(value, reason) {
        var msg = {
          type: 'update',
          from: this._runtimeProtoStubURL,
          to: this._runtimeProtoStubURL + '/status',
          body: {
            value: value,
            resource: this._remoteRuntimeURL
          }
        };
        if (reason) {
          msg.body.desc = reason;
        }
        this._bus.postMessage(msg);
        console.log("+[P2PrequesterStub] sending status update: ", msg);
      }
  
      /**
       * Filter method that should be used for every messages in direction: Protostub -> MessageNode
       * @param  {Message} msg Original message from the MessageBus
       * @return {boolean} true if it's to be deliver in the MessageNode
       */
  
    }, {
      key: '_filter',
      value: function _filter(msg) {
        if (msg.body && msg.body.via === this._runtimeProtoStubURL) return false;
        return true;
      }
  
      /**
       * Method that should be used to deliver the message in direction: Protostub -> MessageBus (core)
       * @param  {Message} msg Original message from the MessageNode
       */
  
    }, {
      key: '_deliver',
      value: function _deliver(msg) {
        console.log("+[P2PrequesterStub] posting message to msg bus: ", msg);
  
        var message = JSON.parse(msg.data);
  
        if (!message.body) msg.body = {};
  
        message.body.via = this._runtimeProtoStubURL;
        this._bus.postMessage(message);
      }
    }]);
  
    return P2PRequesterStub;
  }();
  
  function activate(url, bus, config) {
    return {
      name: 'P2PRequesterStub',
      instance: new P2PRequesterStub(url, bus, config)
    };
  }
  module.exports = exports['default'];
  
  },{"./ConnectionController":12,"service-framework/dist/Syncher":2}]},{},[13])(13)
  });