
// INLINED /Users/user/git/lively.vm/node_modules/babel-regenerator-runtime/runtime.js
/**
 * Copyright (c) 2014, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * https://raw.github.com/facebook/regenerator/master/LICENSE file. An
 * additional grant of patent rights can be found in the PATENTS file in
 * the same directory.
 */

!(function(global) {
  "use strict";

  var hasOwn = Object.prototype.hasOwnProperty;
  var undefined; // More compressible than void 0.
  var iteratorSymbol =
    typeof Symbol === "function" && Symbol.iterator || "@@iterator";

  var inModule = typeof module === "object";
  var runtime = global.regeneratorRuntime;
  if (runtime) {
    if (inModule) {
      // If regeneratorRuntime is defined globally and we're in a module,
      // make the exports object identical to regeneratorRuntime.
      module.exports = runtime;
    }
    // Don't bother evaluating the rest of this file if the runtime was
    // already defined globally.
    return;
  }

  // Define the runtime globally (as expected by generated code) as either
  // module.exports (if we're in a module) or a new, empty object.
  runtime = global.regeneratorRuntime = inModule ? module.exports : {};

  function wrap(innerFn, outerFn, self, tryLocsList) {
    // If outerFn provided, then outerFn.prototype instanceof Generator.
    var generator = Object.create((outerFn || Generator).prototype);
    var context = new Context(tryLocsList || []);

    // The ._invoke method unifies the implementations of the .next,
    // .throw, and .return methods.
    generator._invoke = makeInvokeMethod(innerFn, self, context);

    return generator;
  }
  runtime.wrap = wrap;

  // Try/catch helper to minimize deoptimizations. Returns a completion
  // record like context.tryEntries[i].completion. This interface could
  // have been (and was previously) designed to take a closure to be
  // invoked without arguments, but in all the cases we care about we
  // already have an existing method we want to call, so there's no need
  // to create a new function object. We can even get away with assuming
  // the method takes exactly one argument, since that happens to be true
  // in every case, so we don't have to touch the arguments object. The
  // only additional allocation required is the completion record, which
  // has a stable shape and so hopefully should be cheap to allocate.
  function tryCatch(fn, obj, arg) {
    try {
      return { type: "normal", arg: fn.call(obj, arg) };
    } catch (err) {
      return { type: "throw", arg: err };
    }
  }

  var GenStateSuspendedStart = "suspendedStart";
  var GenStateSuspendedYield = "suspendedYield";
  var GenStateExecuting = "executing";
  var GenStateCompleted = "completed";

  // Returning this object from the innerFn has the same effect as
  // breaking out of the dispatch switch statement.
  var ContinueSentinel = {};

  // Dummy constructor functions that we use as the .constructor and
  // .constructor.prototype properties for functions that return Generator
  // objects. For full spec compliance, you may wish to configure your
  // minifier not to mangle the names of these two functions.
  function Generator() {}
  function GeneratorFunction() {}
  function GeneratorFunctionPrototype() {}

  var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype;
  GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
  GeneratorFunctionPrototype.constructor = GeneratorFunction;
  GeneratorFunction.displayName = "GeneratorFunction";

  // Helper for defining the .next, .throw, and .return methods of the
  // Iterator interface in terms of a single ._invoke method.
  function defineIteratorMethods(prototype) {
    ["next", "throw", "return"].forEach(function(method) {
      prototype[method] = function(arg) {
        return this._invoke(method, arg);
      };
    });
  }

  runtime.isGeneratorFunction = function(genFun) {
    var ctor = typeof genFun === "function" && genFun.constructor;
    return ctor
      ? ctor === GeneratorFunction ||
        // For the native GeneratorFunction constructor, the best we can
        // do is to check its .name property.
        (ctor.displayName || ctor.name) === "GeneratorFunction"
      : false;
  };

  runtime.mark = function(genFun) {
    if (Object.setPrototypeOf) {
      Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
    } else {
      genFun.__proto__ = GeneratorFunctionPrototype;
    }
    genFun.prototype = Object.create(Gp);
    return genFun;
  };

  // Within the body of any async function, `await x` is transformed to
  // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
  // `value instanceof AwaitArgument` to determine if the yielded value is
  // meant to be awaited. Some may consider the name of this method too
  // cutesy, but they are curmudgeons.
  runtime.awrap = function(arg) {
    return new AwaitArgument(arg);
  };

  function AwaitArgument(arg) {
    this.arg = arg;
  }

  function AsyncIterator(generator) {
    // This invoke function is written in a style that assumes some
    // calling function (or Promise) will handle exceptions.
    function invoke(method, arg) {
      var result = generator[method](arg);
      var value = result.value;
      return value instanceof AwaitArgument
        ? Promise.resolve(value.arg).then(invokeNext, invokeThrow)
        : Promise.resolve(value).then(function(unwrapped) {
            // When a yielded Promise is resolved, its final value becomes
            // the .value of the Promise<{value,done}> result for the
            // current iteration. If the Promise is rejected, however, the
            // result for this iteration will be rejected with the same
            // reason. Note that rejections of yielded Promises are not
            // thrown back into the generator function, as is the case
            // when an awaited Promise is rejected. This difference in
            // behavior between yield and await is important, because it
            // allows the consumer to decide what to do with the yielded
            // rejection (swallow it and continue, manually .throw it back
            // into the generator, abandon iteration, whatever). With
            // await, by contrast, there is no opportunity to examine the
            // rejection reason outside the generator function, so the
            // only option is to throw it from the await expression, and
            // let the generator function handle the exception.
            result.value = unwrapped;
            return result;
          });
    }

    if (typeof process === "object" && process.domain) {
      invoke = process.domain.bind(invoke);
    }

    var invokeNext = invoke.bind(generator, "next");
    var invokeThrow = invoke.bind(generator, "throw");
    var invokeReturn = invoke.bind(generator, "return");
    var previousPromise;

    function enqueue(method, arg) {
      function callInvokeWithMethodAndArg() {
        return invoke(method, arg);
      }

      return previousPromise =
        // If enqueue has been called before, then we want to wait until
        // all previous Promises have been resolved before calling invoke,
        // so that results are always delivered in the correct order. If
        // enqueue has not been called before, then it is important to
        // call invoke immediately, without waiting on a callback to fire,
        // so that the async generator function has the opportunity to do
        // any necessary setup in a predictable way. This predictability
        // is why the Promise constructor synchronously invokes its
        // executor callback, and why async functions synchronously
        // execute code before the first await. Since we implement simple
        // async functions in terms of async generators, it is especially
        // important to get this right, even though it requires care.
        previousPromise ? previousPromise.then(
          callInvokeWithMethodAndArg,
          // Avoid propagating failures to Promises returned by later
          // invocations of the iterator.
          callInvokeWithMethodAndArg
        ) : new Promise(function (resolve) {
          resolve(callInvokeWithMethodAndArg());
        });
    }

    // Define the unified helper method that is used to implement .next,
    // .throw, and .return (see defineIteratorMethods).
    this._invoke = enqueue;
  }

  defineIteratorMethods(AsyncIterator.prototype);

  // Note that simple async functions are implemented on top of
  // AsyncIterator objects; they just return a Promise for the value of
  // the final result produced by the iterator.
  runtime.async = function(innerFn, outerFn, self, tryLocsList) {
    var iter = new AsyncIterator(
      wrap(innerFn, outerFn, self, tryLocsList)
    );

    return runtime.isGeneratorFunction(outerFn)
      ? iter // If outerFn is a generator, return the full iterator.
      : iter.next().then(function(result) {
          return result.done ? result.value : iter.next();
        });
  };

  function makeInvokeMethod(innerFn, self, context) {
    var state = GenStateSuspendedStart;

    return function invoke(method, arg) {
      if (state === GenStateExecuting) {
        throw new Error("Generator is already running");
      }

      if (state === GenStateCompleted) {
        if (method === "throw") {
          throw arg;
        }

        // Be forgiving, per 25.3.3.3.3 of the spec:
        // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
        return doneResult();
      }

      while (true) {
        var delegate = context.delegate;
        if (delegate) {
          if (method === "return" ||
              (method === "throw" && delegate.iterator[method] === undefined)) {
            // A return or throw (when the delegate iterator has no throw
            // method) always terminates the yield* loop.
            context.delegate = null;

            // If the delegate iterator has a return method, give it a
            // chance to clean up.
            var returnMethod = delegate.iterator["return"];
            if (returnMethod) {
              var record = tryCatch(returnMethod, delegate.iterator, arg);
              if (record.type === "throw") {
                // If the return method threw an exception, let that
                // exception prevail over the original return or throw.
                method = "throw";
                arg = record.arg;
                continue;
              }
            }

            if (method === "return") {
              // Continue with the outer return, now that the delegate
              // iterator has been terminated.
              continue;
            }
          }

          var record = tryCatch(
            delegate.iterator[method],
            delegate.iterator,
            arg
          );

          if (record.type === "throw") {
            context.delegate = null;

            // Like returning generator.throw(uncaught), but without the
            // overhead of an extra function call.
            method = "throw";
            arg = record.arg;
            continue;
          }

          // Delegate generator ran and handled its own exceptions so
          // regardless of what the method was, we continue as if it is
          // "next" with an undefined arg.
          method = "next";
          arg = undefined;

          var info = record.arg;
          if (info.done) {
            context[delegate.resultName] = info.value;
            context.next = delegate.nextLoc;
          } else {
            state = GenStateSuspendedYield;
            return info;
          }

          context.delegate = null;
        }

        if (method === "next") {
          context._sent = arg;

          if (state === GenStateSuspendedYield) {
            context.sent = arg;
          } else {
            context.sent = undefined;
          }
        } else if (method === "throw") {
          if (state === GenStateSuspendedStart) {
            state = GenStateCompleted;
            throw arg;
          }

          if (context.dispatchException(arg)) {
            // If the dispatched exception was caught by a catch block,
            // then let that catch block handle the exception normally.
            method = "next";
            arg = undefined;
          }

        } else if (method === "return") {
          context.abrupt("return", arg);
        }

        state = GenStateExecuting;

        var record = tryCatch(innerFn, self, context);
        if (record.type === "normal") {
          // If an exception is thrown from innerFn, we leave state ===
          // GenStateExecuting and loop back for another invocation.
          state = context.done
            ? GenStateCompleted
            : GenStateSuspendedYield;

          var info = {
            value: record.arg,
            done: context.done
          };

          if (record.arg === ContinueSentinel) {
            if (context.delegate && method === "next") {
              // Deliberately forget the last sent value so that we don't
              // accidentally pass it on to the delegate.
              arg = undefined;
            }
          } else {
            return info;
          }

        } else if (record.type === "throw") {
          state = GenStateCompleted;
          // Dispatch the exception by looping back around to the
          // context.dispatchException(arg) call above.
          method = "throw";
          arg = record.arg;
        }
      }
    };
  }

  // Define Generator.prototype.{next,throw,return} in terms of the
  // unified ._invoke helper method.
  defineIteratorMethods(Gp);

  Gp[iteratorSymbol] = function() {
    return this;
  };

  Gp.toString = function() {
    return "[object Generator]";
  };

  function pushTryEntry(locs) {
    var entry = { tryLoc: locs[0] };

    if (1 in locs) {
      entry.catchLoc = locs[1];
    }

    if (2 in locs) {
      entry.finallyLoc = locs[2];
      entry.afterLoc = locs[3];
    }

    this.tryEntries.push(entry);
  }

  function resetTryEntry(entry) {
    var record = entry.completion || {};
    record.type = "normal";
    delete record.arg;
    entry.completion = record;
  }

  function Context(tryLocsList) {
    // The root entry object (effectively a try statement without a catch
    // or a finally block) gives us a place to store values thrown from
    // locations where there is no enclosing try statement.
    this.tryEntries = [{ tryLoc: "root" }];
    tryLocsList.forEach(pushTryEntry, this);
    this.reset(true);
  }

  runtime.keys = function(object) {
    var keys = [];
    for (var key in object) {
      keys.push(key);
    }
    keys.reverse();

    // Rather than returning an object with a next method, we keep
    // things simple and return the next function itself.
    return function next() {
      while (keys.length) {
        var key = keys.pop();
        if (key in object) {
          next.value = key;
          next.done = false;
          return next;
        }
      }

      // To avoid creating an additional object, we just hang the .value
      // and .done properties off the next function object itself. This
      // also ensures that the minifier will not anonymize the function.
      next.done = true;
      return next;
    };
  };

  function values(iterable) {
    if (iterable) {
      var iteratorMethod = iterable[iteratorSymbol];
      if (iteratorMethod) {
        return iteratorMethod.call(iterable);
      }

      if (typeof iterable.next === "function") {
        return iterable;
      }

      if (!isNaN(iterable.length)) {
        var i = -1, next = function next() {
          while (++i < iterable.length) {
            if (hasOwn.call(iterable, i)) {
              next.value = iterable[i];
              next.done = false;
              return next;
            }
          }

          next.value = undefined;
          next.done = true;

          return next;
        };

        return next.next = next;
      }
    }

    // Return an iterator with no values.
    return { next: doneResult };
  }
  runtime.values = values;

  function doneResult() {
    return { value: undefined, done: true };
  }

  Context.prototype = {
    constructor: Context,

    reset: function(skipTempReset) {
      this.prev = 0;
      this.next = 0;
      this.sent = undefined;
      this.done = false;
      this.delegate = null;

      this.tryEntries.forEach(resetTryEntry);

      if (!skipTempReset) {
        for (var name in this) {
          // Not sure about the optimal order of these conditions:
          if (name.charAt(0) === "t" &&
              hasOwn.call(this, name) &&
              !isNaN(+name.slice(1))) {
            this[name] = undefined;
          }
        }
      }
    },

    stop: function() {
      this.done = true;

      var rootEntry = this.tryEntries[0];
      var rootRecord = rootEntry.completion;
      if (rootRecord.type === "throw") {
        throw rootRecord.arg;
      }

      return this.rval;
    },

    dispatchException: function(exception) {
      if (this.done) {
        throw exception;
      }

      var context = this;
      function handle(loc, caught) {
        record.type = "throw";
        record.arg = exception;
        context.next = loc;
        return !!caught;
      }

      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        var record = entry.completion;

        if (entry.tryLoc === "root") {
          // Exception thrown outside of any try block that could handle
          // it, so set the completion value of the entire function to
          // throw the exception.
          return handle("end");
        }

        if (entry.tryLoc <= this.prev) {
          var hasCatch = hasOwn.call(entry, "catchLoc");
          var hasFinally = hasOwn.call(entry, "finallyLoc");

          if (hasCatch && hasFinally) {
            if (this.prev < entry.catchLoc) {
              return handle(entry.catchLoc, true);
            } else if (this.prev < entry.finallyLoc) {
              return handle(entry.finallyLoc);
            }

          } else if (hasCatch) {
            if (this.prev < entry.catchLoc) {
              return handle(entry.catchLoc, true);
            }

          } else if (hasFinally) {
            if (this.prev < entry.finallyLoc) {
              return handle(entry.finallyLoc);
            }

          } else {
            throw new Error("try statement without catch or finally");
          }
        }
      }
    },

    abrupt: function(type, arg) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.tryLoc <= this.prev &&
            hasOwn.call(entry, "finallyLoc") &&
            this.prev < entry.finallyLoc) {
          var finallyEntry = entry;
          break;
        }
      }

      if (finallyEntry &&
          (type === "break" ||
           type === "continue") &&
          finallyEntry.tryLoc <= arg &&
          arg <= finallyEntry.finallyLoc) {
        // Ignore the finally entry if control is not jumping to a
        // location outside the try/catch block.
        finallyEntry = null;
      }

      var record = finallyEntry ? finallyEntry.completion : {};
      record.type = type;
      record.arg = arg;

      if (finallyEntry) {
        this.next = finallyEntry.finallyLoc;
      } else {
        this.complete(record);
      }

      return ContinueSentinel;
    },

    complete: function(record, afterLoc) {
      if (record.type === "throw") {
        throw record.arg;
      }

      if (record.type === "break" ||
          record.type === "continue") {
        this.next = record.arg;
      } else if (record.type === "return") {
        this.rval = record.arg;
        this.next = "end";
      } else if (record.type === "normal" && afterLoc) {
        this.next = afterLoc;
      }
    },

    finish: function(finallyLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.finallyLoc === finallyLoc) {
          this.complete(entry.completion, entry.afterLoc);
          resetTryEntry(entry);
          return ContinueSentinel;
        }
      }
    },

    "catch": function(tryLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.tryLoc === tryLoc) {
          var record = entry.completion;
          if (record.type === "throw") {
            var thrown = record.arg;
            resetTryEntry(entry);
          }
          return thrown;
        }
      }

      // The context.catch method must only be called with a location
      // argument that corresponds to a known catch block.
      throw new Error("illegal catch attempt");
    },

    delegateYield: function(iterable, resultName, nextLoc) {
      this.delegate = {
        iterator: values(iterable),
        resultName: resultName,
        nextLoc: nextLoc
      };

      return ContinueSentinel;
    }
  };
})(
  // Among the various tricks for obtaining a reference to the global
  // object, this seems to be the most reliable technique that does not
  // use indirect eval (which violates Content Security Policy).
  typeof global === "object" ? global :
  typeof window === "object" ? window :
  typeof self === "object" ? self : this
);

// INLINED END /Users/user/git/lively.vm/node_modules/babel-regenerator-runtime/runtime.js

// INLINED /Users/user/git/lively.vm/node_modules/lively.lang/dist/lively.lang.js

(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  if (typeof GLOBAL.lively === "undefined") GLOBAL.lively = {};
  (function() {
    this.lively = this.lively || {};
(function (exports,lively_sourceTransform) {
'use strict';

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  return typeof obj;
} : function (obj) {
  return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};





var asyncGenerator = function () {
  function AwaitValue(value) {
    this.value = value;
  }

  function AsyncGenerator(gen) {
    var front, back;

    function send(key, arg) {
      return new Promise(function (resolve, reject) {
        var request = {
          key: key,
          arg: arg,
          resolve: resolve,
          reject: reject,
          next: null
        };

        if (back) {
          back = back.next = request;
        } else {
          front = back = request;
          resume(key, arg);
        }
      });
    }

    function resume(key, arg) {
      try {
        var result = gen[key](arg);
        var value = result.value;

        if (value instanceof AwaitValue) {
          Promise.resolve(value.value).then(function (arg) {
            resume("next", arg);
          }, function (arg) {
            resume("throw", arg);
          });
        } else {
          settle(result.done ? "return" : "normal", result.value);
        }
      } catch (err) {
        settle("throw", err);
      }
    }

    function settle(type, value) {
      switch (type) {
        case "return":
          front.resolve({
            value: value,
            done: true
          });
          break;

        case "throw":
          front.reject(value);
          break;

        default:
          front.resolve({
            value: value,
            done: false
          });
          break;
      }

      front = front.next;

      if (front) {
        resume(front.key, front.arg);
      } else {
        back = null;
      }
    }

    this._invoke = send;

    if (typeof gen.return !== "function") {
      this.return = undefined;
    }
  }

  if (typeof Symbol === "function" && Symbol.asyncIterator) {
    AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
      return this;
    };
  }

  AsyncGenerator.prototype.next = function (arg) {
    return this._invoke("next", arg);
  };

  AsyncGenerator.prototype.throw = function (arg) {
    return this._invoke("throw", arg);
  };

  AsyncGenerator.prototype.return = function (arg) {
    return this._invoke("return", arg);
  };

  return {
    wrap: function (fn) {
      return function () {
        return new AsyncGenerator(fn.apply(this, arguments));
      };
    },
    await: function (value) {
      return new AwaitValue(value);
    }
  };
}();





var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

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;
  };
}();







var get$1 = function get$1(object, property, receiver) {
  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent === null) {
      return undefined;
    } else {
      return get$1(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);
  }
};

















var set$1 = function set$1(object, property, value, receiver) {
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent !== null) {
      set$1(parent, property, value, receiver);
    }
  } else if ("value" in desc && desc.writable) {
    desc.value = value;
  } else {
    var setter = desc.set;

    if (setter !== undefined) {
      setter.call(receiver, value);
    }
  }

  return value;
};

var slicedToArray = function () {
  function sliceIterator(arr, i) {
    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;

    try {
      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);

        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"]) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  return function (arr, i) {
    if (Array.isArray(arr)) {
      return arr;
    } else if (Symbol.iterator in Object(arr)) {
      return sliceIterator(arr, i);
    } else {
      throw new TypeError("Invalid attempt to destructure non-iterable instance");
    }
  };
}();













var toConsumableArray = function (arr) {
  if (Array.isArray(arr)) {
    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

    return arr2;
  } else {
    return Array.from(arr);
  }
};

// A `Closure` is a representation of a JavaScript function that controls what
// values are bound to out-of-scope variables. By default JavaScript has no
// reflection capabilities over closed values in functions. When needing to
// serialize execution or when behavior should become part of the state of a
// system it is often necessary to have first-class control over this language
// aspect.
//
// Typically closures aren't created directly but with the help of [`asScriptOf`](#)
//
// Example:
// function func(a) { return a + b; }
// var closureFunc = Closure.fromFunction(func, {b: 3}).recreateFunc();
// closureFunc(4) // => 7
// var closure = closureFunc.livelyClosure // => {
// //   varMapping: { b: 3 },
// //   originalFunc: function func(a) {/*...*/}
// // }
// closure.lookup("b") // => 3
// closure.getFuncSource() // => "function func(a) { return a + b; }"

var parameterRegex = /function[^\(]*\(([^\)]*)\)|\(?([^\)=]*)\)?\s*=>/;

var Closure = function () {
  createClass(Closure, null, [{
    key: "fromFunction",
    value: function fromFunction(func, varMapping) {
      /*show-in-doc*/
      return new this(func, varMapping || {});
    }
  }, {
    key: "fromSource",
    value: function fromSource(source, varMapping) {
      /*show-in-doc*/
      return new this(null, varMapping || {}, source);
    }
  }]);

  function Closure(func, varMapping, source, funcProperties) {
    classCallCheck(this, Closure);

    this.originalFunc = func;
    this.varMapping = varMapping || {};
    this.setFuncSource(source || func);
    this.setFuncProperties(func || funcProperties);
  }

  createClass(Closure, [{
    key: "setFuncSource",


    // accessing
    value: function setFuncSource(src) {
      /*show-in-doc*/
      src = typeof lively !== "undefined" && lively.sourceTransform && typeof lively.sourceTransform.stringifyFunctionWithoutToplevelRecorder === "function" ? lively.sourceTransform.stringifyFunctionWithoutToplevelRecorder(src) : String(src);
      return this.source = src;
    }
  }, {
    key: "getFuncSource",
    value: function getFuncSource() {
      /*show-in-doc*/
      return this.source || this.setFuncSource(this.originalFunc);
    }
  }, {
    key: "hasFuncSource",
    value: function hasFuncSource() {
      /*show-in-doc*/
      return this.source && true;
    }
  }, {
    key: "getFunc",
    value: function getFunc() {
      /*show-in-doc*/
      return this.originalFunc || this.recreateFunc();
    }
  }, {
    key: "getFuncProperties",
    value: function getFuncProperties() {
      // ignore-in-doc
      // a function may have state attached
      return this.funcProperties || (this.funcProperties = {});
    }
  }, {
    key: "setFuncProperties",
    value: function setFuncProperties(obj) {
      // ignore-in-doc
      var props = this.getFuncProperties();
      for (var name in obj) {
        // The AST implementation assumes that Function objects are some
        // kind of value object. When their identity changes cached state
        // should not be carried over to new function instances. This is a
        // pretty intransparent way to invalidate attributes that are used
        // for caches.
        // @cschuster, can you please fix this by making invalidation more
        // explicit?
        if (obj.hasOwnProperty(name)) props[name] = obj[name];
      }
    }
  }, {
    key: "lookup",
    value: function lookup(name) {
      /*show-in-doc*/
      return this.varMapping[name];
    }
  }, {
    key: "parameterNames",
    value: function parameterNames(methodString) {
      // ignore-in-doc

      if (typeof lively !== "undefined" && lively.ast && lively.ast.parseFunction) {
        return (lively.ast.parseFunction(methodString).params || []).map(function (ea) {
          if (ea.type === "Identifier") return ea.name;
          if (ea.left && ea.left.type === "Identifier") return ea.left.name;
          return null;
        }).filter(Boolean);
      }

      var paramsMatch = parameterRegex.exec(methodString);
      if (!paramsMatch) return [];
      var paramsString = paramsMatch[1] || paramsMatch[2] || "";
      return paramsString.split(",").map(function (ea) {
        return ea.trim();
      });
    }
  }, {
    key: "firstParameter",
    value: function firstParameter(src) {
      // ignore-in-doc
      return this.parameterNames(src)[0] || null;
    }

    // -=-=-=-=-=-=-=-=-=-
    // function creation
    // -=-=-=-=-=-=-=-=-=-

  }, {
    key: "recreateFunc",
    value: function recreateFunc() {
      // Creates a real function object
      return this.recreateFuncFromSource(this.getFuncSource(), this.originalFunc);
    }
  }, {
    key: "recreateFuncFromSource",
    value: function recreateFuncFromSource(funcSource, optFunc) {
      // ignore-in-doc
      // what about objects that are copied by value, e.g. numbers?
      // when those are modified after the originalFunc we captured
      // varMapping then we will have divergent state
      var closureVars = [],
          thisFound = false,
          specificSuperHandling = this.firstParameter(funcSource) === '$super';
      for (var name in this.varMapping) {
        if (!this.varMapping.hasOwnProperty(name)) continue;
        if (name == 'this') {
          thisFound = true;continue;
        }
        // closureVars.push(`var ${name} = this.varMapping.${name};\n`);
        closureVars.push("var " + name + " = this.varMapping." + name + ";\n");
      }

      var src = "";
      if (closureVars.length > 0) src += closureVars.join("\n");
      if (specificSuperHandling) src += '(function superWrapperForClosure() { return ';
      src += "(" + funcSource + ")";
      if (specificSuperHandling) src += '.apply(this, [$super.bind(this)]' + '.concat(Array.from(arguments))) })';
      try {
        var func = evalJS.call(this, src) || this.couldNotCreateFunc(src);
        this.addFuncProperties(func);
        this.originalFunc = func;
        return func;
      } catch (e) {
        // var msg = `Cannot create function ${e} src: ${src}`;
        var msg = "Cannot create function " + e + " src: " + src;
        console.error(msg);
        throw new Error(msg);
      }
    }
  }, {
    key: "addFuncProperties",
    value: function addFuncProperties(func) {
      // ignore-in-doc
      var props = this.getFuncProperties();
      for (var name in props) {
        if (props.hasOwnProperty(name)) func[name] = props[name];
      }this.addClosureInformation(func);
    }
  }, {
    key: "couldNotCreateFunc",
    value: function couldNotCreateFunc(src) {
      // ignore-in-doc
      var msg = 'Could not recreate closure from source: \n' + src;
      console.error(msg);
      return function () {
        throw new Error(msg);
      };
    }

    // -=-=-=-=-=-
    // conversion
    // -=-=-=-=-=-

  }, {
    key: "asFunction",
    value: function asFunction() {
      /*ignore-in-doc*/
      return this.recreateFunc();
    }

    // -=-=-=-=-=-=-=-=-=-=-=-
    // function modification
    // -=-=-=-=-=-=-=-=-=-=-=-

  }, {
    key: "addClosureInformation",
    value: function addClosureInformation(f) {
      /*ignore-in-doc-in-doc*/
      f.hasLivelyClosure = true;
      f.livelyClosure = this;
      return f;
    }
  }, {
    key: "isLivelyClosure",
    get: function get() {
      return true;
    }

    // serialization

  }, {
    key: "doNotSerialize",
    get: function get() {
      return ['originalFunc'];
    }
  }]);
  return Closure;
}();

/*global clearTimeout, setTimeout*/

/*
 * Abstractions around first class functions like augmenting and inspecting
 * functions as well as to control function calls like dealing with asynchronous
 * control flows.
 */

// -=-=-=-=-=-=-=-=-
// static functions
// -=-=-=-=-=-=-=-=-

function Empty() {
  /*`function() {}`*/return function () {};
}
function K() {
  /*`function(arg) { return arg; }`*/return function (arg) {
    return arg;
  };
}
function Null() {
  /*`function() { return null; }`*/return function () {
    return null;
  };
}
function False() {
  /*`function() { return false; }`*/return function () {
    return false;
  };
}
function True() {
  /*`function() { return true; }`*/return function () {
    return true;
  };
}
function notYetImplemented() {
  return function () {
    throw new Error('Not yet implemented');
  };
}

// -=-=-=-=-=-
// accessing
// -=-=-=-=-=-
function all(object) {
  // Returns all property names of `object` that reference a function.
  // Example:
  // var obj = {foo: 23, bar: function() { return 42; }};
  // all(obj) // => ["bar"]
  var a = [];
  for (var name in object) {
    if (!object.__lookupGetter__(name) && typeof object[name] === 'function') a.push(name);
  }
  return a;
}

function own(object) {
  // Returns all local (non-prototype) property names of `object` that
  // reference a function.
  // Example:
  // var obj1 = {foo: 23, bar: function() { return 42; }};
  // var obj2 = {baz: function() { return 43; }};
  // obj2.__proto__ = obj1
  // own(obj2) // => ["baz"]
  // /*vs.*/ all(obj2) // => ["baz","bar"]
  var a = [];
  for (var name in object) {
    if (!object.__lookupGetter__(name) && object.hasOwnProperty(name) && typeof object[name] === 'function') a.push(name);
  }
  return a;
}

// -=-=-=-=-=-
// inspection
// -=-=-=-=-=-

function argumentNames(f) {
  // Example:
  // argumentNames(function(arg1, arg2) {}) // => ["arg1","arg2"]
  // argumentNames(function(/*var args*/) {}) // => []
  if (f.superclass) return []; // it's a class...
  var src = f.toString(),
      names = "",
      arrowMatch = src.match(/(?:\(([^\)]*)\)|([^\(\)-+!]+))\s*=>/);
  if (arrowMatch) names = arrowMatch[1] || arrowMatch[2] || "";else {
    var headerMatch = src.match(/^[\s\(]*function[^(]*\(([^)]*)\)/);
    if (headerMatch && headerMatch[1]) names = headerMatch[1];
  }
  return names.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '').replace(/\s+/g, '').split(',').map(function (ea) {
    return ea.trim();
  }).filter(function (name) {
    return !!name;
  });
}

function qualifiedMethodName(f) {
  // ignore-in-doc
  var objString = "";
  if (f.declaredClass) {
    objString += f.declaredClass + '>>';
  } else if (f.declaredObject) {
    objString += f.declaredObject + '.';
  }
  return objString + (f.methodName || f.displayName || f.name || "anonymous");
}

function extractBody(func) {

  // superflous indent. Useful when you have to stringify code but not want
  // to construct strings by hand.
  // Example:
  // extractBody(function(arg) {
  //   var x = 34;
  //   alert(2 + arg);
  // }) => "var x = 34;\nalert(2 + arg);"
  var codeString = String(func).replace(/^function[^\{]+\{\s*/, '').replace(/\}$/, '').trim(),
      lines = codeString.split(/\n|\r/),
      indent = undefined;
  for (var i = 0; i < lines.length; i++) {
    var m = lines[i].match(/^(\s+)[^\s]/);
    if (m && (indent === undefined || m[1].length < indent.length)) indent = m[1];
  }
  return indent ? codeString.replace(new RegExp("^" + indent, 'gm'), '') : codeString;
}

// -=-=-=-
// timing
// -=-=-=-

function timeToRun(func) {
  // returns synchronous runtime of calling `func` in ms
  // Example:
  // timeToRun(function() { new WebResource("http://google.de").beSync().get() });
  // // => 278 (or something else...)
  var startTime = Date.now();
  func();
  return Date.now() - startTime;
}

function timeToRunN$1(func, n) {
  // Like `timeToRun` but calls function `n` times instead of once. Returns
  // the average runtime of a call in ms.
  var startTime = Date.now();
  for (var i = 0; i < n; i++) {
    func();
  }return (Date.now() - startTime) / n;
}

function delay(func, timeout /*, arg1...argN*/) {
  // Delays calling `func` for `timeout` seconds(!).
  // Example:
  // (function() { alert("Run in the future!"); }).delay(1);
  var args = Array.prototype.slice.call(arguments),
      __method = args.shift(),
      timeout = args.shift() * 1000;
  return setTimeout(function delayed() {
    return __method.apply(__method, args);
  }, timeout);
}

// these last two methods are Underscore.js 1.3.3 and are slightly adapted
// Underscore.js license:
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is distributed under the MIT license.

function throttle(func, wait) {
  // Exec func at most once every wait ms even when called more often
  // useful to calm down eagerly running updaters and such.
  // Example:
  // var i = 0;
  // var throttled = throttle(function() { alert(++i + '-' + Date.now()) }, 500);
  // Array.range(0,100).forEach(function(n) { throttled() });
  var context,
      args,
      timeout,
      throttling,
      more,
      result,
      whenDone = debounce(wait, function () {
    more = throttling = false;
  });
  return function () {
    context = this;args = arguments;
    var later = function later() {
      timeout = null;
      if (more) func.apply(context, args);
      whenDone();
    };
    if (!timeout) timeout = setTimeout(later, wait);
    if (throttling) {
      more = true;
    } else {
      result = func.apply(context, args);
    }
    whenDone();
    throttling = true;
    return result;
  };
}

function debounce(wait, func, immediate) {
  // Call `func` after `wait` milliseconds elapsed since the last invocation.
  // Unlike `throttle` an invocation will restart the wait period. This is
  // useful if you have a stream of events that you want to wait for to finish
  // and run a subsequent function afterwards. When you pass arguments to the
  // debounced functions then the arguments from the last call will be use for
  // the invocation.
  //
  // With `immediate` set to true, immediately call `func` but when called again during `wait` before
  // wait ms are done nothing happens. E.g. to not exec a user invoked
  // action twice accidentally.
  // Example:
  // var start = Date.now();
  // var f = debounce(200, function(arg1) {
  //   alert("running after " + (Date.now()-start) + "ms with arg " + arg1);
  // });
  // f("call1");
  // delay(f.curry("call2"), 0.1);
  // delay(f.curry("call3"), 0.15);
  // // => Will eventually output: "running after 352ms with arg call3"
  var timeout;
  return function () {
    var context = this,
        args = arguments;
    var later = function later() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    if (immediate && !timeout) func.apply(context, args);
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

var _throttledByName = {};
function throttleNamed(name, wait, func) {
  // Like `throttle` but remembers the throttled function once created and
  // repeated calls to `throttleNamed` with the identical name will use the same
  // throttled function. This allows to throttle functions in a central place
  // that might be called various times in different contexts without having to
  // manually store the throttled function.
  var store = _throttledByName;
  if (store[name]) return store[name];
  function throttleNamedWrapper() {
    // ignore-in-doc, cleaning up
    debounceNamed(name, wait, function () {
      delete store[name];
    })();
    func.apply(this, arguments);
  }
  return store[name] = throttle(throttleNamedWrapper, wait);
}

var _debouncedByName = {};
function debounceNamed(name, wait, func, immediate) {
  // Like `debounce` but remembers the debounced function once created and
  // repeated calls to `debounceNamed` with the identical name will use the same
  // debounced function. This allows to debounce functions in a central place
  // that might be called various times in different contexts without having to
  // manually store the debounced function.
  var store = _debouncedByName;
  if (store[name]) return store[name];
  function debounceNamedWrapper() {
    // ignore-in-doc, cleaning up
    delete store[name];
    func.apply(this, arguments);
  }
  return store[name] = debounce(wait, debounceNamedWrapper, immediate);
}

var _queues = {};
function createQueue(id, workerFunc) {
  // A simple queue with an attached asynchronous `workerFunc` to process
  // queued tasks. Calling `createQueue` will return an object with the
  // following interface:
  // ```js
  // {
  //   push: function(task) {/**/},
  //   pushAll: function(tasks) {/**/},
  //   handleError: function(err) {}, // Overwrite to handle errors
  //   dran: function() {}, // Overwrite to react when the queue empties
  // }
  // Example:
  // var sum = 0;
  // var q = createQueue("example-queue", function(arg, thenDo) { sum += arg; thenDo(); });
  // q.pushAll([1,2,3]);
  // queues will be remembered by their name
  // createQueue("example-queue").push(4);
  // sum // => 6

  var store = _queues;

  var queue = store[id] || (store[id] = {
    _workerActive: false,
    worker: workerFunc, tasks: [],
    drain: null, // can be overwritten by a function
    push: function push(task) {
      queue.tasks.push(task);
      queue.activateWorker();
    },
    pushAll: function pushAll(tasks) {
      tasks.forEach(function (ea) {
        queue.tasks.push(ea);
      });
      queue.activateWorker();
    },
    pushNoActivate: function pushNoActivate(task) {
      queue.tasks.push(task);
    },
    handleError: function handleError(err) {
      // can be overwritten
      err && console.error('Error in queue: ' + err);
    },
    activateWorker: function activateWorker() {
      function callback(err) {
        queue.handleError(err);queue.activateWorker();
      }
      var tasks = queue.tasks,
          active = queue._workerActive;
      if (tasks.length === 0) {
        if (active) {
          queue._workerActive = false;
          if (typeof queue.drain === 'function') queue.drain();
        }
        delete store[id];
      } else {
        if (!active) queue._workerActive = true;
        try {
          queue.worker(tasks.shift(), callback);
        } catch (err) {
          callback(err);
        }
      }
    }
  });

  return queue;
}

var _queueUntilCallbacks = {};
function workerWithCallbackQueue(id, workerFunc, optTimeout) {
  // This functions helps when you have a long running computation that
  // multiple call sites (independent from each other) depend on. This
  // function does the housekeeping to start the long running computation
  // just once and returns an object that allows to schedule callbacks
  // once the workerFunc is done.
  // Example:
  // var worker = workerWithCallbackQueue("example",
  //   function slowFunction(thenDo) {
  //     var theAnswer = 42;
  //     setTimeout(function() { thenDo(null, theAnswer); });
  //   });
  // // all "call sites" depend on `slowFunction` but don't have to know about
  // // each other
  // worker.whenDone(function callsite1(err, theAnswer) { alert("callback1: " + theAnswer); })
  // worker.whenDone(function callsite2(err, theAnswer) { alert("callback2: " + theAnswer); })
  // workerWithCallbackQueue("example").whenDone(function callsite3(err, theAnswer) { alert("callback3: " + theAnswer); })
  // // => Will eventually show: callback1: 42, callback2: 42 and callback3: 42


  // ignore-in-doc
  // This is how it works:
  // If `id` does not exist, workerFunc is called, otherwise ignored.
  // workerFunc is expected to call thenDoFunc with arguments: error, arg1, ..., argN
  // if called subsequently before workerFunc is done, the other thenDoFunc
  // will "pile up" and called with the same arguments as the first
  // thenDoFunc once workerFunc is done
  var store = _queueUntilCallbacks,
      queueCallbacks = store[id],
      isRunning = !!queueCallbacks;

  if (isRunning) return queueCallbacks;

  var callbacksRun = false,
      canceled = false;

  function cleanup() {
    if (timeoutProc) clearTimeout(timeoutProc);
    callbacksRun = true;
    delete store[id];
  }

  function runCallbacks(args) {
    if (callbacksRun) return;
    cleanup();
    queueCallbacks.callbacks.forEach(function (cb) {
      try {
        cb.apply(null, args);
      } catch (e) {
        console.error("Error when invoking callbacks in queueUntil [" + id + "]:\n" + String(e.stack || e));
      }
    });
  }

  // timeout
  if (optTimeout) {
    var timeoutProc = setTimeout(function () {
      if (callbacksRun) return;
      runCallbacks([new Error("timeout")]);
    }, optTimeout);
  }

  // init the store
  queueCallbacks = store[id] = {
    callbacks: [],
    cancel: function cancel() {
      canceled = true;
      cleanup();
    },
    whenDone: function whenDone(cb) {
      queueCallbacks.callbacks.push(cb);
      return queueCallbacks;
    }
  };

  // call worker, but delay so we can immediately return
  setTimeout(function () {
    if (canceled) return;
    try {
      workerFunc(function () /*args*/{
        runCallbacks(arguments);
      });
    } catch (e) {
      runCallbacks([e]);
    }
  }, 0);

  return queueCallbacks;
}

function _composeAsyncDefaultEndCallback(err, arg1 /*err + args*/) {
  if (err) console.error("lively.lang.composeAsync error", err);
}

function composeAsync() /*functions*/{
  // Composes functions that are asynchronous and expecting continuations to
  // be called in node.js callback style (error is first argument, real
  // arguments follow).
  // A call like `composeAsync(f,g,h)(arg1, arg2)` has a flow of control like:
  //  `f(arg1, arg2, thenDo1)` -> `thenDo1(err, fResult)`
  // -> `g(fResult, thenDo2)` -> `thenDo2(err, gResult)` ->
  // -> `h(fResult, thenDo3)` -> `thenDo2(err, hResult)`
  // Example:
  // composeAsync(
  //   function(a,b, thenDo) { thenDo(null, a+b); },
  //   function(x, thenDo) { thenDo(x*4); }
  //  )(3,2, function(err, result) { alert(result); });

  var toArray$$1 = Array.prototype.slice,
      functions = toArray$$1.call(arguments),
      defaultEndCb = _composeAsyncDefaultEndCallback,
      endCallback = defaultEndCb,
      endSuccess,
      endFailure,
      endPromise = new Promise(function (resolve, reject) {
    endSuccess = resolve;endFailure = reject;
  });

  return functions.reverse().reduce(function (prevFunc, funcOrPromise, i) {

    var nextActivated = false;
    return function () {
      var args = toArray$$1.call(arguments);

      // ignore-in-doc
      // the last arg needs to be function, discard all non-args
      // following it. This allows to have an optional callback func that can
      // even be `undefined`, e.g. when calling this func from a callsite
      // using var args;
      if (endCallback === defaultEndCb && i === functions.length - 1 /*first function*/) {
          while (args.length && typeof args[args.length - 1] !== 'function') {
            args.pop();
          }if (typeof args[args.length - 1] === 'function') endCallback = args.pop();
        }

      function next() /*err and args*/{
        nextActivated = true;
        var args = toArray$$1.call(arguments),
            err = args.shift();
        if (err) {
          endCallback(err);endFailure(err);
        } else prevFunc.apply(null, args);
      }

      if (typeof funcOrPromise === "function") {
        try {
          var result = funcOrPromise.apply(this, args.concat([next]));
          if (result && typeof result.then === "function" && typeof result.catch === "function") {
            result.then(function (value) {
              return next(null, value);
            }).catch(function (err) {
              return next(err);
            });
          }
        } catch (e) {
          console.error('composeAsync: ', e.stack || e);
          if (!nextActivated) {
            endCallback(e);endFailure(e);
          }
        }
      } else if (funcOrPromise && typeof funcOrPromise.then === "function" && typeof funcOrPromise.catch === "function") {
        funcOrPromise.then(function (value) {
          next(null, value);
        }).catch(function (err) {
          next(err);
        });
      } else {
        var err = new Error("Invalid argument to composeAsync: " + funcOrPromise);
        endCallback(err);
        endFailure(err);
      }

      return endPromise;
    };
  }, function () {
    var args = toArray$$1.call(arguments);
    endCallback.apply(null, [null].concat(args));
    endSuccess(args[0]);
  });
}

function compose() /*functions*/{
  // Composes synchronousefunctions:
  // `compose(f,g,h)(arg1, arg2)` = `h(g(f(arg1, arg2)))`
  // Example:
  // compose(
  //   function(a,b) { return a+b; },
  //   function(x) {return x*4}
  // )(3,2) // => 20

  var functions = Array.prototype.slice.call(arguments);
  return functions.reverse().reduce(function (prevFunc, func) {
    return function () {
      return prevFunc(func.apply(this, arguments));
    };
  }, function (x) {
    return x;
  });
}

function flip(f) {
  // Swaps the first two args
  // Example:
  // flip(function(a, b, c) {
  //   return a + b + c; })(' World', 'Hello', '!') // => "Hello World!"
  return function flipped() /*args*/{
    var args = Array.prototype.slice.call(arguments),
        flippedArgs = [args[1], args[0]].concat(args.slice(2));
    return f.apply(null, flippedArgs);
  };
}

function withNull(func) {
  // returns a modified version of func that will have `null` always curried
  // as first arg. Usful e.g. to make a nodejs-style callback work with a
  // then-able:
  // Example:
  // promise.then(withNull(cb)).catch(cb);
  func = func || function () {};
  return function () /*args*/{
    var args = lively.lang.arr.from(arguments);
    func.apply(null, [null].concat(args));
  };
}

function waitFor(timeoutMs, waitTesterFunc, thenDo) {
  // Wait for waitTesterFunc to return true, then run thenDo, passing
  // failure/timout err as first parameter. A timout occurs after
  // timeoutMs. During the wait period waitTesterFunc might be called
  // multiple times.
  var start = Date.now();
  var timeStep = 50;
  if (!thenDo) {
    thenDo = waitTesterFunc;
    waitTesterFunc = timeoutMs;
    timeoutMs = undefined;
  }
  (function test() {
    if (waitTesterFunc()) return thenDo();
    if (timeoutMs) {
      var duration = Date.now() - start,
          timeLeft = timeoutMs - duration;
      if (timeLeft <= 0) return thenDo(new Error('timeout'));
      if (timeLeft < timeStep) timeStep = timeLeft;
    }
    setTimeout(test, timeStep);
  })();
}

function waitForAll(options, funcs, thenDo) {
  // Wait for multiple asynchronous functions. Once all have called the
  // continuation, call `thenDo`.
  // options can be: `{timeout: NUMBER}` (how long to wait in milliseconds).

  if (!thenDo) {
    thenDo = funcs;funcs = options;options = null;
  }
  options = options || {};

  var results = funcs.map(function () {
    return null;
  });
  if (!funcs.length) {
    thenDo(null, results);return;
  }

  var leftFuncs = Array.prototype.slice.call(funcs);

  funcs.forEach(function (f, i) {
    try {
      f(function () /*err and args*/{
        var args = Array.prototype.slice.call(arguments);
        var err = args.shift();
        markAsDone(f, i, err, args);
      });
    } catch (e) {
      markAsDone(f, i, e, null);
    }
  });

  if (options.timeout) {
    setTimeout(function () {
      if (!leftFuncs.length) return;
      var missing = results.map(function (ea, i) {
        return ea === null && i;
      }).filter(function (ea) {
        return typeof ea === 'number';
      }).join(', ');
      var err = new Error("waitForAll timed out, functions at " + missing + " not done");
      markAsDone(null, null, err, null);
    }, options.timeout);
  }

  function markAsDone(f, i, err, result) {
    if (!leftFuncs.length) return;

    var waitForAllErr = null;
    var fidx = leftFuncs.indexOf(f);
    fidx > -1 && leftFuncs.splice(fidx, 1);
    if (err) {
      leftFuncs.length = 0;
      waitForAllErr = new Error("in waitForAll at" + (typeof i === 'number' ? " " + i : "") + ": \n" + (err.stack || String(err)));
    } else if (result) results[i] = result;
    if (!leftFuncs.length) setTimeout(function () {
      thenDo(waitForAllErr, results);
    }, 0);
  }
}

// -=-=-=-=-
// wrapping
// -=-=-=-=-

function curry(func, arg1, arg2, argN /*func and curry args*/) {
  // Return a version of `func` with args applied.
  // Example:
  // var add1 = (function(a, b) { return a + b; }).curry(1);
  // add1(3) // => 4

  if (arguments.length <= 1) return arguments[0];
  var args = Array.prototype.slice.call(arguments),
      func = args.shift();
  function wrappedFunc() {
    return func.apply(this, args.concat(Array.prototype.slice.call(arguments)));
  }
  wrappedFunc.isWrapper = true;
  wrappedFunc.originalFunction = func;
  return wrappedFunc;
}

function wrap(func, wrapper) {
  // A `wrapper` is another function that is being called with the arguments
  // of `func` and a proceed function that, when called, runs the originally
  // wrapped function.
  // Example:
  // function original(a, b) { return a+b }
  // var wrapped = wrap(original, function logWrapper(proceed, a, b) {
  //   alert("original called with " + a + "and " + b);
  //   return proceed(a, b);
  // })
  // wrapped(3,4) // => 7 and a message will pop up
  var __method = func;
  var wrappedFunc = function wrapped() {
    var args = Array.prototype.slice.call(arguments);
    var wrapperArgs = wrapper.isWrapper ? args : [__method.bind(this)].concat(args);
    return wrapper.apply(this, wrapperArgs);
  };
  wrappedFunc.isWrapper = true;
  wrappedFunc.originalFunction = __method;
  return wrappedFunc;
}

function getOriginal(func) {
  // Get the original function that was augmented by `wrap`. `getOriginal`
  // will traversed as many wrappers as necessary.
  while (func.originalFunction) {
    func = func.originalFunction;
  }return func;
}

function wrapperChain(method) {
  // Function wrappers used for wrapping, cop, and other method
  // manipulations attach a property "originalFunction" to the wrapper. By
  // convention this property references the wrapped method like wrapper
  // -> cop wrapper -> real method.
  // tThis method gives access to the linked list starting with the outmost
  // wrapper.
  var result = [];
  do {
    result.push(method);
    method = method.originalFunction;
  } while (method);
  return result;
}

function replaceMethodForOneCall(obj, methodName, replacement) {
  // Change an objects method for a single invocation.
  // Example:
  // var obj = {foo: function() { return "foo"}};
  // lively.lang.replaceMethodForOneCall(obj, "foo", function() { return "bar"; });
  // obj.foo(); // => "bar"
  // obj.foo(); // => "foo"
  replacement.originalFunction = obj[methodName];
  var reinstall = obj.hasOwnProperty(methodName);
  obj[methodName] = function () {
    if (reinstall) obj[methodName] = replacement.originalFunction;else delete obj[methodName];
    return replacement.apply(this, arguments);
  };
  return obj;
}

function once(func) {
  // Ensure that `func` is only executed once. Multiple calls will not call
  // `func` again but will return the original result.
  if (!func) return undefined;
  if (typeof func !== 'function') throw new Error("once() expecting a function");
  var invoked = false,
      result;
  return function () {
    if (invoked) return result;
    invoked = true;
    return result = func.apply(this, arguments);
  };
}

function either() /*funcs*/{
  // Accepts multiple functions and returns an array of wrapped
  // functions. Those wrapped functions ensure that only one of the original
  // function is run (the first on to be invoked).
  //
  // This is useful if you have multiple asynchronous choices of how the
  // control flow might continue but want to ensure that a continuation
  // is  only triggered once, like in a timeout situation:
  //
  // ```js
  // function outerFunction(callback) {
  //   function timeoutAction() { callback(new Error('timeout!')); }
  //   function otherAction() { callback(null, "All OK"); }
  //   setTimeout(timeoutAction, 200);
  //   doSomethingAsync(otherAction);
  // }
  // ```
  //
  // To ensure that `callback` only runs once you would normally have to write boilerplate like this:
  //
  // ```js
  // var ran = false;
  // function timeoutAction() { if (ran) return; ran = true; callback(new Error('timeout!')); }
  // function otherAction() { if (ran) return; ran = true; callback(null, "All OK"); }
  // ```
  //
  // Since this can get tedious an error prone, especially if more than two choices are involved, `either` can be used like this:
  // Example:
  // function outerFunction(callback) {
  //   var actions = either(
  //     function() { callback(new Error('timeout!')); },
  //     function() { callback(null, "All OK"); });
  //   setTimeout(actions[0], 200);
  //   doSomethingAsync(actions[1]);
  // }
  var funcs = Array.prototype.slice.call(arguments),
      wasCalled = false;
  return funcs.map(function (func) {
    return function () {
      if (wasCalled) return undefined;
      wasCalled = true;
      return func.apply(this, arguments);
    };
  });
}

var _eitherNameRegistry = {};
function eitherNamed(name, func) {
  // Works like [`either`](#) but usage does not require to wrap all
  // functions at once:
  // Example:
  // var log = "", name = "either-example-" + Date.now();
  // function a() { log += "aRun"; };
  // function b() { log += "bRun"; };
  // function c() { log += "cRun"; };
  // setTimeout(eitherNamed(name, a), 100);
  // setTimeout(eitherNamed(name, b), 40);
  // setTimeout(eitherNamed(name, c), 80);
  // setTimeout(function() { alert(log); /* => "bRun" */ }, 150);
  var funcs = Array.prototype.slice.call(arguments);
  var registry = _eitherNameRegistry;
  var name = funcs.shift();
  var eitherCall = registry[name] || (registry[name] = { wasCalled: false, callsLeft: 0 });
  eitherCall.callsLeft++;
  return function () {
    eitherCall.callsLeft--;
    // cleanup the storage if all registered functions fired
    if (eitherCall.callsLeft <= 0) delete registry[name];
    if (eitherCall.wasCalled) return undefined;
    eitherCall.wasCalled = true;
    return func.apply(this, arguments);
  };
}

// -=-=-=-=-
// creation
// -=-=-=-=-
function evalJS(src) {
  return eval(src);
}

function fromString(funcOrString) {
  // Example:
  // fromString("function() { return 3; }")() // => 3
  return evalJS('(' + funcOrString.toString() + ');');
}

function asScript(func, optVarMapping) {
  // Lifts `func` to become a `Closure`, that is that free variables referenced
  // in `func` will be bound to the values of an object that can be passed in as
  // the second parameter. Keys of this object are mapped to the free variables.
  //
  // Please see [`Closure`](#) for a more detailed explanation and examples.
  return Closure.fromFunction(func, optVarMapping).recreateFunc();
}

function asScriptOf(f, obj, optName, optMapping) {
  // Like `asScript` but makes `f` a method of `obj` as `optName` or the name
  // of the function.
  var name = optName || f.name;
  if (!name) {
    throw Error("Function that wants to be a script needs a name: " + this);
  }
  var proto = Object.getPrototypeOf(obj),
      mapping = { "this": obj };
  if (optMapping) mapping = merge([mapping, optMapping]);
  if (proto && proto[name]) {
    var superFunc = function superFunc() {
      try {
        // FIXME super is supposed to be static
        return Object.getPrototypeOf(obj)[name].apply(obj, arguments);
      } catch (e) {
        if (typeof $world !== "undefined") $world.logError(e, 'Error in $super call');else console.error('Error in $super call: ' + e + '\n' + e.stack);
        return null;
      }
    };
    mapping["$super"] = Closure.fromFunction(superFunc, { obj: obj, name: name }).recreateFunc();
  }
  return addToObject(asScript(f, mapping), obj, name);
}

// -=-=-=-=-=-=-=-=-
// closure related
// -=-=-=-=-=-=-=-=-
function addToObject(f, obj, name) {
  // ignore-in-doc
  f.displayName = name;

  var methodConnections = obj.attributeConnections ? obj.attributeConnections.filter(function (con) {
    return con.getSourceAttrName() === 'update';
  }) : [];

  if (methodConnections) methodConnections.forEach(function (ea) {
    ea.disconnect();
  });

  obj[name] = f;

  if (typeof obj === "undefined" ? "undefined" : _typeof(obj)) f.declaredObject = safeToString(obj);

  // suppport for tracing
  if (typeof lively !== "undefined" && obj && lively.Tracing && lively.Tracing.stackTracingEnabled) {
    lively.Tracing.instrumentMethod(obj, name, {
      declaredObject: safeToString(obj)
    });
  }

  if (methodConnections) methodConnections.forEach(function (ea) {
    ea.connect();
  });

  return f;
}

function binds(f, varMapping) {
  // ignore-in-doc
  // convenience function
  return Closure.fromFunction(f, varMapping || {}).recreateFunc();
}

function setLocalVarValue(f, name, value) {
  // ignore-in-doc
  if (f.hasLivelyClosure) f.livelyClosure.funcProperties[name] = value;
}

function getVarMapping(f) {
  // ignore-in-doc
  if (f.hasLivelyClosure) return f.livelyClosure.varMapping;
  if (f.isWrapper) return f.originalFunction.varMapping;
  if (f.varMapping) return f.varMapping;
  return {};
}

function setProperty(func, name, value) {
  func[name] = value;
  if (func.hasLivelyClosure) func.livelyClosure.funcProperties[name] = value;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-
// class-related functions
// -=-=-=-=-=-=-=-=-=-=-=-=-
function functionNames(klass) {
  // Treats passed function as class (constructor).
  // Example:
  // var Klass1 = function() {}
  // Klass1.prototype.foo = function(a, b) { return a + b; };
  // Klass1.prototype.bar = function(a) { return this.foo(a, 3); };
  // Klass1.prototype.baz = 23;
  // functionNames(Klass1); // => ["bar","foo"]

  var result = [],
      lookupObj = klass.prototype;
  while (lookupObj) {
    result = Object.keys(lookupObj).reduce(function (result, name) {
      if (typeof lookupObj[name] === 'function' && result.indexOf(name) === -1) result.push(name);
      return result;
    }, result);
    lookupObj = Object.getPrototypeOf(lookupObj);
  }
  return result;
}

function localFunctionNames(func) {
  return Object.keys(func.prototype).filter(function (name) {
    return typeof func.prototype[name] === 'function';
  });
}

// -=-=-=-=-=-=-=-=-=-=-
// tracing and logging
// -=-=-=-=-=-=-=-=-=-=-

function logErrors(func, prefix) {
  var advice = function logErrorsAdvice(proceed /*,args*/) {
    var args = Array.prototype.slice.call(arguments);
    args.shift();
    try {
      return proceed.apply(func, args);
    } catch (er) {
      if (typeof lively !== "undefined" && lively.morphic && lively.morphic.World && lively.morphic.World.current()) {
        lively.morphic.World.current().logError(er);
        throw er;
      }

      if (prefix) console.warn("ERROR: %s.%s(%s): err: %s %s", func, prefix, args, er, er.stack || "");else console.warn("ERROR: %s %s", er, er.stack || "");
      throw er;
    }
  };

  advice.methodName = "$logErrorsAdvice";
  var result = wrap(func, advice);
  result.originalFunction = func;
  result.methodName = "$logErrorsWrapper";
  return result;
}

function logCompletion(func, module) {
  var advice = function logCompletionAdvice(proceed) {
    var args = Array.prototype.slice.call(arguments);
    args.shift();
    try {
      var result = proceed.apply(func, args);
    } catch (er) {
      console.warn('failed to load ' + module + ': ' + er);
      if (typeof lively !== 'undefined' && lively.lang.Execution) lively.lang.Execution.showStack();
      throw er;
    }
    console.log('completed ' + module);
    return result;
  };

  advice.methodName = "$logCompletionAdvice::" + module;

  var result = wrap(func, advice);
  result.methodName = "$logCompletionWrapper::" + module;
  result.originalFunction = func;
  return result;
}

function logCalls(func, isUrgent) {
  var original = func,
      advice = function logCallsAdvice(proceed) {
    var args = Array.prototype.slice.call(arguments);
    args.shift(), result = proceed.apply(func, args);
    if (isUrgent) {
      console.warn('%s(%s) -> %s', qualifiedMethodName(original), args, result);
    } else {
      console.log('%s(%s) -> %s', qualifiedMethodName(original), args, result);
    }
    return result;
  };

  advice.methodName = "$logCallsAdvice::" + qualifiedMethodName(func);

  var result = wrap(func, advice);
  result.originalFunction = func;
  result.methodName = "$logCallsWrapper::" + qualifiedMethodName(func);
  return result;
}

function traceCalls(func, stack) {
  var advice = function traceCallsAdvice(proceed) {
    var args = Array.prototype.slice.call(arguments);
    args.shift();
    stack.push(args);
    var result = proceed.apply(func, args);
    stack.pop();
    return result;
  };
  return wrap(func, advice);
}

function webkitStack() {
  // this won't work in every browser
  try {
    throw new Error();
  } catch (e) {
    // remove "Error" and this function from stack, rewrite it nicely
    return String(e.stack).split(/\n/).slice(2).map(function (line) {
      return line.replace(/^\s*at\s*([^\s]+).*/, '$1');
    }).join('\n');
  }
}



var fun = Object.freeze({
	Empty: Empty,
	K: K,
	Null: Null,
	False: False,
	True: True,
	notYetImplemented: notYetImplemented,
	withNull: withNull,
	all: all,
	own: own,
	argumentNames: argumentNames,
	qualifiedMethodName: qualifiedMethodName,
	extractBody: extractBody,
	timeToRun: timeToRun,
	timeToRunN: timeToRunN$1,
	delay: delay,
	throttle: throttle,
	debounce: debounce,
	throttleNamed: throttleNamed,
	debounceNamed: debounceNamed,
	createQueue: createQueue,
	workerWithCallbackQueue: workerWithCallbackQueue,
	composeAsync: composeAsync,
	compose: compose,
	waitFor: waitFor,
	waitForAll: waitForAll,
	flip: flip,
	curry: curry,
	wrap: wrap,
	binds: binds,
	getOriginal: getOriginal,
	wrapperChain: wrapperChain,
	replaceMethodForOneCall: replaceMethodForOneCall,
	once: once,
	either: either,
	eitherNamed: eitherNamed,
	evalJS: evalJS,
	fromString: fromString,
	asScript: asScript,
	asScriptOf: asScriptOf,
	addToObject: addToObject,
	setLocalVarValue: setLocalVarValue,
	getVarMapping: getVarMapping,
	setProperty: setProperty,
	functionNames: functionNames,
	localFunctionNames: localFunctionNames,
	logErrors: logErrors,
	logCompletion: logCompletion,
	logCalls: logCalls,
	traceCalls: traceCalls,
	webkitStack: webkitStack
});

// show-in-doc
// A Grouping is created by arr.groupBy and maps keys to Arrays.

var Group = function () {
  function Group() {
    classCallCheck(this, Group);
  }

  createClass(Group, [{
    key: "toArray",
    value: function toArray() {
      // Example:
      // var group = arr.groupBy([1,2,3,4,5], function(n) { return n % 2; })
      // group.toArray(); // => [[2,4],[1,3,5]]
      return this.reduceGroups(function (all$$1, _, group) {
        return all$$1.concat([group]);
      }, []);
    }
  }, {
    key: "forEach",
    value: function forEach(iterator, context) {
      // Iteration for each item in each group, called like `iterator(groupKey, groupItem)`
      var groups = this;
      Object.keys(groups).forEach(function (groupName) {
        groups[groupName].forEach(iterator.bind(context, groupName));
      });
      return groups;
    }
  }, {
    key: "forEachGroup",
    value: function forEachGroup(iterator, context) {
      // Iteration for each group, called like `iterator(groupKey, group)`
      var groups = this;
      Object.keys(groups).forEach(function (groupName) {
        iterator.call(context, groupName, groups[groupName]);
      });
      return groups;
    }
  }, {
    key: "map",
    value: function map(iterator, context) {
      // Map for each item in each group, called like `iterator(groupKey, group)`
      var result = new Group();
      this.forEachGroup(function (groupName, group) {
        result[groupName] = group.map(iterator.bind(context, groupName));
      });
      return result;
    }
  }, {
    key: "mapGroups",
    value: function mapGroups(iterator, context) {
      // Map for each group, called like `iterator(groupKey, group)`
      var result = new Group();
      this.forEachGroup(function (groupName, group) {
        result[groupName] = iterator.call(context, groupName, group);
      });
      return result;
    }
  }, {
    key: "keys",
    value: function keys() {
      // show-in-docs
      return Object.keys(this);
    }
  }, {
    key: "reduceGroups",
    value: function reduceGroups(iterator, carryOver, context) {
      // Reduce/fold for each group, called like `iterator(carryOver, groupKey, group)`
      this.forEachGroup(function (groupName, group) {
        carryOver = iterator.call(context, carryOver, groupName, group);
      });
      return carryOver;
    }
  }, {
    key: "count",
    value: function count() {
      // counts the elements of each group
      return this.reduceGroups(function (groupCount, groupName, group) {
        groupCount[groupName] = group.length;
        return groupCount;
      }, {});
    }
  }], [{
    key: "fromArray",
    value: function fromArray(array, hashFunc, context) {
      // Example:
      // Group.fromArray([1,2,3,4,5,6], function(n) { return n % 2; })
      // // => {"0": [2,4,6], "1": [1,3,5]}
      var grouping = new Group();
      for (var i = 0, len = array.length; i < len; i++) {
        var hash = hashFunc.call(context, array[i], i);
        if (!grouping[hash]) grouping[hash] = [];
        grouping[hash].push(array[i]);
      }
      return grouping;
    }
  }, {
    key: "by",
    get: function get() {
      return groupBy;
    }
  }]);
  return Group;
}();

/*global System, global*/

/*
 * Methods to make working with arrays more convenient and collection-like
 * abstractions for groups, intervals, grids.
 */

var GLOBAL$1 = typeof System !== "undefined" ? System.global : typeof window !== 'undefined' ? window : global;

var features$1 = {
  from: !!Array.from,
  filter: !!Array.prototype.filter,
  find: !!Array.prototype.find,
  findIndex: !!Array.prototype.findIndex,
  includes: !!Array.prototype.includes
};

// variety of functions for Arrays


// -=-=-=-=-=-=-=-
// array creations
// -=-=-=-=-=-=-=-

function range(begin, end, step) {
  // Examples:
  //   arr.range(0,5) // => [0,1,2,3,4,5]
  //   arr.range(0,10,2) // => [0,2,4,6,8,10]
  step = step || 0;
  var result = [];
  if (begin <= end) {
    if (step <= 0) step = -step || 1;
    for (var i = begin; i <= end; i += step) {
      result.push(i);
    }
  } else {
    if (step >= 0) step = -step || -1;
    for (var i = begin; i >= end; i += step) {
      result.push(i);
    }
  }
  return result;
}

var from = features$1.from ? Array.from : function (iterable) {
  // Makes JS arrays out of array like objects like `arguments` or DOM `childNodes`
  if (!iterable) return [];
  if (Array.isArray(iterable)) return iterable;
  if (iterable.toArray) return iterable.toArray();
  var length = iterable.length,
      results = new Array(length);
  while (length--) {
    results[length] = iterable[length];
  }return results;
};

function withN(n, obj) {
  // Example:
  //   arr.withN(3, "Hello") // => ["Hello","Hello","Hello"]
  var result = new Array(n);
  while (n > 0) {
    result[--n] = obj;
  }return result;
}

function genN(n, generator) {
  // Number -> Function -> Array
  // Takes a generator function that is called for each `n`.
  // Example:
  //   arr.genN(3, num.random) // => [46,77,95]
  var result = new Array(n);
  while (n > 0) {
    result[--n] = generator(n);
  }return result;
}

// -=-=-=-=-
// filtering
// -=-=-=-=-

function filter(array, iterator, context) {
  // [a] -> (a -> Boolean) -> c? -> [a]
  // Calls `iterator` for each element in `array` and returns a subset of it
  // including the elements for which `iterator` returned a truthy value.
  // Like `Array.prototype.filter`.
  return array.filter(iterator, context);
}

var detect = features$1.find ? function (arr, iterator, context) {
  return arr.find(iterator, context);
} : function (arr, iterator, context) {
  // [a] -> (a -> Boolean) -> c? -> a
  // returns the first occurrence of an element in `arr` for which iterator
  // returns a truthy value
  for (var value, i = 0, len = arr.length; i < len; i++) {
    value = arr[i];
    if (iterator.call(context, value, i)) return value;
  }
  return undefined;
};

var findIndex = features$1.findIndex ? function (arr, iterator, context) {
  return arr.findIndex(iterator, context);
} : function (arr, iterator, context) {
  var i = -1;
  return arr.find(function (ea, j) {
    i = j;return iterator.call(ea, context);
  }) ? i : -1;
};

function findAndGet(arr, iterator) {
  // find the first occurence for which `iterator` returns a truthy value and
  // return *this* value, i.e. unlike find the iterator result and not the
  // element of the list is returned
  var result;
  arr.find(function (ea, i) {
    return result = iterator(ea, i);
  });
  return result;
}

function filterByKey(arr, key) {
  // [a] -> String -> [a]
  // Example:
  //   var objects = [{x: 3}, {y: 4}, {x:5}]
  //   arr.filterByKey(objects, "x") // => [{x: 3},{x: 5}]
  return arr.filter(function (ea) {
    return !!ea[key];
  });
}

function grep(arr, filter, context) {
  // [a] -> String|RegExp -> [a]
  // `filter` can be a String or RegExp. Will stringify each element in
  // Example:
  // ["Hello", "World", "Lively", "User"].grep("l") // => ["Hello","World","Lively"]
  if (typeof filter === 'string') filter = new RegExp(filter, 'i');
  return arr.filter(filter.test.bind(filter));
}

function mask(array, mask) {
  // select every element in array for which array's element is truthy
  // Example: [1,2,3].mask([false, true, false]) => [2]
  return array.filter(function (_, i) {
    return !!mask[i];
  });
}

function reject(array, func, context) {
  // show-in-doc
  function iterator(val, i) {
    return !func.call(context, val, i);
  }
  return array.filter(iterator);
}

function rejectByKey(array, key) {
  // show-in-doc
  return array.filter(function (ea) {
    return !ea[key];
  });
}

function without(array, elem) {
  // non-mutating
  // Example:
  // arr.without([1,2,3,4,5,6], 3) // => [1,2,4,5,6]
  return array.filter(function (val) {
    return val !== elem;
  });
}

function withoutAll(array, otherArr) {
  // non-mutating
  // Example:
  // arr.withoutAll([1,2,3,4,5,6], [3,4]) // => [1,2,5,6]
  return array.filter(function (val) {
    return otherArr.indexOf(val) === -1;
  });
}

function uniq(array, sorted) {
  // non-mutating
  // Removes duplicates from array.
  // if sorted == true then assume array is sorted which allows uniq to be more
  // efficient
  // uniq([3,5,6,2,3,4,2,6,4])
  if (!array.length) return array;

  var result = [array[0]];
  if (sorted) {
    for (var i = 1; i < array.length; i++) {
      var val = array[i];
      if (val !== result[result.length]) result.push(val);
    }
  } else {
    for (var _i = 1; _i < array.length; _i++) {
      var _val = array[_i];
      if (result.indexOf(_val) === -1) result.push(_val);
    }
  }
  return result;
}

function uniqBy(array, comparator, context) {
  // like `arr.uniq` but with custom equality: `comparator(a,b)` returns
  // BOOL. True if a and be should be regarded equal, false otherwise.
  var result = array.slice();
  for (var i = result.length; i--;) {
    var item = array[i];
    for (var j = i + 1; j < result.length; j++) {
      if (comparator.call(context, item, result[j])) result.splice(j--, 1);
    }
  }
  return result;
}

function uniqByKey(array, key) {
  // like `arr.uniq` but with equality based on item[key]
  var seen = {},
      result = [];
  for (var i = 0; i < array.length; i++) {
    var item = array[i];
    if (!seen[item[key]]) {
      seen[item[key]] = true;
      result.push(item);
    }
  }
  return result;
}

function compact(array) {
  // removes falsy values
  // Example:
  // arr.compact([1,2,undefined,4,0]) // => [1,2,4]
  return array.filter(Boolean);
}

function mutableCompact(array) {
  // fix gaps that were created with 'delete'
  var i = 0,
      j = 0,
      len = array.length;
  while (i < len) {
    if (array.hasOwnProperty(i)) array[j++] = array[i];
    i++;
  }
  while (j++ < len) {
    array.pop();
  }return array;
}

// -=-=-=-=-
// iteration
// -=-=-=-=-

function forEach$1(array, iterator, context) {
  // [a] -> (a -> Undefined) -> c? -> Undefined
  // `iterator` is called on each element in `array` for side effects. Like
  // `Array.prototype.forEach`.
  return array.forEach(iterator, context);
}

function zip() /*arr, arr2, arr3*/{
  // Takes any number of lists as arguments. Combines them elment-wise.
  // Example:
  // arr.zip([1,2,3], ["a", "b", "c"], ["A", "B"])
  // // => [[1,"a","A"],[2,"b","B"],[3,"c",undefined]]
  var args = Array.from(arguments),
      array = args.shift(),
      iterator = typeof last(args) === 'function' ? args.pop() : function (x) {
    return x;
  },
      collections = [array].concat(args).map(function (ea) {
    return Array.from(ea);
  });
  return array.map(function (value, index) {
    return iterator(pluck(collections, index), index);
  });
}

function flatten(array, optDepth) {
  // Turns a nested collection into a flat one.
  // Example:
  // arr.flatten([1, [2, [3,4,5], [6]], 7,8])
  // // => [1,2,3,4,5,6,7,8]
  if (typeof optDepth === "number") {
    if (optDepth <= 0) return array;
    optDepth--;
  }
  return array.reduce(function (flattened, value) {
    return flattened.concat(Array.isArray(value) ? flatten(value, optDepth) : [value]);
  }, []);
}

function flatmap(array, it, ctx) {
  // the simple version
  // Array.prototype.concat.apply([], array.map(it, ctx));
  // causes stack overflows with really big arrays
  var results = [];
  for (var i = 0; i < array.length; i++) {
    results.push.apply(results, it.call(ctx, array[i], i));
  }
  return results;
}

function interpose(array, delim) {
  // Injects delim between elements of array
  // Example:
  // lively.lang.arr.interpose(["test", "abc", 444], "aha"));
  // // => ["test","aha","abc","aha",444]
  return array.reduce(function (xs, x) {
    if (xs.length > 0) xs.push(delim);
    xs.push(x);return xs;
  }, []);
}

function delimWith(array, delim) {
  // ignore-in-doc
  // previously used, use interpose now!
  return interpose(array, delim);
}

// -=-=-=-=-
// mapping
// -=-=-=-=-

function map$1(array, iterator, context) {
  // [a] -> (a -> b) -> c? -> [b]
  // Applies `iterator` to each element of `array` and returns a new Array
  // with the results of those calls. Like `Array.prototype.some`.
  return array.map(iterator, context);
}

function invoke(array, method, arg1, arg2, arg3, arg4, arg5, arg6) {
  // Calls `method` on each element in `array`, passing all arguments. Often
  // a handy way to avoid verbose `map` calls.
  // Example: arr.invoke(["hello", "world"], "toUpperCase") // => ["HELLO","WORLD"]
  return array.map(function (ea) {
    return ea[method](arg1, arg2, arg3, arg4, arg5, arg6);
  });
}

function pluck(array, property) {
  // Returns `property` or undefined from each element of array. For quick
  // `map`s and similar to `invoke`.
  // Example: arr.pluck(["hello", "world"], 0) // => ["h","w"]
  return array.map(function (ea) {
    return ea[property];
  });
}

// -=-=-=-=-
// folding
// -=-=-=-=-

function reduce(array, iterator, memo, context) {
  // Array -> Function -> Object? -> Object? -> Object?
  // Applies `iterator` to each element of `array` and returns a new Array
  // with the results of those calls. Like `Array.prototype.some`.
  return array.reduce(iterator, memo, context);
}

function reduceRight(array, iterator, memo, context) {
  // show-in-doc
  return array.reduceRight(iterator, memo, context);
}

// -=-=-=-=-
// testing
// -=-=-=-=-

var isArray$1 = Array.isArray;

var includes$1 = features$1.includes ? function (array, object) {
  return array.includes(object);
} : function (array, object) {
  // Example: arr.include([1,2,3], 2) // => true
  return array.indexOf(object) !== -1;
};

var include$1 = includes$1;

function some(array, iterator, context) {
  // [a] -> (a -> Boolean) -> c? -> Boolean
  // Returns true if there is at least one abject in `array` for which
  // `iterator` returns a truthy result. Like `Array.prototype.some`.
  return array.some(iterator, context);
}

function every(array, iterator, context) {
  // [a] -> (a -> Boolean) -> c? -> Boolean
  // Returns true if for all abjects in `array` `iterator` returns a truthy
  // result. Like `Array.prototype.every`.
  return array.every(iterator, context);
}

function equals$2(array, otherArray) {
  // Returns true iff each element in `array` is equal (`==`) to its
  // corresponding element in `otherArray`
  var len = array.length;
  if (!otherArray || len !== otherArray.length) return false;
  for (var i = 0; i < len; i++) {
    if (array[i] && otherArray[i] && array[i].equals && otherArray[i].equals) {
      if (!array[i].equals(otherArray[i])) {
        return false;
      } else {
        continue;
      }
    }
    if (array[i] != otherArray[i]) return false;
  }
  return true;
}

function deepEquals(array, otherArray) {
  // Returns true iff each element in `array` is structurally equal
  // (`lang.obj.equals`) to its corresponding element in `otherArray`
  var len = array.length;
  if (!otherArray || len !== otherArray.length) return false;
  for (var i = 0; i < len; i++) {
    if (!equals$1(array[i], otherArray[i])) return false;
  }
  return true;
}

// -=-=-=-=-
// sorting
// -=-=-=-=-

function isSorted(array, descending) {
  if (descending) {
    for (var i = 1; i < array.length; i++) {
      if (array[i - 1] < array[i]) return false;
    }
  } else {
    for (var i = 1; i < array.length; i++) {
      if (array[i - 1] > array[i]) return false;
    }
  }
  return true;
}

function sort(array, sortFunc) {
  // [a] -> (a -> Number)? -> [a]
  // Just `Array.prototype.sort`
  return array.sort(sortFunc);
}

function sortBy(array, iterator, context) {
  // Example:
  // arr.sortBy(["Hello", "Lively", "User"], function(ea) {
  //   return ea.charCodeAt(ea.length-1); }) // => ["Hello","User","Lively"]
  return pluck(array.map(function (value, index) {
    return { value: value, criteria: iterator.call(context, value, index) };
  }).sort(function (left, right) {
    var a = left.criteria,
        b = right.criteria;
    return a < b ? -1 : a > b ? 1 : 0;
  }), 'value');
}

function sortByKey(array, key) {
  // Example:
  // lively.lang.arr.sortByKey([{x: 3}, {x: 2}, {x: 8}], "x")
  // // => [{x: 2},{x: 3},{x: 8}]
  return sortBy(array, function (ea) {
    return ea[key];
  });
}

function reverse(array) {
  return array.reverse();
}

function reversed(array) {
  return array.slice().reverse();
}

// -=-=-=-=-=-=-=-=-=-=-=-=-
// RegExp / String matching
// -=-=-=-=-=-=-=-=-=-=-=-=-

function reMatches$1(arr, re, stringifier) {
  // result might include null items if re did not match (usful for masking)
  // Example:
  //   var morphs = $world.withAllSubmorphsDo(function(x) { return x; ;
  //   morphs.mask(morphs.reMatches(/code/i))
  stringifier = stringifier || String;
  return arr.map(function (ea) {
    return stringifier(ea).match(re);
  });
}

// -=-=-=-=-=-
// accessors
// -=-=-=-=-=-

function first(array) {
  return array[0];
}

function last(array) {
  return array[array.length - 1];
}

// -=-=-=-=-=-=-=-
// Set operations
// -=-=-=-=-=-=-=-

function intersect(array1, array2) {
  // set-like intersection
  return uniq(array1).filter(function (item) {
    return array2.indexOf(item) > -1;
  });
}

function union(array1, array2) {
  // set-like union
  var result = array1.slice();
  for (var i = 0; i < array2.length; i++) {
    var item = array2[i];
    if (result.indexOf(item) === -1) result.push(item);
  }
  return result;
}

function pushAt(array, item, index) {
  // inserts `item` at `index`, mutating
  array.splice(index, 0, item);
}

function removeAt(array, index) {
  // inserts item at `index`, mutating
  array.splice(index, 1);
}

function remove(array, item) {
  // removes first occurrence of item in `array`, mutating
  var index = array.indexOf(item);
  if (index >= 0) removeAt(array, index);
  return item;
}

function pushAll$1(array, items) {
  // appends all `items`, mutating
  array.push.apply(array, items);
  return array;
}

function pushAllAt(array, items, idx) {
  // inserts all `items` at `idx`, mutating
  array.splice.apply(array, [idx, 0].concat(items));
}

function pushIfNotIncluded(array, item) {
  // only appends `item` if its not already in `array`, mutating
  if (!array.includes(item)) array.push(item);
}

function replaceAt(array, item, index) {
  // mutating
  array.splice(index, 1, item);
}

function clear(array) {
  // removes all items, mutating
  array.length = 0;return array;
}

function isSubset(list1, list2) {
  // are all elements in list1 in list2?
  for (var i = 0; i < list1.length; i++) {
    if (!list2.includes(list1[i])) return false;
  }return true;
}

// -=-=-=-=-=-=-=-=-=-=-=-
// asynchronous iteration
// -=-=-=-=-=-=-=-=-=-=-=-
function doAndContinue(array, iterator, endFunc, context) {
  // Iterates over array but instead of consecutively calling iterator,
  // iterator gets passed in the invocation for the next iteration step
  // as a function as first parameter. This allows to wait arbitrarily
  // between operation steps, great for managing dependencies between tasks.
  // Related is [`fun.composeAsync`]().
  // Example:
  // arr.doAndContinue([1,2,3,4], function(next, n) {
  //   alert("At " + n);
  //   setTimeout(next, 100);
  // }, function() { alert("Done"); })
  // // If the elements are functions you can leave out the iterator:
  // arr.doAndContinue([
  //   function(next) { alert("At " + 1); next(); },
  //   function(next) { alert("At " + 2); next(); }
  // ], null, function() { alert("Done"); });
  endFunc = endFunc || Null;
  context = context || GLOBAL$1;
  iterator = iterator || function (next, ea, idx) {
    ea.call(context, next, idx);
  };
  return array.reduceRight(function (nextFunc, ea, idx) {
    return function () {
      iterator.call(context, nextFunc, ea, idx);
    };
  }, endFunc)();
}

function nestedDelay(array, iterator, waitSecs, endFunc, context, optSynchronChunks) {
  // Calls `iterator` for every element in `array` and waits between iterator
  // calls `waitSecs`. Eventually `endFunc` is called. When passing a number n
  // as `optSynchronChunks`, only every nth iteration is delayed.
  endFunc = endFunc || function () {};
  return array.clone().reverse().reduce(function (nextFunc, ea, idx) {
    return function () {
      iterator.call(context || GLOBAL$1, ea, idx);
      // only really delay every n'th call optionally
      if (optSynchronChunks && idx % optSynchronChunks !== 0) {
        nextFunc();
      } else {
        nextFunc.delay(waitSecs);
      }
    };
  }, endFunc)();
}

function forEachShowingProgress() /*array, progressBar, iterator, labelFunc, whenDoneFunc, context or spec*/{
  // ignore-in-doc
  var args = Array.from(arguments),
      array = args.shift(),
      steps = array.length,
      progressBar,
      iterator,
      labelFunc,
      whenDoneFunc,
      context,
      progressBarAdded = false;

  // init args
  if (args.length === 1) {
    progressBar = args[0].progressBar;
    iterator = args[0].iterator;
    labelFunc = args[0].labelFunction;
    whenDoneFunc = args[0].whenDone;
    context = args[0].context;
  } else {
    progressBar = args[0];
    iterator = args[1];
    labelFunc = args[2];
    whenDoneFunc = args[3];
    context = args[4];
  }
  if (!context) context = typeof window !== 'undefined' ? window : global;
  if (!labelFunc) labelFunc = function labelFunc(x) {
    return x;
  };

  // init progressbar
  if (!progressBar) {
    progressBarAdded = true;
    var Global = typeof window !== 'undefined' ? window : global;
    var world = Global.lively && lively.morphic && lively.morphic.World.current();
    progressBar = world ? world.addProgressBar() : {
      setValue: function setValue(val) {},
      setLabel: function setLabel() {},
      remove: function remove() {}
    };
  }
  progressBar.setValue(0);

  // nest functions so that the iterator calls the next after a delay
  array.reduceRight(function (nextFunc, item, idx) {
    return function () {
      try {
        progressBar.setValue(idx / steps);
        if (labelFunc) progressBar.setLabel(labelFunc.call(context, item, idx));
        iterator.call(context, item, idx);
      } catch (e) {
        console.error('Error in forEachShowingProgress at %s (%s)\n%s\n%s', idx, item, e, e.stack);
      }
      nextFunc.delay(0);
    };
  }, function () {
    progressBar.setValue(1);
    if (progressBarAdded) (function () {
      progressBar.remove();
    }).delay(0);
    if (whenDoneFunc) whenDoneFunc.call(context);
  })();

  return array;
}

function swap(array, index1, index2) {
  // mutating
  // Example:
  // var a = [1,2,3,4];
  // arr.swap(a, 3, 1);
  // a // => [1,4,3,2]
  if (index1 < 0) index1 = array.length + index1;
  if (index2 < 0) index2 = array.length + index2;
  var temp = array[index1];
  array[index1] = array[index2];
  array[index2] = temp;
  return array;
}

function rotate(array, times) {
  // non-mutating
  // Example:
  // arr.rotate([1,2,3]) // => [2,3,1]
  times = times || 1;
  return array.slice(times).concat(array.slice(0, times));
}

// -=-=-=-=-
// grouping
// -=-=-=-=-

function groupBy(array, iterator, context) {
  // Applies `iterator` to each element in `array`, and puts the return value
  // into a collection (the group) associated to it's stringified representation
  // (the "hash").
  // See [`Group.prototype`] for available operations on groups.
  // Example:
  // Example 1: Groups characters by how often they occur in a string:
  // var chars = arr.from("Hello World");
  // arr.groupBy(arr.uniq(chars), function(c) {
  //   return arr.count(chars, c); })
  // // => {
  // //   "1": ["H","e"," ","W","r","d"],
  // //   "2": ["o"],
  // //   "3": ["l"]
  // // }
  // // Example 2: Group numbers by a custom qualifier:
  // arr.groupBy([3,4,1,7,4,3,8,4], function(n) {
  //   if (n <= 3) return "small";
  //   if (n <= 7) return "medium";
  //   return "large";
  // });
  // // => {
  // //   large: [8],
  // //   medium: [4,7,4,4],
  // //   small: [3,1,3]
  // // }
  return Group.fromArray(array, iterator, context);
}

function groupByKey(array, key) {
  // var objects = [{x: }]
  // arr.groupBy(arr.uniq(chars), function(c) {
  //   return arr.count(chars, c); })
  // // => {
  // //   "1": ["H","e"," ","W","r","d"],
  // //   "2": ["o"],
  // //   "3": ["l"]
  // // }
  return groupBy(array, function (ea) {
    return ea[key];
  });
}

function partition(array, iterator, context) {
  // Example:
  // var array = [1,2,3,4,5,6];
  // arr.partition(array, function(ea) { return ea > 3; })
  // // => [[1,2,3,4],[5,6]]
  iterator = iterator || function (x) {
    return x;
  };
  var trues = [],
      falses = [];
  array.forEach(function (value, index) {
    (iterator.call(context, value, index) ? trues : falses).push(value);
  });
  return [trues, falses];
}

function batchify(array, constrainedFunc, context) {
  // Takes elements and fits them into subarrays (= batches) so that for
  // each batch constrainedFunc returns true. Note that contrained func
  // should at least produce 1-length batches, otherwise an error is raised
  // Example:
  // // Assume you have list of things that have different sizes and you want to
  // // create sub-arrays of these things, with each sub-array having if possible
  // // less than a `batchMaxSize` of combined things in it:
  // var sizes = [
  //   Math.pow(2, 15), // 32KB
  //   Math.pow(2, 29), // 512MB
  //   Math.pow(2, 29), // 512MB
  //   Math.pow(2, 27), // 128MB
  //   Math.pow(2, 26), // 64MB
  //   Math.pow(2, 26), // 64MB
  //   Math.pow(2, 24), // 16MB
  //   Math.pow(2, 26)] // 64MB
  // var batchMaxSize = Math.pow(2, 28)/*256MB*/;
  // function batchConstrained(batch) {
  //   return batch.length == 1 || batch.sum() < batchMaxSize;
  // }
  // var batches = sizes.batchify(batchConstrained);
  // batches.pluck('length') // => [4,1,1,2]
  // batches.map(arr.sum).map(num.humanReadableByteSize) // => ["208.03MB","512MB","512MB","128MB"]

  return findBatches([], array);

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  function extractBatch(batch, sizes) {
    // ignore-in-doc
    // Array -> Array -> Array[Array,Array]
    // case 1: no sizes to distribute, we are done
    if (!sizes.length) return [batch, []];
    var first = sizes[0],
        rest = sizes.slice(1);
    // if batch is empty we have to take at least one
    // if batch and first still fits, add first
    var candidate = batch.concat([first]);
    if (constrainedFunc.call(context, candidate)) return extractBatch(candidate, rest);
    // otherwise leave first out for now
    var batchAndSizes = extractBatch(batch, rest);
    return [batchAndSizes[0], [first].concat(batchAndSizes[1])];
  }

  function findBatches(batches, sizes) {
    if (!sizes.length) return batches;
    var extracted = extractBatch([], sizes);
    if (!extracted[0].length) throw new Error('Batchify constrained does not ensure consumption ' + 'of at least one item per batch!');
    return findBatches(batches.concat([extracted[0]]), extracted[1]);
  }
}

function toTuples(array, tupleLength) {
  // Creates sub-arrays with length `tupleLength`
  // Example:
  // arr.toTuples(["H","e","l","l","o"," ","W","o","r","l","d"], 4)
  // // => [["H","e","l","l"],["o"," ","W","o"],["r","l","d"]]
  tupleLength = tupleLength || 1;
  return range(0, Math.ceil(array.length / tupleLength) - 1).map(function (n) {
    return array.slice(n * tupleLength, n * tupleLength + tupleLength);
  }, array);
}

var permutations = function () {
  function computePermutations(restArray, values$$1) {
    return !restArray.length ? [values$$1] : flatmap(restArray, function (ea, i) {
      return computePermutations(restArray.slice(0, i).concat(restArray.slice(i + 1)), values$$1.concat([ea]));
    });
  }
  return function (array) {
    return computePermutations(array, []);
  };
}();

function combinationsPick(listOfListsOfValues, pickIndices) {
  // Given a "listOfListsOfValues" in the form of an array of arrays and
  // `pickIndices` list with the size of the number of arrays which indicates what
  // values to pick from each of the arrays, return a list with two values:
  // 1. values picked from each of the arrays, 2. the next pickIndices or null if at end
  // Example:
  //  var searchSpace = [["a", "b", "c"], [1,2]];
  //  arr.combinationsPick(searchSpace, [0,1]);
  //    // => [["a",2], [1,0]]
  //  arr.combinationsPick(searchSpace, [1,0]);
  //    // => [["b",1], [1,1]]
  var values$$1 = listOfListsOfValues.map(function (subspace, i) {
    return subspace[pickIndices[i]];
  }),
      nextState = pickIndices.slice();
  for (var i = listOfListsOfValues.length; i--; i >= 0) {
    var subspace = listOfListsOfValues[i],
        nextIndex = nextState[i] + 1;
    if (subspace[nextIndex]) {
      nextState[i] = nextIndex;break;
    } else if (i === 0) {
      nextState = undefined;break;
    } else {
      nextState[i] = 0;
    }
  }
  return [values$$1, nextState];
}

function combinations(listOfListsOfValues) {
  // Given a "listOfListsOfValues" in the form of an array of arrays,
  // retrieve all the combinations by picking one item from each array.
  // This basically creates a search tree, traverses it and gathers all node
  // values whenever a leaf node is reached.
  // Example:
  //   lively.lang.arr.combinations([['a', 'b', 'c'], [1, 2]])
  //    // => [["a", 1], ["a", 2], ["b", 1], ["b", 2], ["c", 1], ["c", 2]]
  var size = listOfListsOfValues.reduce(function (prod, space) {
    return prod * space.length;
  }, 1),
      searchState = listOfListsOfValues.map(function (_) {
    return 0;
  }),
      results = new Array(size);
  for (var i = 0; i < size; i++) {
    var result = combinationsPick(listOfListsOfValues, searchState);
    results[i] = result[0];
    searchState = result[1];
  }
  return results;
}

function take(arr, n) {
  return arr.slice(0, n);
}

function drop(arr, n) {
  return arr.slice(n);
}

function takeWhile(arr, fun, context) {
  var i = 0;
  for (; i < arr.length; i++) {
    if (!fun.call(context, arr[i], i)) break;
  }return arr.slice(0, i);
}

function dropWhile(arr, fun, context) {
  var i = 0;
  for (; i < arr.length; i++) {
    if (!fun.call(context, arr[i], i)) break;
  }return arr.slice(i);
}

// -=-=-=-=-=-
// randomness
// -=-=-=-=-=-

function shuffle(array) {
  // Ramdomize the order of elements of array. Does not mutate array.
  // Example:
  // shuffle([1,2,3,4,5]) // => [3,1,2,5,4]
  var unusedIndexes = range(0, array.length - 1),
      shuffled = Array(array.length);
  for (var i = 0; i < array.length; i++) {
    var shuffledIndex = unusedIndexes.splice(Math.round(Math.random() * (unusedIndexes.length - 1)), 1);
    shuffled[shuffledIndex] = array[i];
  }
  return shuffled;
}

// -=-=-=-=-=-=-=-
// Number related
// -=-=-=-=-=-=-=-

function max(array, iterator, context) {
  // Example:
  //   var array = [{x:3,y:2}, {x:5,y:1}, {x:1,y:5}];
  //   arr.max(array, function(ea) { return ea.x; }) // => {x: 5, y: 1}
  iterator = iterator || function (x) {
    return x;
  };
  var result;
  array.reduce(function (max, ea, i) {
    var val = iterator.call(context, ea, i);
    if (typeof val !== "number" || val <= max) return max;
    result = ea;return val;
  }, -Infinity);
  return result;
}

function min(array, iterator, context) {
  // Similar to `arr.max`.
  iterator = iterator || function (x) {
    return x;
  };
  return max(array, function (ea, i) {
    return -iterator.call(context, ea, i);
  });
}

function sum(array) {
  // show-in-doc
  var sum = 0;
  for (var i = 0; i < array.length; i++) {
    sum += array[i];
  }return sum;
}

function count$1(array, item) {
  return array.reduce(function (count, ea) {
    return ea === item ? count + 1 : count;
  }, 0);
}

function size$1(array) {
  return array.length;
}

function histogram(data, binSpec) {
  // ignore-in-doc
  // Without a `binSpec` argument partition the data
  // var numbers = arr.genN(10, num.random);
  // var numbers = arr.withN(10, "a");
  // => [65,73,34,94,92,31,27,55,95,48]
  // => [[65,73],[34,94],[92,31],[27,55],[95,48]]
  // => [[82,50,16],[25,43,77],[40,64,31],[51,39,13],[17,34,87],[51,33,30]]
  if (typeof binSpec === 'undefined' || typeof binSpec === 'number') {
    var binNumber = binSpec || function sturge() {
      return Math.ceil(Math.log(data.length) / Math.log(2) + 1);
    }(data);
    var binSize = Math.ceil(Math.round(data.length / binNumber));
    return range(0, binNumber - 1).map(function (i) {
      return data.slice(i * binSize, (i + 1) * binSize);
    });
  } else if (binSpec instanceof Array) {
    // ignore-in-doc
    // bins specifies n threshold values that will create n-1 bins.
    // Each data value d is placed inside a bin i if:
    // threshold[i] >= d && threshold[i+1] < d
    var thresholds = binSpec;
    return data.reduce(function (bins, d) {
      if (d < thresholds[1]) {
        bins[0].push(d);return bins;
      }
      for (var i = 1; i < thresholds.length; i++) {
        if (d >= thresholds[i] && (!thresholds[i + 1] || d <= thresholds[i + 1])) {
          bins[i].push(d);return bins;
        }
      }
      throw new Error("Histogram creation: Cannot group data " + d + " into thresholds " + thresholds);
    }, range(1, thresholds.length).map(function () {
      return [];
    }));
  }
}

// -=-=-=-=-
// Copying
// -=-=-=-=-

function clone$1(array) {
  // shallow copy
  return [].concat(array);
}

// -=-=-=-=-=-
// conversion
// -=-=-=-=-=-

function toArray$3(array) {
  return from(array);
}

// -=-=-=-=-=-
// DEPRECATED
// -=-=-=-=-=-

function each(arr, iterator, context) {
  return arr.forEach(iterator, context);
}

function all$1(arr, iterator, context) {
  return arr.every(iterator, context);
}

function any(arr, iterator, context) {
  return arr.some(iterator, context);
}

function collect(arr, iterator, context) {
  return arr.map(iterator, context);
}

function findAll(arr, iterator, context) {
  return arr.filter(iterator, context);
}

function inject(array, memo, iterator, context) {
  if (context) iterator = iterator.bind(context);
  return array.reduce(iterator, memo);
}

// asynch methods
function mapAsyncSeries(array, iterator, callback) {
  // Apply `iterator` over `array`. Unlike `mapAsync` the invocation of
  // the iterator happens step by step in the order of the items of the array
  // and not concurrently.

  // ignore-in-doc
  // Could simply be:
  // return exports.arr.mapAsync(array, {parallel: 1}, iterator, callback);
  // but the version below is 2x faster

  var result = [],
      callbackTriggered = false;
  return array.reduceRight(function (nextFunc, ea, idx) {
    if (callbackTriggered) return;
    return function (err, eaResult) {
      if (err) return maybeDone(err);
      if (idx > 0) result.push(eaResult);
      try {
        iterator(ea, idx, once(nextFunc));
      } catch (e) {
        maybeDone(e);
      }
    };
  }, function (err, eaResult) {
    result.push(eaResult);
    maybeDone(err, true);
  })();

  function maybeDone(err, finalCall) {
    if (callbackTriggered || !err && !finalCall) return;
    callbackTriggered = true;
    try {
      callback(err, result);
    } catch (e) {
      console.error("Error in mapAsyncSeries - callback invocation error:\n" + (e.stack || e));
    }
  }
}

function mapAsync(array, options, iterator, callback) {
  // Apply `iterator` over `array`. In each iterator gets a callback as third
  // argument that should be called when the iteration is done. After all
  // iterators have called their callbacks, the main `callback` function is
  // invoked with the result array.
  // Example:
  // lively.lang.arr.mapAsync([1,2,3,4],
  //   function(n, i, next) { setTimeout(function() { next(null, n + i); }, 20); },
  //   function(err, result) { /* result => [1,3,5,7] */ });

  if (typeof options === "function") {
    callback = iterator;
    iterator = options;
    options = null;
  }
  options = options || {};

  if (!array.length) return callback && callback(null, []);

  if (!options.parallel) options.parallel = Infinity;

  var results = [],
      completed = [],
      callbackTriggered = false,
      lastIteratorIndex = 0,
      nActive = 0;

  var iterators = array.map(function (item, i) {
    return function () {
      nActive++;
      try {
        iterator(item, i, once(function (err, result) {
          results[i] = err || result;
          maybeDone(i, err);
        }));
      } catch (e) {
        maybeDone(i, e);
      }
    };
  });

  return activate();

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  function activate() {
    while (nActive < options.parallel && lastIteratorIndex < array.length) {
      iterators[lastIteratorIndex++]();
    }
  }

  function maybeDone(idx, err) {
    if (completed.indexOf(idx) > -1) return;
    completed.push(idx);
    nActive--;
    if (callbackTriggered) return;
    if (!err && completed.length < array.length) {
      activate();return;
    }
    callbackTriggered = true;
    try {
      callback && callback(err, results);
    } catch (e) {
      console.error("Error in mapAsync - main callback invocation error:\n" + (e.stack || e));
    }
  }
}

// poly-filling...
if (!features$1.from) Array.from = from;
if (!features$1.filter) Array.prototype.filter = function (it, ctx) {
  return filter(this, it, ctx);
};
if (!features$1.find) Array.prototype.find = function (it, ctx) {
  return detect(this, it, ctx);
};
if (!features$1.findIndex) Array.prototype.findIndex = function (it, ctx) {
  return findIndex(this, it, ctx);
};
if (!features$1.includes) Array.prototype.includes = function (x) {
  return includes$1(this, x);
};



var arr = Object.freeze({
	range: range,
	from: from,
	withN: withN,
	genN: genN,
	filter: filter,
	detect: detect,
	findIndex: findIndex,
	findAndGet: findAndGet,
	filterByKey: filterByKey,
	grep: grep,
	mask: mask,
	reject: reject,
	rejectByKey: rejectByKey,
	without: without,
	withoutAll: withoutAll,
	uniq: uniq,
	uniqBy: uniqBy,
	uniqByKey: uniqByKey,
	compact: compact,
	mutableCompact: mutableCompact,
	forEach: forEach$1,
	zip: zip,
	flatten: flatten,
	flatmap: flatmap,
	interpose: interpose,
	delimWith: delimWith,
	map: map$1,
	invoke: invoke,
	pluck: pluck,
	reduce: reduce,
	reduceRight: reduceRight,
	isArray: isArray$1,
	includes: includes$1,
	include: include$1,
	some: some,
	every: every,
	equals: equals$2,
	deepEquals: deepEquals,
	isSorted: isSorted,
	sort: sort,
	sortBy: sortBy,
	sortByKey: sortByKey,
	reverse: reverse,
	reversed: reversed,
	reMatches: reMatches$1,
	first: first,
	last: last,
	intersect: intersect,
	union: union,
	pushAt: pushAt,
	removeAt: removeAt,
	remove: remove,
	pushAll: pushAll$1,
	pushAllAt: pushAllAt,
	pushIfNotIncluded: pushIfNotIncluded,
	replaceAt: replaceAt,
	clear: clear,
	isSubset: isSubset,
	doAndContinue: doAndContinue,
	nestedDelay: nestedDelay,
	forEachShowingProgress: forEachShowingProgress,
	swap: swap,
	rotate: rotate,
	groupBy: groupBy,
	groupByKey: groupByKey,
	partition: partition,
	batchify: batchify,
	toTuples: toTuples,
	permutations: permutations,
	combinationsPick: combinationsPick,
	combinations: combinations,
	take: take,
	drop: drop,
	takeWhile: takeWhile,
	dropWhile: dropWhile,
	shuffle: shuffle,
	max: max,
	min: min,
	sum: sum,
	count: count$1,
	size: size$1,
	histogram: histogram,
	clone: clone$1,
	toArray: toArray$3,
	each: each,
	all: all$1,
	any: any,
	collect: collect,
	findAll: findAll,
	inject: inject,
	mapAsyncSeries: mapAsyncSeries,
	mapAsync: mapAsync
});

/*
 * Utility functions that help to inspect, enumerate, and create JS objects
 */

// -=-=-=-=-=-=-=-=-
// internal helper
// -=-=-=-=-=-=-=-=-

// serveral methods in lib/object.js are inspired or derived from
// Prototype JavaScript framework, version 1.6.0_rc1
// (c) 2005-2007 Sam Stephenson
// Prototype is freely distributable under the terms of an MIT-style license.
// For details, see the Prototype web site: http://www.prototypejs.org/

function print$1(object) {
  if (object && Array.isArray(object)) {
    return '[' + object.map(print$1) + ']';
  }
  if (typeof object !== "string") {
    return String(object);
  }
  var result = String(object);
  result = result.replace(/\n/g, '\\n\\\n');
  result = result.replace(/(")/g, '\\$1');
  result = '\"' + result + '\"';
  return result;
}

function indent$1(str, indentString, depth) {
  if (!depth || depth <= 0) return str;
  while (depth > 0) {
    depth--;str = indentString + str;
  }
  return str;
}

var getOwnPropertyDescriptors = typeof Object.prototype.getOwnPropertyDescriptors === "function" ? Object.prototype.getOwnPropertyDescriptors : function getOwnPropertyDescriptors(object) {
  var descriptors = {};
  for (var name in object) {
    if (!Object.prototype.hasOwnProperty.call(object, name)) continue;
    Object.defineProperty(descriptors, name, {
      configurable: true,
      enumerable: true,
      writable: true,
      value: Object.getOwnPropertyDescriptor(object, name)
    });
  }
  return descriptors;
};

// show-in-doc

// -=-=-=-=-
// testing
// -=-=-=-=-

function isArray$$1(obj) {
  /*show-in-doc*/return Array.isArray(obj);
}

function isElement(object) {
  /*show-in-doc*/return object && object.nodeType == 1;
}

function isFunction(object) {
  /*show-in-doc*/return object instanceof Function;
}

function isBoolean(object) {
  /*show-in-doc*/return typeof object == "boolean";
}

function isString(object) {
  /*show-in-doc*/return typeof object == "string";
}

function isNumber(object) {
  /*show-in-doc*/return typeof object == "number";
}

function isUndefined(object) {
  /*show-in-doc*/return typeof object == "undefined";
}

function isRegExp(object) {
  /*show-in-doc*/return object instanceof RegExp;
}

function isObject(object) {
  /*show-in-doc*/return (typeof object === "undefined" ? "undefined" : _typeof(object)) == "object";
}

function isPrimitive(obj) {
  // show-in-doc
  if (!obj) return true;
  switch (typeof obj === "undefined" ? "undefined" : _typeof(obj)) {
    case "string":
    case "number":
    case "boolean":
      return true;
  }
  return false;
}

function isEmpty(object) {
  /*show-in-doc*/
  for (var key in object) {
    if (object.hasOwnProperty(key)) return false;
  }return true;
}

function equals$1(a, b) {
  // Is object `a` structurally equivalent to object `b`? Deep comparison.
  if (a === b) return true;
  if (!a || !b) return a == b;
  if (Array.isArray(a)) return deepEquals(a, b);
  switch (a.constructor) {
    case String:
    case Date:
    case Boolean:
    case Number:
      return a == b;
  }
  if (typeof a.isEqualNode === "function") return a.isEqualNode(b);
  if (typeof a.equals === "function") return a.equals(b);
  var seenInA = [];
  for (var name in a) {
    seenInA.push(name);
    if (typeof a[name] === "function") continue;
    if (!equals$1(a[name], b[name])) return false;
  }
  for (var name in b) {
    if (seenInA.indexOf(name) !== -1) continue;
    if (typeof b[name] === "function") continue;
    if (!equals$1(b[name], a[name])) return false;
  }
  return true;
}

// -=-=-=-=-=-
// accessing
// -=-=-=-=-=-

var keys$1 = Object.keys;

function values(object) {
  // Example:
  // var obj1 = {x: 22}, obj2 = {x: 23, y: {z: 3}};
  // obj2.__proto__ = obj1;
  // obj.values(obj1) // => [22]
  // obj.values(obj2) // => [23,{z: 3}]
  return object ? Object.keys(object).map(function (k) {
    return object[k];
  }) : [];
}

function select(obj, keys) {
  // return a new object that copies all properties with `keys` from `obj`
  var selected = {};
  for (var i = 0; i < keys.length; i++) {
    selected[keys[i]] = obj[keys[i]];
  }return selected;
}

function dissoc(object, keys) {
  object = object || {};
  var descriptors = getOwnPropertyDescriptors(object);
  for (var i = 0; i < keys.length; i++) {
    if (keys[i] in descriptors) delete descriptors[keys[i]];
  }
  return Object.defineProperties({}, descriptors);
}

function addScript(object, funcOrString, optName, optMapping) {
  var func = fromString(funcOrString);
  return asScriptOf(func, object, optName, optMapping);
}

// -=-=-=-=-
// mutation
// -=-=-=-=-
function extend(destination, source) {
  // Add all properties of `source` to `destination`.
  // Example:
  // var dest = {x: 22}, src = {x: 23, y: 24}
  // obj.extend(dest, src);
  // dest // => {x: 23,y: 24}

  var currentCategoryNames = null;
  for (var i = 1; i < arguments.length; i++) {
    if (typeof arguments[i] == "string") {
      var catName = arguments[i];
      if (!destination.categories) destination.categories = {};
      if (!destination.categories[catName]) destination.categories[catName] = [];
      currentCategoryNames = destination.categories[catName];
      continue;
    }

    var source = arguments[i];
    for (var property in source) {
      var getter = source.__lookupGetter__(property),
          setter = source.__lookupSetter__(property);
      if (getter) destination.__defineGetter__(property, getter);
      if (setter) destination.__defineSetter__(property, setter);
      if (getter || setter) continue;
      var sourceObj = source[property];
      destination[property] = sourceObj;
      if (currentCategoryNames) currentCategoryNames.push(property);
      if (typeof sourceObj === "function") {
        if (!sourceObj.displayName) sourceObj.displayName = property;
        // remember the module that contains the definition
        if (typeof lively !== "undefined" && lively.Module && lively.Module.current) sourceObj.sourceModule = lively.Module.current();
      }
    }
  }

  return destination;
}

// -=-=-=-=-
// clone
// -=-=-=-=-

function clone$$1(object) {
  // Shallow copy
  if (isPrimitive(object)) return object;
  if (Array.isArray(object)) return Array.prototype.slice.call(object);
  var clone$$1 = {};
  for (var key in object) {
    if (object.hasOwnProperty(key)) clone$$1[key] = object[key];
  }
  return clone$$1;
}

function extract(object, properties, mapFunc) {
  // Takes a list of properties and returns a new object with those
  // properties shallow-copied from object
  var copied = {};
  for (var i = 0; i < properties.length; i++) {
    if (properties[i] in object) copied[properties[i]] = mapFunc ? mapFunc(properties[i], object[properties[i]]) : object[properties[i]];
  }
  return copied;
}

// -=-=-=-=-=-
// inspection
// -=-=-=-=-=-
function inspect(object, options, depth) {
  // Prints a human-readable representation of `obj`. The printed
  // representation will be syntactically correct JavaScript but will not
  // necessarily evaluate to a structurally identical object. `inspect` is
  // meant to be used while interactivively exploring JavaScript programs and
  // state.
  //
  // `options` can be {
  //   printFunctionSource: BOOLEAN,
  //   escapeKeys: BOOLEAN,
  //   maxDepth: NUMBER,
  //   customPrinter: FUNCTION,
  //   maxNumberOfKeys: NUMBER
  // }
  options = options || {};
  depth = depth || 0;

  if (options.customPrinter) {
    var ignoreSignal = options._ignoreSignal || (options._ignoreSignal = {}),
        continueInspectFn = function continueInspectFn(obj) {
      return inspect(obj, options, depth + 1);
    },
        customInspected = options.customPrinter(object, ignoreSignal, continueInspectFn);
    if (customInspected !== ignoreSignal) return customInspected;
  }
  if (!object) return print$1(object);

  // print function
  if (typeof object === 'function') {
    return options.printFunctionSource ? String(object) : 'function' + (object.name ? ' ' + object.name : '') + '(' + argumentNames(object).join(',') + ') {/*...*/}';
  }

  // print "primitive"
  switch (object.constructor) {
    case String:
    case Boolean:
    case RegExp:
    case Number:
      return print$1(object);
  }

  if (typeof object.serializeExpr === 'function') return object.serializeExpr();

  var isArray$$1 = object && Array.isArray(object),
      openBr = isArray$$1 ? '[' : '{',
      closeBr = isArray$$1 ? ']' : '}';
  if (options.maxDepth && depth >= options.maxDepth) return openBr + '/*...*/' + closeBr;

  var printedProps = [];
  if (isArray$$1) {
    printedProps = object.map(function (ea) {
      return inspect(ea, options, depth + 1);
    });
  } else {
    var propsToPrint = Object.keys(object).sort(function (a, b) {
      var aIsFunc = typeof object[a] === 'function',
          bIsFunc = typeof object[b] === 'function';
      if (aIsFunc === bIsFunc) {
        if (a < b) return -1;
        if (a > b) return 1;
        return 0;
      }
      return aIsFunc ? 1 : -1;
    });
    for (var i = 0; i < propsToPrint.length; i++) {
      if (i > (options.maxNumberOfKeys || Infinity)) {
        var hiddenEntryCount = propsToPrint.length - i;
        printedProps.push("..." + hiddenEntryCount + " hidden " + (hiddenEntryCount > 1 ? 'entries' : 'entry') + "...");
        break;
      }
      var key = propsToPrint[i];
      if (isArray$$1) inspect(object[key], options, depth + 1);
      var printedVal = inspect(object[key], options, depth + 1);
      printedProps.push((options.escapeKeys ? JSON.stringify(key) : key) + ": " + printedVal);
    }
  }

  if (printedProps.length === 0) {
    return openBr + closeBr;
  }

  var printedPropsJoined = printedProps.join(', '),
      useNewLines = (!isArray$$1 || options.newLineInArrays) && (!options.minLengthForNewLine || printedPropsJoined.length >= options.minLengthForNewLine),
      ind = indent$1('', options.indent || '  ', depth),
      propIndent = indent$1('', options.indent || '  ', depth + 1),
      startBreak = useNewLines && !isArray$$1 ? '\n' + propIndent : '',
      eachBreak = useNewLines ? '\n' + propIndent : '',
      endBreak = useNewLines && !isArray$$1 ? '\n' + ind : '';
  if (useNewLines) printedPropsJoined = printedProps.join(',' + eachBreak);
  return openBr + startBreak + printedPropsJoined + endBreak + closeBr;
}

// -=-=-=-=-
// merging
// -=-=-=-=-
function merge(objs) {
  // `objs` can be a list of objects. The return value will be a new object,
  // containing all properties of all objects. If the same property exist in
  // multiple objects, the right-most property takes precedence.
  //
  // Like `extend` but will not mutate objects in `objs`.

  // if objs are arrays just concat them
  // if objs are real objs then merge propertdies
  if (arguments.length > 1) {
    return merge(Array.prototype.slice.call(arguments));
  }

  if (Array.isArray(objs[0])) {
    // test for all?
    return Array.prototype.concat.apply([], objs);
  }

  return objs.reduce(function (merged, ea) {
    for (var name in ea) {
      if (ea.hasOwnProperty(name)) merged[name] = ea[name];
    }return merged;
  }, {});
}

function deepMerge(objA, objB) {
  // `objs` can be a list of objects. The return value will be a new object,
  // containing all properties of all objects. If the same property exist in
  // multiple objects, the right-most property takes precedence.
  //
  // Like `extend` but will not mutate objects in `objs`.

  // if objs are arrays just concat them
  // if objs are real objs then merge propertdies

  if (!objA) return objB;
  if (!objB) return objA;

  if (Array.isArray(objA)) {
    if (!Array.isArray(objB)) return objB;
    var merged = objA.map(function (ea, i) {
      return deepMerge(ea, objB[i]);
    });
    if (objB.length > objA.length) merged = merged.concat(objB.slice(objA.length));
    return merged;
  }

  if ((typeof objA === "undefined" ? "undefined" : _typeof(objA)) !== "object" || (typeof objB === "undefined" ? "undefined" : _typeof(objB)) !== "object") return objB;

  return Object.keys(objA).concat(Object.keys(objB)).reduce(function (merged, name) {
    if (!objA[name]) merged[name] = objB[name];else if (!objB[name]) merged[name] = objA[name];else if (_typeof(objA[name]) !== "object" || _typeof(objB[name]) !== "object") merged[name] = objB[name];else merged[name] = deepMerge(objA[name], objB[name]);
    return merged;
  }, {});
}

function sortKeysWithBeforeAndAfterConstraints(properties) {
  var throwErrorOnMissing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

  // Expects `properties` to be a map of keys to objects having optional
  // before/after attributes that, if present, should be lists of other property
  // keys. `sortProperties` will return an ordered list of property keys so
  // that the before / after requirements are fullfilled. If a cyclic
  // dependency is encountered an error will be thrown.
  // Example:
  // ```
  // sortProperties({foo: {}, bar: {after: ["foo"], before: ["baz"]}, "baz": {after: ["foo"]}})
  // // => ["foo","bar","baz"]
  // ```

  // ignore-in-doc
  // 1. convert "before" requirement into "after" and check if all properties
  // mentioned in after/before are actually there
  var keys = [],
      props = [],
      remaining = [];
  for (var key in properties) {
    var prop = properties[key],
        before = prop.hasOwnProperty("before") ? prop.before : prop.before = [],
        after = prop.hasOwnProperty("after") ? prop.after : prop.after = [];

    keys.push(key);
    props.push(prop);

    for (var i = before.length; i--;) {
      var beforePropName = before[i];
      var beforeProp = properties[beforePropName];
      if (!beforeProp) {
        console.warn("[initializeProperties] " + this + " sortProperties: " + ("Property " + key + " requires to be initialized before " + beforePropName + " ") + "but that property cannot be found.");
        before.splice(i, 1);
        continue;
      }
      if (!beforeProp.hasOwnProperty("after")) beforeProp.after = [];
      beforeProp.after.push(key);
    }

    for (var _i = after.length; _i--;) {
      var afterPropName = after[_i];
      var afterProp = properties[afterPropName];
      if (!afterProp) {
        console.warn("[initializeProperties] " + this + " sortProperties: " + ("Property " + key + " requires to be initialized after " + afterPropName + " ") + "but that property cannot be found.");
        after.splice(_i, 1);
      }
    }

    remaining.push(key);
  }

  // ignore-in-doc
  // compute order
  var resolvedGroups = [],
      resolvedKeys = [],
      lastLength = remaining.length + 1;

  while (remaining.length) {
    if (lastLength === remaining.length) throw new Error("Circular dependencies in handler order, could not resolve properties " + remaining.map(function (key) {
      var before = properties[key].before,
          after = properties[key].after;
      if ((!before || !before.length) && (!after || !after.length)) return "";
      var report = key + "\n";
      if (before && before.length) report += "  - before " + before.join(",") + "\n";
      if (after && after.length) report += "  - after " + after.join(",") + "\n";
      return report;
    }).join(""));
    lastLength = remaining.length;
    var resolvedGroup = [];
    for (var _i2 = remaining.length; _i2--;) {
      var _key = remaining[_i2];
      if (isSubset(properties[_key].after, resolvedKeys)) {
        remaining.splice(_i2, 1);
        resolvedKeys.push(_key);
        resolvedGroup.push(_key);
      }
    }
    resolvedGroups.push(resolvedGroup);
  }

  return flatten(resolvedGroups, 1);
}

// -=-=-=-=-=-=-
// inheritance
// -=-=-=-=-=-=-
function inherit(obj) {
  return Object.create(obj);
}

function valuesInPropertyHierarchy(obj, name) {
  // Lookup all properties named name in the proto hierarchy of obj.
  // Example:
  // var a = {foo: 3}, b = Object.create(a), c = Object.create(b);
  // c.foo = 4;
  // obj.valuesInPropertyHierarchy(c, "foo") // => [3,4]
  var result = [],
      lookupObj = obj;
  while (lookupObj) {
    if (lookupObj.hasOwnProperty(name)) result.unshift(lookupObj[name]);
    lookupObj = Object.getPrototypeOf(lookupObj);
  }
  return result;
}

function mergePropertyInHierarchy(obj, propName) {
  // like `merge` but automatically gets all definitions of the value in the
  // prototype chain and merges those.
  // Example:
  // var o1 = {x: {foo: 23}}, o2 = {x: {foo: 24, bar: 15}}, o3 = {x: {baz: "zork"}};
  // o2.__proto__ = o1; o3.__proto__ = o2;
  // obj.mergePropertyInHierarchy(o3, "x");
  // // => {bar: 15, baz: "zork",foo: 24}
  return merge(valuesInPropertyHierarchy(obj, propName));
}

function deepCopy(object) {
  // Recursively traverses `object` and its properties to create a copy.
  if (!object || (typeof object === "undefined" ? "undefined" : _typeof(object)) !== "object" || object instanceof RegExp) return object;
  var result = Array.isArray(object) ? Array(object.length) : {};
  for (var key in object) {
    if (object.hasOwnProperty(key)) result[key] = deepCopy(object[key]);
  }
  return result;
}

// -=-=-=-=-=-=-=-=-
// stringification
// -=-=-=-=-=-=-=-=-
function typeStringOf(obj) {
  // ignore-in-doc
  if (obj === null) return "null";
  if (typeof obj === "undefined") return "undefined";
  return obj.constructor.name;
}

function shortPrintStringOf(obj) {
  // ignore-in-doc
  // primitive values
  if (!isMutableType(obj)) return safeToString(obj);

  // constructed objects
  if (obj.constructor.name !== 'Object' && !Array.isArray(obj)) {
    if (obj.constructor.name) return obj.constructor.name ? obj.constructor.name : Object.prototype.toString.call(obj).split(" ")[1].split("]")[0];
  }

  // arrays or plain objects
  var typeString = "";

  function displayTypeAndLength(obj, collectionType, firstBracket, secondBracket) {
    if (obj.constructor.name === collectionType) {
      typeString += firstBracket;
      if (obj.length || Object.keys(obj).length) typeString += "...";
      typeString += secondBracket;
    }
  }
  displayTypeAndLength(obj, "Object", "{", "}");
  displayTypeAndLength(obj, "Array", "[", "]");
  return typeString;
}

function isMutableType(obj) {
  // Is `obj` a value or mutable type?
  var immutableTypes = ["null", "undefined", "Boolean", "Number", "String"];
  return immutableTypes.indexOf(typeStringOf(obj)) === -1;
}

function safeToString(obj) {
  // Like `toString` but catches errors.
  try {
    return (obj ? obj.toString() : String(obj)).replace('\n', '');
  } catch (e) {
    return '<error printing object>';
  }
}

function asObject(obj) {
  switch (typeof obj === "undefined" ? "undefined" : _typeof(obj)) {
    case 'string':
      return new String(obj);
    case 'boolean':
      return new Boolean(obj);
    case 'number':
      return new Number(obj);
    default:
      return obj;
  }
}

function newKeyIn(obj) {
  var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "_";

  var i = 1,
      key;
  do {
    key = base + "-" + i++;
  } while (key in obj);
  return key;
}



var obj = Object.freeze({
	isArray: isArray$$1,
	isElement: isElement,
	isFunction: isFunction,
	isBoolean: isBoolean,
	isString: isString,
	isNumber: isNumber,
	isUndefined: isUndefined,
	isRegExp: isRegExp,
	isObject: isObject,
	isPrimitive: isPrimitive,
	isEmpty: isEmpty,
	equals: equals$1,
	keys: keys$1,
	values: values,
	select: select,
	dissoc: dissoc,
	addScript: addScript,
	extend: extend,
	clone: clone$$1,
	extract: extract,
	inspect: inspect,
	merge: merge,
	deepMerge: deepMerge,
	inherit: inherit,
	valuesInPropertyHierarchy: valuesInPropertyHierarchy,
	mergePropertyInHierarchy: mergePropertyInHierarchy,
	sortKeysWithBeforeAndAfterConstraints: sortKeysWithBeforeAndAfterConstraints,
	deepCopy: deepCopy,
	typeStringOf: typeStringOf,
	shortPrintStringOf: shortPrintStringOf,
	isMutableType: isMutableType,
	safeToString: safeToString,
	asObject: asObject,
	newKeyIn: newKeyIn
});

/*global btoa,JsDiff*/
/*lively.vm dontTransform: ["btoa"]*/

// String utility methods for printing, parsing, and converting strings.

var features = {
  repeat: !!String.prototype.repeat,
  includes: !!String.prototype.includes,
  startsWith: !!String.prototype.startsWith,
  endsWith: !!String.prototype.endsWith
};

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// printing and formatting strings
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function format() {
  // String+ -> String
  // Takes a variable number of arguments. The first argument is the format
  // string. Placeholders in the format string are marked with `"%s"`.
  // Example:
  //   lively.lang.string.format("Hello %s!", "Lively User"); // => "Hello Lively User!"
  return formatFromArray(Array.prototype.slice.call(arguments));
}

function formatFromArray(objects) {
  var self = objects.shift();
  if (!self) {
    console.log("Error in Strings>>formatFromArray, first arg is undefined");
  }

  function appendText(object, string) {
    return "" + object;
  }

  function appendInteger(value, string) {
    return value.toString();
  }

  function appendFloat(value, string, precision) {
    if (precision > -1) return value.toFixed(precision);else return value.toString();
  }

  function appendObject(value, string) {
    return inspect(value);
  }

  var appenderMap = { s: appendText, d: appendInteger, i: appendInteger, f: appendFloat, o: appendObject };
  var reg = /((^%|[^\\]%)(\d+)?(\.)([a-zA-Z]))|((^%|[^\\]%)([a-zA-Z]))/;

  function parseFormat(fmt) {
    var oldFmt = fmt;
    var parts = [];

    for (var m = reg.exec(fmt); m; m = reg.exec(fmt)) {
      var type = m[8] || m[5],
          appender = type in appenderMap ? appenderMap[type] : appendObject,
          precision = m[3] ? parseInt(m[3]) : m[4] == "." ? -1 : 0;
      parts.push(fmt.substr(0, m[0][0] == "%" ? m.index : m.index + 1));
      parts.push({ appender: appender, precision: precision });

      fmt = fmt.substr(m.index + m[0].length);
    }
    if (fmt) parts.push(fmt.toString());

    return parts;
  }

  var parts = parseFormat(self),
      str = "",
      objIndex = 0;

  for (var i = 0; i < parts.length; ++i) {
    var part = parts[i];
    if (part && (typeof part === "undefined" ? "undefined" : _typeof(part)) == "object") {
      var object = objects[objIndex++];
      str += (part.appender || appendText)(object, str, part.precision);
    } else {
      str += appendText(part, str);
    }
  }
  return str;
}

function indent(str, indentString, depth) {
  // String -> String -> String? -> String
  // Example:
  //   string.indent("Hello", "  ", 2) // => "    Hello"
  if (!depth || depth <= 0) return str;
  var indent = "";while (depth > 0) {
    depth--;indent += indentString;
  }
  return lines(str).map(function (line) {
    return indent + line;
  }).join("\n");
}

function minIndent(str, indentString) {
  // Find out what the minum indentation of the text in str is
  // Example:
  //   minIndent("    Hello", "  ") // => 2
  if (!indentString) indentString = "  ";
  var indentRe = new RegExp("^(" + indentString + ")*", "gm");
  return min(str.match(indentRe).map(function (ea) {
    return Math.floor(ea.length / indentString.length);
  }));
}

function changeIndent(str, indentString, depth) {
  // Add or remove indent from lines in str to match depth
  // Example:
  //   string.changeIndent("    Hello", "  ", 1) // => "  Hello"
  if (!indentString) indentString = "  ";
  if (!depth) depth = 0;
  var existingIndent = minIndent(str, indentString);
  if (existingIndent === depth) return str;
  if (existingIndent < depth) return indent(str, indentString, depth - existingIndent);
  var prefixToRemove = indentString.repeat(existingIndent - depth);
  return lines(str).map(function (line) {
    return line.slice(prefixToRemove.length);
  }).join("\n");
}

function quote(str) {
  // Example:
  //   string.print("fo\"o") // => "\"fo\\\"o\""
  return '"' + str.replace(/"/g, '\\"') + '"';
}

function print(obj) {
  // Prints Arrays and escapes quotations. See `obj.inspect` for how to
  // completely print / inspect JavaScript data strcutures
  // Example:
  //   string.print([[1,2,3], "string", {foo: 23}])
  //      // => [[1,2,3],"string",[object Object]]
  if (obj && Array.isArray(obj)) return '[' + obj.map(print) + ']';
  if (typeof obj !== "string") return String(obj);
  var result = String(obj);
  result = result.replace(/\n/g, '\\n\\\n');
  result = result.replace(/(")/g, '\\$1');
  result = '\"' + result + '\"';
  return result;
}

function printNested(list, depth) {
  // Example:
  //   string.printNested([1,2,[3,4,5]]) // => "1\n2\n  3\n  4\n  5\n"
  depth = depth || 0;
  return list.reduce(function (s, ea) {
    return s += Array.isArray(ea) ? printNested(ea, depth + 1) : indent(ea + "\n", '  ', depth);
  }, "");
}

function pad(string, n, left) {
  // Examples:
  // pad("Foo", 2) // => "Foo  "
  // pad("Foo", 2, true) // => "  Foo"
  return left ? ' '.repeat(n) + string : string + ' '.repeat(n);
}

function printTable(tableArray, options) {
  // Array -> Object? -> String
  // Takes a 2D Array and prints a table string. Kind of the reverse
  // operation to `tableize`
  // Example:
  //   string.printTable([["aaa", "b", "c"], ["d", "e","f"]])
  //    // =>
  //    // aaa b c
  //    // d   e f
  var columnWidths = [],
      separator = options && options.separator || ' ',
      alignLeftAll = !options || !options.align || options.align === 'left',
      alignRightAll = options && options.align === 'right';
  function alignRight(columnIndex) {
    if (alignLeftAll) return false;
    if (alignRightAll) return true;
    return options && Array.isArray(options.align) && options.align[columnIndex] === 'right';
  }
  tableArray.forEach(function (row) {
    row.forEach(function (cellVal, i) {
      if (columnWidths[i] === undefined) columnWidths[i] = 0;
      columnWidths[i] = Math.max(columnWidths[i], String(cellVal).length);
    });
  });
  return tableArray.map(function (row) {
    return row.map(function (cellVal, i) {
      var cellString = String(cellVal);
      return pad(cellString, columnWidths[i] - cellString.length, alignRight(i));
    }).join(separator);
  }).join('\n');
}

function printTree(rootNode, nodePrinter, childGetter, indent) {
  // Object -> Function -> Function -> Number? -> String
  // A generic function to print a tree representation from a nested data structure.
  // Receives three arguments:
  // - `rootNode` an object representing the root node of the tree
  // - `nodePrinter` is a function that gets a tree node and should return stringified version of it
  // - `childGetter` is a function that gets a tree node and should return a list of child nodes
  // Example:
  // var root = {name: "a", subs: [{name: "b", subs: [{name: "c"}]}, {name: "d"}]};
  // string.printTree(root, function(n) { return n.name; }, function(n) { return n.subs; });
  // // =>
  // // a
  // // |-b
  // // | \-c
  // // \-d

  var nodeList = [];
  indent = indent || '  ';
  iterator(0, 0, rootNode);
  return nodeList.join('\n');
  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  function iterator(depth, index, node) {
    // ignore-in-doc
    // 1. Create stringified representation of node
    nodeList[index] = indent.repeat(depth) + nodePrinter(node, depth);
    var children = childGetter(node, depth),
        childIndex = index + 1;
    if (!children || !children.length) return childIndex;
    // 2. If there are children then assemble those linear inside nodeList
    // The childIndex is the pointer of the current items of childList into
    // nodeList.
    var lastIndex = childIndex,
        lastI = children.length - 1;
    children.forEach(function (ea, i) {
      childIndex = iterator(depth + 1, childIndex, ea);
      // 3. When we have printed the recursive version then augment the
      // printed version of the direct children with horizontal slashes
      // directly in front of the represented representation
      var isLast = lastI === i,
          cs = nodeList[lastIndex].split(''),
          fromSlash = depth * indent.length + 1,
          toSlash = depth * indent.length + indent.length;
      for (var i = fromSlash; i < toSlash; i++) {
        cs[i] = '-';
      }if (isLast) cs[depth * indent.length] = '\\';
      nodeList[lastIndex] = cs.join('');
      // 4. For all children (direct and indirect) except for the
      // last one (itself and all its children) add vertical bars in
      // front of each at position of the current nodes depth. This
      // makes is much easier to see which child node belongs to which
      // parent
      if (!isLast) nodeList.slice(lastIndex, childIndex).forEach(function (ea, i) {
        var cs2 = ea.split('');
        cs2[depth * indent.length] = '|';
        nodeList[lastIndex + i] = cs2.join('');
      });
      lastIndex = childIndex;
    });
    return childIndex;
  }
}

function toArray$1(s) {
  // Example:
  // string.toArray("fooo") // => ["f","o","o","o"]
  return s.split('');
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// parsing strings into other entities
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function lines(str) {
  // Example: string.lines("foo\nbar\n\rbaz") // => ["foo","bar","baz"]
  return str.split(/\n\r?/);
}

function paragraphs(string, options) {
  // Examples:
  // var text = "Hello, this is a pretty long sentence\nthat even includes new lines."
  //         + "\n\n\nThis is a sentence in  a new paragraph.";
  // string.paragraphs(text) // => [
  //   // "Hello, this is a pretty long sentence\nthat even includes new lines.",
  //   // "This is a sentence in  a new paragraph."]
  // string.paragraphs(text, {keepEmptyLines: true}) // => [
  //   // "Hello, this is a pretty long sentence\n that even includes new lines.",
  //   // "\n ",
  //   // "This is a sentence in  a new paragraph."]
  var sep = options ? options.sep : '\n\n';
  if (!options || !options.keepEmptyLines) return string.split(new RegExp(sep + '+'));
  function isWhiteSpace(s) {
    return (/^\s*$/.test(s)
    );
  }
  return string.split('\n').concat('').reduce(function (parasAndLast, line) {
    var paras = parasAndLast[0],
        last$$1 = parasAndLast[1];
    if (isWhiteSpace(last$$1) === isWhiteSpace(line)) {
      last$$1 += '\n' + line;
    } else {
      last$$1.length && paras.push(last$$1);last$$1 = line;
    }
    return [paras, last$$1];
  }, [[], ''])[0];
}

function nonEmptyLines(str) {
  // Example: string.nonEmptyLines("foo\n\nbar\n") // => ["foo","bar"]
  return lines(str).compact();
}

function tokens(str, regex) {
  // Example:
  // string.tokens(' a b c') => ['a', 'b', 'c']
  return str.split(regex || /\s+/).filter(function (tok) {
    return !/^\s*$/.test(tok);
  });
}

function tableize(s, options) {
  // String -> Object? -> Array
  // Takes a String representing a "table" and parses it into a 2D-Array (as
  // accepted by the `collection.Grid` methods or `string.printTable`)
  // ```js
  // options = {
  //     convertTypes: BOOLEAN, // automatically convert to Numbers, Dates, ...?
  //     cellSplitter: REGEXP // how to recognize "cells", by default just spaces
  // }
  // ```
  // Examples:
  // string.tableize('a b c\nd e f')
  // // => [["a","b","c"],["d","e","f"]]
  // // can also parse csv like
  // var csv = '"Symbol","Name","LastSale",\n'
  //         + '"FLWS","1-800 FLOWERS.COM, Inc.","5.65",\n'
  //         + '"FCTY","1st Century Bancshares, Inc","5.65",'
  // string.tableize(csv, {cellSplitter: /^\s*"|","|",?\s*$/g})
  // // => [["Symbol","Name","LastSale"],
  // //     ["FLWS","1-800 FLOWERS.COM, Inc.",5.65],
  // //     ["FCTY","1st Century Bancshares, Inc",5.65]]

  options = options || {};
  var splitter = options.cellSplitter || /\s+/,
      emptyStringRe = /^\s*$/,
      convertTypes = options.hasOwnProperty('convertTypes') ? !!options.convertTypes : true,
      _lines = lines(s),
      table = [];
  for (var i = 0; i < _lines.length; i++) {
    var _tokens = tokens(_lines[i], splitter);
    if (convertTypes) {
      _tokens = _tokens.map(function (tok) {
        if (tok.match(emptyStringRe)) return tok;
        var num = Number(tok);
        if (!isNaN(num)) return num;
        var date = new Date(tok);
        if (!isNaN(+date)) return date;
        return tok.trim();
      });
    }
    if (_tokens.length > 0) table.push(_tokens);
  }
  return table;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// (un)escape / encoding / decoding
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function unescapeCharacterEntities(s) {
  // Converts [character entities](http://dev.w3.org/html5/html-author/charref)
  // into utf-8 strings
  // Example:
  //   string.unescapeCharacterEntities("foo &amp;&amp; bar") // => "foo && bar"
  if (typeof document === 'undefined') throw new Error("Cannot unescapeCharacterEntities");
  var div = document.createElement('div');
  div.innerHTML = s;
  return div.textContent;
}

function toQueryParams(s, separator) {
  // Example:
  // string.toQueryParams("http://example.com?foo=23&bar=test")
  //   // => {bar: "test", foo: "23"}
  var match = s.trim().match(/([^?#]*)(#.*)?$/);
  if (!match) return {};

  var hash = match[1].split(separator || '&').inject({}, function (hash, pair) {
    if ((pair = pair.split('='))[0]) {
      var key = decodeURIComponent(pair.shift());
      var value = pair.length > 1 ? pair.join('=') : pair[0];
      if (value != undefined) value = decodeURIComponent(value);

      if (key in hash) {
        if (!Array.isArray(hash[key])) hash[key] = [hash[key]];
        hash[key].push(value);
      } else hash[key] = value;
    }
    return hash;
  });
  return hash;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-
// file system path support
// -=-=-=-=-=-=-=-=-=-=-=-=-
var pathDotRe = /\/\.\//g;
var pathDoubleDotRe = /\/[^\/]+\/\.\./;
var pathDoubleSlashRe = /(^|[^:])[\/]+/g;
var urlStartRe = /^[a-z0-9-_\.]+:\/\//;
function normalizePath$1(pathString) {
  var urlStartMatch = pathString.match(urlStartRe),
      urlStart = urlStartMatch ? urlStartMatch[0] : null,
      result = urlStart ? pathString.slice(urlStart.length) : pathString;
  // /foo/../bar --> /bar
  do {
    pathString = result;
    result = pathString.replace(pathDoubleDotRe, '');
  } while (result != pathString);
  // foo//bar --> foo/bar
  result = result.replace(pathDoubleSlashRe, '$1/');
  // foo/./bar --> foo/bar
  result = result.replace(pathDotRe, '/');
  if (urlStart) result = urlStart + result;
  return result;
}

function joinPath() /*paths*/{
  // Joins the strings passed as paramters together so that ea string is
  // connected via a single "/".
  // Example:
  // string.joinPath("foo", "bar") // => "foo/bar";
  return normalizePath$1(Array.prototype.slice.call(arguments).reduce(function (path, ea) {
    return typeof ea === "string" ? path.replace(/\/*$/, "") + "/" + ea.replace(/^\/*/, "") : path;
  }));
}

// -=-=-=-=-=-=-=-=-
// ids and hashing
// -=-=-=-=-=-=-=-=-
var newUUIDTemplate = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
var newUUIDRe = /[xy]/g;
var newUUIDReplacer = function newUUIDReplacer(c) {
  var r = Math.random() * 16 | 0,
      v = c == 'x' ? r : r & 0x3 | 0x8;
  return v.toString(16);
};

function newUUID() {
  // Example:
  //   newUUID() // => "3B3E74D0-85EA-45F2-901C-23ECF3EAB9FB"
  return newUUIDTemplate.replace(newUUIDRe, newUUIDReplacer).toUpperCase();
}

function createDataURI(content, mimeType) {
  // String -> String -> String
  // Takes some string representing content and a mime type.
  // For a list of mime types see: [http://www.iana.org/assignments/media-types/media-types.xhtml]()
  // More about data URIs: [https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs]()
  // Example:
  //   window.open(string.createDataURI('<h1>test</h1>', 'text/html'));
  mimeType = mimeType || "text/plain";
  return "data:" + mimeType + ";base64," + btoa(content);
}

function hashCode(s) {
  // [http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/]()
  // Example: string.hashCode("foo") // => 101574
  var hash = 0,
      len = s.length;
  if (len == 0) return hash;
  for (var i = 0; i < len; i++) {
    var c = s.charCodeAt(i);
    hash = (hash << 5) - hash + c;
    hash = hash & hash; // Convert to 32bit integer
  }
  return hash;
}

function md5(string) {
  // © Joseph Myers [http://www.myersdaily.org/joseph/javascript/md5-text.html]()
  // Example:
  //   string.md5("foo") // => "acbd18db4cc2f85cedef654fccc4a4d8"

  /* ignore-in-doc
  this function is much faster,
  so if possible we use it. Some IEs
  are the only ones I know of that
  need the idiotic second function,
  generated by an if clause.  */
  // var add32 = hex(md51("hello")) === "5d41402abc4b2a76b9719d911017c592" ?
  //   function add32(a, b) { return (a + b) & 0xFFFFFFFF; } :
  var add32 = function add32(x, y) {
    var lsw = (x & 0xFFFF) + (y & 0xFFFF),
        msw = (x >> 16) + (y >> 16) + (lsw >> 16);
    return msw << 16 | lsw & 0xFFFF;
  };

  function cmn(q, a, b, x, s, t) {
    a = add32(add32(a, q), add32(x, t));
    return add32(a << s | a >>> 32 - s, b);
  }

  function ff(a, b, c, d, x, s, t) {
    return cmn(b & c | ~b & d, a, b, x, s, t);
  }

  function gg(a, b, c, d, x, s, t) {
    return cmn(b & d | c & ~d, a, b, x, s, t);
  }

  function hh(a, b, c, d, x, s, t) {
    return cmn(b ^ c ^ d, a, b, x, s, t);
  }

  function ii(a, b, c, d, x, s, t) {
    return cmn(c ^ (b | ~d), a, b, x, s, t);
  }

  function md5cycle(x, k) {
    var a = x[0],
        b = x[1],
        c = x[2],
        d = x[3];

    a = ff(a, b, c, d, k[0], 7, -680876936);
    d = ff(d, a, b, c, k[1], 12, -389564586);
    c = ff(c, d, a, b, k[2], 17, 606105819);
    b = ff(b, c, d, a, k[3], 22, -1044525330);
    a = ff(a, b, c, d, k[4], 7, -176418897);
    d = ff(d, a, b, c, k[5], 12, 1200080426);
    c = ff(c, d, a, b, k[6], 17, -1473231341);
    b = ff(b, c, d, a, k[7], 22, -45705983);
    a = ff(a, b, c, d, k[8], 7, 1770035416);
    d = ff(d, a, b, c, k[9], 12, -1958414417);
    c = ff(c, d, a, b, k[10], 17, -42063);
    b = ff(b, c, d, a, k[11], 22, -1990404162);
    a = ff(a, b, c, d, k[12], 7, 1804603682);
    d = ff(d, a, b, c, k[13], 12, -40341101);
    c = ff(c, d, a, b, k[14], 17, -1502002290);
    b = ff(b, c, d, a, k[15], 22, 1236535329);

    a = gg(a, b, c, d, k[1], 5, -165796510);
    d = gg(d, a, b, c, k[6], 9, -1069501632);
    c = gg(c, d, a, b, k[11], 14, 643717713);
    b = gg(b, c, d, a, k[0], 20, -373897302);
    a = gg(a, b, c, d, k[5], 5, -701558691);
    d = gg(d, a, b, c, k[10], 9, 38016083);
    c = gg(c, d, a, b, k[15], 14, -660478335);
    b = gg(b, c, d, a, k[4], 20, -405537848);
    a = gg(a, b, c, d, k[9], 5, 568446438);
    d = gg(d, a, b, c, k[14], 9, -1019803690);
    c = gg(c, d, a, b, k[3], 14, -187363961);
    b = gg(b, c, d, a, k[8], 20, 1163531501);
    a = gg(a, b, c, d, k[13], 5, -1444681467);
    d = gg(d, a, b, c, k[2], 9, -51403784);
    c = gg(c, d, a, b, k[7], 14, 1735328473);
    b = gg(b, c, d, a, k[12], 20, -1926607734);

    a = hh(a, b, c, d, k[5], 4, -378558);
    d = hh(d, a, b, c, k[8], 11, -2022574463);
    c = hh(c, d, a, b, k[11], 16, 1839030562);
    b = hh(b, c, d, a, k[14], 23, -35309556);
    a = hh(a, b, c, d, k[1], 4, -1530992060);
    d = hh(d, a, b, c, k[4], 11, 1272893353);
    c = hh(c, d, a, b, k[7], 16, -155497632);
    b = hh(b, c, d, a, k[10], 23, -1094730640);
    a = hh(a, b, c, d, k[13], 4, 681279174);
    d = hh(d, a, b, c, k[0], 11, -358537222);
    c = hh(c, d, a, b, k[3], 16, -722521979);
    b = hh(b, c, d, a, k[6], 23, 76029189);
    a = hh(a, b, c, d, k[9], 4, -640364487);
    d = hh(d, a, b, c, k[12], 11, -421815835);
    c = hh(c, d, a, b, k[15], 16, 530742520);
    b = hh(b, c, d, a, k[2], 23, -995338651);

    a = ii(a, b, c, d, k[0], 6, -198630844);
    d = ii(d, a, b, c, k[7], 10, 1126891415);
    c = ii(c, d, a, b, k[14], 15, -1416354905);
    b = ii(b, c, d, a, k[5], 21, -57434055);
    a = ii(a, b, c, d, k[12], 6, 1700485571);
    d = ii(d, a, b, c, k[3], 10, -1894986606);
    c = ii(c, d, a, b, k[10], 15, -1051523);
    b = ii(b, c, d, a, k[1], 21, -2054922799);
    a = ii(a, b, c, d, k[8], 6, 1873313359);
    d = ii(d, a, b, c, k[15], 10, -30611744);
    c = ii(c, d, a, b, k[6], 15, -1560198380);
    b = ii(b, c, d, a, k[13], 21, 1309151649);
    a = ii(a, b, c, d, k[4], 6, -145523070);
    d = ii(d, a, b, c, k[11], 10, -1120210379);
    c = ii(c, d, a, b, k[2], 15, 718787259);
    b = ii(b, c, d, a, k[9], 21, -343485551);

    x[0] = add32(a, x[0]);
    x[1] = add32(b, x[1]);
    x[2] = add32(c, x[2]);
    x[3] = add32(d, x[3]);
  }

  function md51(s) {
    var n = s.length,
        state = [1732584193, -271733879, -1732584194, 271733878],
        i;
    for (i = 64; i <= n; i += 64) {
      md5cycle(state, md5blk(s.substring(i - 64, i)));
    }
    s = s.substring(i - 64);
    var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        sl = s.length;
    for (i = 0; i < sl; i++) {
      tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
    }tail[i >> 2] |= 0x80 << (i % 4 << 3);
    if (i > 55) {
      md5cycle(state, tail);
      i = 16;
      while (i--) {
        tail[i] = 0;
      }
      //			for (i=0; i<16; i++) tail[i] = 0;
    }
    tail[14] = n * 8;
    md5cycle(state, tail);
    return state;
  }

  /* ignore-in-doc
   * there needs to be support for Unicode here,
   * unless we pretend that we can redefine the MD-5
   * algorithm for multi-byte characters (perhaps
   * by adding every four 16-bit characters and
   * shortening the sum to 32 bits). Otherwise
   * I suggest performing MD-5 as if every character
   * was two bytes--e.g., 0040 0025 = @%--but then
   * how will an ordinary MD-5 sum be matched?
   * There is no way to standardize text to something
   * like UTF-8 before transformation; speed cost is
   * utterly prohibitive. The JavaScript standard
   * itself needs to look at this: it should start
   * providing access to strings as preformed UTF-8
   * 8-bit unsigned value arrays.
   */
  function md5blk(s) {
    // ignore-in-doc
    /* I figured global was faster.   */
    var md5blks = [],
        i; /* Andy King said do it this way. */
    for (i = 0; i < 64; i += 4) {
      md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
    }
    return md5blks;
  }

  var hex_chr = '0123456789abcdef'.split('');

  function rhex(n) {
    var s = '',
        j = 0;
    for (; j < 4; j++) {
      s += hex_chr[n >> j * 8 + 4 & 0x0F] + hex_chr[n >> j * 8 & 0x0F];
    }return s;
  }

  function hex(x) {
    var l = x.length;
    for (var i = 0; i < l; i++) {
      x[i] = rhex(x[i]);
    }return x.join('');
  }

  return hex(md51(string));
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-
// matching strings / regexps
// -=-=-=-=-=-=-=-=-=-=-=-=-=-

function reMatches$$1(string, re) {
  // Different to the native `match` function this method returns an object
  // with `start`, `end`, and `match` fields
  // Example:
  //   string.reMatches("Hello World", /o/g)
  //   // => [{start: 4, end: 5, match: "o"},{start: 7, end: 8, match: "o"}]
  var matches = [];
  string.replace(re, function (match, idx) {
    matches.push({ match: match, start: idx, end: idx + match.length });
  });
  return matches;
}

function stringMatch(s, patternString, options) {
  // returns `{matched: true}` if success otherwise
  // `{matched: false, error: EXPLANATION, pattern: STRING|RE, pos: NUMBER}`
  // Example:
  //   string.stringMatch("foo 123 bar", "foo __/[0-9]+/__ bar") // => {matched: true}
  //   string.stringMatch("foo aaa bar", "foo __/[0-9]+/__ bar")
  //     // => {
  //     //   error: "foo <--UNMATCHED-->aaa bar",
  //     //   matched: false,
  //     //   pattern: /[0-9]+/,
  //     //   pos: 4
  //     // }
  options = options || {};
  if (!!options.normalizeWhiteSpace) s = s.replace(/\s+/g, ' ');
  if (!!options.ignoreIndent) {
    s = s.replace(/^\s+/gm, '');
    patternString = patternString.replace(/^\s+/gm, '');
  }
  return s == patternString ? { matched: true } : embeddedReMatch(s, patternString);

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  function splitInThree(string, start, end, startGap, endGap) {
    // ignore-in-doc
    // split string at start and end
    // return (0, start), (start, end), (end, ...)
    startGap = startGap || 0;endGap = endGap || 0;
    return [string.slice(0, start), string.slice(start + startGap, end - endGap), string.slice(end)];
  }

  function matchStringForward(s, pattern) {
    // ignore-in-doc
    // try to match pattern at beginning of string. if matched, return
    // result object with {
    //   match: STRING,
    //   REST: STRING -- remaining string after pattern was consumed
    // }
    if (pattern.constructor !== RegExp) {
      var idx = s.indexOf(pattern);
      if (idx === 0) return { match: pattern, rest: s.slice(pattern.length) };
      // no match
      for (var i = 0; i < pattern.length; i++) {
        // figure out where we failed
        if (pattern[i] != s[i]) return { match: null, pos: i };
      }return { match: null };
    }
    var matches = reMatches$$1(s, pattern);
    // show(matches)
    // show(string.slice(matches[0].end));
    return !matches || !matches.length || matches[0].start !== 0 ? { match: null } : { match: matches[0].match, rest: s.slice(matches[0].end) };
  }

  function matchStringForwardWithAllPatterns(s, patterns) {
    // ignore-in-doc
    // like matchStringForward, just apply list of patterns
    var pos = 0;
    for (var i = 0; i < patterns.length; i++) {
      var p = patterns[i],
          result = matchStringForward(s, p);
      if (!result.match) return { matched: false, pos: pos + (result.pos || 0), pattern: p };
      pos += result.match.length;
      s = result.rest;
    }
    return s.length ? { matched: false, pos: pos } : { matched: true };
  }

  function splitIntoPatterns(matcher) {
    var starts = reMatches$$1(matcher, /__\//g),
        ends = reMatches$$1(matcher, /\/__/g);
    if (starts.length !== ends.length) {
      throw new Error("pattern invalid: " + matcher + " cannot be split into __/.../__ embedded RegExps" + "\nstarts: " + JSON.stringify(starts) + '\nvs ends:\n' + JSON.stringify(ends));
    }
    var consumed = 0;
    return starts.reduce(function (patterns, start, i) {
      var end = ends[i];
      var matcher = patterns.pop();
      var splitted = splitInThree(matcher, start.start - consumed, end.end - consumed, 3, 3);
      if (splitted[0].length) {
        patterns.push(splitted[0]);
        consumed += splitted[0].length;
      }
      try {
        if (splitted[1].length) {
          patterns.push(new RegExp(splitted[1]));
          consumed += splitted[1].length + 3 + 3;
        }
      } catch (e) {
        throw new Error("Cannot create pattern re from: " + inspect(splitted));
      }
      if (splitted[2].length) {
        patterns.push(splitted[2]);
      }
      return patterns;
    }, [matcher]);
  }

  function embeddedReMatch(s, patternString) {
    // ignore-in-doc
    // the main match func
    var patterns = splitIntoPatterns(patternString);
    var result = matchStringForwardWithAllPatterns(s, patterns);
    if (result.matched) return result;
    result.error = s.slice(0, result.pos) + '<--UNMATCHED-->' + s.slice(result.pos);
    return result;
  }
}

function peekRight(s, start, needle) {
  // Finds the next occurence of `needle` (String or RegExp). Returns delta
  // index.
  // Example:
  // peekRight("Hello World", 0, /o/g) // => 4
  // peekRight("Hello World", 5, /o/) // => 2
  s = s.slice(start);
  if (typeof needle === 'string') {
    var idx = s.indexOf(needle);
    return idx === -1 ? null : idx + start;
  } else if (needle.constructor === RegExp) {
    var matches = reMatches$$1(s, needle);
    return matches[0] ? matches[0].start : null;
  }
  return null;
}

function peekLeft(s, start, needle) {
  // Similar to `peekRight`
  s = s.slice(0, start);
  if (typeof needle === 'string') {
    var idx = s.lastIndexOf(needle);
    return idx === -1 ? null : idx;
  } else if (needle.constructor === RegExp) {
    var matches = reMatches$$1(s, needle);
    return last(matches) ? last(matches).start : null;
  }
  return null;
}

function lineIndexComputer(s) {
  // String -> Function
  // For converting character positions to line numbers.
  // Returns a function accepting char positions. If the char pos is outside
  // of the line ranges -1 is returned.
  // Example:
  // var idxComp = lineIndexComputer("Hello\nWorld\n\nfoo");
  // idxComp(3) // => 0 (index 3 is "l")
  // idxComp(6) // => 1 (index 6 is "W")
  // idxComp(12) // => 2 (index 12 is "\n")

  // ignore-in-doc
  // line ranges: list of numbers, each line has two entries:
  // i -> start of line, i+1 -> end of line
  var _lineRanges = lineRanges(s);
  // ignore-in-doc
  // FIXME, this is O(n). Make cumputation more efficient, binary lookup?
  return function (pos) {
    for (var line = 0; line < _lineRanges.length; line++) {
      var lineRange = _lineRanges[line];
      if (pos >= lineRange[0] && pos < lineRange[1]) return line;
    }
    return -1;
  };
}

function lineNumberToIndexesComputer(s) {
  // String -> Function
  // For converting line numbers to [startIndex, endIndex]
  // Example:
  // var idxComp = lineNumberToIndexesComputer("Hello\nWorld\n\nfoo");
  // idxComp(1) // => [6,12]
  return function (lineNo) {
    return lineRanges(s)[lineNo];
  };
}

function lineRanges(s) {
  var from$$1 = 0,
      to = 0,
      linesOfS = lines(s),
      result = [];
  for (var i = 0; i < linesOfS.length; i++) {
    var line = linesOfS[i];
    to = from$$1 + line.length + 1;
    result.push([from$$1, to]);
    from$$1 = to;
  }
  return result;
}

function findLineWithIndexInLineRanges(lineRanges, idx) {
  // given a list of `lineRanges` (produced by
  // `livley.lang.string.lineRanges(string)`) like lineRanges = [[0, 12], [12, 33]]
  // and an string index `idx` into `string`, find the line no (the index into
  // `lineRanges`) that includes idx.  The index intervals include start and exclude end:
  // Example:
  // findLineWithIndex2(lineRanges, 2); // => 0
  // findLineWithIndex2(lineRanges, 12); // => 1
  // findLineWithIndex2(lineRanges, 33); // => 1
  // findLineWithIndex2(lineRanges, 34); // => -1
  // findLineWithIndex2(lineRanges, -4); // => -1
  var nRows = lineRanges.length;
  if (nRows === 0) return -1;
  // let currentRow = Math.floor(nRows/2), lastRow = nRows;
  var startRow = 0,
      endRow = nRows;
  while (true) {
    var middle = startRow + Math.floor((endRow - startRow) / 2),
        _lineRanges$middle = slicedToArray(lineRanges[middle], 2),
        from$$1 = _lineRanges$middle[0],
        to = _lineRanges$middle[1];

    if (idx < from$$1) {
      if (middle === 0) return -1;
      endRow = middle;
      continue;
    }
    if (idx > to) {
      startRow = middle;continue;
    }
    return middle;
  }
  return -1;
}

function regexIndexOf(string, regex) {
  var startpos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;

  var indexOf = this.substring(startpos || 0).search(regex);
  return indexOf >= 0 ? indexOf + (startpos || 0) : indexOf;
}

function regexLastIndexOf(string, regex) {
  var startpos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : string.length;

  regex = regex.global ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : ""));
  var stringToWorkWith = this.substring(0, startpos + 1),
      lastIndexOf = -1,
      nextStop = 0,
      result;
  while ((result = regex.exec(stringToWorkWith)) != null) {
    lastIndexOf = result.index;
    regex.lastIndex = ++nextStop;
  }
  return lastIndexOf;
}

// -=-=-=-=-
// diffing
// -=-=-=-=-

function diff(s1, s2) {
  if (typeof JsDiff === "undefined") return 'diff not supported';
  return JsDiff.convertChangesToXML(JsDiff.diffWordsWithSpace(s1, s2));
}

// -=-=-=-=-
// testing
// -=-=-=-=-

function empty(s) {
  // show-in-doc
  return s == '';
}

var includes$$1 = features.includes ? function (s, pattern) {
  return s.includes(pattern);
} : function (s, pattern) {
  // Example:
  // include("fooo!", "oo") // => true
  return s.indexOf(pattern) > -1;
};

var include$$1 = includes$$1;

var startsWith = features.startsWith ? function (s, pattern) {
  return s.startsWith(pattern);
} : function (s, pattern) {
  // Example:
  // startsWith("fooo!", "foo") // => true
  return s.indexOf(pattern) === 0;
};

function startsWithVowel(s) {
  // show-in-doc
  var c = s[0];
  return c === 'A' || c === 'E' || c === 'I' || c === 'O' || c === 'U' || c === 'a' || c === 'e' || c === 'i' || c === 'o' || c === 'u' || false;
}

var endsWith = features.endsWith ? function (s, pattern) {
  return s.endsWith(pattern);
} : function (s, pattern) {
  // Example:
  // endsWith("fooo!", "o!") // => true
  var d = s.length - pattern.length;
  return d >= 0 && s.lastIndexOf(pattern) === d;
};

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// string conversion and manipulation
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function withDecimalPrecision(str, precision) {
  // String -> Number -> String
  // Example: withDecimalPrecision("1.12345678", 3) // => "1.123"
  var floatValue = parseFloat(str);
  return isNaN(floatValue) ? str : floatValue.toFixed(precision);
}

function capitalize(s) {
  // Example:
  // capitalize("foo bar") // => "Foo bar"
  return s.length ? s.charAt(0).toUpperCase() + s.slice(1) : s;
}

function camelCaseString(s) {
  // Spaces to camels, including first char
  // Example: camelCaseString("foo bar baz") // => "FooBarBaz"
  return s.split(" ").map(capitalize).join("");
}

function camelize(s) {
  // Dashes to camels, excluding first char
  // Example: camelize("foo-bar-baz") // => "fooBarBaz"
  var parts = s.split('-'),
      len = parts.length;
  if (len == 1) return parts[0];

  var camelized = s.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0];
  for (var i = 1; i < len; i++) {
    camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
  }return camelized;
}

function truncate(s, length, truncation) {
  // Enforces that s is not more then `length` characters long.
  // Example:
  // truncate("123456789", 5) // => "12..."
  length = length || 30;
  truncation = truncation === undefined ? '...' : truncation;
  return s.length > length ? s.slice(0, length - truncation.length) + truncation : String(s);
}

function truncateLeft(s, length, truncation) {
  // Enforces that s is not more then `length` characters long.
  // Example:
  // truncate("123456789", 5) // => "12..."
  length = length || 30;
  truncation = truncation === undefined ? '...' : truncation;
  return s.length > length ? truncation + s.slice(-length) : String(s);
}

function regExpEscape(s) {
  // For creating RegExps from strings and not worrying about proper escaping
  // of RegExp special characters to literally match those.
  // Example:
  // var re = new RegExp(regExpEscape("fooo{20}"));
  // re.test("fooo") // => false
  // re.test("fooo{20}") // => true
  return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').replace(/\x08/g, '\\x08');
}

function succ(s) {
  // Uses char code.
  // Example:
  // succ("a") // => "b"
  // succ("Z") // => "["
  return s.slice(0, s.length - 1) + String.fromCharCode(s.charCodeAt(s.length - 1) + 1);
}

function digitValue(s) {
  // ignore-in-doc
  return s.charCodeAt(0) - "0".charCodeAt(0);
}

var times = features.repeat ? function (s, count$$1) {
  return s.repeat(count$$1);
} : function (s, count$$1) {
  // Example:
  // string.times("test", 3) // => "testtesttest"
  return count$$1 < 1 ? '' : new Array(count$$1 + 1).join(s);
};

function longestCommonSubstring(a, b) {
  // Example:
  // longestCommonSubstring("bar foo barrr", "hello fooo world");
  // => {indexA: 3, indexB: 5, length: 4, string: " foo"}

  var lcs = [];
  for (var i = 0; i < a.length; i++) {
    lcs[i] = [];
    for (var j = 0; j < b.length; j++) {
      lcs[i][j] = 0;
    }
  }

  // if B is null then LCS of A, B =0
  for (var _i = 0; _i < a.length; _i++) {
    lcs[_i][0] = 0;
  } // fill the rest of the matrix
  for (var _i2 = 1; _i2 < a.length; _i2++) {
    for (var _j = 1; _j < b.length; _j++) {
      lcs[_i2][_j] = a[_i2 - 1] == b[_j - 1] ? lcs[_i2 - 1][_j - 1] + 1 : 0;
    }
  }

  var maxLength = -1,
      indexA = -1,
      indexB = -1;
  for (var _i3 = 0; _i3 < a.length; _i3++) {
    for (var _j2 = 0; _j2 < b.length; _j2++) {
      var length = lcs[_i3][_j2];
      if (maxLength < length) {
        maxLength = length;
        indexA = _i3 - length;
        indexB = _j2 - length;
      }
    }
  }

  return {
    length: maxLength, indexA: indexA, indexB: indexB,
    string: maxLength > 0 ? a.slice(indexA, indexA + maxLength) : ""
  };
}

function applyChange(string, change) {
  // change is of the form
  // `{start: Number, end: Number, lines: [String], action: "insert"|"remove"}`
  if (change.action === "insert") {
    return string.slice(0, change.start) + change.lines.join("\n") + string.slice(change.start);
  } else if (change.action === "remove") {
    return string.slice(0, change.start) + string.slice(change.end);
  }
  return string;
}

function applyChanges(s, changes) {
  return changes.reduce(function (result, change) {
    return applyChange(s, change);
  }, s);
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// diffing / comparing

function levenshtein(a, b) {
  // How many edit operations separate string a from b?
  // MIT licensed, https://gist.github.com/andrei-
  // Copyright (c) 2011 Andrei Mackenzie and https://github.com/kigiri
  if (a.length === 0) return b.length;
  if (b.length === 0) return a.length;
  var tmp, i, j, prev, val, row;
  // swap to save some memory O(min(a,b)) instead of O(a)
  if (a.length > b.length) {
    tmp = a;a = b;b = tmp;
  }

  row = Array(a.length + 1);
  // init the row
  for (i = 0; i <= a.length; i++) {
    row[i] = i;
  } // fill in the rest
  for (i = 1; i <= b.length; i++) {
    prev = i;
    for (j = 1; j <= a.length; j++) {
      if (b[i - 1] === a[j - 1]) {
        val = row[j - 1]; // match
      } else {
        val = Math.min(row[j - 1] + 1, // substitution
        Math.min(prev + 1, // insertion
        row[j] + 1)); // deletion
      }
      row[j - 1] = prev;
      prev = val;
    }
    row[a.length] = prev;
  }
  return row[a.length];
}



var string = Object.freeze({
	format: format,
	formatFromArray: formatFromArray,
	indent: indent,
	minIndent: minIndent,
	changeIndent: changeIndent,
	quote: quote,
	print: print,
	printNested: printNested,
	pad: pad,
	printTable: printTable,
	printTree: printTree,
	toArray: toArray$1,
	lines: lines,
	paragraphs: paragraphs,
	nonEmptyLines: nonEmptyLines,
	tokens: tokens,
	tableize: tableize,
	unescapeCharacterEntities: unescapeCharacterEntities,
	toQueryParams: toQueryParams,
	normalizePath: normalizePath$1,
	joinPath: joinPath,
	newUUID: newUUID,
	createDataURI: createDataURI,
	hashCode: hashCode,
	md5: md5,
	reMatches: reMatches$$1,
	stringMatch: stringMatch,
	peekRight: peekRight,
	peekLeft: peekLeft,
	lineIndexComputer: lineIndexComputer,
	lineNumberToIndexesComputer: lineNumberToIndexesComputer,
	findLineWithIndexInLineRanges: findLineWithIndexInLineRanges,
	regexIndexOf: regexIndexOf,
	regexLastIndexOf: regexLastIndexOf,
	lineRanges: lineRanges,
	diff: diff,
	empty: empty,
	includes: includes$$1,
	include: include$$1,
	startsWith: startsWith,
	startsWithVowel: startsWithVowel,
	endsWith: endsWith,
	withDecimalPrecision: withDecimalPrecision,
	capitalize: capitalize,
	camelCaseString: camelCaseString,
	camelize: camelize,
	truncate: truncate,
	truncateLeft: truncateLeft,
	regExpEscape: regExpEscape,
	succ: succ,
	digitValue: digitValue,
	times: times,
	longestCommonSubstring: longestCommonSubstring,
	applyChange: applyChange,
	applyChanges: applyChanges,
	levenshtein: levenshtein
});

/*
 * Utility functions for JS Numbers.
 */

function random(min, max) {
  // random number between (and including) `min` and `max`
  min = min || 0;
  max = max || 100;
  return Math.round(Math.random() * (max - min) + min);
}

var normalRandom = function (mean, stdDev) {
  // returns randomized numbers in a normal distribution that can be
  // controlled ising the `mean` and `stdDev` parameters
  var spare,
      isSpareReady = false;
  return function (mean, stdDev) {
    if (isSpareReady) {
      isSpareReady = false;
      return spare * stdDev + mean;
    } else {
      var u, v, s;
      do {
        u = Math.random() * 2 - 1;
        v = Math.random() * 2 - 1;
        s = u * u + v * v;
      } while (s >= 1 || s == 0);
      var mul = Math.sqrt(-2.0 * Math.log(s) / s);
      spare = v * mul;
      isSpareReady = true;
      return mean + stdDev * u * mul;
    }
  };
}();

function randomSmallerInteger(n) {
  return Math.floor(Math.random() * n);
}

function humanReadableByteSize(n) {
  // interpret `n` as byte size and print a more readable version
  // Example:
  //   num.humanReadableByteSize(Math.pow(2,32)) // => "4096MB"
  function round(n) {
    return Math.round(n * 100) / 100;
  }
  if (n < 1000) return String(round(n)) + 'B';
  n = n / 1024;
  if (n < 1000) return String(round(n)) + 'KB';
  n = n / 1024;
  return String(round(n)) + 'MB';
}

function average(numbers) {
  // show-in-doc
  return numbers.reduce(function (sum, n) {
    return sum + n;
  }, 0) / numbers.length;
}

function averageInc(newVal, oldAvg, n) {
  // show-in-doc
  // Example:
  //   let nums = range(0, 10).map(() => random(0, 10))
  //   nums.reduce((avg, ea, i) => avgInc(ea, avg, i+1), 0);
  return (newVal - oldAvg) / n + oldAvg;
}

function median(numbers) {
  // show-in-doc
  var sorted = numbers.sort(function (a, b) {
    return b - a;
  }),
      len = numbers.length;
  return len % 2 === 0 ? 0.5 * (sorted[len / 2 - 1] + sorted[len / 2]) : sorted[(len - 1) / 2];
}

function between(x, a, b, eps) {
  // is `a` <= `x` <= `y`?
  eps = eps || 0;
  var min, max;
  if (a < b) {
    min = a, max = b;
  } else {
    max = a, min = b;
  }
  return max - x + eps >= 0 && min - x - eps <= 0;
}

function sort$1(arr) {
  // numerical sort, JavaScript native `sort` function is lexical by default.
  return arr.sort(function (a, b) {
    return a - b;
  });
}

function parseLength(string, toUnit) {
  // This converts the length value to pixels or the specified `toUnit`.
  // length converstion, supported units are: mm, cm, in, px, pt, pc
  // Examples:
  // num.parseLength('3cm') // => 113.38582677165354
  // num.parseLength('3cm', "in") // => 1.1811023622047243
  toUnit = toUnit || 'px';
  var match = string.match(/([0-9\.]+)\s*(.*)/);
  if (!match || !match[1]) return undefined;
  var length = parseFloat(match[1]),
      fromUnit = match[2];
  return convertLength(length, fromUnit, toUnit);
}

var convertLength = function () {
  // ignore-in-doc
  // num.convertLength(20, 'px', 'pt').roundTo(0.01)
  function toCm(n, unit) {
    // as defined in http://www.w3.org/TR/css3-values/#absolute-lengths
    if (unit === 'cm') return n;else if (unit === 'mm') return n * 0.1;else if (unit === 'in') return n * 2.54;else if (unit === 'px') return n * toCm(1 / 96, 'in');else if (unit === 'pt') return n * toCm(1 / 72, 'in');else if (unit === 'pc') return n * toCm(12, 'pt');
  }
  return function to(length, fromUnit, toUnit) {
    if (fromUnit === toUnit) return length;else if (toUnit === "cm") return toCm(length, fromUnit);else if (fromUnit === "cm") return length / toCm(1, toUnit);else return to(to(length, fromUnit, 'cm'), 'cm', toUnit);
  };
}();

function roundTo(n, quantum) {
  // `quantum` is something like 0.01,

  // for JS rounding to work we need the reciprocal
  quantum = 1 / quantum;
  return Math.round(n * quantum) / quantum;
}

function detent(n, detent, grid, snap) {
  // This function is useful to implement smooth transitions and snapping.
  // Map all values that are within detent/2 of any multiple of grid to
  // that multiple. Otherwise, if snap is true, return self, meaning that
  // the values in the dead zone will never be returned. If snap is
  // false, then expand the range between dead zone so that it covers the
  // range between multiples of the grid, and scale the value by that
  // factor.
  // Examples:
  // // With snapping:
  // num.detent(0.11, 0.2, 0.5, true) // => 0.11
  // num.detent(0.39, 0.2, 0.5, true) // => 0.39
  // num.detent(0.55, 0.2, 0.5, true)  // => 0.5
  // num.detent(0.61, 0.2, 0.5, true)   // => 0.61
  // // Smooth transitions without snapping:
  // num.detent(0.1,  0.2, 0.5) // => 0
  // num.detent(0.11,  0.2, 0.5) // => 0.0166666
  // num.detent(0.34,  0.2, 0.5)  // => 0.4
  // num.detent(0.39,  0.2, 0.5) // => 0.4833334
  // num.detent(0.4,  0.2, 0.5) // => 0.5
  // num.detent(0.6,  0.2, 0.5) // => 0.5
  var r1 = roundTo(n, grid); // Nearest multiple of grid
  if (Math.abs(n - r1) < detent / 2) return r1; // Snap to that multiple...
  if (snap) return n; // ...and return n
  // or compute nearest end of dead zone
  var r2 = n < r1 ? r1 - detent / 2 : r1 + detent / 2;
  // and scale values between dead zones to fill range between multiples
  return r1 + (n - r2) * grid / (grid - detent);
}

function toDegrees(n) {
  // Example:
  // num.toDegrees(Math.PI/2) // => 90
  return n * 180 / Math.PI % 360;
}

function toRadians(n) {
  // Example:
  // num.toRadians(180) // => 3.141592653589793
  return n / 180 * Math.PI;
}

function backoff(attempt) /*ms*/{
  var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
  var cap = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 30000;

  // exponential backoff function
  // https://www.awsarchitectureblog.com/2015/03/backoff.html
  var temp = Math.min(cap, base * Math.pow(2, attempt)),
      sleep = temp / 2 + Math.round(Math.random() * (temp / 2));
  return Math.min(cap, base + Math.random() * (sleep * 3 - base));
}

function interpolate(i, a, b) {
  return a + i * (b - a);
}



var num = Object.freeze({
	random: random,
	normalRandom: normalRandom,
	randomSmallerInteger: randomSmallerInteger,
	humanReadableByteSize: humanReadableByteSize,
	average: average,
	averageInc: averageInc,
	median: median,
	between: between,
	sort: sort$1,
	parseLength: parseLength,
	convertLength: convertLength,
	roundTo: roundTo,
	detent: detent,
	toDegrees: toDegrees,
	toRadians: toRadians,
	backoff: backoff,
	interpolate: interpolate
});

function all$2(object, predicate) {
  // ignore-in-doc
  var a = [];
  for (var name in object) {
    if ((object.__lookupGetter__(name) || typeof object[name] !== 'function') && (predicate ? predicate(name, object) : true)) a.push(name);
  }
  return a;
}

function allOwnPropertiesOrFunctions(obj, predicate) {
  // ignore-in-doc
  return Object.getOwnPropertyNames(obj).reduce(function (result, name) {
    if (predicate ? predicate(obj, name) : true) result.push(name);
    return result;
  }, []);
}

function own$1(object) {
  // ignore-in-doc
  var a = [];
  for (var name in object) {
    if (object.hasOwnProperty(name) && (object.__lookupGetter__(name) || object[name] !== 'function')) a.push(name);
  }
  return a;
}

function forEachOwn(object, func, context) {
  // ignore-in-doc
  var result = [];
  for (var name in object) {
    if (!object.hasOwnProperty(name)) continue;
    var value = object[name];
    if (value !== 'function') {
      result.push(func.call(context || this, name, value));
    }
  }
  return result;
}

function nameFor(object, value) {
  // ignore-in-doc
  for (var name in object) {
    if (object[name] === value) return name;
  }return undefined;
}

function values$1(obj) {
  // ignore-in-doc
  var values = [];
  for (var name in obj) {
    values.push(obj[name]);
  }return values;
}

function ownValues(obj) {
  // ignore-in-doc
  var values = [];
  for (var name in obj) {
    if (obj.hasOwnProperty(name)) values.push(obj[name]);
  }return values;
}

function any$1(obj, predicate) {
  // ignore-in-doc
  for (var name in obj) {
    if (predicate(obj, name)) return true;
  }return false;
}

function allProperties(obj, predicate) {
  // ignore-in-doc
  var result = [];
  for (var name in obj) {
    if (predicate ? predicate(obj, name) : true) result.push(name);
  }return result;
}

function hash(obj) {
  // ignore-in-doc
  // Using the property names of `obj` to generate a hash value.
  return Object.keys(obj).sort().join('').hashCode();
}



var properties = Object.freeze({
	all: all$2,
	allOwnPropertiesOrFunctions: allOwnPropertiesOrFunctions,
	own: own$1,
	forEachOwn: forEachOwn,
	nameFor: nameFor,
	values: values$1,
	ownValues: ownValues,
	any: any$1,
	allProperties: allProperties,
	hash: hash
});

/*
 * Util functions to print and work with JS date objects.
 */

var dateFormat = function setupDateFormat() {

    /*
     * Date Format 1.2.3
     * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
     * MIT license
     *
     * Includes enhancements by Scott Trenda <scott.trenda.net>
     * and Kris Kowal <cixar.com/~kris.kowal/>
     *
     * Accepts a date, a mask, or a date and a mask.
     * Returns a formatted version of the given date.
     * The date defaults to the current date/time.
     * The mask defaults to dateFormat.masks.default.
     */

    // http://blog.stevenlevithan.com/archives/date-time-format

    var dateFormat = function () {
        var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
            timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
            timezoneClip = /[^-+\dA-Z]/g,
            pad = function pad(val, len) {
            val = String(val);
            len = len || 2;
            while (val.length < len) {
                val = "0" + val;
            }return val;
        };

        // Regexes and supporting functions are cached through closure
        return function (date, mask, utc) {
            var dF = dateFormat;

            // You can't provide utc if you skip other args (use the "UTC:" mask prefix)
            if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
                mask = date;
                date = undefined;
            }

            // Passing date through Date applies Date.parse, if necessary
            date = date ? new Date(date) : new Date();
            if (isNaN(date)) throw SyntaxError("invalid date");

            mask = String(dF.masks[mask] || mask || dF.masks["default"]);

            // Allow setting the utc argument via the mask
            if (mask.slice(0, 4) == "UTC:") {
                mask = mask.slice(4);
                utc = true;
            }

            var _ = utc ? "getUTC" : "get",
                d = date[_ + "Date"](),
                D = date[_ + "Day"](),
                m = date[_ + "Month"](),
                y = date[_ + "FullYear"](),
                H = date[_ + "Hours"](),
                M = date[_ + "Minutes"](),
                s = date[_ + "Seconds"](),
                L = date[_ + "Milliseconds"](),
                o = utc ? 0 : date.getTimezoneOffset(),
                flags = {
                d: d,
                dd: pad(d),
                ddd: dF.i18n.dayNames[D],
                dddd: dF.i18n.dayNames[D + 7],
                m: m + 1,
                mm: pad(m + 1),
                mmm: dF.i18n.monthNames[m],
                mmmm: dF.i18n.monthNames[m + 12],
                yy: String(y).slice(2),
                yyyy: y,
                h: H % 12 || 12,
                hh: pad(H % 12 || 12),
                H: H,
                HH: pad(H),
                M: M,
                MM: pad(M),
                s: s,
                ss: pad(s),
                l: pad(L, 3),
                L: pad(L > 99 ? Math.round(L / 10) : L),
                t: H < 12 ? "a" : "p",
                tt: H < 12 ? "am" : "pm",
                T: H < 12 ? "A" : "P",
                TT: H < 12 ? "AM" : "PM",
                Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
                o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
                S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
            };

            return mask.replace(token, function ($0) {
                return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
            });
        };
    }();

    // Some common format strings
    dateFormat.masks = {
        "default": "ddd mmm dd yyyy HH:MM:ss",
        shortDate: "m/d/yy",
        mediumDate: "mmm d, yyyy",
        longDate: "mmmm d, yyyy",
        fullDate: "dddd, mmmm d, yyyy",
        shortTime: "h:MM TT",
        mediumTime: "h:MM:ss TT",
        longTime: "h:MM:ss TT Z",
        isoDate: "yyyy-mm-dd",
        isoTime: "HH:MM:ss",
        isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
        isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
    };

    // Internationalization strings
    dateFormat.i18n = {
        dayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
        monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
    };

    return dateFormat;
}(); // end of setupDateFormat


function format$1(date, mask, utc) {
    // Custom date / time stringifier. Provides default masks:
    //
    // Mask           | Pattern
    // ---------------|--------------------------------
    // default        | `"ddd mmm dd yyyy HH:MM:ss"`
    // shortDate      | `"m/d/yy"`
    // mediumDate     | `"mmm d, yyyy"`
    // longDate       | `"mmmm d, yyyy"`
    // fullDate       | `"dddd, mmmm d, yyyy"`
    // shortTime      | `"h:MM TT"`
    // mediumTime     | `"h:MM:ss TT"`
    // longTime       | `"h:MM:ss TT Z"`
    // isoDate        | `"yyyy-mm-dd"`
    // isoTime        | `"HH:MM:ss"`
    // isoDateTime    | `"yyyy-mm-dd'T'HH:MM:ss"`
    // isoUtcDateTime | `"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"`
    //
    // and internationalized strings via `date.format.i18n.dayNames`
    // and `date.format.i18n.dayNames`
    // Examples:
    //   date.format(new Date(), date.format.masks.longTime) // => "7:13:31 PM PDT"
    //   date.format(new Date(), "yyyy/mm/dd") // => "2014/10/09"
    return dateFormat(date, mask, utc);
}

function equals$3(date, otherDate) {
    // show-in-doc
    return otherDate && otherDate instanceof Date && otherDate.getTime() === date.getTime();
}

function relativeTo(date, otherDate) {
    // Prints a human readable difference of two Date objects. The older date
    // goes first.
    // Examples:
    //   var now = new Date();
    //   date.relativeTo(new Date(now-2000), now) // => "2 secs"
    //   date.relativeTo(new Date("10/11/2014"), new Date("10/12/2014")) // => "1 day"
    if (!(otherDate instanceof Date)) return '';
    if (otherDate < date) return '';
    if (otherDate === date) return 'now';
    var minuteString = 'min',
        secondString = 'sec',
        hourString = 'hour',
        dayString = 'day',
        diff = otherDate - date,
        totalSecs = Math.round(diff / 1000),
        secs = totalSecs % 60,
        mins = Math.floor(totalSecs / 60) % 60,
        hours = Math.floor(totalSecs / 60 / 60) % 24,
        days = Math.floor(totalSecs / 60 / 60 / 24),
        parts = [];
    if (days > 0) {
        parts.push(days);
        if (days > 1) dayString += 's';
        parts.push(dayString);
    }
    if (hours > 0 && days < 2) {
        parts.push(hours);
        if (hours > 1) hourString += 's';
        parts.push(hourString);
    }
    if (mins > 0 && hours < 3 && days === 0) {
        parts.push(mins);
        if (mins > 1) minuteString += 's';
        parts.push(minuteString);
    }
    if (secs > 0 && mins < 3 && hours === 0 && days === 0) {
        parts.push(secs);
        if (secs > 1) secondString += 's';
        parts.push(secondString);
    }
    return parts.join(' ');
}



var date = Object.freeze({
	format: format$1,
	equals: equals$3,
	relativeTo: relativeTo
});

/*global require, process, Promise, System*/

/*
 * Methods helping with promises (Promise/A+ model). Not a promise shim.
 */

function promise(obj) {
  // Promise object / function converter
  // Example:
  // promise("foo");
  //   // => Promise({state: "fullfilled", value: "foo"})
  // lively.lang.promise({then: (resolve, reject) => resolve(23)})
  //   // => Promise({state: "fullfilled", value: 23})
  // lively.lang.promise(function(val, thenDo) { thenDo(null, val + 1) })(3)
  //   // => Promise({state: "fullfilled", value: 4})
  return typeof obj === "function" ? promise.convertCallbackFun(obj) : Promise.resolve(obj);
}

function delay$1(ms, resolveVal) {
  // Like `Promise.resolve(resolveVal)` but waits for `ms` milliseconds
  // before resolving
  return new Promise(function (resolve) {
    return setTimeout(resolve, ms, resolveVal);
  });
}

function delayReject(ms, rejectVal) {
  // like `promise.delay` but rejects
  return new Promise(function (_, reject$$1) {
    return setTimeout(reject$$1, ms, rejectVal);
  });
}

function timeout(ms, promise) {
  // Takes a promise and either resolves to the value of the original promise
  // when it succeeds before `ms` milliseconds passed or fails with a timeout
  // error
  return new Promise(function (resolve, reject$$1) {
    var done = false;
    setTimeout(function () {
      return !done && (done = true) && reject$$1(new Error('Promise timed out'));
    }, ms);
    promise.then(function (val) {
      return !done && (done = true) && resolve(val);
    }, function (err) {
      return !done && (done = true) && reject$$1(err);
    });
  });
}

function waitFor$1(ms, tester, timeoutObj) {
  // Tests for a condition calling function `tester` until the result is
  // truthy. Resolves with last return value of `tester`. If `ms` is defined
  // and `ms` milliseconds passed, reject with timeout error
  // if timeoutObj is passed will resolve(!) with this object instead of raise
  // an error
  if (typeof ms === "function") {
    tester = ms;ms = undefined;
  }
  return new Promise(function (resolve, reject$$1) {
    var stopped = false,
        timedout = false,
        timeoutValue = undefined,
        error = undefined,
        value = undefined,
        i = setInterval(function () {
      if (stopped) return clearInterval(i);
      try {
        value = tester();
      } catch (e) {
        error = e;
      }
      if (!value && !error && !timedout) return;
      stopped = true;
      clearInterval(i);
      if (error) return reject$$1(error);
      if (timedout) return typeof timeoutObj === "undefined" ? reject$$1(new Error("timeout")) : resolve(timeoutObj);
      return resolve(value);
    }, 10);
    if (typeof ms === "number") setTimeout(function () {
      return timedout = true;
    }, ms);
  });
}

function deferred() {
  // returns an object
  // `{resolve: FUNCTION, reject: FUNCTION, promise: PROMISE}`
  // that separates the resolve/reject handling from the promise itself
  // Similar to the deprecated `Promise.defer()`
  var resolve,
      reject$$1,
      promise = new Promise(function (_resolve, _reject) {
    resolve = _resolve;reject$$1 = _reject;
  });
  return { resolve: resolve, reject: reject$$1, promise: promise };
}

function convertCallbackFun(func) {
  // Takes a function that accepts a nodejs-style callback function as a last
  // parameter and converts it to a function *not* taking the callback but
  // producing a promise instead. The promise will be resolved with the
  // *first* non-error argument.
  // nodejs callback convention: a function that takes as first parameter an
  // error arg and second+ parameters are the result(s).
  // Example:
  // var fs = require("fs"),
  //     readFile = promise.convertCallbackFun(fs.readFile);
  // readFile("./some-file.txt")
  //   .then(content => console.log(String(content)))
  //   .catch(err => console.error("Could not read file!", err));
  return function promiseGenerator() /*args*/{
    var args = Array.from(arguments),
        self = this;
    return new Promise(function (resolve, reject$$1) {
      args.push(function (err, result) {
        return err ? reject$$1(err) : resolve(result);
      });
      func.apply(self, args);
    });
  };
}

function convertCallbackFunWithManyArgs(func) {
  // like convertCallbackFun but the promise will be resolved with the
  // all non-error arguments wrapped in an array.
  return function promiseGenerator() /*args*/{
    var args = Array.from(arguments),
        self = this;
    return new Promise(function (resolve, reject$$1) {
      args.push(function () /*err + args*/{
        var args = Array.from(arguments),
            err = args.shift();
        return err ? reject$$1(err) : resolve(args);
      });
      func.apply(self, args);
    });
  };
}

function _chainResolveNext(promiseFuncs, prevResult, akku, resolve, reject$$1) {
  var next = promiseFuncs.shift();
  if (!next) resolve(prevResult);else {
    try {
      Promise.resolve(next(prevResult, akku)).then(function (result) {
        return _chainResolveNext(promiseFuncs, result, akku, resolve, reject$$1);
      }).catch(function (err) {
        reject$$1(err);
      });
    } catch (err) {
      reject$$1(err);
    }
  }
}

function chain$1(promiseFuncs) {
  // Similar to Promise.all but takes a list of promise-producing functions
  // (instead of Promises directly) that are run sequentially. Each function
  // gets the result of the previous promise and a shared "state" object passed
  // in. The function should return either a value or a promise. The result of
  // the entire chain call is a promise itself that either resolves to the last
  // returned value or rejects with an error that appeared somewhere in the
  // promise chain. In case of an error the chain stops at that point.
  // Example:
  // lively.lang.promise.chain([
  //   () => Promise.resolve(23),
  //   (prevVal, state) => { state.first = prevVal; return prevVal + 2 },
  //   (prevVal, state) => { state.second = prevVal; return state }
  // ]).then(result => console.log(result));
  // // => prints {first: 23,second: 25}
  return new Promise(function (resolve, reject$$1) {
    return _chainResolveNext(promiseFuncs.slice(), undefined, {}, resolve, reject$$1);
  });
}

function promise_finally(promise, finallyFn) {
  return Promise.resolve(promise).then(function (result) {
    try {
      finallyFn();
    } catch (err) {
      console.error("Error in promise finally: " + err.stack || err);
    }return result;
  }).catch(function (err) {
    try {
      finallyFn();
    } catch (err) {
      console.error("Error in promise finally: " + err.stack || err);
    }throw err;
  });
}

function parallel(promiseGenFns) {
  var parallelLimit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Infinity;

  // Starts functions from promiseGenFns that are expected to return a promise
  // Once `parallelLimit` promises are unresolved at the same time, stops
  // spawning further promises until a running promise resolves

  if (!promiseGenFns.length) return Promise.resolve([]);

  var results = [],
      error = null,
      index = 0,
      left = promiseGenFns.length,
      resolve = void 0,
      reject$$1 = void 0;

  return new Promise(function (res, rej) {
    resolve = function resolve() {
      return res(results);
    };
    reject$$1 = function reject$$1(err) {
      return rej(error = err);
    };
    spawnMore();
  });

  function spawn() {
    parallelLimit--;
    try {
      (function () {
        var i = index++,
            prom = promiseGenFns[i]();
        prom.then(function (result) {
          parallelLimit++;
          results[i] = result;
          if (--left === 0) resolve();else spawnMore();
        }).catch(function (err) {
          return reject$$1(err);
        });
      })();
    } catch (err) {
      reject$$1(err);
    }
  }

  function spawnMore() {
    while (!error && left > 0 && index < promiseGenFns.length && parallelLimit > 0) {
      spawn();
    }
  }
}

// FIXME!
Object.assign(promise, {
  delay: delay$1,
  delayReject: delayReject,
  timeout: timeout,
  waitFor: waitFor$1,
  deferred: deferred,
  convertCallbackFun: convertCallbackFun,
  convertCallbackFunWithManyArgs: convertCallbackFunWithManyArgs,
  chain: chain$1,
  "finally": promise_finally,
  parallel: parallel
});

// -=-=-=-=-=-=-=-=-=-=-=-=-=-
// js object path accessor
// -=-=-=-=-=-=-=-=-=-=-=-=-=-

// show-in-doc
// A `Path` is an objectified chain of property names (kind of a "complex"
// getter and setter). Path objects can make access and writes into deeply nested
// structures more convenient. `Path` provide "safe" get and set operations and
// can be used for debugging by providing a hook that allows users to find out
// when get/set operations happen.

function Path(p, splitter) {
  if (p instanceof Path) return p;
  if (!(this instanceof Path)) return new Path(p, splitter);
  this.setSplitter(splitter || '.');
  this.fromPath(p);
}

Object.assign(Path.prototype, {

  get isPathAccessor() {
    return true;
  },

  fromPath: function fromPath(path) {
    // ignore-in-doc
    if (typeof path === "string" && path !== '' && path !== this.splitter) {
      this._parts = path.split(this.splitter);
      this._path = path;
    } else if (Array.isArray(path)) {
      this._parts = [].concat(path);
      this._path = path.join(this.splitter);
    } else {
      this._parts = [];
      this._path = '';
    }
    return this;
  },
  setSplitter: function setSplitter(splitter) {
    // ignore-in-doc
    if (splitter) this.splitter = splitter;
    return this;
  },
  parts: function parts() {
    /*key names as array*/return this._parts;
  },
  size: function size() {
    /*show-in-doc*/return this._parts.length;
  },
  slice: function slice(n, m) {
    /*show-in-doc*/return Path(this.parts().slice(n, m));
  },
  normalizePath: function normalizePath() {
    // ignore-in-doc
    // FIXME: define normalization
    return this._path;
  },
  isRoot: function isRoot(obj) {
    return this._parts.length === 0;
  },
  isIn: function isIn(obj) {
    // Does the Path resolve to a value when applied to `obj`?
    if (this.isRoot()) return true;
    var parent = this.get(obj, -1);
    return parent && parent.hasOwnProperty(this._parts[this._parts.length - 1]);
  },
  equals: function equals(obj) {
    // Example:
    // var p1 = Path("foo.1.bar.baz"), p2 = Path(["foo", 1, "bar", "baz"]);
    // // Path's can be both created via strings or pre-parsed with keys in a list.
    // p1.equals(p2) // => true
    return obj && obj.isPathAccessor && this.parts().equals(obj.parts());
  },
  isParentPathOf: function isParentPathOf(otherPath) {
    // Example:
    // var p1 = Path("foo.1.bar.baz"), p2 = Path("foo.1.bar");
    // p2.isParentPathOf(p1) // => true
    // p1.isParentPathOf(p2) // => false
    otherPath = otherPath && otherPath.isPathAccessor ? otherPath : Path(otherPath);
    var parts = this.parts(),
        otherParts = otherPath.parts();
    for (var i = 0; i < parts.length; i++) {
      if (parts[i] != otherParts[i]) return false;
    }
    return true;
  },
  relativePathTo: function relativePathTo(otherPath) {
    // Example:
    // var p1 = Path("foo.1.bar.baz"), p2 = Path("foo.1");
    // p2.relativePathTo(p1) // => Path(["bar","baz"])
    // p1.relativePathTo(p2) // => undefined
    otherPath = Path(otherPath);
    return this.isParentPathOf(otherPath) ? otherPath.slice(this.size(), otherPath.size()) : undefined;
  },
  del: function del(obj) {
    if (this.isRoot()) return false;
    var parent = obj;
    for (var i = 0; i < this._parts.length - 1; i++) {
      var part = this._parts[i];
      if (parent.hasOwnProperty(part)) {
        parent = parent[part];
      } else return false;
    }
    return delete parent[this._parts[this._parts.length - 1]];
  },
  withParentAndKeyDo: function withParentAndKeyDo(obj, ensure, doFunc) {
    // Deeply resolve path in `obj`, not fully, however, only to the parent
    // element of the last part of path. Take the parent, the key (the last
    // part of path) and pass it to `doFunc`. When `ensure` is true, create
    // objects along path it path does not resolve
    if (this.isRoot()) return doFunc(null, null);
    var parent = obj;
    for (var i = 0; i < this._parts.length - 1; i++) {
      var part = this._parts[i];
      if (parent.hasOwnProperty(part) && (_typeof(parent[part]) === "object" || typeof parent[part] === "function")) {
        parent = parent[part];
      } else if (ensure) {
        parent = parent[part] = {};
      } else {
        return doFunc(null, part);
      }
    }
    return doFunc(parent, this._parts[this._parts.length - 1]);
  },
  set: function set(obj, val, ensure) {
    // Deeply resolve path in `obj` and set the resulting property to `val`. If
    // `ensure` is true, create nested structure in between as necessary.
    // Example:
    // var o1 = {foo: {bar: {baz: 42}}};
    // var path = Path("foo.bar.baz");
    // path.set(o1, 43)
    // o1 // => {foo: {bar: {baz: 43}}}
    // var o2 = {foo: {}};
    // path.set(o2, 43, true)
    // o2 // => {foo: {bar: {baz: 43}}}
    return this.withParentAndKeyDo(obj, ensure, function (parent, key) {
      return parent ? parent[key] = val : undefined;
    });
  },
  defineProperty: function defineProperty(obj, propertySpec, ensure) {
    // like `Path>>set`, however uses Objeect.defineProperty
    return this.withParentAndKeyDo(obj, ensure, function (parent, key) {
      return parent ? Object.defineProperty(parent, key, propertySpec) : undefined;
    });
  },
  get: function get(obj, n) {
    // show-in-doc
    var parts = n ? this._parts.slice(0, n) : this._parts;
    return parts.reduce(function (current, pathPart) {
      return current ? current[pathPart] : current;
    }, obj);
  },
  concat: function concat(p, splitter) {
    // show-in-doc
    return Path(this.parts().concat(Path(p, splitter).parts()));
  },
  toString: function toString() {
    return this.normalizePath();
  },
  serializeExpr: function serializeExpr() {
    // ignore-in-doc
    return 'lively.lang.Path(' + inspect(this.parts()) + ')';
  },
  watch: function watch(options) {
    // React or be notified on reads or writes to a path in a `target`. Options:
    // ```js
    // {
    //   target: OBJECT,
    //   uninstall: BOOLEAN,
    //   onGet: FUNCTION,
    //   onSet: FUNCTION,
    //   haltWhenChanged: BOOLEAN,
    //   verbose: BOOLEAN
    // }
    // ```
    // Example:
    // // Quite useful for debugging to find out what call-sites change an object.
    // var o = {foo: {bar: 23}};
    // Path("foo.bar").watch({target: o, verbose: true});
    // o.foo.bar = 24; // => You should see: "[object Object].bar changed: 23 -> 24"
    if (!options || this.isRoot()) return;
    var target = options.target,
        parent = this.get(target, -1),
        propName = this.parts().slice(-1)[0],
        newPropName = 'propertyWatcher$' + propName,
        watcherIsInstalled = parent && parent.hasOwnProperty(newPropName),
        uninstall = options.uninstall,
        haltWhenChanged = options.haltWhenChanged,
        showStack = options.showStack,
        getter = parent.__lookupGetter__(propName),
        setter = parent.__lookupSetter__(propName);
    if (!target || !propName || !parent) return;
    if (uninstall) {
      if (!watcherIsInstalled) return;
      delete parent[propName];
      parent[propName] = parent[newPropName];
      delete parent[newPropName];
      var msg = 'Watcher for ' + parent + '.' + propName + ' uninstalled';
      show(msg);
      return;
    }
    if (watcherIsInstalled) {
      var msg = 'Watcher for ' + parent + '.' + propName + ' already installed';
      show(msg);
      return;
    }
    if (getter || setter) {
      var msg = parent + '["' + propName + '"] is a getter/setter, watching not support';
      console.log(msg);
      if (typeof show === "undefined") show(msg);
      return;
    }
    // observe slots, for debugging
    parent[newPropName] = parent[propName];
    parent.__defineSetter__(propName, function (v) {
      var oldValue = parent[newPropName];
      if (options.onSet) options.onSet(v, oldValue);
      var msg = parent + "." + propName + " changed: " + oldValue + " -> " + v;
      if (showStack) msg += '\n' + (typeof lively !== "undefined" ? lively.printStack() : console.trace());
      if (options.verbose) {
        console.log(msg);
        if (typeof show !== 'undefined') show(msg);
      }
      if (haltWhenChanged) debugger;
      return parent[newPropName] = v;
    });
    parent.__defineGetter__(propName, function () {
      if (options.onGet) options.onGet(parent[newPropName]);
      return parent[newPropName];
    });
    var msg = 'Watcher for ' + parent + '.' + propName + ' installed';
    console.log(msg);
    if (typeof show !== 'undefined') show(msg);
  },
  debugFunctionWrapper: function debugFunctionWrapper(options) {
    // ignore-in-doc
    // options = {target, [haltWhenChanged, showStack, verbose, uninstall]}
    var target = options.target,
        parent = this.get(target, -1),
        funcName = this.parts().slice(-1)[0],
        uninstall = options.uninstall,
        haltWhenChanged = options.haltWhenChanged === undefined ? true : options.haltWhenChanged,
        showStack = options.showStack,
        func = parent && funcName && parent[funcName],
        debuggerInstalled = func && func.isDebugFunctionWrapper;
    if (!target || !funcName || !func || !parent) return;
    if (uninstall) {
      if (!debuggerInstalled) return;
      parent[funcName] = parent[funcName].debugTargetFunction;
      var msg = 'Uninstalled debugFunctionWrapper for ' + parent + '.' + funcName;
      console.log(msg);
      if (typeof show !== 'undefined') show(msg);
      show(msg);
      return;
    }
    if (debuggerInstalled) {
      var msg = 'debugFunctionWrapper for ' + parent + '.' + funcName + ' already installed';
      console.log(msg);
      if (typeof show !== 'undefined') show(msg);
      return;
    }
    var debugFunc = parent[funcName] = func.wrap(function (proceed) {
      var args = Array.from(arguments);
      if (haltWhenChanged) debugger;
      if (showStack) show(lively.printStack());
      if (options.verbose) show(funcName + ' called');
      return args.shift().apply(parent, args);
    });
    debugFunc.isDebugFunctionWrapper = true;
    debugFunc.debugTargetFunction = func;
    var msg = 'debugFunctionWrapper for ' + parent + '.' + funcName + ' installed';
    console.log(msg);
    if (typeof show !== 'undefined') show(msg);
  }
});

/*
Computation over graphs. Unless otherwise specified a graph is a simple JS
object whose properties are interpreted as nodes that refer to arrays whose
elements describe edges. Example:

```js
var testGraph = {
  "a": ["b", "c"],
  "b": ["c", "d", "e", "f"],
  "d": ["c", "f"],
  "e": ["a", "f"],
  "f": []
}
```
*/

// show-in-doc
function clone$2(graph) {
  // return a copy of graph map
  var cloned = {};
  for (var id in graph) {
    cloned[id] = graph[id].slice();
  }return cloned;
}

function without$1(graph, ids) {
  // return a copy of graph map with ids removed
  var cloned = {};
  for (var id in graph) {
    if (ids.includes(id)) continue;
    cloned[id] = [];
    var refs = graph[id];
    for (var i = 0; i < refs.length; i++) {
      var ref = refs[i];
      if (!ids.includes(ref)) cloned[id].push(ref);
    }
  }
  return cloned;
}

function hull(g, id) {
  var ignoredKeyList = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  var maxDepth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Infinity;

  // Takes a graph in object format and a start id and then traverses the
  // graph and gathers all nodes that can be reached from that start id.
  // Returns a list of those nodes.
  // Optionally use `ignore` list to filter out certain nodes that shouldn't
  // be considered and maxDepth to stop early. By default a maxDepth of 20 is
  // used.
  // Example:
  // var testGraph = {
  // "a": ["b", "c"],
  // "b": ["c", "d", "e", "f"],
  // "d": ["c", "f"],
  // "e": ["a", "f"],
  // "f": []
  // }
  // hull(testGraph, "d") // => ["c", "f"]
  // hull(testGraph, "e") // => ['a', 'f', 'b', 'c', 'd', 'e']
  // hull(testGraph, "e", ["b"]) // => ["a", "f", "c"]

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // below is an optimized variant, the functional but slow version:
  // return uniq(
  //         flatten(
  //           values(
  //             subgraphReachableBy(
  //               graphMap, id, ignore, maxDepth))));

  if (!Array.isArray(g[id])) return [];

  var hull = [],
      visited = {};

  var ignoredKeys = {};
  for (var i = 0; i < ignoredKeyList.length; i++) {
    ignoredKeys[ignoredKeyList[i]] = true;
  }var toVisitList = g[id].slice(),
      toVisitMapAndDistFromRoot = {};
  for (var _i = toVisitList.length; _i--;) {
    var key = toVisitList[_i];
    if (key in ignoredKeys) toVisitList.splice(_i, 1);else toVisitMapAndDistFromRoot[key] = 1;
  }

  if (ignoredKeyList) while (true) {
    if (toVisitList.length === 0) break;
    for (var _i2 = 0; _i2 < toVisitList.length; _i2++) {
      var _key = toVisitList.shift();
      if (_key in visited || _key in ignoredKeys) continue;
      var dist = toVisitMapAndDistFromRoot[_key] || 0;
      if (dist > maxDepth) continue;
      hull.push(_key);
      visited[_key] = true;
      var refs = g[_key];
      if (!refs) continue;
      for (var j = 0; j < refs.length; j++) {
        var refKey = refs[j];
        if (refKey in visited || refKey in toVisitMapAndDistFromRoot) continue;
        toVisitMapAndDistFromRoot[refKey] = dist + 1;
        toVisitList.push(refKey);
      }
    }
  }
  return hull;
}

function subgraphReachableBy(graphMap, startId, ignore) {
  var maxDepth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : Infinity;

  // show-in-doc
  // Like hull but returns subgraph map of `graphMap`
  // Example:
  // subgraphReachableBy(testGraph, "e", [], 2);
  // // => {e: [ 'a', 'f' ], a: [ 'b', 'c' ], f: []}
  if (ignore) graphMap = without$1(graphMap, ignore);
  var ids = [startId],
      step = 0,
      subgraph = {};
  while (ids.length && step++ < maxDepth) {
    var id = ids.shift();
    if (subgraph[id]) continue;
    var newIds = graphMap[id] || [];
    subgraph[id] = newIds;
    ids.push.apply(ids, toConsumableArray(newIds));
  }
  return subgraph;
}

function invert(g) {
  // inverts the references of graph object `g`.
  // Example:
  // invert({a: ["b"], b: ["a", "c"]})
  //   // => {a: ["b"], b: ["a"], c: ["b"]}
  var inverted = {};
  for (var key in g) {
    var refs = g[key];
    for (var i = 0; i < refs.length; i++) {
      var key2 = refs[i];
      if (!inverted[key2]) inverted[key2] = [key];else inverted[key2].push(key);
    }
  }
  return inverted;
}

function sortByReference(depGraph, startNode) {
  // Sorts graph into an array of arrays. Each "bucket" contains the graph
  // nodes that have no other incoming nodes than those already visited. This
  // means, we start with the leaf nodes and then walk our way up.
  // This is useful for computing how to traverse a dependency graph: You get
  // a sorted list of dependencies that also allows circular references.
  // Example:
  // var depGraph = {a: ["b", "c"], b: ["c"], c: ["b"]};
  // sortByReference(depGraph, "a");
  // // => [["c"], ["b"], ["a"]]


  // establish unique list of keys
  var remaining = [],
      remainingSeen = {},
      uniqDepGraph = {},
      inverseDepGraph = {};
  for (var _key2 in depGraph) {
    if (!remainingSeen.hasOwnProperty(_key2)) {
      remainingSeen[_key2] = true;
      remaining.push(_key2);
    }
    var deps = depGraph[_key2],
        uniqDeps = {};
    if (deps) {
      uniqDepGraph[_key2] = [];
      var _iteratorNormalCompletion = true;
      var _didIteratorError = false;
      var _iteratorError = undefined;

      try {
        for (var _iterator = deps[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var dep = _step.value;

          if (uniqDeps.hasOwnProperty(dep) || _key2 === dep) continue;
          var inverse = inverseDepGraph[dep] || (inverseDepGraph[dep] = []);
          if (!inverse.includes(_key2)) inverse.push(_key2);
          uniqDeps[dep] = true;
          uniqDepGraph[_key2].push(dep);
          if (!remainingSeen.hasOwnProperty(dep)) {
            remainingSeen[dep] = true;
            remaining.push(dep);
          }
        }
      } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator.return) {
            _iterator.return();
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError;
          }
        }
      }
    }
  }

  // for each iteration find the keys with the minimum number of dependencies
  // and add them to the result group list
  var groups = [];
  while (remaining.length) {
    var minDepCount = Infinity,
        minKeys = [],
        minKeyIndexes = [],
        affectedKeys = [];
    for (var i = 0; i < remaining.length; i++) {
      var key = remaining[i];
      var _deps = uniqDepGraph[key] || [];
      if (_deps.length > minDepCount) continue;

      // if (deps.length === minDepCount && !minKeys.some(ea => deps.includes(ea))) {
      if (_deps.length === minDepCount && !_deps.some(function (ea) {
        return minKeys.includes(ea);
      })) {
        var _affectedKeys;

        minKeys.push(key);
        minKeyIndexes.push(i);
        (_affectedKeys = affectedKeys).push.apply(_affectedKeys, toConsumableArray(inverseDepGraph[key] || []));
        continue;
      }
      minDepCount = _deps.length;
      minKeys = [key];
      minKeyIndexes = [i];
      affectedKeys = (inverseDepGraph[key] || []).slice();
    }
    for (var i = minKeyIndexes.length; i--;) {
      var key = remaining[minKeyIndexes[i]];
      inverseDepGraph[key] = [];
      remaining.splice(minKeyIndexes[i], 1);
    }
    var _iteratorNormalCompletion2 = true;
    var _didIteratorError2 = false;
    var _iteratorError2 = undefined;

    try {
      for (var _iterator2 = affectedKeys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
        var key = _step2.value;

        uniqDepGraph[key] = uniqDepGraph[key].filter(function (ea) {
          return !minKeys.includes(ea);
        });
      }
    } catch (err) {
      _didIteratorError2 = true;
      _iteratorError2 = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion2 && _iterator2.return) {
          _iterator2.return();
        }
      } finally {
        if (_didIteratorError2) {
          throw _iteratorError2;
        }
      }
    }

    groups.push(minKeys);
  }
  return groups;
}

function reduce$1(doFunc, graph, rootNode, carryOver, ignore, context) {
  // Starts with `rootNode` and visits all (in)directly related nodes, calling
  // `doFunc` at each node. The result of `doFunc` is passed as first
  // argument to the next iterator call. For the first call the value
  // `carryOver` is used.
  // Example:
  // var depGraph = {a: ["b", "c"],b: ["c"]}
  // graphReduce((_, ea, i) => console.log("%s %s", ea, i), depGraph, "a")

  var visitedNodes = ignore || [],
      index = 0;
  iterator(rootNode);
  return carryOver;

  function iterator(currentNode) {
    if (visitedNodes.indexOf(currentNode) > -1) return;
    carryOver = doFunc.call(context, carryOver, currentNode, index++);
    visitedNodes = visitedNodes.concat([currentNode]);
    var next = withoutAll(graph[currentNode] || [], visitedNodes);
    next.forEach(function (ea) {
      return iterator(ea);
    });
  }
}

function random$1() {
  var nKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10;

  var g = {},
      keys$$1 = range(1, nKeys).map(String);
  for (var i = 0; i < keys$$1.length; i++) {
    var r = Math.floor(Math.random() * nKeys);
    g[keys$$1[i]] = shuffle(keys$$1).slice(0, r);
  }
  return g;
}



var graph = Object.freeze({
	clone: clone$2,
	without: without$1,
	hull: hull,
	subgraphReachableBy: subgraphReachableBy,
	invert: invert,
	sortByReference: sortByReference,
	reduce: reduce$1,
	random: random$1
});

/*global System, global*/

// show-in-doc
// Intervals are arrays whose first two elements are numbers and the
// first element should be less or equal the second element, see
// [`interval.isInterval`](). This abstraction is useful when working with text
// ranges in rich text, for example.

var GLOBAL$2 = typeof System !== "undefined" ? System.global : typeof window !== 'undefined' ? window : global;

function isInterval(object) {
  // Example:
  // interval.isInterval([1,12]) // => true
  // interval.isInterval([1,12, {property: 23}]) // => true
  // interval.isInterval([1]) // => false
  // interval.isInterval([12, 1]) // => false
  return Array.isArray(object) && object.length >= 2 && object[0] <= object[1];
}

function sort$2(intervals) {
  // Sorts intervals according to rules defined in [`interval.compare`]().
  return intervals.sort(compare);
}

function compare(a, b) {
  // How [`interval.sort`]() compares.
  // We assume that `a[0] <= a[1] and b[0] <= b[1]` according to `isInterval`
  // ```
  // -3: a < b and non-overlapping, e.g [1,2] and [3,4]
  // -2: a < b and intervals border at each other, e.g [1,3] and [3,4]
  // -1: a < b and overlapping, e.g, [1,3] and [2,4] or [1,3] and [1,4]
  //  0: a = b, e.g. [1,2] and [1,2]
  //  1: a > b and overlapping, e.g. [2,4] and [1,3]
  //  2: a > b and share border, e.g [1,4] and [0,1]
  //  3: a > b and non-overlapping, e.g [2,4] and [0,1]
  // ```
  if (a[0] < b[0]) {
    // -3 || -2 || -1
    if (a[1] < b[0]) return -3;
    if (a[1] === b[0]) return -2;
    return -1;
  }
  if (a[0] === b[0]) {
    // -1 || 0 || 1
    if (a[1] === b[1]) return 0;
    return a[1] < b[1] ? -1 : 1;
  }
  // we know a[0] > b[0], 1 || 2 || 3
  return -1 * compare(b, a);
}

function coalesce(interval1, interval2, optMergeCallback) {
  // Turns two interval into one iff compare(interval1, interval2) ∈ [-2,
  // -1,0,1, 2] (see [`inerval.compare`]()).
  // Otherwise returns null. Optionally uses merge function.
  // Examples:
  //   interval.coalesce([1,4], [5,7]) // => null
  //   interval.coalesce([1,2], [1,2]) // => [1,2]
  //   interval.coalesce([1,4], [3,6]) // => [1,6]
  //   interval.coalesce([3,6], [4,5]) // => [3,6]
  var cmpResult = this.compare(interval1, interval2);
  switch (cmpResult) {
    case -3:
    case 3:
      return null;
    case 0:
      optMergeCallback && optMergeCallback(interval1, interval2, interval1);
      return interval1;
    case 2:
    case 1:
      var temp = interval1;interval1 = interval2;interval2 = temp; // swap
    case -2:
    case -1:
      var coalesced = [interval1[0], Math.max(interval1[1], interval2[1])];
      optMergeCallback && optMergeCallback(interval1, interval2, coalesced);
      return coalesced;
    default:
      throw new Error("Interval compare failed");
  }
}

function coalesceOverlapping(intervals, mergeFunc) {
  // Like `coalesce` but accepts an array of intervals.
  // Example:
  //   interval.coalesceOverlapping([[9,10], [1,8], [3, 7], [15, 20], [14, 21]])
  //   // => [[1,8],[9,10],[14,21]]
  var condensed = [],
      len = intervals.length;
  while (len > 0) {
    var ival = intervals.shift();len--;
    for (var i = 0; i < len; i++) {
      var otherInterval = intervals[i],
          coalesced = coalesce(ival, otherInterval, mergeFunc);
      if (coalesced) {
        ival = coalesced;
        intervals.splice(i, 1);
        len--;i--;
      }
    }
    condensed.push(ival);
  }
  return this.sort(condensed);
}

function mergeOverlapping(intervalsA, intervalsB, mergeFunc) {
  var result = [];
  while (intervalsA.length > 0) {
    var intervalA = intervalsA.shift();

    var toMerge = intervalsB.map(function (intervalB) {
      var cmp = compare(intervalA, intervalB);
      return cmp === -1 || cmp === 0 || cmp === 1;
    });

    result.push(mergeFunc(intervalA, toMerge[0]));

    result.push(intervalA);
  }
  return result;
}

function intervalsInRangeDo(start, end, intervals, iterator, mergeFunc, context) {
  // Merges and iterates through sorted intervals. Will "fill up"
  // intervals. This is currently used for computing text chunks in
  // lively.morphic.TextCore.
  // Example:
  // interval.intervalsInRangeDo(
  //   2, 10, [[0, 1], [5,8], [2,4]],
  //   function(i, isNew) { i.push(isNew); return i; })
  // // => [[2,4,false],[4,5,true],[5,8,false],[8,10,true]]

  context = context || GLOBAL$2;
  // need to be sorted for the algorithm below
  intervals = this.sort(intervals);
  var free = [],
      nextInterval,
      collected = [];
  // merged intervals are already sorted, simply "negate" the interval array;
  while (nextInterval = intervals.shift()) {
    if (nextInterval[1] < start) continue;
    if (nextInterval[0] < start) {
      nextInterval = Array.prototype.slice.call(nextInterval);
      nextInterval[0] = start;
    }
    var nextStart = end < nextInterval[0] ? end : nextInterval[0];
    if (start < nextStart) {
      collected.push(iterator.call(context, [start, nextStart], true));
    }
    if (end < nextInterval[1]) {
      nextInterval = Array.prototype.slice.call(nextInterval);
      nextInterval[1] = end;
    }
    // special case, the newly constructed interval has length 0,
    // happens when intervals contains doubles at the start
    if (nextInterval[0] === nextInterval[1]) {
      var prevInterval;
      if (mergeFunc && (prevInterval = collected.slice(-1)[0])) {
        // arguments: a, b, merged, like in the callback of #merge
        mergeFunc.call(context, prevInterval, nextInterval, prevInterval);
      }
    } else {
      collected.push(iterator.call(context, nextInterval, false));
    }
    start = nextInterval[1];
    if (start >= end) break;
  }
  if (start < end) collected.push(iterator.call(context, [start, end], true));
  return collected;
}

function intervalsInbetween(start, end, intervals) {
  // Computes "free" intervals between the intervals given in range start - end
  // currently used for computing text chunks in lively.morphic.TextCore
  // Example:
  // interval.intervalsInbetween(0, 10,[[1,4], [5,8]])
  // // => [[0,1],[4,5],[8,10]]
  return intervalsInRangeDo(start, end, coalesceOverlapping(Array.prototype.slice.call(intervals)), function (interval, isNew) {
    return isNew ? interval : null;
  }).filter(Boolean);
}

function mapToMatchingIndexes(intervals, intervalsToFind) {
  // Returns an array of indexes of the items in intervals that match
  // items in `intervalsToFind`.
  // Note: We expect intervals and intervals to be sorted according to [`interval.compare`]()!
  // This is the optimized version of:
  // ```
  // return intervalsToFind.collect(function findOne(toFind) {
  //    var startIdx, endIdx;
  //    var start = intervals.detect(function(ea, i) {
  //       startIdx = i; return ea[0] === toFind[0]; });
  //    if (start === undefined) return [];
  //    var end = intervals.detect(function(ea, i) {
  //       endIdx = i; return ea[1] === toFind[1]; });
  //    if (end === undefined) return [];
  //    return Array.range(startIdx, endIdx);
  // });
  // ```

  var startIntervalIndex = 0,
      endIntervalIndex,
      currentInterval;
  return intervalsToFind.map(function (toFind) {
    while (currentInterval = intervals[startIntervalIndex]) {
      if (currentInterval[0] < toFind[0]) {
        startIntervalIndex++;continue;
      }
      break;
    }
    if (currentInterval && currentInterval[0] === toFind[0]) {
      endIntervalIndex = startIntervalIndex;
      while (currentInterval = intervals[endIntervalIndex]) {
        if (currentInterval[1] < toFind[1]) {
          endIntervalIndex++;continue;
        }
        break;
      }
      if (currentInterval && currentInterval[1] === toFind[1]) {
        return range(startIntervalIndex, endIntervalIndex);
      }
    }
    return [];
  });
}



var interval = Object.freeze({
	isInterval: isInterval,
	sort: sort$2,
	compare: compare,
	coalesce: coalesce,
	coalesceOverlapping: coalesceOverlapping,
	mergeOverlapping: mergeOverlapping,
	intervalsInRangeDo: intervalsInRangeDo,
	intervalsInbetween: intervalsInbetween,
	mapToMatchingIndexes: mapToMatchingIndexes
});

// show-in-doc
// Accessor to sub-ranges of arrays. This is used, for example, for rendering
// large lists or tables in which only a part of the items should be used for
// processing or rendering. An array projection provides convenient access and
// can apply operations to sub-ranges.

function create(array, length, optStartIndex) {
  // Example:
  // arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 1)
  // // => { array: [/*...*/], from: 1, to: 5 }
  var startIndex = optStartIndex || 0;
  if (startIndex + length > array.length) startIndex -= startIndex + length - array.length;
  return { array: array, from: startIndex, to: startIndex + length };
}

function toArray$4(projection) {
  // show-in-doc
  return projection.array.slice(projection.from, projection.to);
}

function originalToProjectedIndex(projection, index) {
  // Maps index from original Array to projection.
  // Example:
  //   var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3);
  //   arrayProjection.originalToProjectedIndex(proj, 1) // => null
  //   arrayProjection.originalToProjectedIndex(proj, 3) // => 0
  //   arrayProjection.originalToProjectedIndex(proj, 5) // => 2
  return index < projection.from || index >= projection.to ? null : index - projection.from;
}

function projectedToOriginalIndex(projection, index) {
  // Inverse to `originalToProjectedIndex`.
  // Example:
  //   var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3);
  //   arrayProjection.projectedToOriginalIndex(proj, 1) // => 4
  if (index < 0 || index > projection.to - projection.from) return null;
  return projection.from + index;
}

function transformToIncludeIndex(projection, index) {
  // Computes how the projection needs to shift minimally (think "scroll"
  // down or up) so that index becomes "visible" in projection.
  // Example:
  // var proj = arrayProjection.create([1,2,3,4,5,6,7,8,9], 4, 3);
  // arrayProjection.transformToIncludeIndex(proj, 1)
  // // => { array: [/*...*/], from: 1, to: 5 }
  if (!(index in projection.array)) return null;
  var delta = 0;
  if (index < projection.from) delta = -projection.from + index;
  if (index >= projection.to) delta = index - projection.to + 1;
  if (delta === 0) return projection;
  return create(projection.array, projection.to - projection.from, projection.from + delta);
}



var arrayProjection = Object.freeze({
	create: create,
	toArray: toArray$4,
	originalToProjectedIndex: originalToProjectedIndex,
	projectedToOriginalIndex: projectedToOriginalIndex,
	transformToIncludeIndex: transformToIncludeIndex
});

// show-in-doc
// A grid is a two-dimaensional array, representing a table-like data

function get$2(grid, nRow, nCol) {
  var row = grid[nRow];
  return row ? row[nCol] : undefined;
}

function set$2(grid, nRow, nCol, obj) {
  var row = grid[nRow];
  if (row) row[nCol] = obj;
  return obj;
}

function getRow(grid, nRow) {
  return grid[nRow];
}

function setRow(grid, nRow, newRow) {
  return grid[nRow] = newRow;
}

function getCol(grid, nCol) {
  return grid.reduce(function (col, row) {
    col.push(row[nCol]);return col;
  }, []);
}

function setCol(grid, nCol, newCol) {
  return grid.map(function (row, i) {
    return row[nCol] ? row[nCol] = newCol[i] : undefined;
  });
}

function create$1(rows, columns, initialObj) {
  // Example:
  // grid.create(3, 2, "empty")
  // // => [["empty","empty"],
  // //     ["empty","empty"],
  // //     ["empty","empty"]]
  var result = new Array(rows);
  while (rows > 0) {
    result[--rows] = withN(columns, initialObj);
  }return result;
}

function mapCreate(rows, cols, func, context) {
  // like `grid.create` but takes generator function for cells
  var result = new Array(rows);
  for (var i = 0; i < rows; i++) {
    result[i] = new Array(cols);
    for (var j = 0; j < cols; j++) {
      result[i][j] = func.call(context || this, i, j);
    }
  }
  return result;
}

function forEach$2(grid, func, context) {
  // iterate, `func` is called as `func(cellValue, i, j)`
  grid.forEach(function (row, i) {
    row.forEach(function (val, j) {
      func.call(context || this, val, i, j);
    });
  });
}

function map$2(grid, func, context) {
  // map, `func` is called as `func(cellValue, i, j)`
  var result = new Array(grid.length);
  grid.forEach(function (row, i) {
    result[i] = new Array(row.length);
    row.forEach(function (val, j) {
      result[i][j] = func.call(context || this, val, i, j);
    });
  });
  return result;
}

function toObjects(grid) {
  // The first row of the grid defines the propNames
  // for each following row create a new object with those porperties
  // mapped to the cells of the row as values
  // Example:
  // grid.toObjects([['a', 'b'],[1,2],[3,4]])
  // // => [{a:1,b:2},{a:3,b:4}]
  var props = grid[0],
      objects = new Array(grid.length - 1);
  for (var i = 1; i < grid.length; i++) {
    var obj = objects[i - 1] = {};
    for (var j = 0; j < props.length; j++) {
      obj[props[j]] = grid[i][j];
    }
  }
  return objects;
}

function tableFromObjects(objects, valueForUndefined) {
  // Reverse operation to `grid.toObjects`. Useful for example to convert objectified
  // SQL result sets into tables that can be printed via Strings.printTable.
  // Objects are key/values like [{x:1,y:2},{x:3},{z:4}]. Keys are interpreted as
  // column names and objects as rows.
  // Example:
  // grid.tableFromObjects([{x:1,y:2},{x:3},{z:4}])
  // // => [["x","y","z"],
  // //    [1,2,null],
  // //    [3,null,null],
  // //    [null,null,4]]

  if (!Array.isArray(objects)) objects = [objects];
  var table = [[]],
      columns = table[0],
      rows = objects.reduce(function (rows, ea) {
    return rows.concat([Object.keys(ea).reduce(function (row, col) {
      var colIdx = columns.indexOf(col);
      if (colIdx === -1) {
        colIdx = columns.length;columns.push(col);
      }
      row[colIdx] = ea[col];
      return row;
    }, [])]);
  }, []);
  valueForUndefined = arguments.length === 1 ? null : valueForUndefined;
  rows.forEach(function (row) {
    // fill cells with no value with null
    for (var i = 0; i < columns.length; i++) {
      if (!row[i]) row[i] = valueForUndefined;
    }
  });
  return table.concat(rows);
}



var grid = Object.freeze({
	get: get$2,
	set: set$2,
	getRow: getRow,
	setRow: setRow,
	getCol: getCol,
	setCol: setCol,
	create: create$1,
	mapCreate: mapCreate,
	forEach: forEach$2,
	map: map$2,
	toObjects: toObjects,
	tableFromObjects: tableFromObjects
});

/*
 * Methods for traversing and transforming tree structures.
 */

function prewalk(treeNode, iterator, childGetter) {
  var counter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { i: 0 };
  var depth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;

  var i = counter.i++;
  iterator(treeNode, i, depth);
  (childGetter(treeNode, i, depth) || []).forEach(function (ea) {
    return prewalk(ea, iterator, childGetter, counter, depth + 1);
  });
}

function postwalk(treeNode, iterator, childGetter) {
  var counter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { i: 0 };
  var depth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;

  var i = counter.i++;
  (childGetter(treeNode, i, depth) || []).forEach(function (ea) {
    return postwalk(ea, iterator, childGetter, counter, depth);
  });
  iterator(treeNode, i, depth);
}

function find(treeNode, testFunc, childGetter) {
  // Traverses a `treeNode` recursively and returns the first node for which
  // `testFunc` returns true. `childGetter` is a function to retrieve the
  // children from a node.
  if (testFunc(treeNode)) return treeNode;
  var children = childGetter(treeNode);
  if (!children || !children.length) return undefined;
  for (var i = 0; i < children.length; i++) {
    var found = find(children[i], testFunc, childGetter);
    if (found) return found;
  }
  return undefined;
}
var detect$1 = find;

function filter$1(treeNode, testFunc, childGetter) {
  // Traverses a `treeNode` recursively and returns all nodes for which
  // `testFunc` returns true. `childGetter` is a function to retrieve the
  // children from a node.
  var result = [];
  if (testFunc(treeNode)) result.push(treeNode);
  return result.concat(flatten((childGetter(treeNode) || []).map(function (n) {
    return filter$1(n, testFunc, childGetter);
  })));
}

function map$3(treeNode, mapFunc, childGetter) {
  var depth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;

  // Traverses a `treeNode` recursively and call `mapFunc` on each node. The
  // return values of all mapFunc calls is the result. `childGetter` is a
  // function to retrieve the children from a node.
  return [mapFunc(treeNode, depth)].concat(flatten((childGetter(treeNode) || []).map(function (n) {
    return map$3(n, mapFunc, childGetter, depth + 1);
  })));
}

function mapTree(treeNode, mapFunc, childGetter) {
  var depth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;

  // Traverses the tree and creates a structurally identical tree but with
  // mapped nodes
  var mappedNodes = (childGetter(treeNode) || []).map(function (n) {
    return mapTree(n, mapFunc, childGetter, depth + 1);
  });
  return mapFunc(treeNode, mappedNodes, depth);
}



var tree = Object.freeze({
	prewalk: prewalk,
	postwalk: postwalk,
	find: find,
	detect: detect$1,
	filter: filter$1,
	map: map$3,
	mapTree: mapTree
});

/*global process, require*/

/*
 * A simple node.js-like cross-platform event emitter implementation that can
 * be used as a mixin. Emitters support the methods: `on(eventName, handlerFunc)`,
 * `once(eventName, handlerFunc)`, `emit(eventName, eventData)`,
 * `removeListener(eventName, handlerFunc)`, `removeAllListeners(eventName)`
 * Example:
 * var emitter = events.makeEmitter({});
 * var log = [];
 * emitter.on("test", function() { log.push("listener1"); });
 * emitter.once("test", function() { log.push("listener2"); });
 * emitter.emit("test");
 * emitter.emit("test");
 * log // => ["listener1","listener2","listener1"]
 * emitter.removeAllListeners("test");
 * emitter.emit("test");
 * log // => is still ["listener1","listener2","listener1"]
 */

var isNode$1 = typeof process !== 'undefined' && process.versions && process.versions.node;

var makeEmitter = isNode$1 ? function (obj, options) {
  if (obj.on && obj.removeListener) return obj;
  var events = typeof System !== "undefined" ? System._nodeRequire("events") : require("events");
  Object.assign(obj, events.EventEmitter.prototype);
  events.EventEmitter.call(obj);
  if (options && options.maxListenerLimit) obj.setMaxListeners(options.maxListenerLimit);

  return obj;
} : function (obj) {
  if (obj.on && obj.removeListener) return obj;

  obj.listeners = {};

  obj.on = function (type, handler) {
    if (!handler) return;
    if (!obj.listeners[type]) obj.listeners[type] = [];
    obj.listeners[type].push(handler);
  };

  obj.once = function (type, handler) {
    if (!handler) return;
    function onceHandler /*ignore-in-docs args*/() {
      obj.removeListener(type, onceHandler);
      handler.apply(this, arguments);
    }
    obj.on(type, onceHandler);
  };

  obj.removeListener = function (type, handler) {
    if (!obj.listeners[type]) return;
    obj.listeners[type] = obj.listeners[type].filter(function (h) {
      return h !== handler;
    });
  };

  obj.removeAllListeners = function (type) {
    if (!obj.listeners[type]) return;
    obj.listeners[type] = [];
  };

  obj.emit = function () /*type and args*/{
    var args = Array.prototype.slice.call(arguments),
        type = args.shift(),
        handlers = obj.listeners[type];
    if (!handlers || !handlers.length) return;
    handlers.forEach(function (handler) {
      try {
        handler.apply(null, args);
      } catch (e) {
        console.error("Error in event handler: %s", e.stack || String(e));
      }
    });
  };

  return obj;
};



var events = Object.freeze({
	makeEmitter: makeEmitter
});

/*global clearTimeout, setTimeout, clearInterval, setInterval*/

/*
 * A pluggable interface to provide asynchronous, actor-like message
 * communication between JavaScript systems. Provides a unified message protocol
 * and send / receive methods.
 */

var OFFLINE = 'offline';
var ONLINE = 'online';
/*

TODO: move to promises! include broadcast API

renames:
listen() => open()
id() => id

*/

/*

A messenger is an object that provides a common, message-based interface. Messengers expect you to provide an implementation of a small number of methods: `send`, `listen`, `close`, and `isOnline`. A messenger will then provide a unified interface for sending and receiving messages. Common boilerplate functionality such as queuing messages, error handling, dealing with instable connections, heartbeats, etc. is handled by the messenger object automatically (and can be parameterized).

This allows to use a single interface across a range of heterogeneous objects without having to implement every detail of the abstraction repeatedly. This is especially valuable when dealing with asynchronous or remote communication (web workers, XHR requests, WebSockets, node.js processes, ...).

To see a minimal example of how to use messengers for the local communication between JavaScript objects [see this example](#messenger-example).

A more sophisticated example of messengers is [the worker implementation](worker.js) which provides an actor-like worker interface that uses web workers in web browsers and child_process.fork in node.js.

```js
var msger = lively.lang.messenger.create({
  send: function(msg, onSendDone) { console.log(msg); onSendDone(); },
  listen: function(thenDo) { thenDo(); },
  close: function(thenDo) { thenDo(); },
  isOnline: function() { return true }
});
```

#### Messenger interface

The interface methods are build to enable an user to send and receive
messages. Each messenger provides the following methods:

##### msger.id()

Each msger has an id that can either be defined by the user when the
msger is created or is automatically assigned. The id should be unique for each
messenger in a messenger network. It is used as the `target` attribute to
address messages and internally in the messaging implementation for routing.
See the [message protocol](#messenger-message-protocol) description for more info.

##### msger.isOnline()

Can the msger send and receive messages right now?

##### msger.heartbeatEnabled()

Does the msger send automated heartbeat messages?

##### msger.listen(optionalCallback)

Brings the messenger "online": Starts listening for messages and brings it
into a state to send messages. `optionalCallback` is a function that is called
when listening begins. It should accept one argument `error` that is null if no
error occured when listening was started, an Error object otherwise.

##### msger.send(msg, onReceiveFunc)

Sends a message. The message should be structured according to the [message
protocol](#messenger-message-protocol). `onReceiveFunc` is triggered when the `msg` is being
answered. `onReceiveFunc` should take two arguments: `error` and `answer`.
`answer` is itself a message object.

##### msger.sendTo(target, action, data, onReceiveFunc)

A simpler `send`, the `msg` object is automatically assembled. `target`
should be an id of the receiver and `action` a string naming the service that
should be triggered on the receiver.

##### msger.answer(msg, data, expectMore, whenSend)

Assembles an answer message for `msg` that includes `data`. `expectMore`
should be truthy when multiple answers should be send (a streaming response,
see the [messaging protocol](#messenger-message-protocol)).

##### msger.close(thenDo)

Stops listening.

##### msger.whenOnline(thenDo)

Registers a callback that is triggered as soon as a listen attempt succeeds
(or when the messenger is listening already then it succeeds immediately).

##### msger.outgoingMessages()

Returns the messages that are currently inflight or not yet send.

##### msger.addServices(serviceSpec)

Add services to the messenger. `serviceSpec` should be  JS object whose keys
correspond to message actions:

```js
msg.addServices({
  helloWorld: function(msg, messenger) {
    messenger.answer(msg, "received a message!");
  }
});
```

See the examples below for more information.

##### *[event]* msger.on("message")

To allow users to receive messages that were not initiated by a send,
messengers are [event emitters](events.js) that emit `"message"` events
whenever they receive a new message.

The messenger object is used to create new messenger interfaces and ties
them to a specific implementation. Please see [worker.js]() for examples of
how web workers and node.js processes are wrapped to provide a cross-platform
interface to a worker abstraction.


#### <a name="messenger-message-protocol"></a>Message protocol

A message is a JSON object with the following fields:

```js
var messageSchema = {

    // REQUIRED selector for service lookup. By convention action gets
    // postfixed with "Result" for response messages
    action: STRING,

    // REQUIRED target of the message, the id of the receiver
    target: UUID,

    // OPTIONAL arguments
    data: OBJECT,

    // OPTIONAL identifier of the message, will be provided if not set by user
    messageId: UUID,

    // OPTIONAL sender of the message, will be provided if not set by user
    sender: UUID,

    // OPTIONAL identifier of a message that this message answers, will be provided
    inResponseTo: UUID,

    // OPTIONAL if message is an answer. Can be interpreted by the receiver as
    // a streaming response. Lively participants (tracker and clients) will
    // trigger data bindings and fire callbacks for a message for every streaming
    // response
    expectMoreResponses: BOOL,

    // EXPERIMENTAL UUIDs of trackers/sessions handlers that forwarded this
    // message
    route: ARRAY
}
```

The `sendTo` and `answer` methods of messengers will automatically create these
messages. If the user invokes the `send` method then a JS object according to
the schema above should be passed as the first argument.

#### <a name="messenger-example"></a>Messenger examples

The following code implements what is needed to use a messenger to communicate
between any number of local JavaScript objects. Instead of dispatching methods using
a local list of messengers you will most likely use an existing networking /
messaging mechanism.

See the [worker](#) and [its implementation](worker.js) for a real use case in
which forking processes in the browser using Web Workers and in node.js using
child_process.fork is unified.

```js
// spec that defines message sending in terms of receivers in the messengers list
var messengers = [];
var messengerSpec = {
  send: function(msg, onSendDone) {
    var err = null, recv = arr.detect(messengers, function(ea) {
          return ea.id() === msg.target; });
    if (recv) recv.onMessage(msg);
    else err = new Error("Could not find receiver " + msg.target);
    onSendDone(err);
  },
  listen: function(thenDo) { arr.pushIfNotIncluded(messengers, this); },
  close: function(thenDo) { arr.remove(messengers, this); },
  isOnline: function() { return arr.include(messengers, this); }
};

// Create the messengers and add a simple "service"
var msger1 = messenger.create(messengerSpec);
var msger2 = messenger.create(messengerSpec);
msger2.addServices({
  add: function(msg, msger) { msger.answer(msg, {result: msg.data.a + msg.data.b}); }
});

// turn'em on...
msger1.listen();
msger2.listen();

// ...and action!
msger1.sendTo(msger2.id(), 'add', {a: 3, b: 4},
  function(err, answer) { alert(answer.data.result); });
```

*/

function create$2(spec) {

  var expectedMethods = [{ name: "send", args: ['msg', 'callback'] }, { name: "listen", args: ['messenger', 'callback'] }, { name: "close", args: ['messenger', 'callback'] }, { name: "isOnline", args: [] }];

  var ignoredAttributes = expectedMethods.map(function (ea) {
    return ea.name;
  }).concat(["id", "sendHeartbeat", "heartbeatInterval", "ignoreUnknownMessages", "allowConcurrentSends", "sendTimeout", "services"]);

  expectedMethods.forEach(function (exp) {
    if (spec[exp.name]) return;
    var msg = "message implementation needs function " + exp.name + "(" + exp.args.join(',') + ")";
    throw new Error(msg);
  });

  var heartbeatInterval = spec.sendHeartbeat && (spec.heartbeatInterval || 1000);
  var ignoreUnknownMessages = spec.hasOwnProperty("ignoreUnknownMessages") ? spec.ignoreUnknownMessages : false;

  var messenger = {

    _outgoing: [],
    _inflight: [],
    _id: spec.id || newUUID(),
    _ignoreUnknownMessages: ignoreUnknownMessages,
    _services: {},
    _messageCounter: 0,
    _messageResponseCallbacks: {},
    _whenOnlineCallbacks: [],
    _statusWatcherProc: null,
    _startHeartbeatProcessProc: null,
    _listenInProgress: null,
    _heartbeatInterval: heartbeatInterval,
    _status: OFFLINE,

    // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    _runWhenOnlineCallbacks: function _runWhenOnlineCallbacks() {
      var cbs = messenger._whenOnlineCallbacks.slice();
      messenger._whenOnlineCallbacks = [];
      cbs.forEach(function (ea) {
        try {
          ea.call(null, null, messenger);
        } catch (e) {
          console.error("error in _runWhenOnlineCallbacks: %s", e);
        }
      });
    },

    _ensureStatusWatcher: function _ensureStatusWatcher() {
      if (messenger._statusWatcherProc) return;
      messenger._statusWatcherProc = setInterval(function () {
        if (messenger.isOnline() && messenger._whenOnlineCallbacks.length) messenger._runWhenOnlineCallbacks();
        var prevStatus = messenger._status;
        messenger._status = messenger.isOnline() ? ONLINE : OFFLINE;
        if (messenger._status !== ONLINE && messenger._statusWatcherProc) {
          messenger.reconnect();
        }
        if (messenger._status !== prevStatus && messenger.onStatusChange) {
          messenger.onStatusChange();
        }
      }, 20);
    },

    _addMissingData: function _addMissingData(msg) {
      if (!msg.target) throw new Error("Message needs target!");
      if (!msg.action) throw new Error("Message needs action!");
      if (!msg.data) msg.data = null;
      if (!msg.messageId) msg.messageId = newUUID();
      msg.sender = messenger.id();
      msg.messageIndex = messenger._messageCounter++;
      return msg;
    },

    _queueSend: function _queueSend(msg, onReceiveFunc) {
      if (onReceiveFunc && typeof onReceiveFunc !== 'function') throw new Error("Expecing a when send callback, got: " + onReceiveFunc);
      messenger._outgoing.push([msg, onReceiveFunc]);
    },

    _deliverMessageQueue: function _deliverMessageQueue() {
      if (!spec.allowConcurrentSends && messenger._inflight.length) return;

      var queued = messenger._outgoing.shift();
      if (!queued) return;

      messenger._inflight.push(queued);
      if (messenger.isOnline()) deliver(queued);else messenger.whenOnline(function () {
        deliver(queued);
      });
      startTimeoutProc(queued);

      if (spec.allowConcurrentSends && messenger._outgoing.length) messenger._deliverMessageQueue();

      // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

      function deliver(queued) {
        // ignore-in-doc
        if (messenger._inflight.indexOf(queued) === -1) return; // timed out
        var msg = queued[0],
            callback = queued[1];
        if (callback) messenger._messageResponseCallbacks[msg.messageId] = callback;

        spec.send.call(messenger, msg, function (err) {
          remove(messenger._inflight, queued);
          if (err) onSendError(err, queued);
          messenger._deliverMessageQueue();
        });
      }

      function startTimeoutProc(queued) {
        if (typeof spec.sendTimeout !== 'number') return;
        setTimeout(function () {
          if (messenger._inflight.indexOf(queued) === -1) return; // delivered
          remove(messenger._inflight, queued);
          onSendError(new Error('Timeout sending message'), queued);
          messenger._deliverMessageQueue();
        }, spec.sendTimeout);
      }

      function onSendError(err, queued) {
        var msg = queued[0],
            callback = queued[1];
        delete messenger._messageResponseCallbacks[msg.messageId];
        console.error(err);
        callback && callback(err);
      }
    },

    _startHeartbeatProcess: function _startHeartbeatProcess() {
      if (messenger._startHeartbeatProcessProc) return;
      messenger._startHeartbeatProcessProc = setTimeout(function () {
        spec.sendHeartbeat.call(messenger, function (err, result) {
          messenger._startHeartbeatProcessProc = null;
          messenger._startHeartbeatProcess();
        });
      }, messenger._heartbeatInterval);
    },

    // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    id: function id() {
      return messenger._id;
    },

    isOnline: function isOnline() {
      return spec.isOnline.call(messenger);
    },

    heartbeatEnabled: function heartbeatEnabled() {
      return typeof messenger._heartbeatInterval === 'number';
    },

    listen: function listen(thenDo) {
      if (messenger._listenInProgress) return;
      messenger._listenInProgress = true;
      messenger._ensureStatusWatcher();
      return spec.listen.call(messenger, function (err) {
        messenger._listenInProgress = null;
        thenDo && thenDo(err);
        if (messenger.heartbeatEnabled()) messenger._startHeartbeatProcess();
      });
      return messenger;
    },

    reconnect: function reconnect() {
      if (messenger._status === ONLINE) return;
      messenger.listen();
      return messenger;
    },

    send: function send(msg, onReceiveFunc) {
      messenger._addMissingData(msg);
      messenger._queueSend(msg, onReceiveFunc);
      messenger._deliverMessageQueue();
      return msg;
    },

    sendTo: function sendTo(target, action, data, onReceiveFunc) {
      var msg = { target: target, action: action, data: data };
      return messenger.send(msg, onReceiveFunc);
    },

    onMessage: function onMessage(msg) {
      messenger.emit("message", msg);
      if (msg.inResponseTo) {
        var cb = messenger._messageResponseCallbacks[msg.inResponseTo];
        if (cb && !msg.expectMoreResponses) delete messenger._messageResponseCallbacks[msg.inResponseTo];
        if (cb) cb(null, msg);
      } else {
        var action = messenger._services[msg.action];
        if (action) {
          try {
            action.call(null, msg, messenger);
          } catch (e) {
            var errmMsg = String(e.stack || e);
            console.error("Error invoking service: " + errmMsg);
            messenger.answer(msg, { error: errmMsg });
          }
        } else if (!messenger._ignoreUnknownMessages) {
          var err = new Error("messageNotUnderstood: " + msg.action);
          messenger.answer(msg, { error: String(err) });
        }
      }
    },

    answer: function answer(msg, data, expectMore, whenSend) {
      if (typeof expectMore === 'function') {
        whenSend = expectMore;expectMore = false;
      }
      var answer = {
        target: msg.sender,
        action: msg.action + 'Result',
        inResponseTo: msg.messageId,
        data: data };
      if (expectMore) answer.expectMoreResponses = true;
      return messenger.send(answer, whenSend);
    },

    close: function close(thenDo) {
      clearInterval(messenger._statusWatcherProc);
      messenger._statusWatcherProc = null;
      spec.close.call(messenger, function (err) {
        messenger._status = OFFLINE;
        thenDo && thenDo(err);
      });
      return messenger;
    },

    whenOnline: function whenOnline(thenDo) {
      messenger._whenOnlineCallbacks.push(thenDo);
      if (messenger.isOnline()) messenger._runWhenOnlineCallbacks();
      return messenger;
    },

    outgoingMessages: function outgoingMessages() {
      return pluck(messenger._inflight.concat(messenger._outgoing), 0);
    },

    addServices: function addServices(serviceSpec) {
      Object.assign(messenger._services, serviceSpec);
      return messenger;
    }
  };

  if (spec.services) messenger.addServices(spec.services);
  makeEmitter(messenger);

  for (var name in spec) {
    if (ignoredAttributes.indexOf(name) === -1 && spec.hasOwnProperty(name)) {
      messenger[name] = spec[name];
    }
  }

  return messenger;
}



var messenger = Object.freeze({
	create: create$2
});

/*global, require, Worker, URL, webkitURL, Blob, BlobBuilder, process, require,self,global,remoteWorker,postMessage,XMLHttpRequest,__FUNCTIONDECLARATIONS__,initBrowserGlobals,loadDependenciesBrowser,initOnMessageHandler,initWorkerInterface,initWorkerMessenger,loadDependenciesNodejs,importScripts*/

/*
 * A platform-independent worker interface that will spawn new processes per
 * worker (if the platform you use it on supports it).
 */

var isNodejs = typeof require !== 'undefined' && typeof process !== 'undefined';

// ignore-in-doc
// Code in worker setup is evaluated in the context of workers, it will get to
// workers in a stringified form(!).
var WorkerSetup = {

  loadDependenciesBrowser: function loadDependenciesBrowser(options) {
    var me = typeof self !== "undefined" ? self : this;
    importScripts.apply(me, options.scriptsToLoad || []);
  },

  loadDependenciesNodejs: function loadDependenciesNodejs(options) {
    var lv = global.lively || (global.lively = {});
    lv.lang = require(require("path").join(options.libLocation, "index"));
  },

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  // yoshiki and robert, 05/08/13: Inserted code that sets up the lively context
  // and globals of Lively and other required objects:
  initBrowserGlobals: function initBrowserGlobals(options) {
    remoteWorker.send = function (msg) {
      postMessage(msg);
    };
    var me = typeof self !== "undefined" ? self : this;
    var Global = me.Global = me;
    Global.window = Global;
    Global.console = Global.console || function () {
      var c = {};
      ['log', 'error', 'warn'].forEach(function (name) {
        c[name] = function () /*args*/{
          var string = arguments[0];
          for (var i = 1; i < arguments.length; i++) {
            string = string.replace('%s', arguments[i]);
          }remoteWorker.send({
            type: name,
            message: ['[', name.toUpperCase(), '] ', string].join('')
          });
        };
      });
      return c;
    }();
  },

  initOnMessageHandler: function initOnMessageHandler(options) {
    if (remoteWorker.on) remoteWorker.on('message', onMessage);else remoteWorker.onmessage = onMessage;

    function onMessage(msg) {
      msg = msg.data.data ? msg.data : msg;
      if (remoteWorker.messenger) remoteWorker.messenger.onMessage(msg);else if (msg.action == "close") {
        remoteWorker.send({ type: "closed", workerReady: false });
        remoteWorker.close();
        return;
      }
    }
  },

  initWorkerInterface: function initWorkerInterface(options) {
    remoteWorker.callStringifiedFunction = function (stringifiedFunc, args, thenDo) {
      // ignore-in-doc
      // runs stringified function and passing args. stringifiedFunc might
      // be asynchronous if it takes an addaitional argument. In this case a
      // callback to call when the work is done is passed, otherwise thenDo
      // will be called immediatelly after creating and calling the function

      var func;
      try {
        func = eval('(' + stringifiedFunc + ')');
      } catch (e) {
        thenDo(new Error("Cannot create function from string: " + e.stack || e));
        return;
      }

      // ignore-in-doc
      // when it takes one more arg then we assume that this is the callback
      // to be called by the run func when it considers to be done
      var usesCallback = func.length === args.length + 1;
      var whenDone = lively.lang.fun.once(function (err, result) {
        remoteWorker.isBusy = false;thenDo(err, result);
      });
      remoteWorker.isBusy = true;

      if (usesCallback) args.push(whenDone);

      try {
        var result = func.apply(remoteWorker, args.concat([whenDone]));
      } catch (e) {
        whenDone(e, null);return;
      }

      if (!usesCallback) whenDone(null, result);
    };

    remoteWorker.httpRequest = function (options) {
      if (!options.url) {
        console.log("Error, httpRequest needs url");
        return;
      }
      var req = new XMLHttpRequest(),
          method = options.method || 'GET';
      function handleStateChange() {
        if (req.readyState === 4) {
          // req.status
          options.done && options.done(req);
        }
      }
      req.onreadystatechange = handleStateChange;
      req.open(method, options.url);
      req.send();
    };

    remoteWorker.terminateIfNotBusyIn = function (ms) {
      setTimeout(function () {
        if (remoteWorker.isBusy) {
          remoteWorker.terminateIfNotBusyIn(ms);return;
        }
        remoteWorker.send({ type: "closed", workerReady: false });
        remoteWorker.close();
      }, ms);
    };
  },

  // ignore-in-doc
  // setting up the worker messenger interface, this is how the worker
  // should be communicated with
  initWorkerMessenger: function initWorkerMessenger(options) {
    if (!options.useMessenger) return null;
    if (!lively.lang.messenger) throw new Error("worker.create requires messenger.js to be loaded!");
    if (!lively.lang.events) throw new Error("worker.create requires events.js to be loaded!");

    return remoteWorker.messenger = lively.lang.messenger.create({
      services: {

        remoteEval: function remoteEval(msg, messenger) {
          var result;
          try {
            result = eval(msg.data.expr);
          } catch (e) {
            result = e.stack || e;
          }
          messenger.answer(msg, { result: String(result) });
        },

        run: function run(msg, messenger) {
          var funcString = msg.data.func,
              args = msg.data.args;
          if (!funcString) {
            messenger.answer(msg, { error: 'no funcString' });return;
          }
          remoteWorker.callStringifiedFunction(funcString, args, function (err, result) {
            messenger.answer(msg, { error: err ? String(err) : null, result: result });
          });
        },

        close: function close(msg, messenger) {
          messenger.answer(msg, { status: "OK" });
          remoteWorker.send({ type: "closed", workerReady: false });
          remoteWorker.close();
        }
      },

      isOnline: function isOnline() {
        return true;
      },
      send: function send(msg, whenSend) {
        remoteWorker.send(msg);whenSend();
      },
      listen: function listen(whenListening) {
        whenListening();
      },
      close: function close(whenClosed) {
        remoteWorker.send({ type: "closed", workerReady: false });remoteWorker.close();
      }

    });
  }

};

var BrowserWorker = {

  create: function create$3(options) {
    // ignore-in-doc
    // this function instantiates a browser worker object. We provide a
    // messenger-based interface to the pure Worker. Please use create to get an
    // improved interface to a worker

    options = options || {};

    // ignore-in-doc
    // figure out where the other lang libs can be loaded from
    if (!options.libLocation && !options.scriptsToLoad) {
      var workerScript = document.querySelector("script[src$=\"worker.js\"]");
      if (!workerScript) throw new Error("Cannot find library path to start worker. Use worker.create({libLocation: \"...\"}) to explicitly define the path!");
      options.libLocation = workerScript.src.replace(/worker.js$/, '');
    }

    var workerSetupCode = String(workerSetupFunction).replace("__FUNCTIONDECLARATIONS__", [WorkerSetup.initBrowserGlobals, WorkerSetup.loadDependenciesBrowser, WorkerSetup.initOnMessageHandler, WorkerSetup.initWorkerInterface, WorkerSetup.initWorkerMessenger].join('\n'));
    var workerCode = '(' + lively_sourceTransform.stringifyFunctionWithoutToplevelRecorder(workerSetupCode) + ')();';
    var worker = new Worker(makeDataURI(workerCode));
    init(options, worker);
    return worker;

    // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    // ignore-in-doc
    // This code is triggered in the UI process directly after the
    // creation of the worker and sends the setup message to the worker
    // for initializing it.
    function init(options, worker) {
      makeEmitter(worker);

      if (!options.scriptsToLoad) {
        options.scriptsToLoad = ['base.js', 'events.js', 'object.js', 'collection.js', 'function.js', 'string.js', 'number.js', 'date.js', 'messenger.js', 'worker.js'].map(function (ea) {
          return options.libLocation + ea;
        });
      }

      var workerOptions = Object.keys(options).reduce(function (opts, key) {
        if (typeof options[key] !== 'function') opts[key] = options[key];
        return opts;
      }, {});

      worker.onmessage = function (evt) {
        if (evt.data.workerReady !== undefined) {
          worker.ready = !!evt.data.workerReady;
          if (worker.ready) worker.emit("ready");else worker.emit("close");
        } else worker.emit('message', evt.data);
      };

      worker.errors = [];
      worker.onerror = function (evt) {
        console.error(evt);
        worker.errors.push(evt);
        worker.emit("error", evt);
      };

      worker.postMessage({ action: 'setup', options: workerOptions });
    }

    // ignore-in-doc
    // This code is run inside the worker and bootstraps the messenger
    // interface. It also installs a console.log method since since this is not
    // available by default.
    function workerSetupFunction() {
      var remoteWorker = self;
      remoteWorker.onmessage = function (evt) {
        if (evt.data.action !== "setup") {
          throw new Error("expected setup to be first message but got " + JSON.stringify(evt.data));
        }
        var options = evt.data.options || {};
        initBrowserGlobals(options);
        loadDependenciesBrowser(options);
        initOnMessageHandler(options);
        initWorkerInterface(options);
        initWorkerMessenger(options);
        postMessage({ workerReady: true });
      };
      __FUNCTIONDECLARATIONS__;
    }

    function makeDataURI(codeToInclude) {
      // ignore-in-doc
      // see http://stackoverflow.com/questions/10343913/how-to-create-a-web-worker-from-a-string
      var blob;
      try {
        blob = new Blob([codeToInclude], { type: "text/javascript" });
      } catch (e) {
        /* ignore-in-doc Backwards-compatibility*/
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
        blob = new BlobBuilder();
        blob.append(codeToInclude);
        blob = blob.getBlob();
      }
      var urlInterface = typeof webkitURL !== 'undefined' ? webkitURL : URL;
      return urlInterface.createObjectURL(blob);
    }
  }

};

var NodejsWorker = {

  debug: false,
  initCodeFileCreated: false,

  create: function create$3(options) {
    options = options || {};

    // ignore-in-doc
    // figure out where the other lang libs can be loaded from
    // if (!options.libLocation && !options.scriptsToLoad) {
    //   var workerScript = document.querySelector("script[src$=\"worker.js\"]");
    //   if (!workerScript) throw new Error("Cannot find library path to start worker. Use worker.create({libLocation: \"...\"}) to explicitly define the path!");
    //   options.libLocation = workerScript.src.replace(/worker.js$/, '');
    // }

    var workerProc;
    var worker = makeEmitter({
      ready: false,
      errors: [],

      postMessage: function postMessage(msg) {
        if (!workerProc) {
          worker.emit("error", new Error('nodejs worker process not yet created'));
          return;
        }
        if (!worker.ready) {
          worker.emit("error", new Error('nodejs worker process not ready or already closed'));
          return;
        }
        workerProc.send(msg);
      }
    });

    NodejsWorker.startWorker(options, function (err, _workerProc) {
      if (err) {
        worker.ready = false;worker.emit("error", err);return;
      }

      workerProc = _workerProc;

      workerProc.on('message', function (m) {
        NodejsWorker.debug && console.log('[WORKER PARENT] got message:', m);
        worker.emit("message", m);
      });

      workerProc.on('close', function () {
        console.log("[WORKER PARENT] worker closed");
        worker.emit("close");
      });

      workerProc.on('error', function (err) {
        console.log("[WORKER PARENT] error ", err);
        worker.errors.push(err);
        worker.emit("error", err);
      });

      worker.ready = true;
      worker.emit("ready");
    });

    return worker;
  },

  // this code is run in the context of the worker process
  workerSetupFunction: function workerSetupFunction() {
    var remoteWorker = process;
    var debug = true;
    var close = false;

    debug && console.log("[WORKER] Starting init");
    // ignore-in-doc
    // process.on('message', function(m) {
    //   debug && console.log('[WORKER] got message:', m);
    //   if (m.action === 'ping') process.send({action: 'pong', data: m});
    //   else if (m.action === 'close') close = true;
    //   else if (m.action === 'setup') setup(m.data);
    //   else console.error('[WORKER] unknown message: ', m);
    // });

    remoteWorker.on("message", function (msg) {
      if (msg.action !== "setup") {
        throw new Error("expected setup to be first message but got " + JSON.stringify(msg.data));
      }
      remoteWorker.removeAllListeners("message");
      var options = msg.data.options || {};
      debug && console.log("[WORKER] running setup with options", options);
      loadDependenciesNodejs(options);
      initOnMessageHandler(options);
      initWorkerInterface(options);
      initWorkerMessenger(options);
      remoteWorker.send({ workerReady: true });
    });
    __FUNCTIONDECLARATIONS__;
  },

  ensureInitCodeFile: function ensureInitCodeFile(options, initCode, thenDo) {
    var path = require("path");
    var os = require("os");
    var fs = require("fs");

    var workerTmpDir = path.join(os.tmpDir(), 'lively-nodejs-workers/');
    var fn = path.join(workerTmpDir, 'nodejs-worker-init.js');

    if (!NodejsWorker.initCodeFileCreated) NodejsWorker.createWorkerCodeFile(options, fn, initCode, thenDo);else fs.exists(fn, function (exists) {
      if (exists) thenDo(null, fn);else NodejsWorker.createWorkerCodeFile(options, fn, initCode, thenDo);
    });
  },

  createWorkerCodeFile: function createWorkerCodeFile(options, fileName, initCode, thenDo) {
    var path = require("path");
    var fs = require("fs");
    var exec = require("child_process").exec;

    exec("mkdir -p " + path.dirname(fileName), function (code, out, err) {
      if (code) {
        thenDo(new Error(["[WORKER PARENT] Could not create worker temp dir:", out, err].join('\n')));
        return;
      }
      fs.writeFile(fileName, initCode, function (err) {
        NodejsWorker.debug && console.log('worker code file %s created', fileName);
        NodejsWorker.initCodeFileCreated = true;
        thenDo(err, fileName);
      });
    });
  },

  startWorker: function startWorker(options, thenDo) {
    var util = require("util");
    var fork = require("child_process").fork;

    var workerSetupCode = String(NodejsWorker.workerSetupFunction).replace("__FUNCTIONDECLARATIONS__", [WorkerSetup.loadDependenciesNodejs, WorkerSetup.initOnMessageHandler, WorkerSetup.initWorkerInterface, WorkerSetup.initWorkerMessenger].join('\n'));

    var initCode = util.format("(%s)();\n", workerSetupCode);
    NodejsWorker.ensureInitCodeFile(options, initCode, function (err, codeFileName) {
      if (err) return thenDo(err);
      var worker = fork(codeFileName, {});
      NodejsWorker.debug && console.log('worker forked');
      worker.on('message', function (m) {
        if (m.action === 'pong') console.log("[WORKER pong] ", m);else if (m.action === 'log') console.log("[Message from WORKER] ", m.data);
      });
      worker.once('message', function (m) {
        NodejsWorker.debug && console.log('worker setup done');
        thenDo(null, worker, m);
      });
      worker.on('close', function () {
        NodejsWorker.debug && console.log("[WORKER PARENT] worker closed");
      });
      worker.send({ action: "setup", data: { options: options } });
      global.WORKER = worker;
    });
  }

};

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// the worker interface, usable both in browser and node.js contexts
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

/*
Worker objects allow to fork processes in both Web and node.js JavaScript
environments. They provide this mechanism using web workers in the browser and
node.js child processes in node.js. The interface is unified for all platforms.
 */

function fork(options, workerFunc, thenDo) {
  // Fork automatically starts a worker and calls `workerFunc`. `workerFunc`
  // gets as a last paramter a callback, that, when invoked with an error and
  // result object, ends the worker execution.
  //
  // Options are the same as in `create` except for an `args` property that
  // can be an array of objects. These objects will be passed to `workerFunc`
  // as arguments.
  //
  // Note: `workerFunc` will not be able to capture outside variables (create a
  // closure).
  //
  // Example:
  // // When running this inside a browser: Note how the UI does not block.
  // worker.fork({args: [40]},
  //   function(n, thenDo) {
  //     function fib(n) { return n <= 1 ? n : fib(n-1) + fib(n-2); }
  //     thenDo(null, fib(n));
  //   },
  //   function(err, result) { show(err ? err.stack : result); })

  if (!thenDo) {
    thenDo = workerFunc;workerFunc = options;options = null;
  }
  options = options || {};
  var args = options.args || [];
  var w = create$3(options);
  w.run.apply(w, [workerFunc].concat(args).concat(thenDo));
  return w;
}

function create$3(options) {
  // Explicitly creates a first-class worker. Options:
  // ```js
  // {
  //   workerId: STRING, // optional, id for worker, will be auto assigned if not provided
  //   libLocation: STRING, // optional, path to where the lively.lang lib is located. Worker will try to find it automatically if not provided.
  //   scriptsToLoad: ARRAY // optional, list of path/urls to load. Overwrites `libLocation`
  // }
  // ```
  //
  // Example:
  // // this is just a helper function
  // function resultHandler(err, result) { alert(err ? String(err) : result); }
  //
  // // 1. Create the worker
  // var worker = lively.lang.worker.create({libLocation: baseURL});
  //
  // // 2. You can evaluate arbitrary JS code
  // worker.eval("1+2", function(err, result) { show(err ? String(err) : result); });
  //
  // // 3. Arbitrary functions can be called inside the worker context.
  // //    Note: functions shouldn't be closures / capture local state!) and passing
  // //    in arguments!
  // worker.run(
  //   function(a, b, thenDo) { setTimeout(function() { thenDo(null, a+b); }, 300); },
  //   19, 4, resultHandler);
  //
  // // 4. You can also install your own messenger services...
  // worker.run(
  //   function(thenDo) {
  //     self.messenger.addServices({
  //       foo: function(msg, messenger) { messenger.answer(msg, "bar!"); }
  //     });
  //     thenDo(null, "Service installed!");
  //   }, resultHandler);
  //
  // // ... and call them via the messenger interface
  // worker.sendTo("worker", "foo", {}, resultHandler);
  //
  // // 5. afterwards: shut it down
  // worker.close(function(err) { err && show(String(err)); alertOK("worker shutdown"); })

  options = options || {};
  options.useMessenger = true;

  // if (!exports.messenger)
  //   throw new Error("worker.create requires messenger.js to be loaded!")
  // if (!exports.events)
  //   throw new Error("worker.create requires events.js to be loaded!")
  // if (!exports.obj)
  //   throw new Error("worker.create requires object.js to be loaded!")

  var workerId = options.workerId || newUUID();

  var messenger = create$2({
    sendTimeout: 5000,

    send: function send(msg, whenSend) {
      messenger.worker.postMessage(msg);
      whenSend();
    },

    listen: function listen(whenListening) {
      var w = messenger.worker = isNodejs ? NodejsWorker.create(options) : BrowserWorker.create(options);
      w.on("message", function (msg) {
        messenger.onMessage(msg);
      });
      w.on('ready', function () {
        NodejsWorker.debug && console.log("WORKER READY!!!");
      });
      w.on('close', function () {
        NodejsWorker.debug && console.log("WORKER CLOSED...!!!");
      });
      w.once('ready', whenListening);
    },

    close: function close(whenClosed) {
      if (!messenger.worker.ready) return whenClosed(null);
      return messenger.sendTo(workerId, 'close', {}, function (err, answer) {
        err = err || answer.data.error;
        err && console.error("Error in worker messenger close: " + err.stack || err);
        if (err) whenClosed(err);else {
          var closed = false;
          messenger.worker.once('close', function () {
            closed = true;
          });
          waitFor(1000, function () {
            return !!closed;
          }, whenClosed);
        }
      });
    },

    isOnline: function isOnline() {
      return messenger.worker && messenger.worker.ready;
    }

  });

  Object.assign(messenger, {
    eval: function _eval(code, thenDo) {
      messenger.sendTo(workerId, "remoteEval", { expr: code }, function (err, answer) {
        thenDo(err, answer ? answer.data.result : null);
      });
    },
    run: function run() /*runFunc, arg1, ... argN, thenDo*/{
      var args = Array.prototype.slice.call(arguments),
          workerFunc = args.shift(),
          thenDo = args.pop();
      if (typeof workerFunc !== "function") throw new Error("run: no function that should run in worker passed");
      if (typeof thenDo !== "function") throw new Error("run: no callback passed");

      return messenger.sendTo(workerId, 'run', { func: String(workerFunc), args: args }, function (err, answer) {
        thenDo(err || answer.data.error, answer ? answer.data.result : null);
      });
    }
  });

  messenger.listen();

  return messenger;
}



var worker = Object.freeze({
	fork: fork,
	create: create$3
});

var GLOBAL = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : undefined;

var isNode = typeof process !== "undefined" && process.env && typeof process.exit === "function";

var globalInterfaceSpec = [{ action: "installMethods", target: "Array", sources: ["arr"], methods: ["from", "genN", "range", "withN"] }, { action: "installMethods", target: "Array.prototype", sources: ["arr"], methods: ["all", "any", "batchify", "clear", "clone", "collect", "compact", "delimWith", "detect", "doAndContinue", "each", "equals", "filterByKey", "findAll", "first", "flatten", "forEachShowingProgress", "grep", "groupBy", "groupByKey", "histogram", "include", "inject", "intersect", "invoke", "last", "mapAsync", "mapAsyncSeries", "mask", "max", "min", "mutableCompact", "nestedDelay", "partition", "pluck", "pushAll", "pushAllAt", "pushAt", "pushIfNotIncluded", "reMatches", "reject", "rejectByKey", "remove", "removeAt", "replaceAt", "rotate", "shuffle", "size", "sortBy", "sortByKey", "sum", "swap", "toArray", "toTuples", "union", "uniq", "uniqBy", "without", "withoutAll", "zip"], alias: [["select", "filter"]] }, { action: "installMethods", target: "Date", sources: ["date"], methods: [/*"parse"*/] }, { action: "installMethods", target: "Date.prototype", sources: ["date"], methods: ["equals", "format", "relativeTo"] }, { action: "installMethods", target: "Function", sources: ["fun"], methods: ["fromString"] }, { action: "installMethods", target: "Function.prototype", sources: ["fun"], methods: [/*"addProperties",*/"addToObject", "argumentNames", "asScript", "asScriptOf", "binds", "curry", "delay", "functionNames", "localFunctionNames", "getOriginal", "getVarMapping", "logCalls", "logCompletion", "logErrors", "qualifiedMethodName", "setProperty", "traceCalls", "wrap"] }, { action: "installMethods", target: "Number", sources: ["num"], methods: [] }, { action: "installMethods", target: "Number.prototype", sources: ["num"], methods: ["detent", "randomSmallerInteger", "roundTo", "toDegrees", "toRadians"] }, { action: "installMethods", target: "Object", sources: ["obj"], methods: ["addScript", "clone", "deepCopy", "extend", "inherit", "isArray", "isBoolean", "isElement", "isEmpty", "isFunction", "isNumber", "isObject", "isRegExp", "isString", "isUndefined", "merge", "mergePropertyInHierarchy", "values", "valuesInPropertyHierarchy"] }, { action: "installMethods", target: "Object.prototype", sources: ["obj"], methods: [] }, { action: "installMethods", target: "String.prototype", sources: ["string"], methods: ["camelize", "capitalize", "digitValue", "empty", "hashCode", "include", "pad", "regExpEscape", "startsWithVowel", "succ", "times", "toArray", "toQueryParams", "truncate"] }, { action: "installObject", target: "Numbers", source: "num", methods: ["average", "between", "convertLength", "humanReadableByteSize", "median", "normalRandom", "parseLength", "random", "sort"] }, { action: "installObject", target: "Properties", source: "properties", methods: ["all", "allOwnPropertiesOrFunctions", "allProperties", "any", "forEachOwn", "hash", "nameFor", "own", "ownValues", "values"] }, { action: "installObject", target: "Strings", source: "string", methods: ["camelCaseString", "createDataURI", "diff", "format", "formatFromArray", "indent", "lineIndexComputer", "lines", "md5", "newUUID", "nonEmptyLines", "pad", "paragraphs", "peekLeft", "peekRight", "print", "printNested", "printTable", "printTree", "quote", "reMatches", "stringMatch", "tableize", "tokens", "unescapeCharacterEntities", "withDecimalPrecision"] }, { action: "installObject", target: "Objects", source: "obj", methods: ["asObject", "equals", "inspect", "isMutableType", "safeToString", "shortPrintStringOf", "typeStringOf"] }, { action: "installObject", target: "Functions", source: "fun", methods: ["all", "compose", "composeAsync", "createQueue", "debounce", "debounceNamed", "either", "extractBody", "flip", "notYetImplemented", "once", "own", "throttle", "throttleNamed", "timeToRun", "timeToRunN", "waitFor", "workerWithCallbackQueue", "wrapperChain"] }, { action: "installObject", target: "Grid", source: "grid" }, { action: "installObject", target: "Interval", source: "interval" }, { action: "installObject", target: "lively.ArrayProjection", source: "arrayProjection" }, { action: "installObject", target: "lively.Closure", source: "Closure" }, { action: "installObject", target: "lively.Grouping", source: "Group" }, { action: "installObject", target: "lively.PropertyPath", source: "Path" }, { action: "installObject", target: "lively.Worker", source: "worker" }, { action: "installObject", target: "lively.Class", source: "classHelper" }];

function createLivelyLangObject() {
  return {
    chain: chain$$1,
    noConflict: noConflict,
    installGlobals: installGlobals,
    uninstallGlobals: uninstallGlobals,
    globalInterfaceSpec: globalInterfaceSpec,
    toString: function toString() {
      return "[object lively.lang]";
    }
  };
}

var livelyLang = createLivelyLangObject();



function chain$$1(object) {
  if (!object) return object;

  var chained;
  if (Array.isArray(object)) return createChain(arr, object);
  if (object.constructor.name === "Date") return createChain(date, object);
  switch (typeof object === "undefined" ? "undefined" : _typeof(object)) {
    case 'string':
      return createChain(string, object);
    case 'object':
      return createChain(obj, object);
    case 'function':
      return createChain(fun, object);
    case 'number':
      return createChain(num, object);
  }
  throw new Error("Chain for object " + object + " (" + object.constructor.name + ") no supported");
}

function createChain(interfaceObj, obj) {
  return Object.keys(interfaceObj).reduce(function (chained, methodName) {
    chained[methodName] = function () /*args*/{
      var args = Array.prototype.slice.call(arguments),
          result = interfaceObj[methodName].apply(null, [obj].concat(args));
      return chain$$1(result);
    };
    return chained;
  }, { value: function value() {
      return obj;
    } });
}

function noConflict() {
  if (!isNode) {
    var keepLivelyNS = livelyLang._prevLivelyGlobal;
    if (!keepLivelyNS) delete GLOBAL.lively;else delete GLOBAL.lively.lang;
  }
  return livelyLang;
}

function installGlobals() {
  Object.assign(livelyLang, {
    worker: worker,
    messenger: messenger,
    events: events,
    tree: tree,
    grid: grid,
    arrayProjection: arrayProjection,
    interval: interval,
    graph: graph,
    date: date,
    properties: properties,
    obj: obj,
    arr: arr,
    fun: fun,
    num: num,
    string: string,
    Closure: Closure,
    promise: promise,
    Path: Path,
    Group: Group
  });
  globalInterfaceSpec.forEach(function (ea) {
    if (ea.action === "installMethods") {
      var targetPath = Path(ea.target);
      if (!targetPath.isIn(GLOBAL)) targetPath.set(GLOBAL, {}, true);
      var sourcePath = Path(ea.sources[0]);
      ea.methods.forEach(function (name) {
        installProperty(sourcePath.concat([name]), targetPath.concat([name]));
      });
      if (ea.alias) ea.alias.forEach(function (mapping) {
        installProperty(sourcePath.concat([mapping[1]]), targetPath.concat([mapping[0]]));
      });
    } else if (ea.action === "installObject") {
      var targetPath = Path(ea.target);
      var source = Path(ea.source).get(livelyLang);
      targetPath.set(GLOBAL, source, true);
    } else throw new Error("Cannot deal with global setup action: " + ea.action);
  });
}

function installProperty(sourcePath, targetPath) {
  if (!sourcePath.isIn(livelyLang)) {
    var err = new Error("property not provided by lively.lang: " + sourcePath);
    console.error(err.stack || err);
    throw err;
  }

  var prop = sourcePath.get(livelyLang);
  if (typeof prop === "function" && targetPath.slice(-2, -1).toString() === "prototype") {
    var origFunc = prop;
    prop = function prop() /*this and args*/{
      var args = Array.prototype.slice.call(arguments);
      args.unshift(this);
      return origFunc.apply(null, args);
    };
    prop.toString = function () {
      return origFunc.toString();
    };
  }
  targetPath.set(GLOBAL, prop, true);
}

function uninstallGlobals() {
  globalInterfaceSpec.forEach(function (ea) {
    if (ea.action === "installMethods") {
      var p = Path(ea.target);
      var source = Path(ea.source).get(livelyLang);
      var target = p.get(GLOBAL);
      if (!target) return;
      ea.methods.filter(function (name) {
        return source === target[name];
      }).forEach(function (name) {
        delete target[name];
      });
      if (ea.alias) ea.alias.filter(function (name) {
        return source === target[name];
      }).forEach(function (mapping) {
        delete target[mapping[0]];
      });
    } else if (ea.action === "installObject") {
      var p = Path(ea.target);
      p.del(GLOBAL);
    } else throw new Error("Cannot deal with global setup action: " + ea.action);
  });
}

exports.worker = worker;
exports.messenger = messenger;
exports.events = events;
exports.tree = tree;
exports.grid = grid;
exports.arrayProjection = arrayProjection;
exports.interval = interval;
exports.graph = graph;
exports.date = date;
exports.properties = properties;
exports.obj = obj;
exports.arr = arr;
exports.fun = fun;
exports.num = num;
exports.string = string;
exports.Closure = Closure;
exports.promise = promise;
exports.Path = Path;
exports.Group = Group;
exports.livelyLang = livelyLang;
exports.chain = chain$$1;
exports.noConflict = noConflict;
exports.installGlobals = installGlobals;
exports.uninstallGlobals = uninstallGlobals;

}((this.lively.lang = this.lively.lang || {}),lively.sourceTransform));

  }).call(GLOBAL);
  if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.lang;
})();

// INLINED END /Users/user/git/lively.vm/node_modules/lively.lang/dist/lively.lang.js

// INLINED /Users/user/git/lively.vm/node_modules/lively.notifications/dist/lively.notifications.js
(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  this.lively = this.lively || {};
(function (exports,lively_lang) {
'use strict';

/*global System*/

// type EventType = string
// type EventTime = number
// type Notification = {type: EventType, time: EventTime, ...};
// type Handler = Notification -> ()
// type Notifications = { [number]: Notification, limit: number }
// type Emitter = {isRecording: boolean, isLogging: boolean, ... }
// type Env = {emitter: Emitter, notifications: Notifications}

var env = void 0;

function getEnv(_System) {
  // System? -> Env
  if (_System === undefined) {
    if (typeof System === "undefined") {
      // fallback if not System is available
      if (env !== undefined) return env;
      return env || (env = {
        emitter: lively_lang.events.makeEmitter({}, { maxListenerLimit: 10000 }),
        notifications: []
      });
    }

    _System = System;
  }

  var livelyEnv = _System.get("@lively-env");
  if (!livelyEnv) _System.set("@lively-env", _System.newModule({ options: {} }));

  var options = livelyEnv.options;

  if (!options) throw new Error("@lively-env registered read-only");

  if (!options.emitter) {
    Object.assign(options, {
      emitter: _System["__lively.notifications_emitter"] || (_System["__lively.notifications_emitter"] = lively_lang.events.makeEmitter({}, { maxListenerLimit: 10000 })),
      notifications: _System["__lively.notifications_notifications"] || (_System["__lively.notifications_notifications"] = [])
    });
  }
  var emitter = options.emitter,
      notifications = options.notifications;

  return { emitter: emitter, notifications: notifications };
}

function subscribe(type, handler, system) {
  // EventType, Handler, System? -> Handler
  getEnv(system).emitter.on(type, handler);
  return handler;
}

function subscribeOnce(type, handler, system) {
  // EventType, Handler, System? -> Handler
  getEnv(system).emitter.once(type, handler);
  return handler;
}

function emit(type) {
  var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var time = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Date.now();
  var system = arguments[3];

  // EventType, Notification?, EventTime?, System? -> Notification
  var notification = Object.assign({ type: type, time: time }, data),
      _getEnv = getEnv(system),
      emitter = _getEnv.emitter,
      notifications = _getEnv.notifications;

  emitter.emit(type, notification);
  if (emitter.isLogging) log(notification);
  if (emitter.isRecording) record(notifications, notification);
  return notification;
}

function unsubscribe(type, handler, system) {
  // EventType, Handler, System? -> Handler
  getEnv(system).emitter.removeListener(type, handler);
  return handler;
}

function unsubscribeAll(type, system) {
  // EventType, System? -> ()
  getEnv(system).emitter.removeAllListeners(type);
}

function record(notifications, notification) {
  // Array<Notification>, Notification -> ()
  notifications.push(notification);
  if (notifications.limit) {
    notifications.splice(0, notifications.length - notifications.limit);
  }
}

function startRecording(system) {
  // System? -> ()
  getEnv(system).emitter.isRecording = true;
}

function stopRecording(system) {
  // System? -> ()
  getEnv(system).emitter.isRecording = false;
}

function clearRecord(system) {
  // System? -> ()
  var _getEnv2 = getEnv(system),
      notifications = _getEnv2.notifications;

  notifications.splice(0, notifications.length);
}

function getRecord(system) {
  // System? -> Notifications
  return getEnv(system).notifications;
}

function log(notification) {
  // Notification -> ()
  var padded = notification.type + " ".repeat(Math.max(0, 32 - notification.type.length));
  console.log(padded + " " + lively_lang.obj.inspect(notification, { maxDepth: 2 }));
}

function startLogging(system) {
  // System? -> ()
  getEnv(system).emitter.isLogging = true;
}

function stopLogging(system) {
  // System? -> ()
  getEnv(system).emitter.isLogging = false;
}

exports.subscribe = subscribe;
exports.subscribeOnce = subscribeOnce;
exports.emit = emit;
exports.unsubscribe = unsubscribe;
exports.unsubscribeAll = unsubscribeAll;
exports.startRecording = startRecording;
exports.stopRecording = stopRecording;
exports.clearRecord = clearRecord;
exports.getRecord = getRecord;
exports.startLogging = startLogging;
exports.stopLogging = stopLogging;

}((this.lively.notifications = this.lively.notifications || {}),lively.lang));

  if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.classes;
})();
// INLINED END /Users/user/git/lively.vm/node_modules/lively.notifications/dist/lively.notifications.js

// INLINED /Users/user/git/lively.vm/node_modules/lively.ast/dist/lively.ast.js

;(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  if (GLOBAL.define) { var __define_suckz__ = GLOBAL; delete GLOBAL.define; }
  (function() {
    var module = undefined, require = undefined, define = undefined;
    (function() {
  var module = undefined, require = undefined, define = undefined;
  (function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
	typeof define === 'function' && define.amd ? define(['exports'], factory) :
	(factory((global.acorn = global.acorn || {})));
}(this, (function (exports) { 'use strict';

// Reserved word lists for various dialects of the language

var reservedWords = {
  3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
  5: "class enum extends super const export import",
  6: "enum",
  strict: "implements interface let package private protected public static yield",
  strictBind: "eval arguments"
};

// And the keywords

var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";

var keywords = {
  5: ecma5AndLessKeywords,
  6: ecma5AndLessKeywords + " const class extends export import super"
};

// ## Character categories

// Big ugly regular expressions that match characters in the
// whitespace, identifier, and identifier-start categories. These
// are only applied when a character is found to actually have a
// code point above 128.
// Generated by `bin/generate-identifier-regex.js`.

var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ae\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d4-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";

var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");

nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;

// These are a run-length and offset encoded representation of the
// >0xffff code points that are a valid part of identifiers. The
// offset starts at 0x10000, and each pair of numbers represents an
// offset to the next range, and then a size of the range. They were
// generated by bin/generate-identifier-regex.js

// eslint-disable-next-line comma-spacing
var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541];

// eslint-disable-next-line comma-spacing
var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239];

// This has a complexity linear to the value of the code. The
// assumption is that looking up astral identifier characters is
// rare.
function isInAstralSet(code, set) {
  var pos = 0x10000;
  for (var i = 0; i < set.length; i += 2) {
    pos += set[i];
    if (pos > code) { return false }
    pos += set[i + 1];
    if (pos >= code) { return true }
  }
}

// Test whether a given character code starts an identifier.

function isIdentifierStart(code, astral) {
  if (code < 65) { return code === 36 }
  if (code < 91) { return true }
  if (code < 97) { return code === 95 }
  if (code < 123) { return true }
  if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) }
  if (astral === false) { return false }
  return isInAstralSet(code, astralIdentifierStartCodes)
}

// Test whether a given character is part of an identifier.

function isIdentifierChar(code, astral) {
  if (code < 48) { return code === 36 }
  if (code < 58) { return true }
  if (code < 65) { return false }
  if (code < 91) { return true }
  if (code < 97) { return code === 95 }
  if (code < 123) { return true }
  if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) }
  if (astral === false) { return false }
  return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)
}

// ## Token types

// The assignment of fine-grained, information-carrying type objects
// allows the tokenizer to store the information it has about a
// token in a way that is very cheap for the parser to look up.

// All token type variables start with an underscore, to make them
// easy to recognize.

// The `beforeExpr` property is used to disambiguate between regular
// expressions and divisions. It is set on all token types that can
// be followed by an expression (thus, a slash after them would be a
// regular expression).
//
// The `startsExpr` property is used to check if the token ends a
// `yield` expression. It is set on all token types that either can
// directly start an expression (like a quotation mark) or can
// continue an expression (like the body of a string).
//
// `isLoop` marks a keyword as starting a loop, which is important
// to know when parsing a label, in order to allow or disallow
// continue jumps to that label.

var TokenType = function TokenType(label, conf) {
  if ( conf === void 0 ) conf = {};

  this.label = label;
  this.keyword = conf.keyword;
  this.beforeExpr = !!conf.beforeExpr;
  this.startsExpr = !!conf.startsExpr;
  this.isLoop = !!conf.isLoop;
  this.isAssign = !!conf.isAssign;
  this.prefix = !!conf.prefix;
  this.postfix = !!conf.postfix;
  this.binop = conf.binop || null;
  this.updateContext = null;
};

function binop(name, prec) {
  return new TokenType(name, {beforeExpr: true, binop: prec})
}
var beforeExpr = {beforeExpr: true};
var startsExpr = {startsExpr: true};

// Map keyword names to token types.

var keywords$1 = {};

// Succinct definitions of keyword token types
function kw(name, options) {
  if ( options === void 0 ) options = {};

  options.keyword = name;
  return keywords$1[name] = new TokenType(name, options)
}

var types = {
  num: new TokenType("num", startsExpr),
  regexp: new TokenType("regexp", startsExpr),
  string: new TokenType("string", startsExpr),
  name: new TokenType("name", startsExpr),
  eof: new TokenType("eof"),

  // Punctuation token types.
  bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
  bracketR: new TokenType("]"),
  braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
  braceR: new TokenType("}"),
  parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
  parenR: new TokenType(")"),
  comma: new TokenType(",", beforeExpr),
  semi: new TokenType(";", beforeExpr),
  colon: new TokenType(":", beforeExpr),
  dot: new TokenType("."),
  question: new TokenType("?", beforeExpr),
  arrow: new TokenType("=>", beforeExpr),
  template: new TokenType("template"),
  invalidTemplate: new TokenType("invalidTemplate"),
  ellipsis: new TokenType("...", beforeExpr),
  backQuote: new TokenType("`", startsExpr),
  dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),

  // Operators. These carry several kinds of properties to help the
  // parser use them properly (the presence of these properties is
  // what categorizes them as operators).
  //
  // `binop`, when present, specifies that this operator is a binary
  // operator, and will refer to its precedence.
  //
  // `prefix` and `postfix` mark the operator as a prefix or postfix
  // unary operator.
  //
  // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
  // binary operators with a very low precedence, that should result
  // in AssignmentExpression nodes.

  eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
  assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
  incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
  prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}),
  logicalOR: binop("||", 1),
  logicalAND: binop("&&", 2),
  bitwiseOR: binop("|", 3),
  bitwiseXOR: binop("^", 4),
  bitwiseAND: binop("&", 5),
  equality: binop("==/!=/===/!==", 6),
  relational: binop("</>/<=/>=", 7),
  bitShift: binop("<</>>/>>>", 8),
  plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
  modulo: binop("%", 10),
  star: binop("*", 10),
  slash: binop("/", 10),
  starstar: new TokenType("**", {beforeExpr: true}),

  // Keyword token types.
  _break: kw("break"),
  _case: kw("case", beforeExpr),
  _catch: kw("catch"),
  _continue: kw("continue"),
  _debugger: kw("debugger"),
  _default: kw("default", beforeExpr),
  _do: kw("do", {isLoop: true, beforeExpr: true}),
  _else: kw("else", beforeExpr),
  _finally: kw("finally"),
  _for: kw("for", {isLoop: true}),
  _function: kw("function", startsExpr),
  _if: kw("if"),
  _return: kw("return", beforeExpr),
  _switch: kw("switch"),
  _throw: kw("throw", beforeExpr),
  _try: kw("try"),
  _var: kw("var"),
  _const: kw("const"),
  _while: kw("while", {isLoop: true}),
  _with: kw("with"),
  _new: kw("new", {beforeExpr: true, startsExpr: true}),
  _this: kw("this", startsExpr),
  _super: kw("super", startsExpr),
  _class: kw("class", startsExpr),
  _extends: kw("extends", beforeExpr),
  _export: kw("export"),
  _import: kw("import"),
  _null: kw("null", startsExpr),
  _true: kw("true", startsExpr),
  _false: kw("false", startsExpr),
  _in: kw("in", {beforeExpr: true, binop: 7}),
  _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
  _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
  _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
  _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})
};

// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.

var lineBreak = /\r\n?|\n|\u2028|\u2029/;
var lineBreakG = new RegExp(lineBreak.source, "g");

function isNewLine(code) {
  return code === 10 || code === 13 || code === 0x2028 || code === 0x2029
}

var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/;

var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;

var ref = Object.prototype;
var hasOwnProperty = ref.hasOwnProperty;
var toString = ref.toString;

// Checks if an object has a property.

function has(obj, propName) {
  return hasOwnProperty.call(obj, propName)
}

var isArray = Array.isArray || (function (obj) { return (
  toString.call(obj) === "[object Array]"
); });

// These are used when `options.locations` is on, for the
// `startLoc` and `endLoc` properties.

var Position = function Position(line, col) {
  this.line = line;
  this.column = col;
};

Position.prototype.offset = function offset (n) {
  return new Position(this.line, this.column + n)
};

var SourceLocation = function SourceLocation(p, start, end) {
  this.start = start;
  this.end = end;
  if (p.sourceFile !== null) { this.source = p.sourceFile; }
};

// The `getLineInfo` function is mostly useful when the
// `locations` option is off (for performance reasons) and you
// want to find the line/column position for a given character
// offset. `input` should be the code string that the offset refers
// into.

function getLineInfo(input, offset) {
  for (var line = 1, cur = 0;;) {
    lineBreakG.lastIndex = cur;
    var match = lineBreakG.exec(input);
    if (match && match.index < offset) {
      ++line;
      cur = match.index + match[0].length;
    } else {
      return new Position(line, offset - cur)
    }
  }
}

// A second optional argument can be given to further configure
// the parser process. These options are recognized:

var defaultOptions = {
  // `ecmaVersion` indicates the ECMAScript version to parse. Must
  // be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support
  // for strict mode, the set of reserved words, and support for
  // new syntax features. The default is 7.
  ecmaVersion: 7,
  // `sourceType` indicates the mode the code should be parsed in.
  // Can be either `"script"` or `"module"`. This influences global
  // strict mode and parsing of `import` and `export` declarations.
  sourceType: "script",
  // `onInsertedSemicolon` can be a callback that will be called
  // when a semicolon is automatically inserted. It will be passed
  // th position of the comma as an offset, and if `locations` is
  // enabled, it is given the location as a `{line, column}` object
  // as second argument.
  onInsertedSemicolon: null,
  // `onTrailingComma` is similar to `onInsertedSemicolon`, but for
  // trailing commas.
  onTrailingComma: null,
  // By default, reserved words are only enforced if ecmaVersion >= 5.
  // Set `allowReserved` to a boolean value to explicitly turn this on
  // an off. When this option has the value "never", reserved words
  // and keywords can also not be used as property names.
  allowReserved: null,
  // When enabled, a return at the top level is not considered an
  // error.
  allowReturnOutsideFunction: false,
  // When enabled, import/export statements are not constrained to
  // appearing at the top of the program.
  allowImportExportEverywhere: false,
  // When enabled, hashbang directive in the beginning of file
  // is allowed and treated as a line comment.
  allowHashBang: false,
  // When `locations` is on, `loc` properties holding objects with
  // `start` and `end` properties in `{line, column}` form (with
  // line being 1-based and column 0-based) will be attached to the
  // nodes.
  locations: false,
  // A function can be passed as `onToken` option, which will
  // cause Acorn to call that function with object in the same
  // format as tokens returned from `tokenizer().getToken()`. Note
  // that you are not allowed to call the parser from the
  // callback—that will corrupt its internal state.
  onToken: null,
  // A function can be passed as `onComment` option, which will
  // cause Acorn to call that function with `(block, text, start,
  // end)` parameters whenever a comment is skipped. `block` is a
  // boolean indicating whether this is a block (`/* */`) comment,
  // `text` is the content of the comment, and `start` and `end` are
  // character offsets that denote the start and end of the comment.
  // When the `locations` option is on, two more parameters are
  // passed, the full `{line, column}` locations of the start and
  // end of the comments. Note that you are not allowed to call the
  // parser from the callback—that will corrupt its internal state.
  onComment: null,
  // Nodes have their start and end characters offsets recorded in
  // `start` and `end` properties (directly on the node, rather than
  // the `loc` object, which holds line/column data. To also add a
  // [semi-standardized][range] `range` property holding a `[start,
  // end]` array with the same numbers, set the `ranges` option to
  // `true`.
  //
  // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
  ranges: false,
  // It is possible to parse multiple files into a single AST by
  // passing the tree produced by parsing the first file as
  // `program` option in subsequent parses. This will add the
  // toplevel forms of the parsed file to the `Program` (top) node
  // of an existing parse tree.
  program: null,
  // When `locations` is on, you can pass this to record the source
  // file in every node's `loc` object.
  sourceFile: null,
  // This value, if given, is stored in every node, whether
  // `locations` is on or off.
  directSourceFile: null,
  // When enabled, parenthesized expressions are represented by
  // (non-standard) ParenthesizedExpression nodes
  preserveParens: false,
  plugins: {}
};

// Interpret and default an options object

function getOptions(opts) {
  var options = {};

  for (var opt in defaultOptions)
    { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; }

  if (options.ecmaVersion >= 2015)
    { options.ecmaVersion -= 2009; }

  if (options.allowReserved == null)
    { options.allowReserved = options.ecmaVersion < 5; }

  if (isArray(options.onToken)) {
    var tokens = options.onToken;
    options.onToken = function (token) { return tokens.push(token); };
  }
  if (isArray(options.onComment))
    { options.onComment = pushComment(options, options.onComment); }

  return options
}

function pushComment(options, array) {
  return function(block, text, start, end, startLoc, endLoc) {
    var comment = {
      type: block ? "Block" : "Line",
      value: text,
      start: start,
      end: end
    };
    if (options.locations)
      { comment.loc = new SourceLocation(this, startLoc, endLoc); }
    if (options.ranges)
      { comment.range = [start, end]; }
    array.push(comment);
  }
}

// Registered plugins
var plugins = {};

function keywordRegexp(words) {
  return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$")
}

var Parser = function Parser(options, input, startPos) {
  this.options = options = getOptions(options);
  this.sourceFile = options.sourceFile;
  this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]);
  var reserved = "";
  if (!options.allowReserved) {
    for (var v = options.ecmaVersion;; v--)
      { if (reserved = reservedWords[v]) { break } }
    if (options.sourceType == "module") { reserved += " await"; }
  }
  this.reservedWords = keywordRegexp(reserved);
  var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
  this.reservedWordsStrict = keywordRegexp(reservedStrict);
  this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind);
  this.input = String(input);

  // Used to signal to callers of `readWord1` whether the word
  // contained any escape sequences. This is needed because words with
  // escape sequences must not be interpreted as keywords.
  this.containsEsc = false;

  // Load plugins
  this.loadPlugins(options.plugins);

  // Set up token state

  // The current position of the tokenizer in the input.
  if (startPos) {
    this.pos = startPos;
    this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
    this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
  } else {
    this.pos = this.lineStart = 0;
    this.curLine = 1;
  }

  // Properties of the current token:
  // Its type
  this.type = types.eof;
  // For tokens that include more information than their type, the value
  this.value = null;
  // Its start and end offset
  this.start = this.end = this.pos;
  // And, if locations are used, the {line, column} object
  // corresponding to those offsets
  this.startLoc = this.endLoc = this.curPosition();

  // Position information for the previous token
  this.lastTokEndLoc = this.lastTokStartLoc = null;
  this.lastTokStart = this.lastTokEnd = this.pos;

  // The context stack is used to superficially track syntactic
  // context to predict whether a regular expression is allowed in a
  // given position.
  this.context = this.initialContext();
  this.exprAllowed = true;

  // Figure out if it's a module code.
  this.inModule = options.sourceType === "module";
  this.strict = this.inModule || this.strictDirective(this.pos);

  // Used to signify the start of a potential arrow function
  this.potentialArrowAt = -1;

  // Flags to track whether we are in a function, a generator, an async function.
  this.inFunction = this.inGenerator = this.inAsync = false;
  // Positions to delayed-check that yield/await does not exist in default parameters.
  this.yieldPos = this.awaitPos = 0;
  // Labels in scope.
  this.labels = [];

  // If enabled, skip leading hashbang line.
  if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!")
    { this.skipLineComment(2); }

  // Scope tracking for duplicate variable names (see scope.js)
  this.scopeStack = [];
  this.enterFunctionScope();
};

// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them
Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) };
Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) };

Parser.prototype.extend = function extend (name, f) {
  this[name] = f(this[name]);
};

Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) {
    var this$1 = this;

  for (var name in pluginConfigs) {
    var plugin = plugins[name];
    if (!plugin) { throw new Error("Plugin '" + name + "' not found") }
    plugin(this$1, pluginConfigs[name]);
  }
};

Parser.prototype.parse = function parse () {
  var node = this.options.program || this.startNode();
  this.nextToken();
  return this.parseTopLevel(node)
};

var pp = Parser.prototype;

// ## Parser utilities

var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/;
pp.strictDirective = function(start) {
  var this$1 = this;

  for (;;) {
    skipWhiteSpace.lastIndex = start;
    start += skipWhiteSpace.exec(this$1.input)[0].length;
    var match = literal.exec(this$1.input.slice(start));
    if (!match) { return false }
    if ((match[1] || match[2]) == "use strict") { return true }
    start += match[0].length;
  }
};

// Predicate that tests whether the next token is of the given
// type, and if yes, consumes it as a side effect.

pp.eat = function(type) {
  if (this.type === type) {
    this.next();
    return true
  } else {
    return false
  }
};

// Tests whether parsed token is a contextual keyword.

pp.isContextual = function(name) {
  return this.type === types.name && this.value === name
};

// Consumes contextual keyword if possible.

pp.eatContextual = function(name) {
  return this.value === name && this.eat(types.name)
};

// Asserts that following token is given contextual keyword.

pp.expectContextual = function(name) {
  if (!this.eatContextual(name)) { this.unexpected(); }
};

// Test whether a semicolon can be inserted at the current position.

pp.canInsertSemicolon = function() {
  return this.type === types.eof ||
    this.type === types.braceR ||
    lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
};

pp.insertSemicolon = function() {
  if (this.canInsertSemicolon()) {
    if (this.options.onInsertedSemicolon)
      { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); }
    return true
  }
};

// Consume a semicolon, or, failing that, see if we are allowed to
// pretend that there is a semicolon at this position.

pp.semicolon = function() {
  if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); }
};

pp.afterTrailingComma = function(tokType, notNext) {
  if (this.type == tokType) {
    if (this.options.onTrailingComma)
      { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); }
    if (!notNext)
      { this.next(); }
    return true
  }
};

// Expect a token of a given type. If found, consume it, otherwise,
// raise an unexpected token error.

pp.expect = function(type) {
  this.eat(type) || this.unexpected();
};

// Raise an unexpected token error.

pp.unexpected = function(pos) {
  this.raise(pos != null ? pos : this.start, "Unexpected token");
};

function DestructuringErrors() {
  this.shorthandAssign =
  this.trailingComma =
  this.parenthesizedAssign =
  this.parenthesizedBind =
    -1;
}

pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {
  if (!refDestructuringErrors) { return }
  if (refDestructuringErrors.trailingComma > -1)
    { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); }
  var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
  if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); }
};

pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {
  var pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1;
  if (!andThrow) { return pos >= 0 }
  if (pos > -1) { this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns"); }
};

pp.checkYieldAwaitInDefaultParams = function() {
  if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
    { this.raise(this.yieldPos, "Yield expression cannot be a default value"); }
  if (this.awaitPos)
    { this.raise(this.awaitPos, "Await expression cannot be a default value"); }
};

pp.isSimpleAssignTarget = function(expr) {
  if (expr.type === "ParenthesizedExpression")
    { return this.isSimpleAssignTarget(expr.expression) }
  return expr.type === "Identifier" || expr.type === "MemberExpression"
};

var pp$1 = Parser.prototype;

// ### Statement parsing

// Parse a program. Initializes the parser, reads any number of
// statements, and wraps them in a Program node.  Optionally takes a
// `program` argument.  If present, the statements will be appended
// to its body instead of creating a new node.

pp$1.parseTopLevel = function(node) {
  var this$1 = this;

  var exports = {};
  if (!node.body) { node.body = []; }
  while (this.type !== types.eof) {
    var stmt = this$1.parseStatement(true, true, exports);
    node.body.push(stmt);
  }
  this.adaptDirectivePrologue(node.body);
  this.next();
  if (this.options.ecmaVersion >= 6) {
    node.sourceType = this.options.sourceType;
  }
  return this.finishNode(node, "Program")
};

var loopLabel = {kind: "loop"};
var switchLabel = {kind: "switch"};

pp$1.isLet = function() {
  if (this.type !== types.name || this.options.ecmaVersion < 6 || this.value != "let") { return false }
  skipWhiteSpace.lastIndex = this.pos;
  var skip = skipWhiteSpace.exec(this.input);
  var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
  if (nextCh === 91 || nextCh == 123) { return true } // '{' and '['
  if (isIdentifierStart(nextCh, true)) {
    var pos = next + 1;
    while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; }
    var ident = this.input.slice(next, pos);
    if (!this.isKeyword(ident)) { return true }
  }
  return false
};

// check 'async [no LineTerminator here] function'
// - 'async /*foo*/ function' is OK.
// - 'async /*\n*/ function' is invalid.
pp$1.isAsyncFunction = function() {
  if (this.type !== types.name || this.options.ecmaVersion < 8 || this.value != "async")
    { return false }

  skipWhiteSpace.lastIndex = this.pos;
  var skip = skipWhiteSpace.exec(this.input);
  var next = this.pos + skip[0].length;
  return !lineBreak.test(this.input.slice(this.pos, next)) &&
    this.input.slice(next, next + 8) === "function" &&
    (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))
};

// Parse a single statement.
//
// If expecting a statement and finding a slash operator, parse a
// regular expression literal. This is to handle cases like
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
// does not help.

pp$1.parseStatement = function(declaration, topLevel, exports) {
  var starttype = this.type, node = this.startNode(), kind;

  if (this.isLet()) {
    starttype = types._var;
    kind = "let";
  }

  // Most types of statements are recognized by the keyword they
  // start with. Many are trivial to parse, some require a bit of
  // complexity.

  switch (starttype) {
  case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
  case types._debugger: return this.parseDebuggerStatement(node)
  case types._do: return this.parseDoStatement(node)
  case types._for: return this.parseForStatement(node)
  case types._function:
    if (!declaration && this.options.ecmaVersion >= 6) { this.unexpected(); }
    return this.parseFunctionStatement(node, false)
  case types._class:
    if (!declaration) { this.unexpected(); }
    return this.parseClass(node, true)
  case types._if: return this.parseIfStatement(node)
  case types._return: return this.parseReturnStatement(node)
  case types._switch: return this.parseSwitchStatement(node)
  case types._throw: return this.parseThrowStatement(node)
  case types._try: return this.parseTryStatement(node)
  case types._const: case types._var:
    kind = kind || this.value;
    if (!declaration && kind != "var") { this.unexpected(); }
    return this.parseVarStatement(node, kind)
  case types._while: return this.parseWhileStatement(node)
  case types._with: return this.parseWithStatement(node)
  case types.braceL: return this.parseBlock()
  case types.semi: return this.parseEmptyStatement(node)
  case types._export:
  case types._import:
    if (!this.options.allowImportExportEverywhere) {
      if (!topLevel)
        { this.raise(this.start, "'import' and 'export' may only appear at the top level"); }
      if (!this.inModule)
        { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); }
    }
    return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports)

    // If the statement does not start with a statement keyword or a
    // brace, it's an ExpressionStatement or LabeledStatement. We
    // simply start parsing an expression, and afterwards, if the
    // next token is a colon and the expression was a simple
    // Identifier node, we switch to interpreting it as a label.
  default:
    if (this.isAsyncFunction() && declaration) {
      this.next();
      return this.parseFunctionStatement(node, true)
    }

    var maybeName = this.value, expr = this.parseExpression();
    if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon))
      { return this.parseLabeledStatement(node, maybeName, expr) }
    else { return this.parseExpressionStatement(node, expr) }
  }
};

pp$1.parseBreakContinueStatement = function(node, keyword) {
  var this$1 = this;

  var isBreak = keyword == "break";
  this.next();
  if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; }
  else if (this.type !== types.name) { this.unexpected(); }
  else {
    node.label = this.parseIdent();
    this.semicolon();
  }

  // Verify that there is an actual destination to break or
  // continue to.
  var i = 0;
  for (; i < this.labels.length; ++i) {
    var lab = this$1.labels[i];
    if (node.label == null || lab.name === node.label.name) {
      if (lab.kind != null && (isBreak || lab.kind === "loop")) { break }
      if (node.label && isBreak) { break }
    }
  }
  if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); }
  return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")
};

pp$1.parseDebuggerStatement = function(node) {
  this.next();
  this.semicolon();
  return this.finishNode(node, "DebuggerStatement")
};

pp$1.parseDoStatement = function(node) {
  this.next();
  this.labels.push(loopLabel);
  node.body = this.parseStatement(false);
  this.labels.pop();
  this.expect(types._while);
  node.test = this.parseParenExpression();
  if (this.options.ecmaVersion >= 6)
    { this.eat(types.semi); }
  else
    { this.semicolon(); }
  return this.finishNode(node, "DoWhileStatement")
};

// Disambiguating between a `for` and a `for`/`in` or `for`/`of`
// loop is non-trivial. Basically, we have to parse the init `var`
// statement or expression, disallowing the `in` operator (see
// the second parameter to `parseExpression`), and then check
// whether the next token is `in` or `of`. When there is no init
// part (semicolon immediately after the opening parenthesis), it
// is a regular `for` loop.

pp$1.parseForStatement = function(node) {
  this.next();
  this.labels.push(loopLabel);
  this.enterLexicalScope();
  this.expect(types.parenL);
  if (this.type === types.semi) { return this.parseFor(node, null) }
  var isLet = this.isLet();
  if (this.type === types._var || this.type === types._const || isLet) {
    var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
    this.next();
    this.parseVar(init$1, true, kind);
    this.finishNode(init$1, "VariableDeclaration");
    if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 &&
        !(kind !== "var" && init$1.declarations[0].init))
      { return this.parseForIn(node, init$1) }
    return this.parseFor(node, init$1)
  }
  var refDestructuringErrors = new DestructuringErrors;
  var init = this.parseExpression(true, refDestructuringErrors);
  if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
    this.toAssignable(init);
    this.checkLVal(init);
    this.checkPatternErrors(refDestructuringErrors, true);
    return this.parseForIn(node, init)
  } else {
    this.checkExpressionErrors(refDestructuringErrors, true);
  }
  return this.parseFor(node, init)
};

pp$1.parseFunctionStatement = function(node, isAsync) {
  this.next();
  return this.parseFunction(node, true, false, isAsync)
};

pp$1.isFunction = function() {
  return this.type === types._function || this.isAsyncFunction()
};

pp$1.parseIfStatement = function(node) {
  this.next();
  node.test = this.parseParenExpression();
  // allow function declarations in branches, but only in non-strict mode
  node.consequent = this.parseStatement(!this.strict && this.isFunction());
  node.alternate = this.eat(types._else) ? this.parseStatement(!this.strict && this.isFunction()) : null;
  return this.finishNode(node, "IfStatement")
};

pp$1.parseReturnStatement = function(node) {
  if (!this.inFunction && !this.options.allowReturnOutsideFunction)
    { this.raise(this.start, "'return' outside of function"); }
  this.next();

  // In `return` (and `break`/`continue`), the keywords with
  // optional arguments, we eagerly look for a semicolon or the
  // possibility to insert one.

  if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; }
  else { node.argument = this.parseExpression(); this.semicolon(); }
  return this.finishNode(node, "ReturnStatement")
};

pp$1.parseSwitchStatement = function(node) {
  var this$1 = this;

  this.next();
  node.discriminant = this.parseParenExpression();
  node.cases = [];
  this.expect(types.braceL);
  this.labels.push(switchLabel);
  this.enterLexicalScope();

  // Statements under must be grouped (by label) in SwitchCase
  // nodes. `cur` is used to keep the node that we are currently
  // adding statements to.

  var cur;
  for (var sawDefault = false; this.type != types.braceR;) {
    if (this$1.type === types._case || this$1.type === types._default) {
      var isCase = this$1.type === types._case;
      if (cur) { this$1.finishNode(cur, "SwitchCase"); }
      node.cases.push(cur = this$1.startNode());
      cur.consequent = [];
      this$1.next();
      if (isCase) {
        cur.test = this$1.parseExpression();
      } else {
        if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); }
        sawDefault = true;
        cur.test = null;
      }
      this$1.expect(types.colon);
    } else {
      if (!cur) { this$1.unexpected(); }
      cur.consequent.push(this$1.parseStatement(true));
    }
  }
  this.exitLexicalScope();
  if (cur) { this.finishNode(cur, "SwitchCase"); }
  this.next(); // Closing brace
  this.labels.pop();
  return this.finishNode(node, "SwitchStatement")
};

pp$1.parseThrowStatement = function(node) {
  this.next();
  if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
    { this.raise(this.lastTokEnd, "Illegal newline after throw"); }
  node.argument = this.parseExpression();
  this.semicolon();
  return this.finishNode(node, "ThrowStatement")
};

// Reused empty array added for node fields that are always empty.

var empty = [];

pp$1.parseTryStatement = function(node) {
  this.next();
  node.block = this.parseBlock();
  node.handler = null;
  if (this.type === types._catch) {
    var clause = this.startNode();
    this.next();
    this.expect(types.parenL);
    clause.param = this.parseBindingAtom();
    this.enterLexicalScope();
    this.checkLVal(clause.param, "let");
    this.expect(types.parenR);
    clause.body = this.parseBlock(false);
    this.exitLexicalScope();
    node.handler = this.finishNode(clause, "CatchClause");
  }
  node.finalizer = this.eat(types._finally) ? this.parseBlock() : null;
  if (!node.handler && !node.finalizer)
    { this.raise(node.start, "Missing catch or finally clause"); }
  return this.finishNode(node, "TryStatement")
};

pp$1.parseVarStatement = function(node, kind) {
  this.next();
  this.parseVar(node, false, kind);
  this.semicolon();
  return this.finishNode(node, "VariableDeclaration")
};

pp$1.parseWhileStatement = function(node) {
  this.next();
  node.test = this.parseParenExpression();
  this.labels.push(loopLabel);
  node.body = this.parseStatement(false);
  this.labels.pop();
  return this.finishNode(node, "WhileStatement")
};

pp$1.parseWithStatement = function(node) {
  if (this.strict) { this.raise(this.start, "'with' in strict mode"); }
  this.next();
  node.object = this.parseParenExpression();
  node.body = this.parseStatement(false);
  return this.finishNode(node, "WithStatement")
};

pp$1.parseEmptyStatement = function(node) {
  this.next();
  return this.finishNode(node, "EmptyStatement")
};

pp$1.parseLabeledStatement = function(node, maybeName, expr) {
  var this$1 = this;

  for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1)
    {
    var label = list[i$1];

    if (label.name === maybeName)
      { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared");
  } }
  var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null;
  for (var i = this.labels.length - 1; i >= 0; i--) {
    var label$1 = this$1.labels[i];
    if (label$1.statementStart == node.start) {
      label$1.statementStart = this$1.start;
      label$1.kind = kind;
    } else { break }
  }
  this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
  node.body = this.parseStatement(true);
  if (node.body.type == "ClassDeclaration" ||
      node.body.type == "VariableDeclaration" && node.body.kind != "var" ||
      node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator))
    { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); }
  this.labels.pop();
  node.label = expr;
  return this.finishNode(node, "LabeledStatement")
};

pp$1.parseExpressionStatement = function(node, expr) {
  node.expression = expr;
  this.semicolon();
  return this.finishNode(node, "ExpressionStatement")
};

// Parse a semicolon-enclosed block of statements, handling `"use
// strict"` declarations when `allowStrict` is true (used for
// function bodies).

pp$1.parseBlock = function(createNewLexicalScope) {
  var this$1 = this;
  if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true;

  var node = this.startNode();
  node.body = [];
  this.expect(types.braceL);
  if (createNewLexicalScope) {
    this.enterLexicalScope();
  }
  while (!this.eat(types.braceR)) {
    var stmt = this$1.parseStatement(true);
    node.body.push(stmt);
  }
  if (createNewLexicalScope) {
    this.exitLexicalScope();
  }
  return this.finishNode(node, "BlockStatement")
};

// Parse a regular `for` loop. The disambiguation code in
// `parseStatement` will already have parsed the init statement or
// expression.

pp$1.parseFor = function(node, init) {
  node.init = init;
  this.expect(types.semi);
  node.test = this.type === types.semi ? null : this.parseExpression();
  this.expect(types.semi);
  node.update = this.type === types.parenR ? null : this.parseExpression();
  this.expect(types.parenR);
  this.exitLexicalScope();
  node.body = this.parseStatement(false);
  this.labels.pop();
  return this.finishNode(node, "ForStatement")
};

// Parse a `for`/`in` and `for`/`of` loop, which are almost
// same from parser's perspective.

pp$1.parseForIn = function(node, init) {
  var type = this.type === types._in ? "ForInStatement" : "ForOfStatement";
  this.next();
  node.left = init;
  node.right = this.parseExpression();
  this.expect(types.parenR);
  this.exitLexicalScope();
  node.body = this.parseStatement(false);
  this.labels.pop();
  return this.finishNode(node, type)
};

// Parse a list of variable declarations.

pp$1.parseVar = function(node, isFor, kind) {
  var this$1 = this;

  node.declarations = [];
  node.kind = kind;
  for (;;) {
    var decl = this$1.startNode();
    this$1.parseVarId(decl, kind);
    if (this$1.eat(types.eq)) {
      decl.init = this$1.parseMaybeAssign(isFor);
    } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) {
      this$1.unexpected();
    } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) {
      this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value");
    } else {
      decl.init = null;
    }
    node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
    if (!this$1.eat(types.comma)) { break }
  }
  return node
};

pp$1.parseVarId = function(decl, kind) {
  decl.id = this.parseBindingAtom(kind);
  this.checkLVal(decl.id, kind, false);
};

// Parse a function declaration or literal (depending on the
// `isStatement` parameter).

pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {
  this.initFunction(node);
  if (this.options.ecmaVersion >= 6 && !isAsync)
    { node.generator = this.eat(types.star); }
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }

  if (isStatement) {
    node.id = isStatement === "nullableID" && this.type != types.name ? null : this.parseIdent();
    if (node.id) {
      this.checkLVal(node.id, "var");
    }
  }

  var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
      oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
  this.inGenerator = node.generator;
  this.inAsync = node.async;
  this.yieldPos = 0;
  this.awaitPos = 0;
  this.inFunction = true;
  this.enterFunctionScope();

  if (!isStatement)
    { node.id = this.type == types.name ? this.parseIdent() : null; }

  this.parseFunctionParams(node);
  this.parseFunctionBody(node, allowExpressionBody);

  this.inGenerator = oldInGen;
  this.inAsync = oldInAsync;
  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.inFunction = oldInFunc;
  return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
};

pp$1.parseFunctionParams = function(node) {
  this.expect(types.parenL);
  node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
  this.checkYieldAwaitInDefaultParams();
};

// Parse a class declaration or literal (depending on the
// `isStatement` parameter).

pp$1.parseClass = function(node, isStatement) {
  var this$1 = this;

  this.next();

  this.parseClassId(node, isStatement);
  this.parseClassSuper(node);
  var classBody = this.startNode();
  var hadConstructor = false;
  classBody.body = [];
  this.expect(types.braceL);
  while (!this.eat(types.braceR)) {
    if (this$1.eat(types.semi)) { continue }
    var method = this$1.startNode();
    var isGenerator = this$1.eat(types.star);
    var isAsync = false;
    var isMaybeStatic = this$1.type === types.name && this$1.value === "static";
    this$1.parsePropertyName(method);
    method.static = isMaybeStatic && this$1.type !== types.parenL;
    if (method.static) {
      if (isGenerator) { this$1.unexpected(); }
      isGenerator = this$1.eat(types.star);
      this$1.parsePropertyName(method);
    }
    if (this$1.options.ecmaVersion >= 8 && !isGenerator && !method.computed &&
        method.key.type === "Identifier" && method.key.name === "async" && this$1.type !== types.parenL &&
        !this$1.canInsertSemicolon()) {
      isAsync = true;
      this$1.parsePropertyName(method);
    }
    method.kind = "method";
    var isGetSet = false;
    if (!method.computed) {
      var key = method.key;
      if (!isGenerator && !isAsync && key.type === "Identifier" && this$1.type !== types.parenL && (key.name === "get" || key.name === "set")) {
        isGetSet = true;
        method.kind = key.name;
        key = this$1.parsePropertyName(method);
      }
      if (!method.static && (key.type === "Identifier" && key.name === "constructor" ||
          key.type === "Literal" && key.value === "constructor")) {
        if (hadConstructor) { this$1.raise(key.start, "Duplicate constructor in the same class"); }
        if (isGetSet) { this$1.raise(key.start, "Constructor can't have get/set modifier"); }
        if (isGenerator) { this$1.raise(key.start, "Constructor can't be a generator"); }
        if (isAsync) { this$1.raise(key.start, "Constructor can't be an async method"); }
        method.kind = "constructor";
        hadConstructor = true;
      }
    }
    this$1.parseClassMethod(classBody, method, isGenerator, isAsync);
    if (isGetSet) {
      var paramCount = method.kind === "get" ? 0 : 1;
      if (method.value.params.length !== paramCount) {
        var start = method.value.start;
        if (method.kind === "get")
          { this$1.raiseRecoverable(start, "getter should have no params"); }
        else
          { this$1.raiseRecoverable(start, "setter should have exactly one param"); }
      } else {
        if (method.kind === "set" && method.value.params[0].type === "RestElement")
          { this$1.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); }
      }
    }
  }
  node.body = this.finishNode(classBody, "ClassBody");
  return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
};

pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) {
  method.value = this.parseMethod(isGenerator, isAsync);
  classBody.body.push(this.finishNode(method, "MethodDefinition"));
};

pp$1.parseClassId = function(node, isStatement) {
  node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null;
};

pp$1.parseClassSuper = function(node) {
  node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null;
};

// Parses module export declaration.

pp$1.parseExport = function(node, exports) {
  var this$1 = this;

  this.next();
  // export * from '...'
  if (this.eat(types.star)) {
    this.expectContextual("from");
    node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
    this.semicolon();
    return this.finishNode(node, "ExportAllDeclaration")
  }
  if (this.eat(types._default)) { // export default ...
    this.checkExport(exports, "default", this.lastTokStart);
    var isAsync;
    if (this.type === types._function || (isAsync = this.isAsyncFunction())) {
      var fNode = this.startNode();
      this.next();
      if (isAsync) { this.next(); }
      node.declaration = this.parseFunction(fNode, "nullableID", false, isAsync);
    } else if (this.type === types._class) {
      var cNode = this.startNode();
      node.declaration = this.parseClass(cNode, "nullableID");
    } else {
      node.declaration = this.parseMaybeAssign();
      this.semicolon();
    }
    return this.finishNode(node, "ExportDefaultDeclaration")
  }
  // export var|const|let|function|class ...
  if (this.shouldParseExportStatement()) {
    node.declaration = this.parseStatement(true);
    if (node.declaration.type === "VariableDeclaration")
      { this.checkVariableExport(exports, node.declaration.declarations); }
    else
      { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); }
    node.specifiers = [];
    node.source = null;
  } else { // export { x, y as z } [from '...']
    node.declaration = null;
    node.specifiers = this.parseExportSpecifiers(exports);
    if (this.eatContextual("from")) {
      node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
    } else {
      // check for keywords used as local names
      for (var i = 0, list = node.specifiers; i < list.length; i += 1) {
        var spec = list[i];

        this$1.checkUnreserved(spec.local);
      }

      node.source = null;
    }
    this.semicolon();
  }
  return this.finishNode(node, "ExportNamedDeclaration")
};

pp$1.checkExport = function(exports, name, pos) {
  if (!exports) { return }
  if (has(exports, name))
    { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); }
  exports[name] = true;
};

pp$1.checkPatternExport = function(exports, pat) {
  var this$1 = this;

  var type = pat.type;
  if (type == "Identifier")
    { this.checkExport(exports, pat.name, pat.start); }
  else if (type == "ObjectPattern")
    { for (var i = 0, list = pat.properties; i < list.length; i += 1)
      {
        var prop = list[i];

        this$1.checkPatternExport(exports, prop.value);
      } }
  else if (type == "ArrayPattern")
    { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) {
      var elt = list$1[i$1];

        if (elt) { this$1.checkPatternExport(exports, elt); }
    } }
  else if (type == "AssignmentPattern")
    { this.checkPatternExport(exports, pat.left); }
  else if (type == "ParenthesizedExpression")
    { this.checkPatternExport(exports, pat.expression); }
};

pp$1.checkVariableExport = function(exports, decls) {
  var this$1 = this;

  if (!exports) { return }
  for (var i = 0, list = decls; i < list.length; i += 1)
    {
    var decl = list[i];

    this$1.checkPatternExport(exports, decl.id);
  }
};

pp$1.shouldParseExportStatement = function() {
  return this.type.keyword === "var" ||
    this.type.keyword === "const" ||
    this.type.keyword === "class" ||
    this.type.keyword === "function" ||
    this.isLet() ||
    this.isAsyncFunction()
};

// Parses a comma-separated list of module exports.

pp$1.parseExportSpecifiers = function(exports) {
  var this$1 = this;

  var nodes = [], first = true;
  // export { x, y as z } [from '...']
  this.expect(types.braceL);
  while (!this.eat(types.braceR)) {
    if (!first) {
      this$1.expect(types.comma);
      if (this$1.afterTrailingComma(types.braceR)) { break }
    } else { first = false; }

    var node = this$1.startNode();
    node.local = this$1.parseIdent(true);
    node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local;
    this$1.checkExport(exports, node.exported.name, node.exported.start);
    nodes.push(this$1.finishNode(node, "ExportSpecifier"));
  }
  return nodes
};

// Parses import declaration.

pp$1.parseImport = function(node) {
  this.next();
  // import '...'
  if (this.type === types.string) {
    node.specifiers = empty;
    node.source = this.parseExprAtom();
  } else {
    node.specifiers = this.parseImportSpecifiers();
    this.expectContextual("from");
    node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected();
  }
  this.semicolon();
  return this.finishNode(node, "ImportDeclaration")
};

// Parses a comma-separated list of module imports.

pp$1.parseImportSpecifiers = function() {
  var this$1 = this;

  var nodes = [], first = true;
  if (this.type === types.name) {
    // import defaultObj, { x, y as z } from '...'
    var node = this.startNode();
    node.local = this.parseIdent();
    this.checkLVal(node.local, "let");
    nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
    if (!this.eat(types.comma)) { return nodes }
  }
  if (this.type === types.star) {
    var node$1 = this.startNode();
    this.next();
    this.expectContextual("as");
    node$1.local = this.parseIdent();
    this.checkLVal(node$1.local, "let");
    nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
    return nodes
  }
  this.expect(types.braceL);
  while (!this.eat(types.braceR)) {
    if (!first) {
      this$1.expect(types.comma);
      if (this$1.afterTrailingComma(types.braceR)) { break }
    } else { first = false; }

    var node$2 = this$1.startNode();
    node$2.imported = this$1.parseIdent(true);
    if (this$1.eatContextual("as")) {
      node$2.local = this$1.parseIdent();
    } else {
      this$1.checkUnreserved(node$2.imported);
      node$2.local = node$2.imported;
    }
    this$1.checkLVal(node$2.local, "let");
    nodes.push(this$1.finishNode(node$2, "ImportSpecifier"));
  }
  return nodes
};

// Set `ExpressionStatement#directive` property for directive prologues.
pp$1.adaptDirectivePrologue = function(statements) {
  for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
    statements[i].directive = statements[i].expression.raw.slice(1, -1);
  }
};
pp$1.isDirectiveCandidate = function(statement) {
  return (
    statement.type === "ExpressionStatement" &&
    statement.expression.type === "Literal" &&
    typeof statement.expression.value === "string" &&
    // Reject parenthesized strings.
    (this.input[statement.start] === "\"" || this.input[statement.start] === "'")
  )
};

var pp$2 = Parser.prototype;

// Convert existing expression atom to assignable pattern
// if possible.

pp$2.toAssignable = function(node, isBinding) {
  var this$1 = this;

  if (this.options.ecmaVersion >= 6 && node) {
    switch (node.type) {
    case "Identifier":
      if (this.inAsync && node.name === "await")
        { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); }
      break

    case "ObjectPattern":
    case "ArrayPattern":
      break

    case "ObjectExpression":
      node.type = "ObjectPattern";
      for (var i = 0, list = node.properties; i < list.length; i += 1) {
        var prop = list[i];

      if (prop.kind !== "init") { this$1.raise(prop.key.start, "Object pattern can't contain getter or setter"); }
        this$1.toAssignable(prop.value, isBinding);
      }
      break

    case "ArrayExpression":
      node.type = "ArrayPattern";
      this.toAssignableList(node.elements, isBinding);
      break

    case "AssignmentExpression":
      if (node.operator === "=") {
        node.type = "AssignmentPattern";
        delete node.operator;
        this.toAssignable(node.left, isBinding);
        // falls through to AssignmentPattern
      } else {
        this.raise(node.left.end, "Only '=' operator can be used for specifying default value.");
        break
      }

    case "AssignmentPattern":
      break

    case "ParenthesizedExpression":
      this.toAssignable(node.expression, isBinding);
      break

    case "MemberExpression":
      if (!isBinding) { break }

    default:
      this.raise(node.start, "Assigning to rvalue");
    }
  }
  return node
};

// Convert list of expression atoms to binding list.

pp$2.toAssignableList = function(exprList, isBinding) {
  var this$1 = this;

  var end = exprList.length;
  if (end) {
    var last = exprList[end - 1];
    if (last && last.type == "RestElement") {
      --end;
    } else if (last && last.type == "SpreadElement") {
      last.type = "RestElement";
      var arg = last.argument;
      this.toAssignable(arg, isBinding);
      --end;
    }

    if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
      { this.unexpected(last.argument.start); }
  }
  for (var i = 0; i < end; i++) {
    var elt = exprList[i];
    if (elt) { this$1.toAssignable(elt, isBinding); }
  }
  return exprList
};

// Parses spread element.

pp$2.parseSpread = function(refDestructuringErrors) {
  var node = this.startNode();
  this.next();
  node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
  return this.finishNode(node, "SpreadElement")
};

pp$2.parseRestBinding = function() {
  var node = this.startNode();
  this.next();

  // RestElement inside of a function parameter must be an identifier
  if (this.options.ecmaVersion === 6 && this.type !== types.name)
    { this.unexpected(); }

  node.argument = this.parseBindingAtom();

  return this.finishNode(node, "RestElement")
};

// Parses lvalue (assignable) atom.

pp$2.parseBindingAtom = function() {
  if (this.options.ecmaVersion >= 6) {
    switch (this.type) {
    case types.bracketL:
      var node = this.startNode();
      this.next();
      node.elements = this.parseBindingList(types.bracketR, true, true);
      return this.finishNode(node, "ArrayPattern")

    case types.braceL:
      return this.parseObj(true)
    }
  }
  return this.parseIdent()
};

pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) {
  var this$1 = this;

  var elts = [], first = true;
  while (!this.eat(close)) {
    if (first) { first = false; }
    else { this$1.expect(types.comma); }
    if (allowEmpty && this$1.type === types.comma) {
      elts.push(null);
    } else if (allowTrailingComma && this$1.afterTrailingComma(close)) {
      break
    } else if (this$1.type === types.ellipsis) {
      var rest = this$1.parseRestBinding();
      this$1.parseBindingListItem(rest);
      elts.push(rest);
      if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
      this$1.expect(close);
      break
    } else {
      var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc);
      this$1.parseBindingListItem(elem);
      elts.push(elem);
    }
  }
  return elts
};

pp$2.parseBindingListItem = function(param) {
  return param
};

// Parses assignment pattern around given atom if possible.

pp$2.parseMaybeDefault = function(startPos, startLoc, left) {
  left = left || this.parseBindingAtom();
  if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left }
  var node = this.startNodeAt(startPos, startLoc);
  node.left = left;
  node.right = this.parseMaybeAssign();
  return this.finishNode(node, "AssignmentPattern")
};

// Verify that a node is an lval — something that can be assigned
// to.
// bindingType can be either:
// 'var' indicating that the lval creates a 'var' binding
// 'let' indicating that the lval creates a lexical ('let' or 'const') binding
// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references

pp$2.checkLVal = function(expr, bindingType, checkClashes) {
  var this$1 = this;

  switch (expr.type) {
  case "Identifier":
    if (this.strict && this.reservedWordsStrictBind.test(expr.name))
      { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); }
    if (checkClashes) {
      if (has(checkClashes, expr.name))
        { this.raiseRecoverable(expr.start, "Argument name clash"); }
      checkClashes[expr.name] = true;
    }
    if (bindingType && bindingType !== "none") {
      if (
        bindingType === "var" && !this.canDeclareVarName(expr.name) ||
        bindingType !== "var" && !this.canDeclareLexicalName(expr.name)
      ) {
        this.raiseRecoverable(expr.start, ("Identifier '" + (expr.name) + "' has already been declared"));
      }
      if (bindingType === "var") {
        this.declareVarName(expr.name);
      } else {
        this.declareLexicalName(expr.name);
      }
    }
    break

  case "MemberExpression":
    if (bindingType) { this.raiseRecoverable(expr.start, (bindingType ? "Binding" : "Assigning to") + " member expression"); }
    break

  case "ObjectPattern":
    for (var i = 0, list = expr.properties; i < list.length; i += 1)
      {
    var prop = list[i];

    this$1.checkLVal(prop.value, bindingType, checkClashes);
  }
    break

  case "ArrayPattern":
    for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) {
      var elem = list$1[i$1];

    if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); }
    }
    break

  case "AssignmentPattern":
    this.checkLVal(expr.left, bindingType, checkClashes);
    break

  case "RestElement":
    this.checkLVal(expr.argument, bindingType, checkClashes);
    break

  case "ParenthesizedExpression":
    this.checkLVal(expr.expression, bindingType, checkClashes);
    break

  default:
    this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue");
  }
};

// A recursive descent parser operates by defining functions for all
// syntactic elements, and recursively calling those, each function
// advancing the input stream and returning an AST node. Precedence
// of constructs (for example, the fact that `!x[1]` means `!(x[1])`
// instead of `(!x)[1]` is handled by the fact that the parser
// function that parses unary prefix operators is called first, and
// in turn calls the function that parses `[]` subscripts — that
// way, it'll receive the node for `x[1]` already parsed, and wraps
// *that* in the unary operator node.
//
// Acorn uses an [operator precedence parser][opp] to handle binary
// operator precedence, because it is much more compact than using
// the technique outlined above, which uses different, nesting
// functions to specify precedence, for all of the ten binary
// precedence levels that JavaScript defines.
//
// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser

var pp$3 = Parser.prototype;

// Check if property name clashes with already added.
// Object/class getters and setters are not allowed to clash —
// either with each other or with an init property — and in
// strict mode, init properties are also not allowed to be repeated.

pp$3.checkPropClash = function(prop, propHash) {
  if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
    { return }
  var key = prop.key;
  var name;
  switch (key.type) {
  case "Identifier": name = key.name; break
  case "Literal": name = String(key.value); break
  default: return
  }
  var kind = prop.kind;
  if (this.options.ecmaVersion >= 6) {
    if (name === "__proto__" && kind === "init") {
      if (propHash.proto) { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); }
      propHash.proto = true;
    }
    return
  }
  name = "$" + name;
  var other = propHash[name];
  if (other) {
    var redefinition;
    if (kind === "init") {
      redefinition = this.strict && other.init || other.get || other.set;
    } else {
      redefinition = other.init || other[kind];
    }
    if (redefinition)
      { this.raiseRecoverable(key.start, "Redefinition of property"); }
  } else {
    other = propHash[name] = {
      init: false,
      get: false,
      set: false
    };
  }
  other[kind] = true;
};

// ### Expression parsing

// These nest, from the most general expression type at the top to
// 'atomic', nondivisible expression types at the bottom. Most of
// the functions will simply let the function(s) below them parse,
// and, *if* the syntactic construct they handle is present, wrap
// the AST node that the inner parser gave them in another node.

// Parse a full expression. The optional arguments are used to
// forbid the `in` operator (in for loops initalization expressions)
// and provide reference for storing '=' operator inside shorthand
// property assignment in contexts where both object expression
// and object pattern might appear (so it's possible to raise
// delayed syntax error at correct position).

pp$3.parseExpression = function(noIn, refDestructuringErrors) {
  var this$1 = this;

  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
  if (this.type === types.comma) {
    var node = this.startNodeAt(startPos, startLoc);
    node.expressions = [expr];
    while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); }
    return this.finishNode(node, "SequenceExpression")
  }
  return expr
};

// Parse an assignment expression. This includes applications of
// operators like `+=`.

pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
  if (this.inGenerator && this.isContextual("yield")) { return this.parseYield() }

  var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1;
  if (refDestructuringErrors) {
    oldParenAssign = refDestructuringErrors.parenthesizedAssign;
    oldTrailingComma = refDestructuringErrors.trailingComma;
    refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
  } else {
    refDestructuringErrors = new DestructuringErrors;
    ownDestructuringErrors = true;
  }

  var startPos = this.start, startLoc = this.startLoc;
  if (this.type == types.parenL || this.type == types.name)
    { this.potentialArrowAt = this.start; }
  var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
  if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); }
  if (this.type.isAssign) {
    this.checkPatternErrors(refDestructuringErrors, true);
    if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); }
    var node = this.startNodeAt(startPos, startLoc);
    node.operator = this.value;
    node.left = this.type === types.eq ? this.toAssignable(left) : left;
    refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
    this.checkLVal(left);
    this.next();
    node.right = this.parseMaybeAssign(noIn);
    return this.finishNode(node, "AssignmentExpression")
  } else {
    if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); }
  }
  if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; }
  if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; }
  return left
};

// Parse a ternary conditional (`?:`) operator.

pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseExprOps(noIn, refDestructuringErrors);
  if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
  if (this.eat(types.question)) {
    var node = this.startNodeAt(startPos, startLoc);
    node.test = expr;
    node.consequent = this.parseMaybeAssign();
    this.expect(types.colon);
    node.alternate = this.parseMaybeAssign(noIn);
    return this.finishNode(node, "ConditionalExpression")
  }
  return expr
};

// Start the precedence parser.

pp$3.parseExprOps = function(noIn, refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseMaybeUnary(refDestructuringErrors, false);
  if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
  return expr.start == startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn)
};

// Parse binary operators with the operator precedence parsing
// algorithm. `left` is the left-hand side of the operator.
// `minPrec` provides context that allows the function to stop and
// defer further parser to one of its callers when it encounters an
// operator that has a lower precedence than the set it is parsing.

pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
  var prec = this.type.binop;
  if (prec != null && (!noIn || this.type !== types._in)) {
    if (prec > minPrec) {
      var logical = this.type === types.logicalOR || this.type === types.logicalAND;
      var op = this.value;
      this.next();
      var startPos = this.start, startLoc = this.startLoc;
      var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
      var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
      return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
    }
  }
  return left
};

pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {
  var node = this.startNodeAt(startPos, startLoc);
  node.left = left;
  node.operator = op;
  node.right = right;
  return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
};

// Parse unary operators, both prefix and postfix.

pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
  var this$1 = this;

  var startPos = this.start, startLoc = this.startLoc, expr;
  if (this.inAsync && this.isContextual("await")) {
    expr = this.parseAwait();
    sawUnary = true;
  } else if (this.type.prefix) {
    var node = this.startNode(), update = this.type === types.incDec;
    node.operator = this.value;
    node.prefix = true;
    this.next();
    node.argument = this.parseMaybeUnary(null, true);
    this.checkExpressionErrors(refDestructuringErrors, true);
    if (update) { this.checkLVal(node.argument); }
    else if (this.strict && node.operator === "delete" &&
             node.argument.type === "Identifier")
      { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); }
    else { sawUnary = true; }
    expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
  } else {
    expr = this.parseExprSubscripts(refDestructuringErrors);
    if (this.checkExpressionErrors(refDestructuringErrors)) { return expr }
    while (this.type.postfix && !this.canInsertSemicolon()) {
      var node$1 = this$1.startNodeAt(startPos, startLoc);
      node$1.operator = this$1.value;
      node$1.prefix = false;
      node$1.argument = expr;
      this$1.checkLVal(expr);
      this$1.next();
      expr = this$1.finishNode(node$1, "UpdateExpression");
    }
  }

  if (!sawUnary && this.eat(types.starstar))
    { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) }
  else
    { return expr }
};

// Parse call, dot, and `[]`-subscript expressions.

pp$3.parseExprSubscripts = function(refDestructuringErrors) {
  var startPos = this.start, startLoc = this.startLoc;
  var expr = this.parseExprAtom(refDestructuringErrors);
  var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")";
  if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr }
  var result = this.parseSubscripts(expr, startPos, startLoc);
  if (refDestructuringErrors && result.type === "MemberExpression") {
    if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; }
    if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; }
  }
  return result
};

pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {
  var this$1 = this;

  var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
      this.lastTokEnd == base.end && !this.canInsertSemicolon();
  for (var computed = (void 0);;) {
    if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) {
      var node = this$1.startNodeAt(startPos, startLoc);
      node.object = base;
      node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true);
      node.computed = !!computed;
      if (computed) { this$1.expect(types.bracketR); }
      base = this$1.finishNode(node, "MemberExpression");
    } else if (!noCalls && this$1.eat(types.parenL)) {
      var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos;
      this$1.yieldPos = 0;
      this$1.awaitPos = 0;
      var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors);
      if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) {
        this$1.checkPatternErrors(refDestructuringErrors, false);
        this$1.checkYieldAwaitInDefaultParams();
        this$1.yieldPos = oldYieldPos;
        this$1.awaitPos = oldAwaitPos;
        return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true)
      }
      this$1.checkExpressionErrors(refDestructuringErrors, true);
      this$1.yieldPos = oldYieldPos || this$1.yieldPos;
      this$1.awaitPos = oldAwaitPos || this$1.awaitPos;
      var node$1 = this$1.startNodeAt(startPos, startLoc);
      node$1.callee = base;
      node$1.arguments = exprList;
      base = this$1.finishNode(node$1, "CallExpression");
    } else if (this$1.type === types.backQuote) {
      var node$2 = this$1.startNodeAt(startPos, startLoc);
      node$2.tag = base;
      node$2.quasi = this$1.parseTemplate({isTagged: true});
      base = this$1.finishNode(node$2, "TaggedTemplateExpression");
    } else {
      return base
    }
  }
};

// Parse an atomic expression — either a single token that is an
// expression, an expression started by a keyword like `function` or
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
// or `{}`.

pp$3.parseExprAtom = function(refDestructuringErrors) {
  var node, canBeArrow = this.potentialArrowAt == this.start;
  switch (this.type) {
  case types._super:
    if (!this.inFunction)
      { this.raise(this.start, "'super' outside of function or class"); }
    node = this.startNode();
    this.next();
    // The `super` keyword can appear at below:
    // SuperProperty:
    //     super [ Expression ]
    //     super . IdentifierName
    // SuperCall:
    //     super Arguments
    if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
      { this.unexpected(); }
    return this.finishNode(node, "Super")

  case types._this:
    node = this.startNode();
    this.next();
    return this.finishNode(node, "ThisExpression")

  case types.name:
    var startPos = this.start, startLoc = this.startLoc;
    var id = this.parseIdent(this.type !== types.name);
    if (this.options.ecmaVersion >= 8 && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function))
      { return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true) }
    if (canBeArrow && !this.canInsertSemicolon()) {
      if (this.eat(types.arrow))
        { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) }
      if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name) {
        id = this.parseIdent();
        if (this.canInsertSemicolon() || !this.eat(types.arrow))
          { this.unexpected(); }
        return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
      }
    }
    return id

  case types.regexp:
    var value = this.value;
    node = this.parseLiteral(value.value);
    node.regex = {pattern: value.pattern, flags: value.flags};
    return node

  case types.num: case types.string:
    return this.parseLiteral(this.value)

  case types._null: case types._true: case types._false:
    node = this.startNode();
    node.value = this.type === types._null ? null : this.type === types._true;
    node.raw = this.type.keyword;
    this.next();
    return this.finishNode(node, "Literal")

  case types.parenL:
    var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
    if (refDestructuringErrors) {
      if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
        { refDestructuringErrors.parenthesizedAssign = start; }
      if (refDestructuringErrors.parenthesizedBind < 0)
        { refDestructuringErrors.parenthesizedBind = start; }
    }
    return expr

  case types.bracketL:
    node = this.startNode();
    this.next();
    node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors);
    return this.finishNode(node, "ArrayExpression")

  case types.braceL:
    return this.parseObj(false, refDestructuringErrors)

  case types._function:
    node = this.startNode();
    this.next();
    return this.parseFunction(node, false)

  case types._class:
    return this.parseClass(this.startNode(), false)

  case types._new:
    return this.parseNew()

  case types.backQuote:
    return this.parseTemplate()

  default:
    this.unexpected();
  }
};

pp$3.parseLiteral = function(value) {
  var node = this.startNode();
  node.value = value;
  node.raw = this.input.slice(this.start, this.end);
  this.next();
  return this.finishNode(node, "Literal")
};

pp$3.parseParenExpression = function() {
  this.expect(types.parenL);
  var val = this.parseExpression();
  this.expect(types.parenR);
  return val
};

pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {
  var this$1 = this;

  var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
  if (this.options.ecmaVersion >= 6) {
    this.next();

    var innerStartPos = this.start, innerStartLoc = this.startLoc;
    var exprList = [], first = true, lastIsComma = false;
    var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart, innerParenStart;
    this.yieldPos = 0;
    this.awaitPos = 0;
    while (this.type !== types.parenR) {
      first ? first = false : this$1.expect(types.comma);
      if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) {
        lastIsComma = true;
        break
      } else if (this$1.type === types.ellipsis) {
        spreadStart = this$1.start;
        exprList.push(this$1.parseParenItem(this$1.parseRestBinding()));
        if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); }
        break
      } else {
        if (this$1.type === types.parenL && !innerParenStart) {
          innerParenStart = this$1.start;
        }
        exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem));
      }
    }
    var innerEndPos = this.start, innerEndLoc = this.startLoc;
    this.expect(types.parenR);

    if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) {
      this.checkPatternErrors(refDestructuringErrors, false);
      this.checkYieldAwaitInDefaultParams();
      if (innerParenStart) { this.unexpected(innerParenStart); }
      this.yieldPos = oldYieldPos;
      this.awaitPos = oldAwaitPos;
      return this.parseParenArrowList(startPos, startLoc, exprList)
    }

    if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); }
    if (spreadStart) { this.unexpected(spreadStart); }
    this.checkExpressionErrors(refDestructuringErrors, true);
    this.yieldPos = oldYieldPos || this.yieldPos;
    this.awaitPos = oldAwaitPos || this.awaitPos;

    if (exprList.length > 1) {
      val = this.startNodeAt(innerStartPos, innerStartLoc);
      val.expressions = exprList;
      this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
    } else {
      val = exprList[0];
    }
  } else {
    val = this.parseParenExpression();
  }

  if (this.options.preserveParens) {
    var par = this.startNodeAt(startPos, startLoc);
    par.expression = val;
    return this.finishNode(par, "ParenthesizedExpression")
  } else {
    return val
  }
};

pp$3.parseParenItem = function(item) {
  return item
};

pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {
  return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
};

// New's precedence is slightly tricky. It must allow its argument to
// be a `[]` or dot subscript expression, but not a call — at least,
// not without wrapping it in parentheses. Thus, it uses the noCalls
// argument to parseSubscripts to prevent it from consuming the
// argument list.

var empty$1 = [];

pp$3.parseNew = function() {
  var node = this.startNode();
  var meta = this.parseIdent(true);
  if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) {
    node.meta = meta;
    node.property = this.parseIdent(true);
    if (node.property.name !== "target")
      { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); }
    if (!this.inFunction)
      { this.raiseRecoverable(node.start, "new.target can only be used in functions"); }
    return this.finishNode(node, "MetaProperty")
  }
  var startPos = this.start, startLoc = this.startLoc;
  node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
  if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); }
  else { node.arguments = empty$1; }
  return this.finishNode(node, "NewExpression")
};

// Parse template expression.

pp$3.parseTemplateElement = function(ref) {
  var isTagged = ref.isTagged;

  var elem = this.startNode();
  if (this.type === types.invalidTemplate) {
    if (!isTagged) {
      this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
    }
    elem.value = {
      raw: this.value,
      cooked: null
    };
  } else {
    elem.value = {
      raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
      cooked: this.value
    };
  }
  this.next();
  elem.tail = this.type === types.backQuote;
  return this.finishNode(elem, "TemplateElement")
};

pp$3.parseTemplate = function(ref) {
  var this$1 = this;
  if ( ref === void 0 ) ref = {};
  var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false;

  var node = this.startNode();
  this.next();
  node.expressions = [];
  var curElt = this.parseTemplateElement({isTagged: isTagged});
  node.quasis = [curElt];
  while (!curElt.tail) {
    this$1.expect(types.dollarBraceL);
    node.expressions.push(this$1.parseExpression());
    this$1.expect(types.braceR);
    node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged}));
  }
  this.next();
  return this.finishNode(node, "TemplateLiteral")
};

pp$3.isAsyncProp = function(prop) {
  return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" &&
    (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword) &&
    !lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
};

// Parse an object literal or binding pattern.

pp$3.parseObj = function(isPattern, refDestructuringErrors) {
  var this$1 = this;

  var node = this.startNode(), first = true, propHash = {};
  node.properties = [];
  this.next();
  while (!this.eat(types.braceR)) {
    if (!first) {
      this$1.expect(types.comma);
      if (this$1.afterTrailingComma(types.braceR)) { break }
    } else { first = false; }

    var prop = this$1.parseProperty(isPattern, refDestructuringErrors);
    this$1.checkPropClash(prop, propHash);
    node.properties.push(prop);
  }
  return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
};

pp$3.parseProperty = function(isPattern, refDestructuringErrors) {
  var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
  if (this.options.ecmaVersion >= 6) {
    prop.method = false;
    prop.shorthand = false;
    if (isPattern || refDestructuringErrors) {
      startPos = this.start;
      startLoc = this.startLoc;
    }
    if (!isPattern)
      { isGenerator = this.eat(types.star); }
  }
  this.parsePropertyName(prop);
  if (!isPattern && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
    isAsync = true;
    this.parsePropertyName(prop, refDestructuringErrors);
  } else {
    isAsync = false;
  }
  this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors);
  return this.finishNode(prop, "Property")
};

pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors) {
  if ((isGenerator || isAsync) && this.type === types.colon)
    { this.unexpected(); }

  if (this.eat(types.colon)) {
    prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
    prop.kind = "init";
  } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) {
    if (isPattern) { this.unexpected(); }
    prop.kind = "init";
    prop.method = true;
    prop.value = this.parseMethod(isGenerator, isAsync);
  } else if (!isPattern &&
             this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
             (prop.key.name === "get" || prop.key.name === "set") &&
             (this.type != types.comma && this.type != types.braceR)) {
    if (isGenerator || isAsync) { this.unexpected(); }
    prop.kind = prop.key.name;
    this.parsePropertyName(prop);
    prop.value = this.parseMethod(false);
    var paramCount = prop.kind === "get" ? 0 : 1;
    if (prop.value.params.length !== paramCount) {
      var start = prop.value.start;
      if (prop.kind === "get")
        { this.raiseRecoverable(start, "getter should have no params"); }
      else
        { this.raiseRecoverable(start, "setter should have exactly one param"); }
    } else {
      if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
        { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); }
    }
  } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
    this.checkUnreserved(prop.key);
    prop.kind = "init";
    if (isPattern) {
      prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
    } else if (this.type === types.eq && refDestructuringErrors) {
      if (refDestructuringErrors.shorthandAssign < 0)
        { refDestructuringErrors.shorthandAssign = this.start; }
      prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
    } else {
      prop.value = prop.key;
    }
    prop.shorthand = true;
  } else { this.unexpected(); }
};

pp$3.parsePropertyName = function(prop) {
  if (this.options.ecmaVersion >= 6) {
    if (this.eat(types.bracketL)) {
      prop.computed = true;
      prop.key = this.parseMaybeAssign();
      this.expect(types.bracketR);
      return prop.key
    } else {
      prop.computed = false;
    }
  }
  return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true)
};

// Initialize empty function node.

pp$3.initFunction = function(node) {
  node.id = null;
  if (this.options.ecmaVersion >= 6) {
    node.generator = false;
    node.expression = false;
  }
  if (this.options.ecmaVersion >= 8)
    { node.async = false; }
};

// Parse object or class method.

pp$3.parseMethod = function(isGenerator, isAsync) {
  var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync,
      oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;

  this.initFunction(node);
  if (this.options.ecmaVersion >= 6)
    { node.generator = isGenerator; }
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }

  this.inGenerator = node.generator;
  this.inAsync = node.async;
  this.yieldPos = 0;
  this.awaitPos = 0;
  this.inFunction = true;
  this.enterFunctionScope();

  this.expect(types.parenL);
  node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8);
  this.checkYieldAwaitInDefaultParams();
  this.parseFunctionBody(node, false);

  this.inGenerator = oldInGen;
  this.inAsync = oldInAsync;
  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.inFunction = oldInFunc;
  return this.finishNode(node, "FunctionExpression")
};

// Parse arrow function expression with given parameters.

pp$3.parseArrowExpression = function(node, params, isAsync) {
  var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
      oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;

  this.enterFunctionScope();
  this.initFunction(node);
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }

  this.inGenerator = false;
  this.inAsync = node.async;
  this.yieldPos = 0;
  this.awaitPos = 0;
  this.inFunction = true;

  node.params = this.toAssignableList(params, true);
  this.parseFunctionBody(node, true);

  this.inGenerator = oldInGen;
  this.inAsync = oldInAsync;
  this.yieldPos = oldYieldPos;
  this.awaitPos = oldAwaitPos;
  this.inFunction = oldInFunc;
  return this.finishNode(node, "ArrowFunctionExpression")
};

// Parse function body and check parameters.

pp$3.parseFunctionBody = function(node, isArrowFunction) {
  var isExpression = isArrowFunction && this.type !== types.braceL;
  var oldStrict = this.strict, useStrict = false;

  if (isExpression) {
    node.body = this.parseMaybeAssign();
    node.expression = true;
    this.checkParams(node, false);
  } else {
    var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
    if (!oldStrict || nonSimple) {
      useStrict = this.strictDirective(this.end);
      // If this is a strict mode function, verify that argument names
      // are not repeated, and it does not try to bind the words `eval`
      // or `arguments`.
      if (useStrict && nonSimple)
        { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); }
    }
    // Start a new scope with regard to labels and the `inFunction`
    // flag (restore them to their old value afterwards).
    var oldLabels = this.labels;
    this.labels = [];
    if (useStrict) { this.strict = true; }

    // Add the params to varDeclaredNames to ensure that an error is thrown
    // if a let/const declaration in the function clashes with one of the params.
    this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params));
    node.body = this.parseBlock(false);
    node.expression = false;
    this.adaptDirectivePrologue(node.body.body);
    this.labels = oldLabels;
  }
  this.exitFunctionScope();

  if (this.strict && node.id) {
    // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
    this.checkLVal(node.id, "none");
  }
  this.strict = oldStrict;
};

pp$3.isSimpleParamList = function(params) {
  for (var i = 0, list = params; i < list.length; i += 1)
    {
    var param = list[i];

    if (param.type !== "Identifier") { return false
  } }
  return true
};

// Checks function params for various disallowed patterns such as using "eval"
// or "arguments" and duplicate parameters.

pp$3.checkParams = function(node, allowDuplicates) {
  var this$1 = this;

  var nameHash = {};
  for (var i = 0, list = node.params; i < list.length; i += 1)
    {
    var param = list[i];

    this$1.checkLVal(param, "var", allowDuplicates ? null : nameHash);
  }
};

// Parses a comma-separated list of expressions, and returns them as
// an array. `close` is the token type that ends the list, and
// `allowEmpty` can be turned on to allow subsequent commas with
// nothing in between them to be parsed as `null` (which is needed
// for array literals).

pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
  var this$1 = this;

  var elts = [], first = true;
  while (!this.eat(close)) {
    if (!first) {
      this$1.expect(types.comma);
      if (allowTrailingComma && this$1.afterTrailingComma(close)) { break }
    } else { first = false; }

    var elt = (void 0);
    if (allowEmpty && this$1.type === types.comma)
      { elt = null; }
    else if (this$1.type === types.ellipsis) {
      elt = this$1.parseSpread(refDestructuringErrors);
      if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0)
        { refDestructuringErrors.trailingComma = this$1.start; }
    } else {
      elt = this$1.parseMaybeAssign(false, refDestructuringErrors);
    }
    elts.push(elt);
  }
  return elts
};

pp$3.checkUnreserved = function(ref) {
  var start = ref.start;
  var end = ref.end;
  var name = ref.name;

  if (this.inGenerator && name === "yield")
    { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); }
  if (this.inAsync && name === "await")
    { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); }
  if (this.isKeyword(name))
    { this.raise(start, ("Unexpected keyword '" + name + "'")); }
  if (this.options.ecmaVersion < 6 &&
    this.input.slice(start, end).indexOf("\\") != -1) { return }
  var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
  if (re.test(name))
    { this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); }
};

// Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into
// identifiers.

pp$3.parseIdent = function(liberal, isBinding) {
  var node = this.startNode();
  if (liberal && this.options.allowReserved == "never") { liberal = false; }
  if (this.type === types.name) {
    node.name = this.value;
  } else if (this.type.keyword) {
    node.name = this.type.keyword;

    // To fix https://github.com/ternjs/acorn/issues/575
    // `class` and `function` keywords push new context into this.context.
    // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
    // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
    if ((node.name === "class" || node.name === "function") &&
        (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
      this.context.pop();
    }
  } else {
    this.unexpected();
  }
  this.next();
  this.finishNode(node, "Identifier");
  if (!liberal) { this.checkUnreserved(node); }
  return node
};

// Parses yield expression inside generator.

pp$3.parseYield = function() {
  if (!this.yieldPos) { this.yieldPos = this.start; }

  var node = this.startNode();
  this.next();
  if (this.type == types.semi || this.canInsertSemicolon() || (this.type != types.star && !this.type.startsExpr)) {
    node.delegate = false;
    node.argument = null;
  } else {
    node.delegate = this.eat(types.star);
    node.argument = this.parseMaybeAssign();
  }
  return this.finishNode(node, "YieldExpression")
};

pp$3.parseAwait = function() {
  if (!this.awaitPos) { this.awaitPos = this.start; }

  var node = this.startNode();
  this.next();
  node.argument = this.parseMaybeUnary(null, true);
  return this.finishNode(node, "AwaitExpression")
};

var pp$4 = Parser.prototype;

// This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
// the location of the error, attaches the position to the end
// of the error message, and then raises a `SyntaxError` with that
// message.

pp$4.raise = function(pos, message) {
  var loc = getLineInfo(this.input, pos);
  message += " (" + loc.line + ":" + loc.column + ")";
  var err = new SyntaxError(message);
  err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
  throw err
};

pp$4.raiseRecoverable = pp$4.raise;

pp$4.curPosition = function() {
  if (this.options.locations) {
    return new Position(this.curLine, this.pos - this.lineStart)
  }
};

var pp$5 = Parser.prototype;

// Object.assign polyfill
var assign = Object.assign || function(target) {
  var sources = [], len = arguments.length - 1;
  while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];

  for (var i = 0, list = sources; i < list.length; i += 1) {
    var source = list[i];

    for (var key in source) {
      if (has(source, key)) {
        target[key] = source[key];
      }
    }
  }
  return target
};

// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.

pp$5.enterFunctionScope = function() {
  // var: a hash of var-declared names in the current lexical scope
  // lexical: a hash of lexically-declared names in the current lexical scope
  // childVar: a hash of var-declared names in all child lexical scopes of the current lexical scope (within the current function scope)
  // parentLexical: a hash of lexically-declared names in all parent lexical scopes of the current lexical scope (within the current function scope)
  this.scopeStack.push({var: {}, lexical: {}, childVar: {}, parentLexical: {}});
};

pp$5.exitFunctionScope = function() {
  this.scopeStack.pop();
};

pp$5.enterLexicalScope = function() {
  var parentScope = this.scopeStack[this.scopeStack.length - 1];
  var childScope = {var: {}, lexical: {}, childVar: {}, parentLexical: {}};

  this.scopeStack.push(childScope);
  assign(childScope.parentLexical, parentScope.lexical, parentScope.parentLexical);
};

pp$5.exitLexicalScope = function() {
  var childScope = this.scopeStack.pop();
  var parentScope = this.scopeStack[this.scopeStack.length - 1];

  assign(parentScope.childVar, childScope.var, childScope.childVar);
};

/**
 * A name can be declared with `var` if there are no variables with the same name declared with `let`/`const`
 * in the current lexical scope or any of the parent lexical scopes in this function.
 */
pp$5.canDeclareVarName = function(name) {
  var currentScope = this.scopeStack[this.scopeStack.length - 1];

  return !has(currentScope.lexical, name) && !has(currentScope.parentLexical, name)
};

/**
 * A name can be declared with `let`/`const` if there are no variables with the same name declared with `let`/`const`
 * in the current scope, and there are no variables with the same name declared with `var` in the current scope or in
 * any child lexical scopes in this function.
 */
pp$5.canDeclareLexicalName = function(name) {
  var currentScope = this.scopeStack[this.scopeStack.length - 1];

  return !has(currentScope.lexical, name) && !has(currentScope.var, name) && !has(currentScope.childVar, name)
};

pp$5.declareVarName = function(name) {
  this.scopeStack[this.scopeStack.length - 1].var[name] = true;
};

pp$5.declareLexicalName = function(name) {
  this.scopeStack[this.scopeStack.length - 1].lexical[name] = true;
};

var Node = function Node(parser, pos, loc) {
  this.type = "";
  this.start = pos;
  this.end = 0;
  if (parser.options.locations)
    { this.loc = new SourceLocation(parser, loc); }
  if (parser.options.directSourceFile)
    { this.sourceFile = parser.options.directSourceFile; }
  if (parser.options.ranges)
    { this.range = [pos, 0]; }
};

// Start an AST node, attaching a start offset.

var pp$6 = Parser.prototype;

pp$6.startNode = function() {
  return new Node(this, this.start, this.startLoc)
};

pp$6.startNodeAt = function(pos, loc) {
  return new Node(this, pos, loc)
};

// Finish an AST node, adding `type` and `end` properties.

function finishNodeAt(node, type, pos, loc) {
  node.type = type;
  node.end = pos;
  if (this.options.locations)
    { node.loc.end = loc; }
  if (this.options.ranges)
    { node.range[1] = pos; }
  return node
}

pp$6.finishNode = function(node, type) {
  return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)
};

// Finish node at given position

pp$6.finishNodeAt = function(node, type, pos, loc) {
  return finishNodeAt.call(this, node, type, pos, loc)
};

// The algorithm used to determine whether a regexp can appear at a
// given point in the program is loosely based on sweet.js' approach.
// See https://github.com/mozilla/sweet.js/wiki/design

var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) {
  this.token = token;
  this.isExpr = !!isExpr;
  this.preserveSpace = !!preserveSpace;
  this.override = override;
  this.generator = !!generator;
};

var types$1 = {
  b_stat: new TokContext("{", false),
  b_expr: new TokContext("{", true),
  b_tmpl: new TokContext("${", false),
  p_stat: new TokContext("(", false),
  p_expr: new TokContext("(", true),
  q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
  f_stat: new TokContext("function", false),
  f_expr: new TokContext("function", true),
  f_expr_gen: new TokContext("function", true, false, null, true),
  f_gen: new TokContext("function", false, false, null, true)
};

var pp$7 = Parser.prototype;

pp$7.initialContext = function() {
  return [types$1.b_stat]
};

pp$7.braceIsBlock = function(prevType) {
  var parent = this.curContext();
  if (parent === types$1.f_expr || parent === types$1.f_stat)
    { return true }
  if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr))
    { return !parent.isExpr }

  // The check for `tt.name && exprAllowed` detects whether we are
  // after a `yield` or `of` construct. See the `updateContext` for
  // `tt.name`.
  if (prevType === types._return || prevType == types.name && this.exprAllowed)
    { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) }
  if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType == types.arrow)
    { return true }
  if (prevType == types.braceL)
    { return parent === types$1.b_stat }
  if (prevType == types._var || prevType == types.name)
    { return false }
  return !this.exprAllowed
};

pp$7.inGeneratorContext = function() {
  var this$1 = this;

  for (var i = this.context.length - 1; i >= 1; i--) {
    var context = this$1.context[i];
    if (context.token === "function")
      { return context.generator }
  }
  return false
};

pp$7.updateContext = function(prevType) {
  var update, type = this.type;
  if (type.keyword && prevType == types.dot)
    { this.exprAllowed = false; }
  else if (update = type.updateContext)
    { update.call(this, prevType); }
  else
    { this.exprAllowed = type.beforeExpr; }
};

// Token-specific context update code

types.parenR.updateContext = types.braceR.updateContext = function() {
  if (this.context.length == 1) {
    this.exprAllowed = true;
    return
  }
  var out = this.context.pop();
  if (out === types$1.b_stat && this.curContext().token === "function") {
    out = this.context.pop();
  }
  this.exprAllowed = !out.isExpr;
};

types.braceL.updateContext = function(prevType) {
  this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr);
  this.exprAllowed = true;
};

types.dollarBraceL.updateContext = function() {
  this.context.push(types$1.b_tmpl);
  this.exprAllowed = true;
};

types.parenL.updateContext = function(prevType) {
  var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while;
  this.context.push(statementParens ? types$1.p_stat : types$1.p_expr);
  this.exprAllowed = true;
};

types.incDec.updateContext = function() {
  // tokExprAllowed stays unchanged
};

types._function.updateContext = types._class.updateContext = function(prevType) {
  if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else &&
      !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat))
    { this.context.push(types$1.f_expr); }
  else
    { this.context.push(types$1.f_stat); }
  this.exprAllowed = false;
};

types.backQuote.updateContext = function() {
  if (this.curContext() === types$1.q_tmpl)
    { this.context.pop(); }
  else
    { this.context.push(types$1.q_tmpl); }
  this.exprAllowed = false;
};

types.star.updateContext = function(prevType) {
  if (prevType == types._function) {
    var index = this.context.length - 1;
    if (this.context[index] === types$1.f_expr)
      { this.context[index] = types$1.f_expr_gen; }
    else
      { this.context[index] = types$1.f_gen; }
  }
  this.exprAllowed = true;
};

types.name.updateContext = function(prevType) {
  var allowed = false;
  if (this.options.ecmaVersion >= 6) {
    if (this.value == "of" && !this.exprAllowed ||
        this.value == "yield" && this.inGeneratorContext())
      { allowed = true; }
  }
  this.exprAllowed = allowed;
};

// Object type used to represent tokens. Note that normally, tokens
// simply exist as properties on the parser object. This is only
// used for the onToken callback and the external tokenizer.

var Token = function Token(p) {
  this.type = p.type;
  this.value = p.value;
  this.start = p.start;
  this.end = p.end;
  if (p.options.locations)
    { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); }
  if (p.options.ranges)
    { this.range = [p.start, p.end]; }
};

// ## Tokenizer

var pp$8 = Parser.prototype;

// Are we running under Rhino?
var isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]";

// Move to the next token

pp$8.next = function() {
  if (this.options.onToken)
    { this.options.onToken(new Token(this)); }

  this.lastTokEnd = this.end;
  this.lastTokStart = this.start;
  this.lastTokEndLoc = this.endLoc;
  this.lastTokStartLoc = this.startLoc;
  this.nextToken();
};

pp$8.getToken = function() {
  this.next();
  return new Token(this)
};

// If we're in an ES6 environment, make parsers iterable
if (typeof Symbol !== "undefined")
  { pp$8[Symbol.iterator] = function() {
    var this$1 = this;

    return {
      next: function () {
        var token = this$1.getToken();
        return {
          done: token.type === types.eof,
          value: token
        }
      }
    }
  }; }

// Toggle strict mode. Re-reads the next number or string to please
// pedantic tests (`"use strict"; 010;` should fail).

pp$8.curContext = function() {
  return this.context[this.context.length - 1]
};

// Read a single token, updating the parser object's token-related
// properties.

pp$8.nextToken = function() {
  var curContext = this.curContext();
  if (!curContext || !curContext.preserveSpace) { this.skipSpace(); }

  this.start = this.pos;
  if (this.options.locations) { this.startLoc = this.curPosition(); }
  if (this.pos >= this.input.length) { return this.finishToken(types.eof) }

  if (curContext.override) { return curContext.override(this) }
  else { this.readToken(this.fullCharCodeAtPos()); }
};

pp$8.readToken = function(code) {
  // Identifier or keyword. '\uXXXX' sequences are allowed in
  // identifiers, so '\' also dispatches to that.
  if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
    { return this.readWord() }

  return this.getTokenFromCode(code)
};

pp$8.fullCharCodeAtPos = function() {
  var code = this.input.charCodeAt(this.pos);
  if (code <= 0xd7ff || code >= 0xe000) { return code }
  var next = this.input.charCodeAt(this.pos + 1);
  return (code << 10) + next - 0x35fdc00
};

pp$8.skipBlockComment = function() {
  var this$1 = this;

  var startLoc = this.options.onComment && this.curPosition();
  var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
  if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); }
  this.pos = end + 2;
  if (this.options.locations) {
    lineBreakG.lastIndex = start;
    var match;
    while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
      ++this$1.curLine;
      this$1.lineStart = match.index + match[0].length;
    }
  }
  if (this.options.onComment)
    { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
                           startLoc, this.curPosition()); }
};

pp$8.skipLineComment = function(startSkip) {
  var this$1 = this;

  var start = this.pos;
  var startLoc = this.options.onComment && this.curPosition();
  var ch = this.input.charCodeAt(this.pos += startSkip);
  while (this.pos < this.input.length && !isNewLine(ch)) {
    ch = this$1.input.charCodeAt(++this$1.pos);
  }
  if (this.options.onComment)
    { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
                           startLoc, this.curPosition()); }
};

// Called at the start of the parse and after every token. Skips
// whitespace and comments, and.

pp$8.skipSpace = function() {
  var this$1 = this;

  loop: while (this.pos < this.input.length) {
    var ch = this$1.input.charCodeAt(this$1.pos);
    switch (ch) {
    case 32: case 160: // ' '
      ++this$1.pos;
      break
    case 13:
      if (this$1.input.charCodeAt(this$1.pos + 1) === 10) {
        ++this$1.pos;
      }
    case 10: case 8232: case 8233:
      ++this$1.pos;
      if (this$1.options.locations) {
        ++this$1.curLine;
        this$1.lineStart = this$1.pos;
      }
      break
    case 47: // '/'
      switch (this$1.input.charCodeAt(this$1.pos + 1)) {
      case 42: // '*'
        this$1.skipBlockComment();
        break
      case 47:
        this$1.skipLineComment(2);
        break
      default:
        break loop
      }
      break
    default:
      if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
        ++this$1.pos;
      } else {
        break loop
      }
    }
  }
};

// Called at the end of every token. Sets `end`, `val`, and
// maintains `context` and `exprAllowed`, and skips the space after
// the token, so that the next one's `start` will point at the
// right position.

pp$8.finishToken = function(type, val) {
  this.end = this.pos;
  if (this.options.locations) { this.endLoc = this.curPosition(); }
  var prevType = this.type;
  this.type = type;
  this.value = val;

  this.updateContext(prevType);
};

// ### Token reading

// This is the function that is called to fetch the next token. It
// is somewhat obscure, because it works in character codes rather
// than characters, and because operator parsing has been inlined
// into it.
//
// All in the name of speed.
//
pp$8.readToken_dot = function() {
  var next = this.input.charCodeAt(this.pos + 1);
  if (next >= 48 && next <= 57) { return this.readNumber(true) }
  var next2 = this.input.charCodeAt(this.pos + 2);
  if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
    this.pos += 3;
    return this.finishToken(types.ellipsis)
  } else {
    ++this.pos;
    return this.finishToken(types.dot)
  }
};

pp$8.readToken_slash = function() { // '/'
  var next = this.input.charCodeAt(this.pos + 1);
  if (this.exprAllowed) { ++this.pos; return this.readRegexp() }
  if (next === 61) { return this.finishOp(types.assign, 2) }
  return this.finishOp(types.slash, 1)
};

pp$8.readToken_mult_modulo_exp = function(code) { // '%*'
  var next = this.input.charCodeAt(this.pos + 1);
  var size = 1;
  var tokentype = code === 42 ? types.star : types.modulo;

  // exponentiation operator ** and **=
  if (this.options.ecmaVersion >= 7 && code == 42 && next === 42) {
    ++size;
    tokentype = types.starstar;
    next = this.input.charCodeAt(this.pos + 2);
  }

  if (next === 61) { return this.finishOp(types.assign, size + 1) }
  return this.finishOp(tokentype, size)
};

pp$8.readToken_pipe_amp = function(code) { // '|&'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) }
  if (next === 61) { return this.finishOp(types.assign, 2) }
  return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1)
};

pp$8.readToken_caret = function() { // '^'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === 61) { return this.finishOp(types.assign, 2) }
  return this.finishOp(types.bitwiseXOR, 1)
};

pp$8.readToken_plus_min = function(code) { // '+-'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === code) {
    if (next == 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 62 &&
        (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
      // A `-->` line comment
      this.skipLineComment(3);
      this.skipSpace();
      return this.nextToken()
    }
    return this.finishOp(types.incDec, 2)
  }
  if (next === 61) { return this.finishOp(types.assign, 2) }
  return this.finishOp(types.plusMin, 1)
};

pp$8.readToken_lt_gt = function(code) { // '<>'
  var next = this.input.charCodeAt(this.pos + 1);
  var size = 1;
  if (next === code) {
    size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
    if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) }
    return this.finishOp(types.bitShift, size)
  }
  if (next == 33 && code == 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) == 45 &&
      this.input.charCodeAt(this.pos + 3) == 45) {
    // `<!--`, an XML-style comment that should be interpreted as a line comment
    this.skipLineComment(4);
    this.skipSpace();
    return this.nextToken()
  }
  if (next === 61) { size = 2; }
  return this.finishOp(types.relational, size)
};

pp$8.readToken_eq_excl = function(code) { // '=!'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) }
  if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
    this.pos += 2;
    return this.finishToken(types.arrow)
  }
  return this.finishOp(code === 61 ? types.eq : types.prefix, 1)
};

pp$8.getTokenFromCode = function(code) {
  switch (code) {
    // The interpretation of a dot depends on whether it is followed
    // by a digit or another two dots.
  case 46: // '.'
    return this.readToken_dot()

    // Punctuation tokens.
  case 40: ++this.pos; return this.finishToken(types.parenL)
  case 41: ++this.pos; return this.finishToken(types.parenR)
  case 59: ++this.pos; return this.finishToken(types.semi)
  case 44: ++this.pos; return this.finishToken(types.comma)
  case 91: ++this.pos; return this.finishToken(types.bracketL)
  case 93: ++this.pos; return this.finishToken(types.bracketR)
  case 123: ++this.pos; return this.finishToken(types.braceL)
  case 125: ++this.pos; return this.finishToken(types.braceR)
  case 58: ++this.pos; return this.finishToken(types.colon)
  case 63: ++this.pos; return this.finishToken(types.question)

  case 96: // '`'
    if (this.options.ecmaVersion < 6) { break }
    ++this.pos;
    return this.finishToken(types.backQuote)

  case 48: // '0'
    var next = this.input.charCodeAt(this.pos + 1);
    if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number
    if (this.options.ecmaVersion >= 6) {
      if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number
      if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number
    }
    // Anything else beginning with a digit is an integer, octal
    // number, or float.
  case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
    return this.readNumber(false)

    // Quotes produce strings.
  case 34: case 39: // '"', "'"
    return this.readString(code)

    // Operators are parsed inline in tiny state machines. '=' (61) is
    // often referred to. `finishOp` simply skips the amount of
    // characters it is given as second argument, and returns a token
    // of the type given by its first argument.

  case 47: // '/'
    return this.readToken_slash()

  case 37: case 42: // '%*'
    return this.readToken_mult_modulo_exp(code)

  case 124: case 38: // '|&'
    return this.readToken_pipe_amp(code)

  case 94: // '^'
    return this.readToken_caret()

  case 43: case 45: // '+-'
    return this.readToken_plus_min(code)

  case 60: case 62: // '<>'
    return this.readToken_lt_gt(code)

  case 61: case 33: // '=!'
    return this.readToken_eq_excl(code)

  case 126: // '~'
    return this.finishOp(types.prefix, 1)
  }

  this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};

pp$8.finishOp = function(type, size) {
  var str = this.input.slice(this.pos, this.pos + size);
  this.pos += size;
  return this.finishToken(type, str)
};

// Parse a regular expression. Some context-awareness is necessary,
// since a '/' inside a '[]' set does not end the expression.

function tryCreateRegexp(src, flags, throwErrorAt, parser) {
  try {
    return new RegExp(src, flags)
  } catch (e) {
    if (throwErrorAt !== undefined) {
      if (e instanceof SyntaxError) { parser.raise(throwErrorAt, "Error parsing regular expression: " + e.message); }
      throw e
    }
  }
}

var regexpUnicodeSupport = !!tryCreateRegexp("\uffff", "u");

pp$8.readRegexp = function() {
  var this$1 = this;

  var escaped, inClass, start = this.pos;
  for (;;) {
    if (this$1.pos >= this$1.input.length) { this$1.raise(start, "Unterminated regular expression"); }
    var ch = this$1.input.charAt(this$1.pos);
    if (lineBreak.test(ch)) { this$1.raise(start, "Unterminated regular expression"); }
    if (!escaped) {
      if (ch === "[") { inClass = true; }
      else if (ch === "]" && inClass) { inClass = false; }
      else if (ch === "/" && !inClass) { break }
      escaped = ch === "\\";
    } else { escaped = false; }
    ++this$1.pos;
  }
  var content = this.input.slice(start, this.pos);
  ++this.pos;
  // Need to use `readWord1` because '\uXXXX' sequences are allowed
  // here (don't ask).
  var mods = this.readWord1();
  var tmp = content, tmpFlags = "";
  if (mods) {
    var validFlags = /^[gim]*$/;
    if (this.options.ecmaVersion >= 6) { validFlags = /^[gimuy]*$/; }
    if (!validFlags.test(mods)) { this.raise(start, "Invalid regular expression flag"); }
    if (mods.indexOf("u") >= 0) {
      if (regexpUnicodeSupport) {
        tmpFlags = "u";
      } else {
        // Replace each astral symbol and every Unicode escape sequence that
        // possibly represents an astral symbol or a paired surrogate with a
        // single ASCII symbol to avoid throwing on regular expressions that
        // are only valid in combination with the `/u` flag.
        // Note: replacing with the ASCII symbol `x` might cause false
        // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
        // perfectly valid pattern that is equivalent to `[a-b]`, but it would
        // be replaced by `[x-b]` which throws an error.
        tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, function (_match, code, offset) {
          code = Number("0x" + code);
          if (code > 0x10FFFF) { this$1.raise(start + offset + 3, "Code point out of bounds"); }
          return "x"
        });
        tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x");
        tmpFlags = tmpFlags.replace("u", "");
      }
    }
  }
  // Detect invalid regular expressions.
  var value = null;
  // Rhino's regular expression parser is flaky and throws uncatchable exceptions,
  // so don't do detection if we are running under Rhino
  if (!isRhino) {
    tryCreateRegexp(tmp, tmpFlags, start, this);
    // Get a regular expression object for this pattern-flag pair, or `null` in
    // case the current environment doesn't support the flags it uses.
    value = tryCreateRegexp(content, mods);
  }
  return this.finishToken(types.regexp, {pattern: content, flags: mods, value: value})
};

// Read an integer in the given radix. Return null if zero digits
// were read, the integer value otherwise. When `len` is given, this
// will return `null` unless the integer has exactly `len` digits.

pp$8.readInt = function(radix, len) {
  var this$1 = this;

  var start = this.pos, total = 0;
  for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
    var code = this$1.input.charCodeAt(this$1.pos), val = (void 0);
    if (code >= 97) { val = code - 97 + 10; } // a
    else if (code >= 65) { val = code - 65 + 10; } // A
    else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9
    else { val = Infinity; }
    if (val >= radix) { break }
    ++this$1.pos;
    total = total * radix + val;
  }
  if (this.pos === start || len != null && this.pos - start !== len) { return null }

  return total
};

pp$8.readRadixNumber = function(radix) {
  this.pos += 2; // 0x
  var val = this.readInt(radix);
  if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); }
  if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }
  return this.finishToken(types.num, val)
};

// Read an integer, octal integer, or floating-point number.

pp$8.readNumber = function(startsWithDot) {
  var start = this.pos, isFloat = false, octal = this.input.charCodeAt(this.pos) === 48;
  if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); }
  if (octal && this.pos == start + 1) { octal = false; }
  var next = this.input.charCodeAt(this.pos);
  if (next === 46 && !octal) { // '.'
    ++this.pos;
    this.readInt(10);
    isFloat = true;
    next = this.input.charCodeAt(this.pos);
  }
  if ((next === 69 || next === 101) && !octal) { // 'eE'
    next = this.input.charCodeAt(++this.pos);
    if (next === 43 || next === 45) { ++this.pos; } // '+-'
    if (this.readInt(10) === null) { this.raise(start, "Invalid number"); }
    isFloat = true;
  }
  if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); }

  var str = this.input.slice(start, this.pos), val;
  if (isFloat) { val = parseFloat(str); }
  else if (!octal || str.length === 1) { val = parseInt(str, 10); }
  else if (this.strict) { this.raise(start, "Invalid number"); }
  else if (/[89]/.test(str)) { val = parseInt(str, 10); }
  else { val = parseInt(str, 8); }
  return this.finishToken(types.num, val)
};

// Read a string value, interpreting backslash-escapes.

pp$8.readCodePoint = function() {
  var ch = this.input.charCodeAt(this.pos), code;

  if (ch === 123) { // '{'
    if (this.options.ecmaVersion < 6) { this.unexpected(); }
    var codePos = ++this.pos;
    code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
    ++this.pos;
    if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); }
  } else {
    code = this.readHexChar(4);
  }
  return code
};

function codePointToString(code) {
  // UTF-16 Decoding
  if (code <= 0xFFFF) { return String.fromCharCode(code) }
  code -= 0x10000;
  return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)
}

pp$8.readString = function(quote) {
  var this$1 = this;

  var out = "", chunkStart = ++this.pos;
  for (;;) {
    if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated string constant"); }
    var ch = this$1.input.charCodeAt(this$1.pos);
    if (ch === quote) { break }
    if (ch === 92) { // '\'
      out += this$1.input.slice(chunkStart, this$1.pos);
      out += this$1.readEscapedChar(false);
      chunkStart = this$1.pos;
    } else {
      if (isNewLine(ch)) { this$1.raise(this$1.start, "Unterminated string constant"); }
      ++this$1.pos;
    }
  }
  out += this.input.slice(chunkStart, this.pos++);
  return this.finishToken(types.string, out)
};

// Reads template string tokens.

var INVALID_TEMPLATE_ESCAPE_ERROR = {};

pp$8.tryReadTemplateToken = function() {
  this.inTemplateElement = true;
  try {
    this.readTmplToken();
  } catch (err) {
    if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
      this.readInvalidTemplateToken();
    } else {
      throw err
    }
  }

  this.inTemplateElement = false;
};

pp$8.invalidStringToken = function(position, message) {
  if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
    throw INVALID_TEMPLATE_ESCAPE_ERROR
  } else {
    this.raise(position, message);
  }
};

pp$8.readTmplToken = function() {
  var this$1 = this;

  var out = "", chunkStart = this.pos;
  for (;;) {
    if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated template"); }
    var ch = this$1.input.charCodeAt(this$1.pos);
    if (ch === 96 || ch === 36 && this$1.input.charCodeAt(this$1.pos + 1) === 123) { // '`', '${'
      if (this$1.pos === this$1.start && (this$1.type === types.template || this$1.type === types.invalidTemplate)) {
        if (ch === 36) {
          this$1.pos += 2;
          return this$1.finishToken(types.dollarBraceL)
        } else {
          ++this$1.pos;
          return this$1.finishToken(types.backQuote)
        }
      }
      out += this$1.input.slice(chunkStart, this$1.pos);
      return this$1.finishToken(types.template, out)
    }
    if (ch === 92) { // '\'
      out += this$1.input.slice(chunkStart, this$1.pos);
      out += this$1.readEscapedChar(true);
      chunkStart = this$1.pos;
    } else if (isNewLine(ch)) {
      out += this$1.input.slice(chunkStart, this$1.pos);
      ++this$1.pos;
      switch (ch) {
      case 13:
        if (this$1.input.charCodeAt(this$1.pos) === 10) { ++this$1.pos; }
      case 10:
        out += "\n";
        break
      default:
        out += String.fromCharCode(ch);
        break
      }
      if (this$1.options.locations) {
        ++this$1.curLine;
        this$1.lineStart = this$1.pos;
      }
      chunkStart = this$1.pos;
    } else {
      ++this$1.pos;
    }
  }
};

// Reads a template token to search for the end, without validating any escape sequences
pp$8.readInvalidTemplateToken = function() {
  var this$1 = this;

  for (; this.pos < this.input.length; this.pos++) {
    switch (this$1.input[this$1.pos]) {
    case "\\":
      ++this$1.pos;
      break

    case "$":
      if (this$1.input[this$1.pos + 1] !== "{") {
        break
      }
    // falls through

    case "`":
      return this$1.finishToken(types.invalidTemplate, this$1.input.slice(this$1.start, this$1.pos))

    // no default
    }
  }
  this.raise(this.start, "Unterminated template");
};

// Used to read escaped characters

pp$8.readEscapedChar = function(inTemplate) {
  var ch = this.input.charCodeAt(++this.pos);
  ++this.pos;
  switch (ch) {
  case 110: return "\n" // 'n' -> '\n'
  case 114: return "\r" // 'r' -> '\r'
  case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
  case 117: return codePointToString(this.readCodePoint()) // 'u'
  case 116: return "\t" // 't' -> '\t'
  case 98: return "\b" // 'b' -> '\b'
  case 118: return "\u000b" // 'v' -> '\u000b'
  case 102: return "\f" // 'f' -> '\f'
  case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n'
  case 10: // ' \n'
    if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
    return ""
  default:
    if (ch >= 48 && ch <= 55) {
      var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
      var octal = parseInt(octalStr, 8);
      if (octal > 255) {
        octalStr = octalStr.slice(0, -1);
        octal = parseInt(octalStr, 8);
      }
      if (octalStr !== "0" && (this.strict || inTemplate)) {
        this.invalidStringToken(this.pos - 2, "Octal literal in strict mode");
      }
      this.pos += octalStr.length - 1;
      return String.fromCharCode(octal)
    }
    return String.fromCharCode(ch)
  }
};

// Used to read character escape sequences ('\x', '\u', '\U').

pp$8.readHexChar = function(len) {
  var codePos = this.pos;
  var n = this.readInt(16, len);
  if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); }
  return n
};

// Read an identifier, and return it as a string. Sets `this.containsEsc`
// to whether the word contained a '\u' escape.
//
// Incrementally adds only escaped chars, adding other chunks as-is
// as a micro-optimization.

pp$8.readWord1 = function() {
  var this$1 = this;

  this.containsEsc = false;
  var word = "", first = true, chunkStart = this.pos;
  var astral = this.options.ecmaVersion >= 6;
  while (this.pos < this.input.length) {
    var ch = this$1.fullCharCodeAtPos();
    if (isIdentifierChar(ch, astral)) {
      this$1.pos += ch <= 0xffff ? 1 : 2;
    } else if (ch === 92) { // "\"
      this$1.containsEsc = true;
      word += this$1.input.slice(chunkStart, this$1.pos);
      var escStart = this$1.pos;
      if (this$1.input.charCodeAt(++this$1.pos) != 117) // "u"
        { this$1.invalidStringToken(this$1.pos, "Expecting Unicode escape sequence \\uXXXX"); }
      ++this$1.pos;
      var esc = this$1.readCodePoint();
      if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
        { this$1.invalidStringToken(escStart, "Invalid Unicode escape"); }
      word += codePointToString(esc);
      chunkStart = this$1.pos;
    } else {
      break
    }
    first = false;
  }
  return word + this.input.slice(chunkStart, this.pos)
};

// Read an identifier or keyword token. Will check for reserved
// words when necessary.

pp$8.readWord = function() {
  var word = this.readWord1();
  var type = types.name;
  if (this.keywords.test(word)) {
    if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); }
    type = keywords$1[word];
  }
  return this.finishToken(type, word)
};

// Acorn is a tiny, fast JavaScript parser written in JavaScript.
//
// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
// various contributors and released under an MIT license.
//
// Git repositories for Acorn are available at
//
//     http://marijnhaverbeke.nl/git/acorn
//     https://github.com/ternjs/acorn.git
//
// Please use the [github bug tracker][ghbt] to report issues.
//
// [ghbt]: https://github.com/ternjs/acorn/issues
//
// This file defines the main parser interface. The library also comes
// with a [error-tolerant parser][dammit] and an
// [abstract syntax tree walker][walk], defined in other files.
//
// [dammit]: acorn_loose.js
// [walk]: util/walk.js

var version = "5.2.1";

// The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and
// returns an abstract syntax tree as specified by [Mozilla parser
// API][api].
//
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API

function parse(input, options) {
  return new Parser(options, input).parse()
}

// This function tries to parse a single expression at a given
// offset in a string. Useful for parsing mixed-language formats
// that embed JavaScript expressions.

function parseExpressionAt(input, pos, options) {
  var p = new Parser(options, input, pos);
  p.nextToken();
  return p.parseExpression()
}

// Acorn is organized as a tokenizer and a recursive-descent parser.
// The `tokenizer` export provides an interface to the tokenizer.

function tokenizer(input, options) {
  return new Parser(options, input)
}

// This is a terrible kludge to support the existing, pre-ES6
// interface where the loose parser module retroactively adds exports
// to this module.
 // eslint-disable-line camelcase
function addLooseExports(parse, Parser$$1, plugins$$1) {
  exports.parse_dammit = parse; // eslint-disable-line camelcase
  exports.LooseParser = Parser$$1;
  exports.pluginsLoose = plugins$$1;
}

exports.version = version;
exports.parse = parse;
exports.parseExpressionAt = parseExpressionAt;
exports.tokenizer = tokenizer;
exports.addLooseExports = addLooseExports;
exports.Parser = Parser;
exports.plugins = plugins;
exports.defaultOptions = defaultOptions;
exports.Position = Position;
exports.SourceLocation = SourceLocation;
exports.getLineInfo = getLineInfo;
exports.Node = Node;
exports.TokenType = TokenType;
exports.tokTypes = types;
exports.keywordTypes = keywords$1;
exports.TokContext = TokContext;
exports.tokContexts = types$1;
exports.isIdentifierChar = isIdentifierChar;
exports.isIdentifierStart = isIdentifierStart;
exports.Token = Token;
exports.isNewLine = isNewLine;
exports.lineBreak = lineBreak;
exports.lineBreakG = lineBreakG;
exports.nonASCIIwhitespace = nonASCIIwhitespace;

Object.defineProperty(exports, '__esModule', { value: true });

})));
;
  (function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
	typeof define === 'function' && define.amd ? define(['exports'], factory) :
	(factory((global.acorn = global.acorn || {}, global.acorn.walk = global.acorn.walk || {})));
}(this, (function (exports) { 'use strict';

// AST walker module for Mozilla Parser API compatible trees

// A simple walk is one where you simply specify callbacks to be
// called on specific nodes. The last two arguments are optional. A
// simple use would be
//
//     walk.simple(myTree, {
//         Expression: function(node) { ... }
//     });
//
// to do something with all expressions. All Parser API node types
// can be used to identify node types, as well as Expression,
// Statement, and ScopeBody, which denote categories of nodes.
//
// The base argument can be used to pass a custom (recursive)
// walker, and state can be used to give this walked an initial
// state.

function simple(node, visitors, base, state, override) {
  if (!base) { base = exports.base
  ; }(function c(node, st, override) {
    var type = override || node.type, found = visitors[type];
    base[type](node, st, c);
    if (found) { found(node, st); }
  })(node, state, override);
}

// An ancestor walk keeps an array of ancestor nodes (including the
// current node) and passes them to the callback as third parameter
// (and also as state parameter when no other state is present).
function ancestor(node, visitors, base, state) {
  if (!base) { base = exports.base; }
  var ancestors = [];(function c(node, st, override) {
    var type = override || node.type, found = visitors[type];
    var isNew = node != ancestors[ancestors.length - 1];
    if (isNew) { ancestors.push(node); }
    base[type](node, st, c);
    if (found) { found(node, st || ancestors, ancestors); }
    if (isNew) { ancestors.pop(); }
  })(node, state);
}

// A recursive walk is one where your functions override the default
// walkers. They can modify and replace the state parameter that's
// threaded through the walk, and can opt how and whether to walk
// their child nodes (by calling their third argument on these
// nodes).
function recursive(node, state, funcs, base, override) {
  var visitor = funcs ? exports.make(funcs, base) : base;(function c(node, st, override) {
    visitor[override || node.type](node, st, c);
  })(node, state, override);
}

function makeTest(test) {
  if (typeof test == "string")
    { return function (type) { return type == test; } }
  else if (!test)
    { return function () { return true; } }
  else
    { return test }
}

var Found = function Found(node, state) { this.node = node; this.state = state; };

// A full walk triggers the callback on each node
function full(node, callback, base, state, override) {
  if (!base) { base = exports.base
  ; }(function c(node, st, override) {
    var type = override || node.type;
    base[type](node, st, c);
    if (!override) { callback(node, st, type); }
  })(node, state, override);
}

// An fullAncestor walk is like an ancestor walk, but triggers
// the callback on each node
function fullAncestor(node, callback, base, state) {
  if (!base) { base = exports.base; }
  var ancestors = [];(function c(node, st, override) {
    var type = override || node.type;
    var isNew = node != ancestors[ancestors.length - 1];
    if (isNew) { ancestors.push(node); }
    base[type](node, st, c);
    if (!override) { callback(node, st || ancestors, ancestors, type); }
    if (isNew) { ancestors.pop(); }
  })(node, state);
}

// Find a node with a given start, end, and type (all are optional,
// null can be used as wildcard). Returns a {node, state} object, or
// undefined when it doesn't find a matching node.
function findNodeAt(node, start, end, test, base, state) {
  test = makeTest(test);
  if (!base) { base = exports.base; }
  try {
    (function c(node, st, override) {
      var type = override || node.type;
      if ((start == null || node.start <= start) &&
          (end == null || node.end >= end))
        { base[type](node, st, c); }
      if ((start == null || node.start == start) &&
          (end == null || node.end == end) &&
          test(type, node))
        { throw new Found(node, st) }
    })(node, state);
  } catch (e) {
    if (e instanceof Found) { return e }
    throw e
  }
}

// Find the innermost node of a given type that contains the given
// position. Interface similar to findNodeAt.
function findNodeAround(node, pos, test, base, state) {
  test = makeTest(test);
  if (!base) { base = exports.base; }
  try {
    (function c(node, st, override) {
      var type = override || node.type;
      if (node.start > pos || node.end < pos) { return }
      base[type](node, st, c);
      if (test(type, node)) { throw new Found(node, st) }
    })(node, state);
  } catch (e) {
    if (e instanceof Found) { return e }
    throw e
  }
}

// Find the outermost matching node after a given position.
function findNodeAfter(node, pos, test, base, state) {
  test = makeTest(test);
  if (!base) { base = exports.base; }
  try {
    (function c(node, st, override) {
      if (node.end < pos) { return }
      var type = override || node.type;
      if (node.start >= pos && test(type, node)) { throw new Found(node, st) }
      base[type](node, st, c);
    })(node, state);
  } catch (e) {
    if (e instanceof Found) { return e }
    throw e
  }
}

// Find the outermost matching node before a given position.
function findNodeBefore(node, pos, test, base, state) {
  test = makeTest(test);
  if (!base) { base = exports.base; }
  var max;(function c(node, st, override) {
    if (node.start > pos) { return }
    var type = override || node.type;
    if (node.end <= pos && (!max || max.node.end < node.end) && test(type, node))
      { max = new Found(node, st); }
    base[type](node, st, c);
  })(node, state);
  return max
}

// Fallback to an Object.create polyfill for older environments.
var create = Object.create || function(proto) {
  function Ctor() {}
  Ctor.prototype = proto;
  return new Ctor
};

// Used to create a custom walker. Will fill in all missing node
// type properties with the defaults.
function make(funcs, base) {
  if (!base) { base = exports.base; }
  var visitor = create(base);
  for (var type in funcs) { visitor[type] = funcs[type]; }
  return visitor
}

function skipThrough(node, st, c) { c(node, st); }
function ignore(_node, _st, _c) {}

// Node walkers.

var base = {};

base.Program = base.BlockStatement = function (node, st, c) {
  for (var i = 0, list = node.body; i < list.length; i += 1)
    {
    var stmt = list[i];

    c(stmt, st, "Statement");
  }
};
base.Statement = skipThrough;
base.EmptyStatement = ignore;
base.ExpressionStatement = base.ParenthesizedExpression =
  function (node, st, c) { return c(node.expression, st, "Expression"); };
base.IfStatement = function (node, st, c) {
  c(node.test, st, "Expression");
  c(node.consequent, st, "Statement");
  if (node.alternate) { c(node.alternate, st, "Statement"); }
};
base.LabeledStatement = function (node, st, c) { return c(node.body, st, "Statement"); };
base.BreakStatement = base.ContinueStatement = ignore;
base.WithStatement = function (node, st, c) {
  c(node.object, st, "Expression");
  c(node.body, st, "Statement");
};
base.SwitchStatement = function (node, st, c) {
  c(node.discriminant, st, "Expression");
  for (var i = 0, list = node.cases; i < list.length; i += 1) {
    var cs = list[i];

    if (cs.test) { c(cs.test, st, "Expression"); }
    for (var i$1 = 0, list$1 = cs.consequent; i$1 < list$1.length; i$1 += 1)
      {
      var cons = list$1[i$1];

      c(cons, st, "Statement");
    }
  }
};
base.ReturnStatement = base.YieldExpression = base.AwaitExpression = function (node, st, c) {
  if (node.argument) { c(node.argument, st, "Expression"); }
};
base.ThrowStatement = base.SpreadElement =
  function (node, st, c) { return c(node.argument, st, "Expression"); };
base.TryStatement = function (node, st, c) {
  c(node.block, st, "Statement");
  if (node.handler) { c(node.handler, st); }
  if (node.finalizer) { c(node.finalizer, st, "Statement"); }
};
base.CatchClause = function (node, st, c) {
  c(node.param, st, "Pattern");
  c(node.body, st, "ScopeBody");
};
base.WhileStatement = base.DoWhileStatement = function (node, st, c) {
  c(node.test, st, "Expression");
  c(node.body, st, "Statement");
};
base.ForStatement = function (node, st, c) {
  if (node.init) { c(node.init, st, "ForInit"); }
  if (node.test) { c(node.test, st, "Expression"); }
  if (node.update) { c(node.update, st, "Expression"); }
  c(node.body, st, "Statement");
};
base.ForInStatement = base.ForOfStatement = function (node, st, c) {
  c(node.left, st, "ForInit");
  c(node.right, st, "Expression");
  c(node.body, st, "Statement");
};
base.ForInit = function (node, st, c) {
  if (node.type == "VariableDeclaration") { c(node, st); }
  else { c(node, st, "Expression"); }
};
base.DebuggerStatement = ignore;

base.FunctionDeclaration = function (node, st, c) { return c(node, st, "Function"); };
base.VariableDeclaration = function (node, st, c) {
  for (var i = 0, list = node.declarations; i < list.length; i += 1)
    {
    var decl = list[i];

    c(decl, st);
  }
};
base.VariableDeclarator = function (node, st, c) {
  c(node.id, st, "Pattern");
  if (node.init) { c(node.init, st, "Expression"); }
};

base.Function = function (node, st, c) {
  if (node.id) { c(node.id, st, "Pattern"); }
  for (var i = 0, list = node.params; i < list.length; i += 1)
    {
    var param = list[i];

    c(param, st, "Pattern");
  }
  c(node.body, st, node.expression ? "ScopeExpression" : "ScopeBody");
};
// FIXME drop these node types in next major version
// (They are awkward, and in ES6 every block can be a scope.)
base.ScopeBody = function (node, st, c) { return c(node, st, "Statement"); };
base.ScopeExpression = function (node, st, c) { return c(node, st, "Expression"); };

base.Pattern = function (node, st, c) {
  if (node.type == "Identifier")
    { c(node, st, "VariablePattern"); }
  else if (node.type == "MemberExpression")
    { c(node, st, "MemberPattern"); }
  else
    { c(node, st); }
};
base.VariablePattern = ignore;
base.MemberPattern = skipThrough;
base.RestElement = function (node, st, c) { return c(node.argument, st, "Pattern"); };
base.ArrayPattern = function (node, st, c) {
  for (var i = 0, list = node.elements; i < list.length; i += 1) {
    var elt = list[i];

    if (elt) { c(elt, st, "Pattern"); }
  }
};
base.ObjectPattern = function (node, st, c) {
  for (var i = 0, list = node.properties; i < list.length; i += 1)
    {
    var prop = list[i];

    c(prop.value, st, "Pattern");
  }
};

base.Expression = skipThrough;
base.ThisExpression = base.Super = base.MetaProperty = ignore;
base.ArrayExpression = function (node, st, c) {
  for (var i = 0, list = node.elements; i < list.length; i += 1) {
    var elt = list[i];

    if (elt) { c(elt, st, "Expression"); }
  }
};
base.ObjectExpression = function (node, st, c) {
  for (var i = 0, list = node.properties; i < list.length; i += 1)
    {
    var prop = list[i];

    c(prop, st);
  }
};
base.FunctionExpression = base.ArrowFunctionExpression = base.FunctionDeclaration;
base.SequenceExpression = base.TemplateLiteral = function (node, st, c) {
  for (var i = 0, list = node.expressions; i < list.length; i += 1)
    {
    var expr = list[i];

    c(expr, st, "Expression");
  }
};
base.UnaryExpression = base.UpdateExpression = function (node, st, c) {
  c(node.argument, st, "Expression");
};
base.BinaryExpression = base.LogicalExpression = function (node, st, c) {
  c(node.left, st, "Expression");
  c(node.right, st, "Expression");
};
base.AssignmentExpression = base.AssignmentPattern = function (node, st, c) {
  c(node.left, st, "Pattern");
  c(node.right, st, "Expression");
};
base.ConditionalExpression = function (node, st, c) {
  c(node.test, st, "Expression");
  c(node.consequent, st, "Expression");
  c(node.alternate, st, "Expression");
};
base.NewExpression = base.CallExpression = function (node, st, c) {
  c(node.callee, st, "Expression");
  if (node.arguments)
    { for (var i = 0, list = node.arguments; i < list.length; i += 1)
      {
        var arg = list[i];

        c(arg, st, "Expression");
      } }
};
base.MemberExpression = function (node, st, c) {
  c(node.object, st, "Expression");
  if (node.computed) { c(node.property, st, "Expression"); }
};
base.ExportNamedDeclaration = base.ExportDefaultDeclaration = function (node, st, c) {
  if (node.declaration)
    { c(node.declaration, st, node.type == "ExportNamedDeclaration" || node.declaration.id ? "Statement" : "Expression"); }
  if (node.source) { c(node.source, st, "Expression"); }
};
base.ExportAllDeclaration = function (node, st, c) {
  c(node.source, st, "Expression");
};
base.ImportDeclaration = function (node, st, c) {
  for (var i = 0, list = node.specifiers; i < list.length; i += 1)
    {
    var spec = list[i];

    c(spec, st);
  }
  c(node.source, st, "Expression");
};
base.ImportSpecifier = base.ImportDefaultSpecifier = base.ImportNamespaceSpecifier = base.Identifier = base.Literal = ignore;

base.TaggedTemplateExpression = function (node, st, c) {
  c(node.tag, st, "Expression");
  c(node.quasi, st);
};
base.ClassDeclaration = base.ClassExpression = function (node, st, c) { return c(node, st, "Class"); };
base.Class = function (node, st, c) {
  if (node.id) { c(node.id, st, "Pattern"); }
  if (node.superClass) { c(node.superClass, st, "Expression"); }
  for (var i = 0, list = node.body.body; i < list.length; i += 1)
    {
    var item = list[i];

    c(item, st);
  }
};
base.MethodDefinition = base.Property = function (node, st, c) {
  if (node.computed) { c(node.key, st, "Expression"); }
  c(node.value, st, "Expression");
};

exports.simple = simple;
exports.ancestor = ancestor;
exports.recursive = recursive;
exports.full = full;
exports.fullAncestor = fullAncestor;
exports.findNodeAt = findNodeAt;
exports.findNodeAround = findNodeAround;
exports.findNodeAfter = findNodeAfter;
exports.findNodeBefore = findNodeBefore;
exports.make = make;
exports.base = base;

Object.defineProperty(exports, '__esModule', { value: true });

})));

  (function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('./acorn')) :
	typeof define === 'function' && define.amd ? define(['exports', './acorn'], factory) :
	(factory((global.acorn = global.acorn || {}, global.acorn.loose = global.acorn.loose || {}),global.acorn));
}(this, (function (exports,__acorn) { 'use strict';

// Registered plugins
var pluginsLoose = {};

var LooseParser = function LooseParser(input, options) {
  if ( options === void 0 ) options = {};

  this.toks = __acorn.tokenizer(input, options);
  this.options = this.toks.options;
  this.input = this.toks.input;
  this.tok = this.last = {type: __acorn.tokTypes.eof, start: 0, end: 0};
  if (this.options.locations) {
    var here = this.toks.curPosition();
    this.tok.loc = new __acorn.SourceLocation(this.toks, here, here);
  }
  this.ahead = []; // Tokens ahead
  this.context = []; // Indentation contexted
  this.curIndent = 0;
  this.curLineStart = 0;
  this.nextLineStart = this.lineEnd(this.curLineStart) + 1;
  this.inAsync = false;
  // Load plugins
  this.options.pluginsLoose = options.pluginsLoose || {};
  this.loadPlugins(this.options.pluginsLoose);
};

LooseParser.prototype.startNode = function startNode () {
  return new __acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null)
};

LooseParser.prototype.storeCurrentPos = function storeCurrentPos () {
  return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start
};

LooseParser.prototype.startNodeAt = function startNodeAt (pos) {
  if (this.options.locations) {
    return new __acorn.Node(this.toks, pos[0], pos[1])
  } else {
    return new __acorn.Node(this.toks, pos)
  }
};

LooseParser.prototype.finishNode = function finishNode (node, type) {
  node.type = type;
  node.end = this.last.end;
  if (this.options.locations)
    { node.loc.end = this.last.loc.end; }
  if (this.options.ranges)
    { node.range[1] = this.last.end; }
  return node
};

LooseParser.prototype.dummyNode = function dummyNode (type) {
  var dummy = this.startNode();
  dummy.type = type;
  dummy.end = dummy.start;
  if (this.options.locations)
    { dummy.loc.end = dummy.loc.start; }
  if (this.options.ranges)
    { dummy.range[1] = dummy.start; }
  this.last = {type: __acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc};
  return dummy
};

LooseParser.prototype.dummyIdent = function dummyIdent () {
  var dummy = this.dummyNode("Identifier");
  dummy.name = "✖";
  return dummy
};

LooseParser.prototype.dummyString = function dummyString () {
  var dummy = this.dummyNode("Literal");
  dummy.value = dummy.raw = "✖";
  return dummy
};

LooseParser.prototype.eat = function eat (type) {
  if (this.tok.type === type) {
    this.next();
    return true
  } else {
    return false
  }
};

LooseParser.prototype.isContextual = function isContextual (name) {
  return this.tok.type === __acorn.tokTypes.name && this.tok.value === name
};

LooseParser.prototype.eatContextual = function eatContextual (name) {
  return this.tok.value === name && this.eat(__acorn.tokTypes.name)
};

LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () {
  return this.tok.type === __acorn.tokTypes.eof || this.tok.type === __acorn.tokTypes.braceR ||
    __acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start))
};

LooseParser.prototype.semicolon = function semicolon () {
  return this.eat(__acorn.tokTypes.semi)
};

LooseParser.prototype.expect = function expect (type) {
    var this$1 = this;

  if (this.eat(type)) { return true }
  for (var i = 1; i <= 2; i++) {
    if (this$1.lookAhead(i).type == type) {
      for (var j = 0; j < i; j++) { this$1.next(); }
      return true
    }
  }
};

LooseParser.prototype.pushCx = function pushCx () {
  this.context.push(this.curIndent);
};

LooseParser.prototype.popCx = function popCx () {
  this.curIndent = this.context.pop();
};

LooseParser.prototype.lineEnd = function lineEnd (pos) {
  while (pos < this.input.length && !__acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; }
  return pos
};

LooseParser.prototype.indentationAfter = function indentationAfter (pos) {
    var this$1 = this;

  for (var count = 0;; ++pos) {
    var ch = this$1.input.charCodeAt(pos);
    if (ch === 32) { ++count; }
    else if (ch === 9) { count += this$1.options.tabSize; }
    else { return count }
  }
};

LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) {
  if (this.tok.type === closeTok || this.tok.type === __acorn.tokTypes.eof) { return true }
  return line != this.curLineStart && this.curIndent < indent && this.tokenStartsLine() &&
    (!blockHeuristic || this.nextLineStart >= this.input.length ||
     this.indentationAfter(this.nextLineStart) < indent)
};

LooseParser.prototype.tokenStartsLine = function tokenStartsLine () {
    var this$1 = this;

  for (var p = this.tok.start - 1; p >= this.curLineStart; --p) {
    var ch = this$1.input.charCodeAt(p);
    if (ch !== 9 && ch !== 32) { return false }
  }
  return true
};

LooseParser.prototype.extend = function extend (name, f) {
  this[name] = f(this[name]);
};

LooseParser.prototype.loadPlugins = function loadPlugins (pluginConfigs) {
    var this$1 = this;

  for (var name in pluginConfigs) {
    var plugin = pluginsLoose[name];
    if (!plugin) { throw new Error("Plugin '" + name + "' not found") }
    plugin(this$1, pluginConfigs[name]);
  }
};

LooseParser.prototype.parse = function parse () {
  this.next();
  return this.parseTopLevel()
};

var lp = LooseParser.prototype;

function isSpace(ch) {
  return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || __acorn.isNewLine(ch)
}

lp.next = function() {
  var this$1 = this;

  this.last = this.tok;
  if (this.ahead.length)
    { this.tok = this.ahead.shift(); }
  else
    { this.tok = this.readToken(); }

  if (this.tok.start >= this.nextLineStart) {
    while (this.tok.start >= this.nextLineStart) {
      this$1.curLineStart = this$1.nextLineStart;
      this$1.nextLineStart = this$1.lineEnd(this$1.curLineStart) + 1;
    }
    this.curIndent = this.indentationAfter(this.curLineStart);
  }
};

lp.readToken = function() {
  var this$1 = this;

  for (;;) {
    try {
      this$1.toks.next();
      if (this$1.toks.type === __acorn.tokTypes.dot &&
          this$1.input.substr(this$1.toks.end, 1) === "." &&
          this$1.options.ecmaVersion >= 6) {
        this$1.toks.end++;
        this$1.toks.type = __acorn.tokTypes.ellipsis;
      }
      return new __acorn.Token(this$1.toks)
    } catch (e) {
      if (!(e instanceof SyntaxError)) { throw e }

      // Try to skip some text, based on the error message, and then continue
      var msg = e.message, pos = e.raisedAt, replace = true;
      if (/unterminated/i.test(msg)) {
        pos = this$1.lineEnd(e.pos + 1);
        if (/string/.test(msg)) {
          replace = {start: e.pos, end: pos, type: __acorn.tokTypes.string, value: this$1.input.slice(e.pos + 1, pos)};
        } else if (/regular expr/i.test(msg)) {
          var re = this$1.input.slice(e.pos, pos);
          try { re = new RegExp(re); } catch (e) { /* ignore compilation error due to new syntax */ }
          replace = {start: e.pos, end: pos, type: __acorn.tokTypes.regexp, value: re};
        } else if (/template/.test(msg)) {
          replace = {
            start: e.pos,
            end: pos,
            type: __acorn.tokTypes.template,
            value: this$1.input.slice(e.pos, pos)
          };
        } else {
          replace = false;
        }
      } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) {
        while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) { ++pos; }
      } else if (/character escape|expected hexadecimal/i.test(msg)) {
        while (pos < this.input.length) {
          var ch = this$1.input.charCodeAt(pos++);
          if (ch === 34 || ch === 39 || __acorn.isNewLine(ch)) { break }
        }
      } else if (/unexpected character/i.test(msg)) {
        pos++;
        replace = false;
      } else if (/regular expression/i.test(msg)) {
        replace = true;
      } else {
        throw e
      }
      this$1.resetTo(pos);
      if (replace === true) { replace = {start: pos, end: pos, type: __acorn.tokTypes.name, value: "✖"}; }
      if (replace) {
        if (this$1.options.locations)
          { replace.loc = new __acorn.SourceLocation(
            this$1.toks,
            __acorn.getLineInfo(this$1.input, replace.start),
            __acorn.getLineInfo(this$1.input, replace.end)); }
        return replace
      }
    }
  }
};

lp.resetTo = function(pos) {
  var this$1 = this;

  this.toks.pos = pos;
  var ch = this.input.charAt(pos - 1);
  this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) ||
    /[enwfd]/.test(ch) &&
    /\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(this.input.slice(pos - 10, pos));

  if (this.options.locations) {
    this.toks.curLine = 1;
    this.toks.lineStart = __acorn.lineBreakG.lastIndex = 0;
    var match;
    while ((match = __acorn.lineBreakG.exec(this.input)) && match.index < pos) {
      ++this$1.toks.curLine;
      this$1.toks.lineStart = match.index + match[0].length;
    }
  }
};

lp.lookAhead = function(n) {
  var this$1 = this;

  while (n > this.ahead.length)
    { this$1.ahead.push(this$1.readToken()); }
  return this.ahead[n - 1]
};

function isDummy(node) { return node.name == "✖" }

var lp$1 = LooseParser.prototype;

lp$1.parseTopLevel = function() {
  var this$1 = this;

  var node = this.startNodeAt(this.options.locations ? [0, __acorn.getLineInfo(this.input, 0)] : 0);
  node.body = [];
  while (this.tok.type !== __acorn.tokTypes.eof) { node.body.push(this$1.parseStatement()); }
  this.toks.adaptDirectivePrologue(node.body);
  this.last = this.tok;
  if (this.options.ecmaVersion >= 6) {
    node.sourceType = this.options.sourceType;
  }
  return this.finishNode(node, "Program")
};

lp$1.parseStatement = function() {
  var this$1 = this;

  var starttype = this.tok.type, node = this.startNode(), kind;

  if (this.toks.isLet()) {
    starttype = __acorn.tokTypes._var;
    kind = "let";
  }

  switch (starttype) {
  case __acorn.tokTypes._break: case __acorn.tokTypes._continue:
    this.next();
    var isBreak = starttype === __acorn.tokTypes._break;
    if (this.semicolon() || this.canInsertSemicolon()) {
      node.label = null;
    } else {
      node.label = this.tok.type === __acorn.tokTypes.name ? this.parseIdent() : null;
      this.semicolon();
    }
    return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")

  case __acorn.tokTypes._debugger:
    this.next();
    this.semicolon();
    return this.finishNode(node, "DebuggerStatement")

  case __acorn.tokTypes._do:
    this.next();
    node.body = this.parseStatement();
    node.test = this.eat(__acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent();
    this.semicolon();
    return this.finishNode(node, "DoWhileStatement")

  case __acorn.tokTypes._for:
    this.next();
    this.pushCx();
    this.expect(__acorn.tokTypes.parenL);
    if (this.tok.type === __acorn.tokTypes.semi) { return this.parseFor(node, null) }
    var isLet = this.toks.isLet();
    if (isLet || this.tok.type === __acorn.tokTypes._var || this.tok.type === __acorn.tokTypes._const) {
      var init$1 = this.parseVar(true, isLet ? "let" : this.tok.value);
      if (init$1.declarations.length === 1 && (this.tok.type === __acorn.tokTypes._in || this.isContextual("of"))) {
        return this.parseForIn(node, init$1)
      }
      return this.parseFor(node, init$1)
    }
    var init = this.parseExpression(true);
    if (this.tok.type === __acorn.tokTypes._in || this.isContextual("of"))
      { return this.parseForIn(node, this.toAssignable(init)) }
    return this.parseFor(node, init)

  case __acorn.tokTypes._function:
    this.next();
    return this.parseFunction(node, true)

  case __acorn.tokTypes._if:
    this.next();
    node.test = this.parseParenExpression();
    node.consequent = this.parseStatement();
    node.alternate = this.eat(__acorn.tokTypes._else) ? this.parseStatement() : null;
    return this.finishNode(node, "IfStatement")

  case __acorn.tokTypes._return:
    this.next();
    if (this.eat(__acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; }
    else { node.argument = this.parseExpression(); this.semicolon(); }
    return this.finishNode(node, "ReturnStatement")

  case __acorn.tokTypes._switch:
    var blockIndent = this.curIndent, line = this.curLineStart;
    this.next();
    node.discriminant = this.parseParenExpression();
    node.cases = [];
    this.pushCx();
    this.expect(__acorn.tokTypes.braceL);

    var cur;
    while (!this.closes(__acorn.tokTypes.braceR, blockIndent, line, true)) {
      if (this$1.tok.type === __acorn.tokTypes._case || this$1.tok.type === __acorn.tokTypes._default) {
        var isCase = this$1.tok.type === __acorn.tokTypes._case;
        if (cur) { this$1.finishNode(cur, "SwitchCase"); }
        node.cases.push(cur = this$1.startNode());
        cur.consequent = [];
        this$1.next();
        if (isCase) { cur.test = this$1.parseExpression(); }
        else { cur.test = null; }
        this$1.expect(__acorn.tokTypes.colon);
      } else {
        if (!cur) {
          node.cases.push(cur = this$1.startNode());
          cur.consequent = [];
          cur.test = null;
        }
        cur.consequent.push(this$1.parseStatement());
      }
    }
    if (cur) { this.finishNode(cur, "SwitchCase"); }
    this.popCx();
    this.eat(__acorn.tokTypes.braceR);
    return this.finishNode(node, "SwitchStatement")

  case __acorn.tokTypes._throw:
    this.next();
    node.argument = this.parseExpression();
    this.semicolon();
    return this.finishNode(node, "ThrowStatement")

  case __acorn.tokTypes._try:
    this.next();
    node.block = this.parseBlock();
    node.handler = null;
    if (this.tok.type === __acorn.tokTypes._catch) {
      var clause = this.startNode();
      this.next();
      this.expect(__acorn.tokTypes.parenL);
      clause.param = this.toAssignable(this.parseExprAtom(), true);
      this.expect(__acorn.tokTypes.parenR);
      clause.body = this.parseBlock();
      node.handler = this.finishNode(clause, "CatchClause");
    }
    node.finalizer = this.eat(__acorn.tokTypes._finally) ? this.parseBlock() : null;
    if (!node.handler && !node.finalizer) { return node.block }
    return this.finishNode(node, "TryStatement")

  case __acorn.tokTypes._var:
  case __acorn.tokTypes._const:
    return this.parseVar(false, kind || this.tok.value)

  case __acorn.tokTypes._while:
    this.next();
    node.test = this.parseParenExpression();
    node.body = this.parseStatement();
    return this.finishNode(node, "WhileStatement")

  case __acorn.tokTypes._with:
    this.next();
    node.object = this.parseParenExpression();
    node.body = this.parseStatement();
    return this.finishNode(node, "WithStatement")

  case __acorn.tokTypes.braceL:
    return this.parseBlock()

  case __acorn.tokTypes.semi:
    this.next();
    return this.finishNode(node, "EmptyStatement")

  case __acorn.tokTypes._class:
    return this.parseClass(true)

  case __acorn.tokTypes._import:
    return this.parseImport()

  case __acorn.tokTypes._export:
    return this.parseExport()

  default:
    if (this.toks.isAsyncFunction()) {
      this.next();
      this.next();
      return this.parseFunction(node, true, true)
    }
    var expr = this.parseExpression();
    if (isDummy(expr)) {
      this.next();
      if (this.tok.type === __acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") }
      return this.parseStatement()
    } else if (starttype === __acorn.tokTypes.name && expr.type === "Identifier" && this.eat(__acorn.tokTypes.colon)) {
      node.body = this.parseStatement();
      node.label = expr;
      return this.finishNode(node, "LabeledStatement")
    } else {
      node.expression = expr;
      this.semicolon();
      return this.finishNode(node, "ExpressionStatement")
    }
  }
};

lp$1.parseBlock = function() {
  var this$1 = this;

  var node = this.startNode();
  this.pushCx();
  this.expect(__acorn.tokTypes.braceL);
  var blockIndent = this.curIndent, line = this.curLineStart;
  node.body = [];
  while (!this.closes(__acorn.tokTypes.braceR, blockIndent, line, true))
    { node.body.push(this$1.parseStatement()); }
  this.popCx();
  this.eat(__acorn.tokTypes.braceR);
  return this.finishNode(node, "BlockStatement")
};

lp$1.parseFor = function(node, init) {
  node.init = init;
  node.test = node.update = null;
  if (this.eat(__acorn.tokTypes.semi) && this.tok.type !== __acorn.tokTypes.semi) { node.test = this.parseExpression(); }
  if (this.eat(__acorn.tokTypes.semi) && this.tok.type !== __acorn.tokTypes.parenR) { node.update = this.parseExpression(); }
  this.popCx();
  this.expect(__acorn.tokTypes.parenR);
  node.body = this.parseStatement();
  return this.finishNode(node, "ForStatement")
};

lp$1.parseForIn = function(node, init) {
  var type = this.tok.type === __acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement";
  this.next();
  node.left = init;
  node.right = this.parseExpression();
  this.popCx();
  this.expect(__acorn.tokTypes.parenR);
  node.body = this.parseStatement();
  return this.finishNode(node, type)
};

lp$1.parseVar = function(noIn, kind) {
  var this$1 = this;

  var node = this.startNode();
  node.kind = kind;
  this.next();
  node.declarations = [];
  do {
    var decl = this$1.startNode();
    decl.id = this$1.options.ecmaVersion >= 6 ? this$1.toAssignable(this$1.parseExprAtom(), true) : this$1.parseIdent();
    decl.init = this$1.eat(__acorn.tokTypes.eq) ? this$1.parseMaybeAssign(noIn) : null;
    node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
  } while (this.eat(__acorn.tokTypes.comma))
  if (!node.declarations.length) {
    var decl$1 = this.startNode();
    decl$1.id = this.dummyIdent();
    node.declarations.push(this.finishNode(decl$1, "VariableDeclarator"));
  }
  if (!noIn) { this.semicolon(); }
  return this.finishNode(node, "VariableDeclaration")
};

lp$1.parseClass = function(isStatement) {
  var this$1 = this;

  var node = this.startNode();
  this.next();
  if (this.tok.type === __acorn.tokTypes.name) { node.id = this.parseIdent(); }
  else if (isStatement === true) { node.id = this.dummyIdent(); }
  else { node.id = null; }
  node.superClass = this.eat(__acorn.tokTypes._extends) ? this.parseExpression() : null;
  node.body = this.startNode();
  node.body.body = [];
  this.pushCx();
  var indent = this.curIndent + 1, line = this.curLineStart;
  this.eat(__acorn.tokTypes.braceL);
  if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
  while (!this.closes(__acorn.tokTypes.braceR, indent, line)) {
    if (this$1.semicolon()) { continue }
    var method = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0);
    if (this$1.options.ecmaVersion >= 6) {
      method.static = false;
      isGenerator = this$1.eat(__acorn.tokTypes.star);
    }
    this$1.parsePropertyName(method);
    if (isDummy(method.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(__acorn.tokTypes.comma); continue }
    if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" &&
        (this$1.tok.type != __acorn.tokTypes.parenL && this$1.tok.type != __acorn.tokTypes.braceL)) {
      method.static = true;
      isGenerator = this$1.eat(__acorn.tokTypes.star);
      this$1.parsePropertyName(method);
    } else {
      method.static = false;
    }
    if (!method.computed &&
        method.key.type === "Identifier" && method.key.name === "async" && this$1.tok.type !== __acorn.tokTypes.parenL &&
        !this$1.canInsertSemicolon()) {
      this$1.parsePropertyName(method);
      isAsync = true;
    } else {
      isAsync = false;
    }
    if (this$1.options.ecmaVersion >= 5 && method.key.type === "Identifier" &&
        !method.computed && (method.key.name === "get" || method.key.name === "set") &&
        this$1.tok.type !== __acorn.tokTypes.parenL && this$1.tok.type !== __acorn.tokTypes.braceL) {
      method.kind = method.key.name;
      this$1.parsePropertyName(method);
      method.value = this$1.parseMethod(false);
    } else {
      if (!method.computed && !method.static && !isGenerator && !isAsync && (
        method.key.type === "Identifier" && method.key.name === "constructor" ||
          method.key.type === "Literal" && method.key.value === "constructor")) {
        method.kind = "constructor";
      } else {
        method.kind = "method";
      }
      method.value = this$1.parseMethod(isGenerator, isAsync);
    }
    node.body.body.push(this$1.finishNode(method, "MethodDefinition"));
  }
  this.popCx();
  if (!this.eat(__acorn.tokTypes.braceR)) {
    // If there is no closing brace, make the node span to the start
    // of the next token (this is useful for Tern)
    this.last.end = this.tok.start;
    if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
  }
  this.semicolon();
  this.finishNode(node.body, "ClassBody");
  return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")
};

lp$1.parseFunction = function(node, isStatement, isAsync) {
  var oldInAsync = this.inAsync;
  this.initFunction(node);
  if (this.options.ecmaVersion >= 6) {
    node.generator = this.eat(__acorn.tokTypes.star);
  }
  if (this.options.ecmaVersion >= 8) {
    node.async = !!isAsync;
  }
  if (this.tok.type === __acorn.tokTypes.name) { node.id = this.parseIdent(); }
  else if (isStatement === true) { node.id = this.dummyIdent(); }
  this.inAsync = node.async;
  node.params = this.parseFunctionParams();
  node.body = this.parseBlock();
  this.toks.adaptDirectivePrologue(node.body.body);
  this.inAsync = oldInAsync;
  return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")
};

lp$1.parseExport = function() {
  var node = this.startNode();
  this.next();
  if (this.eat(__acorn.tokTypes.star)) {
    node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString();
    return this.finishNode(node, "ExportAllDeclaration")
  }
  if (this.eat(__acorn.tokTypes._default)) {
    // export default (function foo() {}) // This is FunctionExpression.
    var isAsync;
    if (this.tok.type === __acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) {
      var fNode = this.startNode();
      this.next();
      if (isAsync) { this.next(); }
      node.declaration = this.parseFunction(fNode, "nullableID", isAsync);
    } else if (this.tok.type === __acorn.tokTypes._class) {
      node.declaration = this.parseClass("nullableID");
    } else {
      node.declaration = this.parseMaybeAssign();
      this.semicolon();
    }
    return this.finishNode(node, "ExportDefaultDeclaration")
  }
  if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) {
    node.declaration = this.parseStatement();
    node.specifiers = [];
    node.source = null;
  } else {
    node.declaration = null;
    node.specifiers = this.parseExportSpecifierList();
    node.source = this.eatContextual("from") ? this.parseExprAtom() : null;
    this.semicolon();
  }
  return this.finishNode(node, "ExportNamedDeclaration")
};

lp$1.parseImport = function() {
  var node = this.startNode();
  this.next();
  if (this.tok.type === __acorn.tokTypes.string) {
    node.specifiers = [];
    node.source = this.parseExprAtom();
  } else {
    var elt;
    if (this.tok.type === __acorn.tokTypes.name && this.tok.value !== "from") {
      elt = this.startNode();
      elt.local = this.parseIdent();
      this.finishNode(elt, "ImportDefaultSpecifier");
      this.eat(__acorn.tokTypes.comma);
    }
    node.specifiers = this.parseImportSpecifierList();
    node.source = this.eatContextual("from") && this.tok.type == __acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString();
    if (elt) { node.specifiers.unshift(elt); }
  }
  this.semicolon();
  return this.finishNode(node, "ImportDeclaration")
};

lp$1.parseImportSpecifierList = function() {
  var this$1 = this;

  var elts = [];
  if (this.tok.type === __acorn.tokTypes.star) {
    var elt = this.startNode();
    this.next();
    elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent();
    elts.push(this.finishNode(elt, "ImportNamespaceSpecifier"));
  } else {
    var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
    this.pushCx();
    this.eat(__acorn.tokTypes.braceL);
    if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
    while (!this.closes(__acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
      var elt$1 = this$1.startNode();
      if (this$1.eat(__acorn.tokTypes.star)) {
        elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : this$1.dummyIdent();
        this$1.finishNode(elt$1, "ImportNamespaceSpecifier");
      } else {
        if (this$1.isContextual("from")) { break }
        elt$1.imported = this$1.parseIdent();
        if (isDummy(elt$1.imported)) { break }
        elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : elt$1.imported;
        this$1.finishNode(elt$1, "ImportSpecifier");
      }
      elts.push(elt$1);
      this$1.eat(__acorn.tokTypes.comma);
    }
    this.eat(__acorn.tokTypes.braceR);
    this.popCx();
  }
  return elts
};

lp$1.parseExportSpecifierList = function() {
  var this$1 = this;

  var elts = [];
  var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart;
  this.pushCx();
  this.eat(__acorn.tokTypes.braceL);
  if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; }
  while (!this.closes(__acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) {
    if (this$1.isContextual("from")) { break }
    var elt = this$1.startNode();
    elt.local = this$1.parseIdent();
    if (isDummy(elt.local)) { break }
    elt.exported = this$1.eatContextual("as") ? this$1.parseIdent() : elt.local;
    this$1.finishNode(elt, "ExportSpecifier");
    elts.push(elt);
    this$1.eat(__acorn.tokTypes.comma);
  }
  this.eat(__acorn.tokTypes.braceR);
  this.popCx();
  return elts
};

var lp$2 = LooseParser.prototype;

lp$2.checkLVal = function(expr) {
  if (!expr) { return expr }
  switch (expr.type) {
  case "Identifier":
  case "MemberExpression":
    return expr

  case "ParenthesizedExpression":
    expr.expression = this.checkLVal(expr.expression);
    return expr

  default:
    return this.dummyIdent()
  }
};

lp$2.parseExpression = function(noIn) {
  var this$1 = this;

  var start = this.storeCurrentPos();
  var expr = this.parseMaybeAssign(noIn);
  if (this.tok.type === __acorn.tokTypes.comma) {
    var node = this.startNodeAt(start);
    node.expressions = [expr];
    while (this.eat(__acorn.tokTypes.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn)); }
    return this.finishNode(node, "SequenceExpression")
  }
  return expr
};

lp$2.parseParenExpression = function() {
  this.pushCx();
  this.expect(__acorn.tokTypes.parenL);
  var val = this.parseExpression();
  this.popCx();
  this.expect(__acorn.tokTypes.parenR);
  return val
};

lp$2.parseMaybeAssign = function(noIn) {
  if (this.toks.isContextual("yield")) {
    var node = this.startNode();
    this.next();
    if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type != __acorn.tokTypes.star && !this.tok.type.startsExpr)) {
      node.delegate = false;
      node.argument = null;
    } else {
      node.delegate = this.eat(__acorn.tokTypes.star);
      node.argument = this.parseMaybeAssign();
    }
    return this.finishNode(node, "YieldExpression")
  }

  var start = this.storeCurrentPos();
  var left = this.parseMaybeConditional(noIn);
  if (this.tok.type.isAssign) {
    var node$1 = this.startNodeAt(start);
    node$1.operator = this.tok.value;
    node$1.left = this.tok.type === __acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left);
    this.next();
    node$1.right = this.parseMaybeAssign(noIn);
    return this.finishNode(node$1, "AssignmentExpression")
  }
  return left
};

lp$2.parseMaybeConditional = function(noIn) {
  var start = this.storeCurrentPos();
  var expr = this.parseExprOps(noIn);
  if (this.eat(__acorn.tokTypes.question)) {
    var node = this.startNodeAt(start);
    node.test = expr;
    node.consequent = this.parseMaybeAssign();
    node.alternate = this.expect(__acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent();
    return this.finishNode(node, "ConditionalExpression")
  }
  return expr
};

lp$2.parseExprOps = function(noIn) {
  var start = this.storeCurrentPos();
  var indent = this.curIndent, line = this.curLineStart;
  return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line)
};

lp$2.parseExprOp = function(left, start, minPrec, noIn, indent, line) {
  if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) { return left }
  var prec = this.tok.type.binop;
  if (prec != null && (!noIn || this.tok.type !== __acorn.tokTypes._in)) {
    if (prec > minPrec) {
      var node = this.startNodeAt(start);
      node.left = left;
      node.operator = this.tok.value;
      this.next();
      if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) {
        node.right = this.dummyIdent();
      } else {
        var rightStart = this.storeCurrentPos();
        node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line);
      }
      this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression");
      return this.parseExprOp(node, start, minPrec, noIn, indent, line)
    }
  }
  return left
};

lp$2.parseMaybeUnary = function(sawUnary) {
  var this$1 = this;

  var start = this.storeCurrentPos(), expr;
  if (this.options.ecmaVersion >= 8 && this.inAsync && this.toks.isContextual("await")) {
    expr = this.parseAwait();
    sawUnary = true;
  } else if (this.tok.type.prefix) {
    var node = this.startNode(), update = this.tok.type === __acorn.tokTypes.incDec;
    if (!update) { sawUnary = true; }
    node.operator = this.tok.value;
    node.prefix = true;
    this.next();
    node.argument = this.parseMaybeUnary(true);
    if (update) { node.argument = this.checkLVal(node.argument); }
    expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
  } else if (this.tok.type === __acorn.tokTypes.ellipsis) {
    var node$1 = this.startNode();
    this.next();
    node$1.argument = this.parseMaybeUnary(sawUnary);
    expr = this.finishNode(node$1, "SpreadElement");
  } else {
    expr = this.parseExprSubscripts();
    while (this.tok.type.postfix && !this.canInsertSemicolon()) {
      var node$2 = this$1.startNodeAt(start);
      node$2.operator = this$1.tok.value;
      node$2.prefix = false;
      node$2.argument = this$1.checkLVal(expr);
      this$1.next();
      expr = this$1.finishNode(node$2, "UpdateExpression");
    }
  }

  if (!sawUnary && this.eat(__acorn.tokTypes.starstar)) {
    var node$3 = this.startNodeAt(start);
    node$3.operator = "**";
    node$3.left = expr;
    node$3.right = this.parseMaybeUnary(false);
    return this.finishNode(node$3, "BinaryExpression")
  }

  return expr
};

lp$2.parseExprSubscripts = function() {
  var start = this.storeCurrentPos();
  return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart)
};

lp$2.parseSubscripts = function(base, start, noCalls, startIndent, line) {
  var this$1 = this;

  for (;;) {
    if (this$1.curLineStart != line && this$1.curIndent <= startIndent && this$1.tokenStartsLine()) {
      if (this$1.tok.type == __acorn.tokTypes.dot && this$1.curIndent == startIndent)
        { --startIndent; }
      else
        { return base }
    }

    var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this$1.canInsertSemicolon();

    if (this$1.eat(__acorn.tokTypes.dot)) {
      var node = this$1.startNodeAt(start);
      node.object = base;
      if (this$1.curLineStart != line && this$1.curIndent <= startIndent && this$1.tokenStartsLine())
        { node.property = this$1.dummyIdent(); }
      else
        { node.property = this$1.parsePropertyAccessor() || this$1.dummyIdent(); }
      node.computed = false;
      base = this$1.finishNode(node, "MemberExpression");
    } else if (this$1.tok.type == __acorn.tokTypes.bracketL) {
      this$1.pushCx();
      this$1.next();
      var node$1 = this$1.startNodeAt(start);
      node$1.object = base;
      node$1.property = this$1.parseExpression();
      node$1.computed = true;
      this$1.popCx();
      this$1.expect(__acorn.tokTypes.bracketR);
      base = this$1.finishNode(node$1, "MemberExpression");
    } else if (!noCalls && this$1.tok.type == __acorn.tokTypes.parenL) {
      var exprList = this$1.parseExprList(__acorn.tokTypes.parenR);
      if (maybeAsyncArrow && this$1.eat(__acorn.tokTypes.arrow))
        { return this$1.parseArrowExpression(this$1.startNodeAt(start), exprList, true) }
      var node$2 = this$1.startNodeAt(start);
      node$2.callee = base;
      node$2.arguments = exprList;
      base = this$1.finishNode(node$2, "CallExpression");
    } else if (this$1.tok.type == __acorn.tokTypes.backQuote) {
      var node$3 = this$1.startNodeAt(start);
      node$3.tag = base;
      node$3.quasi = this$1.parseTemplate();
      base = this$1.finishNode(node$3, "TaggedTemplateExpression");
    } else {
      return base
    }
  }
};

lp$2.parseExprAtom = function() {
  var node;
  switch (this.tok.type) {
  case __acorn.tokTypes._this:
  case __acorn.tokTypes._super:
    var type = this.tok.type === __acorn.tokTypes._this ? "ThisExpression" : "Super";
    node = this.startNode();
    this.next();
    return this.finishNode(node, type)

  case __acorn.tokTypes.name:
    var start = this.storeCurrentPos();
    var id = this.parseIdent();
    var isAsync = false;
    if (id.name === "async" && !this.canInsertSemicolon()) {
      if (this.eat(__acorn.tokTypes._function))
        { return this.parseFunction(this.startNodeAt(start), false, true) }
      if (this.tok.type === __acorn.tokTypes.name) {
        id = this.parseIdent();
        isAsync = true;
      }
    }
    return this.eat(__acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id

  case __acorn.tokTypes.regexp:
    node = this.startNode();
    var val = this.tok.value;
    node.regex = {pattern: val.pattern, flags: val.flags};
    node.value = val.value;
    node.raw = this.input.slice(this.tok.start, this.tok.end);
    this.next();
    return this.finishNode(node, "Literal")

  case __acorn.tokTypes.num: case __acorn.tokTypes.string:
    node = this.startNode();
    node.value = this.tok.value;
    node.raw = this.input.slice(this.tok.start, this.tok.end);
    this.next();
    return this.finishNode(node, "Literal")

  case __acorn.tokTypes._null: case __acorn.tokTypes._true: case __acorn.tokTypes._false:
    node = this.startNode();
    node.value = this.tok.type === __acorn.tokTypes._null ? null : this.tok.type === __acorn.tokTypes._true;
    node.raw = this.tok.type.keyword;
    this.next();
    return this.finishNode(node, "Literal")

  case __acorn.tokTypes.parenL:
    var parenStart = this.storeCurrentPos();
    this.next();
    var inner = this.parseExpression();
    this.expect(__acorn.tokTypes.parenR);
    if (this.eat(__acorn.tokTypes.arrow)) {
      // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy.
      var params = inner.expressions || [inner];
      if (params.length && isDummy(params[params.length - 1]))
        { params.pop(); }
      return this.parseArrowExpression(this.startNodeAt(parenStart), params)
    }
    if (this.options.preserveParens) {
      var par = this.startNodeAt(parenStart);
      par.expression = inner;
      inner = this.finishNode(par, "ParenthesizedExpression");
    }
    return inner

  case __acorn.tokTypes.bracketL:
    node = this.startNode();
    node.elements = this.parseExprList(__acorn.tokTypes.bracketR, true);
    return this.finishNode(node, "ArrayExpression")

  case __acorn.tokTypes.braceL:
    return this.parseObj()

  case __acorn.tokTypes._class:
    return this.parseClass(false)

  case __acorn.tokTypes._function:
    node = this.startNode();
    this.next();
    return this.parseFunction(node, false)

  case __acorn.tokTypes._new:
    return this.parseNew()

  case __acorn.tokTypes.backQuote:
    return this.parseTemplate()

  default:
    return this.dummyIdent()
  }
};

lp$2.parseNew = function() {
  var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart;
  var meta = this.parseIdent(true);
  if (this.options.ecmaVersion >= 6 && this.eat(__acorn.tokTypes.dot)) {
    node.meta = meta;
    node.property = this.parseIdent(true);
    return this.finishNode(node, "MetaProperty")
  }
  var start = this.storeCurrentPos();
  node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line);
  if (this.tok.type == __acorn.tokTypes.parenL) {
    node.arguments = this.parseExprList(__acorn.tokTypes.parenR);
  } else {
    node.arguments = [];
  }
  return this.finishNode(node, "NewExpression")
};

lp$2.parseTemplateElement = function() {
  var elem = this.startNode();

  // The loose parser accepts invalid unicode escapes even in untagged templates.
  if (this.tok.type === __acorn.tokTypes.invalidTemplate) {
    elem.value = {
      raw: this.tok.value,
      cooked: null
    };
  } else {
    elem.value = {
      raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"),
      cooked: this.tok.value
    };
  }
  this.next();
  elem.tail = this.tok.type === __acorn.tokTypes.backQuote;
  return this.finishNode(elem, "TemplateElement")
};

lp$2.parseTemplate = function() {
  var this$1 = this;

  var node = this.startNode();
  this.next();
  node.expressions = [];
  var curElt = this.parseTemplateElement();
  node.quasis = [curElt];
  while (!curElt.tail) {
    this$1.next();
    node.expressions.push(this$1.parseExpression());
    if (this$1.expect(__acorn.tokTypes.braceR)) {
      curElt = this$1.parseTemplateElement();
    } else {
      curElt = this$1.startNode();
      curElt.value = {cooked: "", raw: ""};
      curElt.tail = true;
      this$1.finishNode(curElt, "TemplateElement");
    }
    node.quasis.push(curElt);
  }
  this.expect(__acorn.tokTypes.backQuote);
  return this.finishNode(node, "TemplateLiteral")
};

lp$2.parseObj = function() {
  var this$1 = this;

  var node = this.startNode();
  node.properties = [];
  this.pushCx();
  var indent = this.curIndent + 1, line = this.curLineStart;
  this.eat(__acorn.tokTypes.braceL);
  if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; }
  while (!this.closes(__acorn.tokTypes.braceR, indent, line)) {
    var prop = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0);
    if (this$1.options.ecmaVersion >= 6) {
      start = this$1.storeCurrentPos();
      prop.method = false;
      prop.shorthand = false;
      isGenerator = this$1.eat(__acorn.tokTypes.star);
    }
    this$1.parsePropertyName(prop);
    if (this$1.toks.isAsyncProp(prop)) {
      this$1.parsePropertyName(prop);
      isAsync = true;
    } else {
      isAsync = false;
    }
    if (isDummy(prop.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(__acorn.tokTypes.comma); continue }
    if (this$1.eat(__acorn.tokTypes.colon)) {
      prop.kind = "init";
      prop.value = this$1.parseMaybeAssign();
    } else if (this$1.options.ecmaVersion >= 6 && (this$1.tok.type === __acorn.tokTypes.parenL || this$1.tok.type === __acorn.tokTypes.braceL)) {
      prop.kind = "init";
      prop.method = true;
      prop.value = this$1.parseMethod(isGenerator, isAsync);
    } else if (this$1.options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&
               !prop.computed && (prop.key.name === "get" || prop.key.name === "set") &&
               (this$1.tok.type != __acorn.tokTypes.comma && this$1.tok.type != __acorn.tokTypes.braceR && this$1.tok.type != __acorn.tokTypes.eq)) {
      prop.kind = prop.key.name;
      this$1.parsePropertyName(prop);
      prop.value = this$1.parseMethod(false);
    } else {
      prop.kind = "init";
      if (this$1.options.ecmaVersion >= 6) {
        if (this$1.eat(__acorn.tokTypes.eq)) {
          var assign = this$1.startNodeAt(start);
          assign.operator = "=";
          assign.left = prop.key;
          assign.right = this$1.parseMaybeAssign();
          prop.value = this$1.finishNode(assign, "AssignmentExpression");
        } else {
          prop.value = prop.key;
        }
      } else {
        prop.value = this$1.dummyIdent();
      }
      prop.shorthand = true;
    }
    node.properties.push(this$1.finishNode(prop, "Property"));
    this$1.eat(__acorn.tokTypes.comma);
  }
  this.popCx();
  if (!this.eat(__acorn.tokTypes.braceR)) {
    // If there is no closing brace, make the node span to the start
    // of the next token (this is useful for Tern)
    this.last.end = this.tok.start;
    if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
  }
  return this.finishNode(node, "ObjectExpression")
};

lp$2.parsePropertyName = function(prop) {
  if (this.options.ecmaVersion >= 6) {
    if (this.eat(__acorn.tokTypes.bracketL)) {
      prop.computed = true;
      prop.key = this.parseExpression();
      this.expect(__acorn.tokTypes.bracketR);
      return
    } else {
      prop.computed = false;
    }
  }
  var key = (this.tok.type === __acorn.tokTypes.num || this.tok.type === __acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent();
  prop.key = key || this.dummyIdent();
};

lp$2.parsePropertyAccessor = function() {
  if (this.tok.type === __acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() }
};

lp$2.parseIdent = function() {
  var name = this.tok.type === __acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword;
  if (!name) { return this.dummyIdent() }
  var node = this.startNode();
  this.next();
  node.name = name;
  return this.finishNode(node, "Identifier")
};

lp$2.initFunction = function(node) {
  node.id = null;
  node.params = [];
  if (this.options.ecmaVersion >= 6) {
    node.generator = false;
    node.expression = false;
  }
  if (this.options.ecmaVersion >= 8)
    { node.async = false; }
};

// Convert existing expression atom to assignable pattern
// if possible.

lp$2.toAssignable = function(node, binding) {
  var this$1 = this;

  if (!node || node.type == "Identifier" || (node.type == "MemberExpression" && !binding)) {
    // Okay
  } else if (node.type == "ParenthesizedExpression") {
    this.toAssignable(node.expression, binding);
  } else if (this.options.ecmaVersion < 6) {
    return this.dummyIdent()
  } else if (node.type == "ObjectExpression") {
    node.type = "ObjectPattern";
    var props = node.properties;
    for (var i = 0, list = props; i < list.length; i += 1)
      {
      var prop = list[i];

      this$1.toAssignable(prop.value, binding);
    }
  } else if (node.type == "ArrayExpression") {
    node.type = "ArrayPattern";
    this.toAssignableList(node.elements, binding);
  } else if (node.type == "SpreadElement") {
    node.type = "RestElement";
    this.toAssignable(node.argument, binding);
  } else if (node.type == "AssignmentExpression") {
    node.type = "AssignmentPattern";
    delete node.operator;
  } else {
    return this.dummyIdent()
  }
  return node
};

lp$2.toAssignableList = function(exprList, binding) {
  var this$1 = this;

  for (var i = 0, list = exprList; i < list.length; i += 1)
    {
    var expr = list[i];

    this$1.toAssignable(expr, binding);
  }
  return exprList
};

lp$2.parseFunctionParams = function(params) {
  params = this.parseExprList(__acorn.tokTypes.parenR);
  return this.toAssignableList(params, true)
};

lp$2.parseMethod = function(isGenerator, isAsync) {
  var node = this.startNode(), oldInAsync = this.inAsync;
  this.initFunction(node);
  if (this.options.ecmaVersion >= 6)
    { node.generator = !!isGenerator; }
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }
  this.inAsync = node.async;
  node.params = this.parseFunctionParams();
  node.body = this.parseBlock();
  this.toks.adaptDirectivePrologue(node.body.body);
  this.inAsync = oldInAsync;
  return this.finishNode(node, "FunctionExpression")
};

lp$2.parseArrowExpression = function(node, params, isAsync) {
  var oldInAsync = this.inAsync;
  this.initFunction(node);
  if (this.options.ecmaVersion >= 8)
    { node.async = !!isAsync; }
  this.inAsync = node.async;
  node.params = this.toAssignableList(params, true);
  node.expression = this.tok.type !== __acorn.tokTypes.braceL;
  if (node.expression) {
    node.body = this.parseMaybeAssign();
  } else {
    node.body = this.parseBlock();
    this.toks.adaptDirectivePrologue(node.body.body);
  }
  this.inAsync = oldInAsync;
  return this.finishNode(node, "ArrowFunctionExpression")
};

lp$2.parseExprList = function(close, allowEmpty) {
  var this$1 = this;

  this.pushCx();
  var indent = this.curIndent, line = this.curLineStart, elts = [];
  this.next(); // Opening bracket
  while (!this.closes(close, indent + 1, line)) {
    if (this$1.eat(__acorn.tokTypes.comma)) {
      elts.push(allowEmpty ? null : this$1.dummyIdent());
      continue
    }
    var elt = this$1.parseMaybeAssign();
    if (isDummy(elt)) {
      if (this$1.closes(close, indent, line)) { break }
      this$1.next();
    } else {
      elts.push(elt);
    }
    this$1.eat(__acorn.tokTypes.comma);
  }
  this.popCx();
  if (!this.eat(close)) {
    // If there is no closing brace, make the node span to the start
    // of the next token (this is useful for Tern)
    this.last.end = this.tok.start;
    if (this.options.locations) { this.last.loc.end = this.tok.loc.start; }
  }
  return elts
};

lp$2.parseAwait = function() {
  var node = this.startNode();
  this.next();
  node.argument = this.parseMaybeUnary();
  return this.finishNode(node, "AwaitExpression")
};

// Acorn: Loose parser
//
// This module provides an alternative parser (`parse_dammit`) that
// exposes that same interface as `parse`, but will try to parse
// anything as JavaScript, repairing syntax error the best it can.
// There are circumstances in which it will raise an error and give
// up, but they are very rare. The resulting AST will be a mostly
// valid JavaScript AST (as per the [Mozilla parser API][api], except
// that:
//
// - Return outside functions is allowed
//
// - Label consistency (no conflicts, break only to existing labels)
//   is not enforced.
//
// - Bogus Identifier nodes with a name of `"✖"` are inserted whenever
//   the parser got too confused to return anything meaningful.
//
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
//
// The expected use for this is to *first* try `acorn.parse`, and only
// if that fails switch to `parse_dammit`. The loose parser might
// parse badly indented code incorrectly, so **don't** use it as
// your default parser.
//
// Quite a lot of acorn.js is duplicated here. The alternative was to
// add a *lot* of extra cruft to that file, making it less readable
// and slower. Copying and editing the code allowed me to make
// invasive changes and simplifications without creating a complicated
// tangle.

__acorn.defaultOptions.tabSize = 4;

// eslint-disable-next-line camelcase
function parse_dammit(input, options) {
  return new LooseParser(input, options).parse()
}

__acorn.addLooseExports(parse_dammit, LooseParser, pluginsLoose);

exports.parse_dammit = parse_dammit;
exports.LooseParser = LooseParser;
exports.pluginsLoose = pluginsLoose;

Object.defineProperty(exports, '__esModule', { value: true });

})));

  
/* <<< acorn-es7-plugin/acorn-v4.js >>> */
(function(acorn) {
  var module = {exports: {}};
  var asyncExit = /^async[\t ]+(return|throw)/ ;
var atomOrPropertyOrLabel = /^\s*[):;]/ ;
var removeComments = /([^\n])\/\*(\*(?!\/)|[^\n*])*\*\/([^\n])/g ;

function hasLineTerminatorBeforeNext(st, since) {
    return st.lineStart >= since;
}

function test(regex,st,noComment) {
    var src = st.input.slice(st.start) ;
    if (noComment) {
        src = src.replace(removeComments,"$1 $3") ;
    }
    return regex.test(src);
}

/* Create a new parser derived from the specified parser, so that in the
 * event of an error we can back out and try again */
function subParse(parser, pos, extensions) {
    var p = new parser.constructor(parser.options, parser.input, pos);
    if (extensions)
        for (var k in extensions)
            p[k] = extensions[k] ;

    var src = parser ;
    var dest = p ;
    ['inFunction','inAsync','inGenerator','inModule'].forEach(function(k){
        if (k in src)
            dest[k] = src[k] ;
    }) ;
    p.nextToken();
    return p;
}

function asyncAwaitPlugin (parser,options){
    if (!options || typeof options !== "object")
        options = {} ;

    parser.extend("parse",function(base){
        return function(){
            this.inAsync = options.inAsyncFunction ;
            if (options.awaitAnywhere && options.inAsyncFunction)
                parser.raise(node.start,"The options awaitAnywhere and inAsyncFunction are mutually exclusive") ;

            return base.apply(this,arguments);
        }
    }) ;

    parser.extend("parseStatement",function(base){
        return function (declaration, topLevel) {
            var start = this.start;
            var startLoc = this.startLoc;
            if (this.type.label==='name') {
                if ((options.asyncExits) && test(asyncExit,this)) {
                    // TODO: Ensure this function is itself nested in an async function or Method
                    this.next() ;

                    var r = this.parseStatement(declaration, topLevel) ;
                    r.async = true ;
                    r.start = start;
                    r.loc && (r.loc.start = startLoc);
                    r.range && (r.range[0] = start);
                    return r ;
                }
            }
            return base.apply(this,arguments);
        }
    }) ;

    parser.extend("parseIdent",function(base){
        return function(liberal) {
            if (this.options.sourceType==='module' && this.options.ecmaVersion >= 8 && options.awaitAnywhere)
                return base.call(this,true) ; // Force liberal mode if awaitAnywhere is set
            return base.apply(this,arguments) ;
        }
    }) ;

    parser.extend("parseExprAtom",function(base){
        var NotAsync = {};
        return function(refShorthandDefaultPos){
            var start = this.start ;
            var startLoc = this.startLoc;

            var rhs,r = base.apply(this,arguments);

            if (r.type==='Identifier') {
                if (r.name==='await' && !this.inAsync) {
                    if (options.awaitAnywhere) {
                        var n = this.startNodeAt(r.start, r.loc && r.loc.start);

                        start = this.start ;

                        var parseHooks = {
                            raise:function(){
                                try {
                                    return pp.raise.apply(this,arguments) ;
                                } catch(ex) {
                                    throw /*inBody?ex:*/NotAsync ;
                                }
                            }
                        } ;

                        try {
                            rhs = subParse(this,start-4,parseHooks).parseExprSubscripts() ;
                            if (rhs.end<=start) {
                                rhs = subParse(this,start,parseHooks).parseExprSubscripts() ;
                                n.argument = rhs ;
                                n = this.finishNodeAt(n,'AwaitExpression', rhs.end, rhs.loc && rhs.loc.end) ;
                                this.pos = rhs.end;
                                this.end = rhs.end ;
                                this.endLoc = rhs.endLoc ;
                                this.next();
                                return n ;
                            }
                        } catch (ex) {
                            if (ex===NotAsync)
                                return r ;
                            throw ex ;
                        }
                    }
                }
            }
            return r ;
        }
    }) ;

    var allowedPropValues = {
        undefined:true,
        get:true,
        set:true,
        static:true,
        async:true,
        constructor:true
    };
    parser.extend("parsePropertyName",function(base){
        return function (prop) {
            var prevName = prop.key && prop.key.name ;
            var key = base.apply(this,arguments) ;
            if (this.value==='get') {
                prop.__maybeStaticAsyncGetter = true ;
            }
            var next ;
            if (allowedPropValues[this.value])
                return key ;

            if (key.type === "Identifier" && (key.name === "async" || prevName === "async") && !hasLineTerminatorBeforeNext(this, key.end) 
                // Look-ahead to see if this is really a property or label called async or await
                && !this.input.slice(key.end).match(atomOrPropertyOrLabel)) {
                if (prop.kind === 'set' || key.name === 'set') 
                    this.raise(key.start,"'set <member>(value)' cannot be be async") ;
                else {
                    this.__isAsyncProp = true ;
                    key = base.apply(this,arguments) ;
                    if (key.type==='Identifier') {
                        if (key.name==='set')
                            this.raise(key.start,"'set <member>(value)' cannot be be async") ;
                    }
                }
            } else {
                delete prop.__maybeStaticAsyncGetter ;
            }
            return key;
        };
    }) ;

    parser.extend("parseClassMethod",function(base){
        return function (classBody, method, isGenerator) {
            var r = base.apply(this,arguments) ;
            if (method.__maybeStaticAsyncGetter) {
                delete method.__maybeStaticAsyncGetter ;
                if (method.key.name!=='get')
                    method.kind = "get" ;
            }
            return r ;
        }
    }) ;


    parser.extend("parseFunctionBody",function(base){
        return function (node, isArrowFunction) {
            var wasAsync = this.inAsync ;
            if (this.__isAsyncProp) {
                node.async = true ;
                this.inAsync = true ;
                delete this.__isAsyncProp ;
            }
            var r = base.apply(this,arguments) ;
            this.inAsync = wasAsync ;
            return r ;
        }
    }) ;
}

module.exports = asyncAwaitPlugin ;

  acorn.plugins.asyncawait = module.exports;
})(this.acorn);
  
/* <<< acorn-object-spread/inject.js >>> */
(function(acorn) {
  var module = {exports: {}};
  'use strict';

module.exports = function(acorn) {
  if (acorn.version.substr(0, 1) !== "5") {
    throw new Error("Unsupported acorn version " + acorn.version + ", please use acorn 5");
  }
  var tt = acorn.tokTypes;
  var pp = acorn.Parser.prototype;

  // this is the same parseObj that acorn has with...
  function parseObj(isPattern, refDestructuringErrors) {
    var node = this.startNode(), first = true, propHash = {}
    node.properties = []
    this.next()
    while (!this.eat(tt.braceR)) {
      if (!first) {
        this.expect(tt.comma)
        if (this.afterTrailingComma(tt.braceR)) break
      } else first = false

      var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc
      if (this.options.ecmaVersion >= 6) {
        // ...the spread logic borrowed from babylon :)
        if (this.type === tt.ellipsis) {
          if (isPattern) {
            this.next()
            prop.argument = this.parseIdent()
            this.finishNode(prop, "RestElement")
          } else {
            prop = this.parseSpread(refDestructuringErrors)
          }
          node.properties.push(prop)
          if (this.type === tt.comma) {
            if (isPattern) {
              this.raise(this.start, "Comma is not permitted after the rest element")
            } else if (refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
              refDestructuringErrors.trailingComma = this.start
            }
          }
          continue
        }

        prop.method = false
        prop.shorthand = false
        if (isPattern || refDestructuringErrors) {
          startPos = this.start
          startLoc = this.startLoc
        }
        if (!isPattern)
          isGenerator = this.eat(tt.star)
      }
      this.parsePropertyName(prop)
      if (!isPattern && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
        isAsync = true
        this.parsePropertyName(prop, refDestructuringErrors)
      } else {
        isAsync = false
      }
      this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors)
      if (!isPattern) this.checkPropClash(prop, propHash)
      node.properties.push(this.finishNode(prop, "Property"))
    }
    return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
  }

  const getCheckLVal = origCheckLVal => function (expr, bindingType, checkClashes) {
    if (expr.type == "ObjectPattern") {
      for (var prop of expr.properties)
        this.checkLVal(prop, bindingType, checkClashes)
      return
    } else if (expr.type === "Property") {
      // AssignmentProperty has type == "Property"
      return this.checkLVal(expr.value, bindingType, checkClashes)
    }
    return origCheckLVal.apply(this, arguments)
  }

  acorn.plugins.objectSpread = function objectSpreadPlugin(instance) {
    pp.parseObj = parseObj;
    instance.extend("checkLVal", getCheckLVal)
    instance.extend("toAssignable", nextMethod => function(node, isBinding) {
      if (this.options.ecmaVersion >= 6 && node) {
        if (node.type == "ObjectExpression") {
          node.type = "ObjectPattern"
          for (var prop of node.properties)
            this.toAssignable(prop, isBinding)
          return node
        } else if (node.type === "Property") {
          // AssignmentProperty has type == "Property"
          if (node.kind !== "init") this.raise(node.key.start, "Object pattern can't contain getter or setter")
          return this.toAssignable(node.value, isBinding)
        } else if (node.type === "SpreadElement") {
          node.type = "RestElement"
          return this.toAssignable(node.argument, isBinding)
        }
      }
      return nextMethod.apply(this, arguments)
    })
    instance.extend("checkPatternExport", nextMethod => function(exports, pat) {
      if (pat.type == "ObjectPattern") {
        for (var prop of pat.properties)
          this.checkPatternExport(exports, prop)
        return
      } else if (pat.type === "Property") {
        return this.checkPatternExport(exports, pat.value)
      } else if (pat.type === "RestElement") {
        return this.checkPatternExport(exports, pat.argument)
      }
      nextMethod.apply(this, arguments)
    })
  };

  return acorn;
};

  module.exports(acorn);
})(this.acorn);
  /* <<< acorn-jsx/inject.js >>> */
(function(acorn) {
  var module = {exports: {}};
  'use strict';

var XHTMLEntities = {
  quot: '\u0022',
  amp: '&',
  apos: '\u0027',
  lt: '<',
  gt: '>',
  nbsp: '\u00A0',
  iexcl: '\u00A1',
  cent: '\u00A2',
  pound: '\u00A3',
  curren: '\u00A4',
  yen: '\u00A5',
  brvbar: '\u00A6',
  sect: '\u00A7',
  uml: '\u00A8',
  copy: '\u00A9',
  ordf: '\u00AA',
  laquo: '\u00AB',
  not: '\u00AC',
  shy: '\u00AD',
  reg: '\u00AE',
  macr: '\u00AF',
  deg: '\u00B0',
  plusmn: '\u00B1',
  sup2: '\u00B2',
  sup3: '\u00B3',
  acute: '\u00B4',
  micro: '\u00B5',
  para: '\u00B6',
  middot: '\u00B7',
  cedil: '\u00B8',
  sup1: '\u00B9',
  ordm: '\u00BA',
  raquo: '\u00BB',
  frac14: '\u00BC',
  frac12: '\u00BD',
  frac34: '\u00BE',
  iquest: '\u00BF',
  Agrave: '\u00C0',
  Aacute: '\u00C1',
  Acirc: '\u00C2',
  Atilde: '\u00C3',
  Auml: '\u00C4',
  Aring: '\u00C5',
  AElig: '\u00C6',
  Ccedil: '\u00C7',
  Egrave: '\u00C8',
  Eacute: '\u00C9',
  Ecirc: '\u00CA',
  Euml: '\u00CB',
  Igrave: '\u00CC',
  Iacute: '\u00CD',
  Icirc: '\u00CE',
  Iuml: '\u00CF',
  ETH: '\u00D0',
  Ntilde: '\u00D1',
  Ograve: '\u00D2',
  Oacute: '\u00D3',
  Ocirc: '\u00D4',
  Otilde: '\u00D5',
  Ouml: '\u00D6',
  times: '\u00D7',
  Oslash: '\u00D8',
  Ugrave: '\u00D9',
  Uacute: '\u00DA',
  Ucirc: '\u00DB',
  Uuml: '\u00DC',
  Yacute: '\u00DD',
  THORN: '\u00DE',
  szlig: '\u00DF',
  agrave: '\u00E0',
  aacute: '\u00E1',
  acirc: '\u00E2',
  atilde: '\u00E3',
  auml: '\u00E4',
  aring: '\u00E5',
  aelig: '\u00E6',
  ccedil: '\u00E7',
  egrave: '\u00E8',
  eacute: '\u00E9',
  ecirc: '\u00EA',
  euml: '\u00EB',
  igrave: '\u00EC',
  iacute: '\u00ED',
  icirc: '\u00EE',
  iuml: '\u00EF',
  eth: '\u00F0',
  ntilde: '\u00F1',
  ograve: '\u00F2',
  oacute: '\u00F3',
  ocirc: '\u00F4',
  otilde: '\u00F5',
  ouml: '\u00F6',
  divide: '\u00F7',
  oslash: '\u00F8',
  ugrave: '\u00F9',
  uacute: '\u00FA',
  ucirc: '\u00FB',
  uuml: '\u00FC',
  yacute: '\u00FD',
  thorn: '\u00FE',
  yuml: '\u00FF',
  OElig: '\u0152',
  oelig: '\u0153',
  Scaron: '\u0160',
  scaron: '\u0161',
  Yuml: '\u0178',
  fnof: '\u0192',
  circ: '\u02C6',
  tilde: '\u02DC',
  Alpha: '\u0391',
  Beta: '\u0392',
  Gamma: '\u0393',
  Delta: '\u0394',
  Epsilon: '\u0395',
  Zeta: '\u0396',
  Eta: '\u0397',
  Theta: '\u0398',
  Iota: '\u0399',
  Kappa: '\u039A',
  Lambda: '\u039B',
  Mu: '\u039C',
  Nu: '\u039D',
  Xi: '\u039E',
  Omicron: '\u039F',
  Pi: '\u03A0',
  Rho: '\u03A1',
  Sigma: '\u03A3',
  Tau: '\u03A4',
  Upsilon: '\u03A5',
  Phi: '\u03A6',
  Chi: '\u03A7',
  Psi: '\u03A8',
  Omega: '\u03A9',
  alpha: '\u03B1',
  beta: '\u03B2',
  gamma: '\u03B3',
  delta: '\u03B4',
  epsilon: '\u03B5',
  zeta: '\u03B6',
  eta: '\u03B7',
  theta: '\u03B8',
  iota: '\u03B9',
  kappa: '\u03BA',
  lambda: '\u03BB',
  mu: '\u03BC',
  nu: '\u03BD',
  xi: '\u03BE',
  omicron: '\u03BF',
  pi: '\u03C0',
  rho: '\u03C1',
  sigmaf: '\u03C2',
  sigma: '\u03C3',
  tau: '\u03C4',
  upsilon: '\u03C5',
  phi: '\u03C6',
  chi: '\u03C7',
  psi: '\u03C8',
  omega: '\u03C9',
  thetasym: '\u03D1',
  upsih: '\u03D2',
  piv: '\u03D6',
  ensp: '\u2002',
  emsp: '\u2003',
  thinsp: '\u2009',
  zwnj: '\u200C',
  zwj: '\u200D',
  lrm: '\u200E',
  rlm: '\u200F',
  ndash: '\u2013',
  mdash: '\u2014',
  lsquo: '\u2018',
  rsquo: '\u2019',
  sbquo: '\u201A',
  ldquo: '\u201C',
  rdquo: '\u201D',
  bdquo: '\u201E',
  dagger: '\u2020',
  Dagger: '\u2021',
  bull: '\u2022',
  hellip: '\u2026',
  permil: '\u2030',
  prime: '\u2032',
  Prime: '\u2033',
  lsaquo: '\u2039',
  rsaquo: '\u203A',
  oline: '\u203E',
  frasl: '\u2044',
  euro: '\u20AC',
  image: '\u2111',
  weierp: '\u2118',
  real: '\u211C',
  trade: '\u2122',
  alefsym: '\u2135',
  larr: '\u2190',
  uarr: '\u2191',
  rarr: '\u2192',
  darr: '\u2193',
  harr: '\u2194',
  crarr: '\u21B5',
  lArr: '\u21D0',
  uArr: '\u21D1',
  rArr: '\u21D2',
  dArr: '\u21D3',
  hArr: '\u21D4',
  forall: '\u2200',
  part: '\u2202',
  exist: '\u2203',
  empty: '\u2205',
  nabla: '\u2207',
  isin: '\u2208',
  notin: '\u2209',
  ni: '\u220B',
  prod: '\u220F',
  sum: '\u2211',
  minus: '\u2212',
  lowast: '\u2217',
  radic: '\u221A',
  prop: '\u221D',
  infin: '\u221E',
  ang: '\u2220',
  and: '\u2227',
  or: '\u2228',
  cap: '\u2229',
  cup: '\u222A',
  'int': '\u222B',
  there4: '\u2234',
  sim: '\u223C',
  cong: '\u2245',
  asymp: '\u2248',
  ne: '\u2260',
  equiv: '\u2261',
  le: '\u2264',
  ge: '\u2265',
  sub: '\u2282',
  sup: '\u2283',
  nsub: '\u2284',
  sube: '\u2286',
  supe: '\u2287',
  oplus: '\u2295',
  otimes: '\u2297',
  perp: '\u22A5',
  sdot: '\u22C5',
  lceil: '\u2308',
  rceil: '\u2309',
  lfloor: '\u230A',
  rfloor: '\u230B',
  lang: '\u2329',
  rang: '\u232A',
  loz: '\u25CA',
  spades: '\u2660',
  clubs: '\u2663',
  hearts: '\u2665',
  diams: '\u2666'
};


var hexNumber = /^[\da-fA-F]+$/;
var decimalNumber = /^\d+$/;

module.exports = function(acorn) {
  var tt = acorn.tokTypes;
  var tc = acorn.tokContexts;

  tc.j_oTag = new acorn.TokContext('<tag', false);
  tc.j_cTag = new acorn.TokContext('</tag', false);
  tc.j_expr = new acorn.TokContext('<tag>...</tag>', true, true);

  tt.jsxName = new acorn.TokenType('jsxName');
  tt.jsxText = new acorn.TokenType('jsxText', {beforeExpr: true});
  tt.jsxTagStart = new acorn.TokenType('jsxTagStart');
  tt.jsxTagEnd = new acorn.TokenType('jsxTagEnd');

  tt.jsxTagStart.updateContext = function() {
    this.context.push(tc.j_expr); // treat as beginning of JSX expression
    this.context.push(tc.j_oTag); // start opening tag context
    this.exprAllowed = false;
  };
  tt.jsxTagEnd.updateContext = function(prevType) {
    var out = this.context.pop();
    if (out === tc.j_oTag && prevType === tt.slash || out === tc.j_cTag) {
      this.context.pop();
      this.exprAllowed = this.curContext() === tc.j_expr;
    } else {
      this.exprAllowed = true;
    }
  };

  var pp = acorn.Parser.prototype;

  // Reads inline JSX contents token.

  pp.jsx_readToken = function() {
    var out = '', chunkStart = this.pos;
    for (;;) {
      if (this.pos >= this.input.length)
        this.raise(this.start, 'Unterminated JSX contents');
      var ch = this.input.charCodeAt(this.pos);

      switch (ch) {
      case 60: // '<'
      case 123: // '{'
        if (this.pos === this.start) {
          if (ch === 60 && this.exprAllowed) {
            ++this.pos;
            return this.finishToken(tt.jsxTagStart);
          }
          return this.getTokenFromCode(ch);
        }
        out += this.input.slice(chunkStart, this.pos);
        return this.finishToken(tt.jsxText, out);

      case 38: // '&'
        out += this.input.slice(chunkStart, this.pos);
        out += this.jsx_readEntity();
        chunkStart = this.pos;
        break;

      default:
        if (acorn.isNewLine(ch)) {
          out += this.input.slice(chunkStart, this.pos);
          out += this.jsx_readNewLine(true);
          chunkStart = this.pos;
        } else {
          ++this.pos;
        }
      }
    }
  };

  pp.jsx_readNewLine = function(normalizeCRLF) {
    var ch = this.input.charCodeAt(this.pos);
    var out;
    ++this.pos;
    if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
      ++this.pos;
      out = normalizeCRLF ? '\n' : '\r\n';
    } else {
      out = String.fromCharCode(ch);
    }
    if (this.options.locations) {
      ++this.curLine;
      this.lineStart = this.pos;
    }

    return out;
  };

  pp.jsx_readString = function(quote) {
    var out = '', chunkStart = ++this.pos;
    for (;;) {
      if (this.pos >= this.input.length)
        this.raise(this.start, 'Unterminated string constant');
      var ch = this.input.charCodeAt(this.pos);
      if (ch === quote) break;
      if (ch === 38) { // '&'
        out += this.input.slice(chunkStart, this.pos);
        out += this.jsx_readEntity();
        chunkStart = this.pos;
      } else if (acorn.isNewLine(ch)) {
        out += this.input.slice(chunkStart, this.pos);
        out += this.jsx_readNewLine(false);
        chunkStart = this.pos;
      } else {
        ++this.pos;
      }
    }
    out += this.input.slice(chunkStart, this.pos++);
    return this.finishToken(tt.string, out);
  };

  pp.jsx_readEntity = function() {
    var str = '', count = 0, entity;
    var ch = this.input[this.pos];
    if (ch !== '&')
      this.raise(this.pos, 'Entity must start with an ampersand');
    var startPos = ++this.pos;
    while (this.pos < this.input.length && count++ < 10) {
      ch = this.input[this.pos++];
      if (ch === ';') {
        if (str[0] === '#') {
          if (str[1] === 'x') {
            str = str.substr(2);
            if (hexNumber.test(str))
              entity = String.fromCharCode(parseInt(str, 16));
          } else {
            str = str.substr(1);
            if (decimalNumber.test(str))
              entity = String.fromCharCode(parseInt(str, 10));
          }
        } else {
          entity = XHTMLEntities[str];
        }
        break;
      }
      str += ch;
    }
    if (!entity) {
      this.pos = startPos;
      return '&';
    }
    return entity;
  };


  // Read a JSX identifier (valid tag or attribute name).
  //
  // Optimized version since JSX identifiers can't contain
  // escape characters and so can be read as single slice.
  // Also assumes that first character was already checked
  // by isIdentifierStart in readToken.

  pp.jsx_readWord = function() {
    var ch, start = this.pos;
    do {
      ch = this.input.charCodeAt(++this.pos);
    } while (acorn.isIdentifierChar(ch) || ch === 45); // '-'
    return this.finishToken(tt.jsxName, this.input.slice(start, this.pos));
  };

  // Transforms JSX element name to string.

  function getQualifiedJSXName(object) {
    if (!object)
      return object;

    if (object.type === 'JSXIdentifier')
      return object.name;

    if (object.type === 'JSXNamespacedName')
      return object.namespace.name + ':' + object.name.name;

    if (object.type === 'JSXMemberExpression')
      return getQualifiedJSXName(object.object) + '.' +
      getQualifiedJSXName(object.property);
  }

  // Parse next token as JSX identifier

  pp.jsx_parseIdentifier = function() {
    var node = this.startNode();
    if (this.type === tt.jsxName)
      node.name = this.value;
    else if (this.type.keyword)
      node.name = this.type.keyword;
    else
      this.unexpected();
    this.next();
    return this.finishNode(node, 'JSXIdentifier');
  };

  // Parse namespaced identifier.

  pp.jsx_parseNamespacedName = function() {
    var startPos = this.start, startLoc = this.startLoc;
    var name = this.jsx_parseIdentifier();
    if (!this.options.plugins.jsx.allowNamespaces || !this.eat(tt.colon)) return name;
    var node = this.startNodeAt(startPos, startLoc);
    node.namespace = name;
    node.name = this.jsx_parseIdentifier();
    return this.finishNode(node, 'JSXNamespacedName');
  };

  // Parses element name in any form - namespaced, member
  // or single identifier.

  pp.jsx_parseElementName = function() {
    if (this.type === tt.jsxTagEnd)
      return '';
    var startPos = this.start, startLoc = this.startLoc;
    var node = this.jsx_parseNamespacedName();
    if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !this.options.plugins.jsx.allowNamespacedObjects) {
      this.unexpected();
    }
    while (this.eat(tt.dot)) {
      var newNode = this.startNodeAt(startPos, startLoc);
      newNode.object = node;
      newNode.property = this.jsx_parseIdentifier();
      node = this.finishNode(newNode, 'JSXMemberExpression');
    }
    return node;
  };

  // Parses any type of JSX attribute value.

  pp.jsx_parseAttributeValue = function() {
    switch (this.type) {
    case tt.braceL:
      var node = this.jsx_parseExpressionContainer();
      if (node.expression.type === 'JSXEmptyExpression')
        this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression');
      return node;

    case tt.jsxTagStart:
    case tt.string:
      return this.parseExprAtom();

    default:
      this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text');
    }
  };

  // JSXEmptyExpression is unique type since it doesn't actually parse anything,
  // and so it should start at the end of last read token (left brace) and finish
  // at the beginning of the next one (right brace).

  pp.jsx_parseEmptyExpression = function() {
    var node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
    return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc);
  };

  // Parses JSX expression enclosed into curly brackets.


  pp.jsx_parseExpressionContainer = function() {
    var node = this.startNode();
    this.next();
    node.expression = this.type === tt.braceR
      ? this.jsx_parseEmptyExpression()
      : this.parseExpression();
    this.expect(tt.braceR);
    return this.finishNode(node, 'JSXExpressionContainer');
  };

  // Parses following JSX attribute name-value pair.

  pp.jsx_parseAttribute = function() {
    var node = this.startNode();
    if (this.eat(tt.braceL)) {
      this.expect(tt.ellipsis);
      node.argument = this.parseMaybeAssign();
      this.expect(tt.braceR);
      return this.finishNode(node, 'JSXSpreadAttribute');
    }
    node.name = this.jsx_parseNamespacedName();
    node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
    return this.finishNode(node, 'JSXAttribute');
  };

  // Parses JSX opening tag starting after '<'.

  pp.jsx_parseOpeningElementAt = function(startPos, startLoc) {
    var node = this.startNodeAt(startPos, startLoc);
    node.attributes = [];
    node.name = this.jsx_parseElementName();
    while (this.type !== tt.slash && this.type !== tt.jsxTagEnd)
      node.attributes.push(this.jsx_parseAttribute());
    node.selfClosing = this.eat(tt.slash);
    this.expect(tt.jsxTagEnd);
    return this.finishNode(node, 'JSXOpeningElement');
  };

  // Parses JSX closing tag starting after '</'.

  pp.jsx_parseClosingElementAt = function(startPos, startLoc) {
    var node = this.startNodeAt(startPos, startLoc);
    node.name = this.jsx_parseElementName();
    this.expect(tt.jsxTagEnd);
    return this.finishNode(node, 'JSXClosingElement');
  };

  // Parses entire JSX element, including it's opening tag
  // (starting after '<'), attributes, contents and closing tag.

  pp.jsx_parseElementAt = function(startPos, startLoc) {
    var node = this.startNodeAt(startPos, startLoc);
    var children = [];
    var openingElement = this.jsx_parseOpeningElementAt(startPos, startLoc);
    var closingElement = null;

    if (!openingElement.selfClosing) {
      contents: for (;;) {
        switch (this.type) {
        case tt.jsxTagStart:
          startPos = this.start; startLoc = this.startLoc;
          this.next();
          if (this.eat(tt.slash)) {
            closingElement = this.jsx_parseClosingElementAt(startPos, startLoc);
            break contents;
          }
          children.push(this.jsx_parseElementAt(startPos, startLoc));
          break;

        case tt.jsxText:
          children.push(this.parseExprAtom());
          break;

        case tt.braceL:
          children.push(this.jsx_parseExpressionContainer());
          break;

        default:
          this.unexpected();
        }
      }
      if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
        this.raise(
          closingElement.start,
          'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>');
      }
    }

    node.openingElement = openingElement;
    node.closingElement = closingElement;
    node.children = children;
    if (this.type === tt.relational && this.value === "<") {
      this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
    }
    return this.finishNode(node, openingElement.name ? 'JSXElement' : 'JSXFragment');
  };

  // Parse JSX text

  pp.jsx_parseText = function(value) {
    var node = this.parseLiteral(value);
    node.type = "JSXText";

    return node;
  };

  // Parses entire JSX element from current position.

  pp.jsx_parseElement = function() {
    var startPos = this.start, startLoc = this.startLoc;
    this.next();
    return this.jsx_parseElementAt(startPos, startLoc);
  };

  acorn.plugins.jsx = function(instance, opts) {
    if (!opts) {
      return;
    }

    if (typeof opts !== 'object') {
      opts = {};
    }

    instance.options.plugins.jsx = {
      allowNamespaces: opts.allowNamespaces !== false,
      allowNamespacedObjects: !!opts.allowNamespacedObjects
    };

    instance.extend('parseExprAtom', function(inner) {
      return function(refShortHandDefaultPos) {
        if (this.type === tt.jsxText)
          return this.jsx_parseText(this.value);
        else if (this.type === tt.jsxTagStart)
          return this.jsx_parseElement();
        else
          return inner.call(this, refShortHandDefaultPos);
      };
    });

    instance.extend('readToken', function(inner) {
      return function(code) {
        var context = this.curContext();

        if (context === tc.j_expr) return this.jsx_readToken();

        if (context === tc.j_oTag || context === tc.j_cTag) {
          if (acorn.isIdentifierStart(code)) return this.jsx_readWord();

          if (code == 62) {
            ++this.pos;
            return this.finishToken(tt.jsxTagEnd);
          }

          if ((code === 34 || code === 39) && context == tc.j_oTag)
            return this.jsx_readString(code);
        }

        if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) {
          ++this.pos;
          return this.finishToken(tt.jsxTagStart);
        }
        return inner.call(this, code);
      };
    });

    instance.extend('updateContext', function(inner) {
      return function(prevType) {
        if (this.type == tt.braceL) {
          var curContext = this.curContext();
          if (curContext == tc.j_oTag) this.context.push(tc.b_expr);
          else if (curContext == tc.j_expr) this.context.push(tc.b_tmpl);
          else inner.call(this, prevType);
          this.exprAllowed = true;
        } else if (this.type === tt.slash && prevType === tt.jsxTagStart) {
          this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
          this.context.push(tc.j_cTag); // reconsider as closing tag context
          this.exprAllowed = false;
        } else {
          return inner.call(this, prevType);
        }
      };
    });
  };

  return acorn;
};

  module.exports(acorn);
})(this.acorn);
  return this.acorn;
})();;
    ;(function(GLOBAL) {
  // Generated by CommonJS Everywhere 0.9.7
(function (global) {
  function require(file, parentModule) {
    if ({}.hasOwnProperty.call(require.cache, file))
      return require.cache[file];
    var resolved = require.resolve(file);
    if (!resolved)
      throw new Error('Failed to resolve module ' + file);
    var module$ = {
        id: file,
        require: require,
        filename: file,
        exports: {},
        loaded: false,
        parent: parentModule,
        children: []
      };
    if (parentModule)
      parentModule.children.push(module$);
    var dirname = file.slice(0, file.lastIndexOf('/') + 1);
    require.cache[file] = module$.exports;
    resolved.call(module$.exports, module$, module$.exports, dirname, file);
    module$.loaded = true;
    return require.cache[file] = module$.exports;
  }
  require.modules = {};
  require.cache = {};
  require.resolve = function (file) {
    return {}.hasOwnProperty.call(require.modules, file) ? require.modules[file] : void 0;
  };
  require.define = function (file, fn) {
    require.modules[file] = fn;
  };
  var process = function () {
      var cwd = '/';
      return {
        title: 'browser',
        version: 'v8.6.0',
        browser: true,
        env: {},
        argv: [],
        nextTick: global.setImmediate || function (fn) {
          setTimeout(fn, 0);
        },
        cwd: function () {
          return cwd;
        },
        chdir: function (dir) {
          cwd = dir;
        }
      };
    }();
  require.define('/tools/entry-point.js', function (module, exports, __dirname, __filename) {
    (function () {
      'use strict';
      global.escodegen = require('/escodegen.js', module);
      GLOBAL.escodegen.browser = true;
    }());
  });
  require.define('/escodegen.js', function (module, exports, __dirname, __filename) {
    (function () {
      'use strict';
      var Syntax, Precedence, BinaryPrecedence, SourceNode, estraverse, esutils, isArray, base, indent, json, renumber, hexadecimal, quotes, escapeless, newline, space, parentheses, semicolons, safeConcatenation, directive, extra, parse, sourceMap, sourceCode, preserveBlankLines, FORMAT_MINIFY, FORMAT_DEFAULTS;
      estraverse = require('/node_modules/estraverse/estraverse.js', module);
      esutils = require('/node_modules/esutils/lib/utils.js', module);
      Syntax = estraverse.Syntax;
      function isExpression(node) {
        return CodeGenerator.Expression.hasOwnProperty(node.type);
      }
      function isStatement(node) {
        return CodeGenerator.Statement.hasOwnProperty(node.type);
      }
      Precedence = {
        Sequence: 0,
        Yield: 1,
        Await: 1,
        Assignment: 1,
        Conditional: 2,
        ArrowFunction: 2,
        LogicalOR: 3,
        LogicalAND: 4,
        BitwiseOR: 5,
        BitwiseXOR: 6,
        BitwiseAND: 7,
        Equality: 8,
        Relational: 9,
        BitwiseSHIFT: 10,
        Additive: 11,
        Multiplicative: 12,
        Exponentiation: 13,
        Unary: 14,
        Postfix: 15,
        Call: 16,
        New: 17,
        TaggedTemplate: 18,
        Member: 19,
        Primary: 20
      };
      BinaryPrecedence = {
        '||': Precedence.LogicalOR,
        '&&': Precedence.LogicalAND,
        '|': Precedence.BitwiseOR,
        '^': Precedence.BitwiseXOR,
        '&': Precedence.BitwiseAND,
        '==': Precedence.Equality,
        '!=': Precedence.Equality,
        '===': Precedence.Equality,
        '!==': Precedence.Equality,
        'is': Precedence.Equality,
        'isnt': Precedence.Equality,
        '<': Precedence.Relational,
        '>': Precedence.Relational,
        '<=': Precedence.Relational,
        '>=': Precedence.Relational,
        'in': Precedence.Relational,
        'instanceof': Precedence.Relational,
        '<<': Precedence.BitwiseSHIFT,
        '>>': Precedence.BitwiseSHIFT,
        '>>>': Precedence.BitwiseSHIFT,
        '+': Precedence.Additive,
        '-': Precedence.Additive,
        '*': Precedence.Multiplicative,
        '%': Precedence.Multiplicative,
        '/': Precedence.Multiplicative,
        '**': Precedence.Exponentiation
      };
      var F_ALLOW_IN = 1, F_ALLOW_CALL = 1 << 1, F_ALLOW_UNPARATH_NEW = 1 << 2, F_FUNC_BODY = 1 << 3, F_DIRECTIVE_CTX = 1 << 4, F_SEMICOLON_OPT = 1 << 5;
      var F_XJS_NOINDENT = 1 << 8, F_XJS_NOPAREN = 1 << 9;
      var E_FTT = F_ALLOW_CALL | F_ALLOW_UNPARATH_NEW, E_TTF = F_ALLOW_IN | F_ALLOW_CALL, E_TTT = F_ALLOW_IN | F_ALLOW_CALL | F_ALLOW_UNPARATH_NEW, E_TFF = F_ALLOW_IN, E_FFT = F_ALLOW_UNPARATH_NEW, E_TFT = F_ALLOW_IN | F_ALLOW_UNPARATH_NEW;
      var S_TFFF = F_ALLOW_IN, S_TFFT = F_ALLOW_IN | F_SEMICOLON_OPT, S_FFFF = 0, S_TFTF = F_ALLOW_IN | F_DIRECTIVE_CTX, S_TTFF = F_ALLOW_IN | F_FUNC_BODY;
      function getDefaultOptions() {
        return {
          indent: null,
          base: null,
          parse: null,
          comment: false,
          format: {
            indent: {
              style: '    ',
              base: 0,
              adjustMultilineComment: false
            },
            newline: '\n',
            space: ' ',
            json: false,
            renumber: false,
            hexadecimal: false,
            quotes: 'single',
            escapeless: false,
            compact: false,
            parentheses: true,
            semicolons: true,
            safeConcatenation: false,
            preserveBlankLines: false
          },
          moz: {
            comprehensionExpressionStartsWithAssignment: false,
            starlessGenerator: false
          },
          sourceMap: null,
          sourceMapRoot: null,
          sourceMapWithCode: false,
          directive: false,
          raw: true,
          verbatim: null,
          sourceCode: null
        };
      }
      function stringRepeat(str, num) {
        var result = '';
        for (num |= 0; num > 0; num >>>= 1, str += str) {
          if (num & 1) {
            result += str;
          }
        }
        return result;
      }
      isArray = Array.isArray;
      if (!isArray) {
        isArray = function isArray(array) {
          return Object.prototype.toString.call(array) === '[object Array]';
        };
      }
      function hasLineTerminator(str) {
        return /[\r\n]/g.test(str);
      }
      function endsWithLineTerminator(str) {
        var len = str.length;
        return len && esutils.code.isLineTerminator(str.charCodeAt(len - 1));
      }
      function merge(target, override) {
        var key;
        for (key in override) {
          if (override.hasOwnProperty(key)) {
            target[key] = override[key];
          }
        }
        return target;
      }
      function updateDeeply(target, override) {
        var key, val;
        function isHashObject(target) {
          return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
        }
        for (key in override) {
          if (override.hasOwnProperty(key)) {
            val = override[key];
            if (isHashObject(val)) {
              if (isHashObject(target[key])) {
                updateDeeply(target[key], val);
              } else {
                target[key] = updateDeeply({}, val);
              }
            } else {
              target[key] = val;
            }
          }
        }
        return target;
      }
      function generateNumber(value) {
        var result, point, temp, exponent, pos;
        if (value !== value) {
          throw new Error('Numeric literal whose value is NaN');
        }
        if (value < 0 || value === 0 && 1 / value < 0) {
          throw new Error('Numeric literal whose value is negative');
        }
        if (value === 1 / 0) {
          return json ? 'null' : renumber ? '1e400' : '1e+400';
        }
        result = '' + value;
        if (!renumber || result.length < 3) {
          return result;
        }
        point = result.indexOf('.');
        if (!json && result.charCodeAt(0) === 48 && point === 1) {
          point = 0;
          result = result.slice(1);
        }
        temp = result;
        result = result.replace('e+', 'e');
        exponent = 0;
        if ((pos = temp.indexOf('e')) > 0) {
          exponent = +temp.slice(pos + 1);
          temp = temp.slice(0, pos);
        }
        if (point >= 0) {
          exponent -= temp.length - point - 1;
          temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
        }
        pos = 0;
        while (temp.charCodeAt(temp.length + pos - 1) === 48) {
          --pos;
        }
        if (pos !== 0) {
          exponent -= pos;
          temp = temp.slice(0, pos);
        }
        if (exponent !== 0) {
          temp += 'e' + exponent;
        }
        if ((temp.length < result.length || hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length) && +temp === value) {
          result = temp;
        }
        return result;
      }
      function escapeRegExpCharacter(ch, previousIsBackslash) {
        if ((ch & ~1) === 8232) {
          return (previousIsBackslash ? 'u' : '\\u') + (ch === 8232 ? '2028' : '2029');
        } else if (ch === 10 || ch === 13) {
          return (previousIsBackslash ? '' : '\\') + (ch === 10 ? 'n' : 'r');
        }
        return String.fromCharCode(ch);
      }
      function generateRegExp(reg) {
        var match, result, flags, i, iz, ch, characterInBrack, previousIsBackslash;
        result = reg.toString();
        if (reg.source) {
          match = result.match(/\/([^\/]*)$/);
          if (!match) {
            return result;
          }
          flags = match[1];
          result = '';
          characterInBrack = false;
          previousIsBackslash = false;
          for (i = 0, iz = reg.source.length; i < iz; ++i) {
            ch = reg.source.charCodeAt(i);
            if (!previousIsBackslash) {
              if (characterInBrack) {
                if (ch === 93) {
                  characterInBrack = false;
                }
              } else {
                if (ch === 47) {
                  result += '\\';
                } else if (ch === 91) {
                  characterInBrack = true;
                }
              }
              result += escapeRegExpCharacter(ch, previousIsBackslash);
              previousIsBackslash = ch === 92;
            } else {
              result += escapeRegExpCharacter(ch, previousIsBackslash);
              previousIsBackslash = false;
            }
          }
          return '/' + result + '/' + flags;
        }
        return result;
      }
      function escapeAllowedCharacter(code, next) {
        var hex;
        if (code === 8) {
          return '\\b';
        }
        if (code === 12) {
          return '\\f';
        }
        if (code === 9) {
          return '\\t';
        }
        hex = code.toString(16).toUpperCase();
        if (json || code > 255) {
          return '\\u' + '0000'.slice(hex.length) + hex;
        } else if (code === 0 && !esutils.code.isDecimalDigit(next)) {
          return '\\0';
        } else if (code === 11) {
          return '\\x0B';
        } else {
          return '\\x' + '00'.slice(hex.length) + hex;
        }
      }
      function escapeDisallowedCharacter(code) {
        if (code === 92) {
          return '\\\\';
        }
        if (code === 10) {
          return '\\n';
        }
        if (code === 13) {
          return '\\r';
        }
        if (code === 8232) {
          return '\\u2028';
        }
        if (code === 8233) {
          return '\\u2029';
        }
        throw new Error('Incorrectly classified character');
      }
      function escapeDirective(str) {
        var i, iz, code, quote;
        quote = quotes === 'double' ? '"' : "'";
        for (i = 0, iz = str.length; i < iz; ++i) {
          code = str.charCodeAt(i);
          if (code === 39) {
            quote = '"';
            break;
          } else if (code === 34) {
            quote = "'";
            break;
          } else if (code === 92) {
            ++i;
          }
        }
        return quote + str + quote;
      }
      function escapeString(str) {
        var result = '', i, len, code, singleQuotes = 0, doubleQuotes = 0, single, quote;
        for (i = 0, len = str.length; i < len; ++i) {
          code = str.charCodeAt(i);
          if (code === 39) {
            ++singleQuotes;
          } else if (code === 34) {
            ++doubleQuotes;
          } else if (code === 47 && json) {
            result += '\\';
          } else if (esutils.code.isLineTerminator(code) || code === 92) {
            result += escapeDisallowedCharacter(code);
            continue;
          } else if (!esutils.code.isIdentifierPartES5(code) && (json && code < 32 || !json && !escapeless && (code < 32 || code > 126))) {
            result += escapeAllowedCharacter(code, str.charCodeAt(i + 1));
            continue;
          }
          result += String.fromCharCode(code);
        }
        single = !(quotes === 'double' || quotes === 'auto' && doubleQuotes < singleQuotes);
        quote = single ? "'" : '"';
        if (!(single ? singleQuotes : doubleQuotes)) {
          return quote + result + quote;
        }
        str = result;
        result = quote;
        for (i = 0, len = str.length; i < len; ++i) {
          code = str.charCodeAt(i);
          if (code === 39 && single || code === 34 && !single) {
            result += '\\';
          }
          result += String.fromCharCode(code);
        }
        return result + quote;
      }
      function flattenToString(arr) {
        var i, iz, elem, result = '';
        for (i = 0, iz = arr.length; i < iz; ++i) {
          elem = arr[i];
          result += isArray(elem) ? flattenToString(elem) : elem;
        }
        return result;
      }
      function toSourceNodeWhenNeeded(generated, node) {
        if (!sourceMap) {
          if (isArray(generated)) {
            return flattenToString(generated);
          } else {
            return generated;
          }
        }
        if (node == null) {
          if (generated instanceof SourceNode) {
            return generated;
          } else {
            node = {};
          }
        }
        if (node.loc == null) {
          return new SourceNode(null, null, sourceMap, generated, node.name || null);
        }
        return new SourceNode(node.loc.start.line, node.loc.start.column, sourceMap === true ? node.loc.source || null : sourceMap, generated, node.name || null);
      }
      function noEmptySpace() {
        return space ? space : ' ';
      }
      function join(left, right) {
        var leftSource, rightSource, leftCharCode, rightCharCode;
        leftSource = toSourceNodeWhenNeeded(left).toString();
        if (leftSource.length === 0) {
          return [right];
        }
        rightSource = toSourceNodeWhenNeeded(right).toString();
        if (rightSource.length === 0) {
          return [left];
        }
        leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
        rightCharCode = rightSource.charCodeAt(0);
        if ((leftCharCode === 43 || leftCharCode === 45) && leftCharCode === rightCharCode || esutils.code.isIdentifierPartES5(leftCharCode) && esutils.code.isIdentifierPartES5(rightCharCode) || leftCharCode === 47 && rightCharCode === 105) {
          return [
            left,
            noEmptySpace(),
            right
          ];
        } else if (esutils.code.isWhiteSpace(leftCharCode) || esutils.code.isLineTerminator(leftCharCode) || esutils.code.isWhiteSpace(rightCharCode) || esutils.code.isLineTerminator(rightCharCode)) {
          return [
            left,
            right
          ];
        }
        return [
          left,
          space,
          right
        ];
      }
      function addIndent(stmt) {
        return [
          base,
          stmt
        ];
      }
      function withIndent(fn) {
        var previousBase;
        previousBase = base;
        base += indent;
        fn(base);
        base = previousBase;
      }
      function calculateSpaces(str) {
        var i;
        for (i = str.length - 1; i >= 0; --i) {
          if (esutils.code.isLineTerminator(str.charCodeAt(i))) {
            break;
          }
        }
        return str.length - 1 - i;
      }
      function adjustMultilineComment(value, specialBase) {
        var array, i, len, line, j, spaces, previousBase, sn;
        array = value.split(/\r\n|[\r\n]/);
        spaces = Number.MAX_VALUE;
        for (i = 1, len = array.length; i < len; ++i) {
          line = array[i];
          j = 0;
          while (j < line.length && esutils.code.isWhiteSpace(line.charCodeAt(j))) {
            ++j;
          }
          if (spaces > j) {
            spaces = j;
          }
        }
        if (typeof specialBase !== 'undefined') {
          previousBase = base;
          if (array[1][spaces] === '*') {
            specialBase += ' ';
          }
          base = specialBase;
        } else {
          if (spaces & 1) {
            --spaces;
          }
          previousBase = base;
        }
        for (i = 1, len = array.length; i < len; ++i) {
          sn = toSourceNodeWhenNeeded(addIndent(array[i].slice(spaces)));
          array[i] = sourceMap ? sn.join('') : sn;
        }
        base = previousBase;
        return array.join('\n');
      }
      function generateComment(comment, specialBase) {
        if (comment.type === 'Line') {
          if (endsWithLineTerminator(comment.value)) {
            return '//' + comment.value;
          } else {
            var result = '//' + comment.value;
            if (!preserveBlankLines) {
              result += '\n';
            }
            return result;
          }
        }
        if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
          return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
        }
        return '/*' + comment.value + '*/';
      }
      function addComments(stmt, result) {
        var i, len, comment, save, tailingToStatement, specialBase, fragment, extRange, range, prevRange, prefix, infix, suffix, count;
        if (stmt.leadingComments && stmt.leadingComments.length > 0) {
          save = result;
          if (preserveBlankLines) {
            comment = stmt.leadingComments[0];
            result = [];
            extRange = comment.extendedRange;
            range = comment.range;
            prefix = sourceCode.substring(extRange[0], range[0]);
            count = (prefix.match(/\n/g) || []).length;
            if (count > 0) {
              result.push(stringRepeat('\n', count));
              result.push(addIndent(generateComment(comment)));
            } else {
              result.push(prefix);
              result.push(generateComment(comment));
            }
            prevRange = range;
            for (i = 1, len = stmt.leadingComments.length; i < len; i++) {
              comment = stmt.leadingComments[i];
              range = comment.range;
              infix = sourceCode.substring(prevRange[1], range[0]);
              count = (infix.match(/\n/g) || []).length;
              result.push(stringRepeat('\n', count));
              result.push(addIndent(generateComment(comment)));
              prevRange = range;
            }
            suffix = sourceCode.substring(range[1], extRange[1]);
            count = (suffix.match(/\n/g) || []).length;
            result.push(stringRepeat('\n', count));
          } else {
            comment = stmt.leadingComments[0];
            result = [];
            if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
              result.push('\n');
            }
            result.push(generateComment(comment));
            if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
              result.push('\n');
            }
            for (i = 1, len = stmt.leadingComments.length; i < len; ++i) {
              comment = stmt.leadingComments[i];
              fragment = [generateComment(comment)];
              if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
                fragment.push('\n');
              }
              result.push(addIndent(fragment));
            }
          }
          result.push(addIndent(save));
        }
        if (stmt.trailingComments) {
          if (preserveBlankLines) {
            comment = stmt.trailingComments[0];
            extRange = comment.extendedRange;
            range = comment.range;
            prefix = sourceCode.substring(extRange[0], range[0]);
            count = (prefix.match(/\n/g) || []).length;
            if (count > 0) {
              result.push(stringRepeat('\n', count));
              result.push(addIndent(generateComment(comment)));
            } else {
              result.push(prefix);
              result.push(generateComment(comment));
            }
          } else {
            tailingToStatement = !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());
            specialBase = stringRepeat(' ', calculateSpaces(toSourceNodeWhenNeeded([
              base,
              result,
              indent
            ]).toString()));
            for (i = 0, len = stmt.trailingComments.length; i < len; ++i) {
              comment = stmt.trailingComments[i];
              if (tailingToStatement) {
                if (i === 0) {
                  result = [
                    result,
                    indent
                  ];
                } else {
                  result = [
                    result,
                    specialBase
                  ];
                }
                result.push(generateComment(comment, specialBase));
              } else {
                result = [
                  result,
                  addIndent(generateComment(comment))
                ];
              }
              if (i !== len - 1 && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
                result = [
                  result,
                  '\n'
                ];
              }
            }
          }
        }
        return result;
      }
      function generateBlankLines(start, end, result) {
        var j, newlineCount = 0;
        for (j = start; j < end; j++) {
          if (sourceCode[j] === '\n') {
            newlineCount++;
          }
        }
        for (j = 1; j < newlineCount; j++) {
          result.push(newline);
        }
      }
      function parenthesize(text, current, should) {
        if (current < should) {
          return [
            '(',
            text,
            ')'
          ];
        }
        return text;
      }
      function generateVerbatimString(string) {
        var i, iz, result;
        result = string.split(/\r\n|\n/);
        for (i = 1, iz = result.length; i < iz; i++) {
          result[i] = newline + base + result[i];
        }
        return result;
      }
      function generateVerbatim(expr, precedence) {
        var verbatim, result, prec;
        verbatim = expr[extra.verbatim];
        if (typeof verbatim === 'string') {
          result = parenthesize(generateVerbatimString(verbatim), Precedence.Sequence, precedence);
        } else {
          result = generateVerbatimString(verbatim.content);
          prec = verbatim.precedence != null ? verbatim.precedence : Precedence.Sequence;
          result = parenthesize(result, prec, precedence);
        }
        return toSourceNodeWhenNeeded(result, expr);
      }
      function CodeGenerator() {
      }
      CodeGenerator.prototype.maybeBlock = function (stmt, flags) {
        var result, noLeadingComment, that = this;
        noLeadingComment = !extra.comment || !stmt.leadingComments;
        if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
          return [
            space,
            this.generateStatement(stmt, flags)
          ];
        }
        if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {
          return ';';
        }
        withIndent(function () {
          result = [
            newline,
            addIndent(that.generateStatement(stmt, flags))
          ];
        });
        return result;
      };
      CodeGenerator.prototype.maybeBlockSuffix = function (stmt, result) {
        var ends = endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString());
        if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) {
          return [
            result,
            space
          ];
        }
        if (ends) {
          return [
            result,
            base
          ];
        }
        return [
          result,
          newline,
          base
        ];
      };
      function generateIdentifier(node) {
        return toSourceNodeWhenNeeded(node.name, node);
      }
      function generateAsyncPrefix(node, spaceRequired) {
        return node.async ? 'async' + (spaceRequired ? noEmptySpace() : space) : '';
      }
      function generateStarSuffix(node) {
        var isGenerator = node.generator && !extra.moz.starlessGenerator;
        return isGenerator ? '*' + space : '';
      }
      function generateMethodPrefix(prop) {
        var func = prop.value;
        if (func.async) {
          return generateAsyncPrefix(func, !prop.computed);
        } else {
          return generateStarSuffix(func) ? '*' : '';
        }
      }
      CodeGenerator.prototype.generatePattern = function (node, precedence, flags) {
        if (node.type === Syntax.Identifier) {
          return generateIdentifier(node);
        }
        return this.generateExpression(node, precedence, flags);
      };
      CodeGenerator.prototype.generateFunctionParams = function (node) {
        var i, iz, result, hasDefault;
        hasDefault = false;
        if (node.type === Syntax.ArrowFunctionExpression && !node.rest && (!node.defaults || node.defaults.length === 0) && node.params.length === 1 && node.params[0].type === Syntax.Identifier) {
          result = [
            generateAsyncPrefix(node, true),
            generateIdentifier(node.params[0])
          ];
        } else {
          result = node.type === Syntax.ArrowFunctionExpression ? [generateAsyncPrefix(node, false)] : [];
          result.push('(');
          if (node.defaults) {
            hasDefault = true;
          }
          for (i = 0, iz = node.params.length; i < iz; ++i) {
            if (hasDefault && node.defaults[i]) {
              result.push(this.generateAssignment(node.params[i], node.defaults[i], '=', Precedence.Assignment, E_TTT));
            } else {
              result.push(this.generatePattern(node.params[i], Precedence.Assignment, E_TTT));
            }
            if (i + 1 < iz) {
              result.push(',' + space);
            }
          }
          if (node.rest) {
            if (node.params.length) {
              result.push(',' + space);
            }
            result.push('...');
            result.push(generateIdentifier(node.rest));
          }
          result.push(')');
        }
        return result;
      };
      CodeGenerator.prototype.generateFunctionBody = function (node) {
        var result, expr;
        result = this.generateFunctionParams(node);
        if (node.type === Syntax.ArrowFunctionExpression) {
          result.push(space);
          result.push('=>');
        }
        if (node.expression) {
          result.push(space);
          expr = this.generateExpression(node.body, Precedence.Assignment, E_TTT);
          if (expr.toString().charAt(0) === '{') {
            expr = [
              '(',
              expr,
              ')'
            ];
          }
          result.push(expr);
        } else {
          result.push(this.maybeBlock(node.body, S_TTFF));
        }
        return result;
      };
      CodeGenerator.prototype.generateIterationForStatement = function (operator, stmt, flags) {
        var result = ['for' + space + '('], that = this;
        withIndent(function () {
          if (stmt.left.type === Syntax.VariableDeclaration) {
            withIndent(function () {
              result.push(stmt.left.kind + noEmptySpace());
              result.push(that.generateStatement(stmt.left.declarations[0], S_FFFF));
            });
          } else {
            result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
          }
          result = join(result, operator);
          result = [
            join(result, that.generateExpression(stmt.right, Precedence.Sequence + (operator === 'of' ? 1 : 0), E_TTT)),
            ')'
          ];
        });
        result.push(this.maybeBlock(stmt.body, flags));
        return result;
      };
      CodeGenerator.prototype.generatePropertyKey = function (expr, computed) {
        var result = [];
        if (computed) {
          result.push('[');
        }
        result.push(this.generateExpression(expr, Precedence.Sequence, E_TTT));
        if (computed) {
          result.push(']');
        }
        return result;
      };
      CodeGenerator.prototype.generateAssignment = function (left, right, operator, precedence, flags) {
        if (Precedence.Assignment < precedence) {
          flags |= F_ALLOW_IN;
        }
        return parenthesize([
          this.generateExpression(left, Precedence.Call, flags),
          space + operator + space,
          this.generateExpression(right, Precedence.Assignment, flags)
        ], Precedence.Assignment, precedence);
      };
      CodeGenerator.prototype.semicolon = function (flags) {
        if (!semicolons && flags & F_SEMICOLON_OPT) {
          return '';
        }
        return ';';
      };
      CodeGenerator.Statement = {
        BlockStatement: function (stmt, flags) {
          var range, content, result = [
              '{',
              newline
            ], that = this;
          withIndent(function () {
            if (stmt.body.length === 0 && preserveBlankLines) {
              range = stmt.range;
              if (range[1] - range[0] > 2) {
                content = sourceCode.substring(range[0] + 1, range[1] - 1);
                if (content[0] === '\n') {
                  result = ['{'];
                }
                result.push(content);
              }
            }
            var i, iz, fragment, bodyFlags;
            bodyFlags = S_TFFF;
            if (flags & F_FUNC_BODY) {
              bodyFlags |= F_DIRECTIVE_CTX;
            }
            for (i = 0, iz = stmt.body.length; i < iz; ++i) {
              if (preserveBlankLines) {
                if (i === 0) {
                  if (stmt.body[0].leadingComments) {
                    range = stmt.body[0].leadingComments[0].extendedRange;
                    content = sourceCode.substring(range[0], range[1]);
                    if (content[0] === '\n') {
                      result = ['{'];
                    }
                  }
                  if (!stmt.body[0].leadingComments) {
                    generateBlankLines(stmt.range[0], stmt.body[0].range[0], result);
                  }
                }
                if (i > 0) {
                  if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) {
                    generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result);
                  }
                }
              }
              if (i === iz - 1) {
                bodyFlags |= F_SEMICOLON_OPT;
              }
              if (stmt.body[i].leadingComments && preserveBlankLines) {
                fragment = that.generateStatement(stmt.body[i], bodyFlags);
              } else {
                fragment = addIndent(that.generateStatement(stmt.body[i], bodyFlags));
              }
              result.push(fragment);
              if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
                if (preserveBlankLines && i < iz - 1) {
                  if (!stmt.body[i + 1].leadingComments) {
                    result.push(newline);
                  }
                } else {
                  result.push(newline);
                }
              }
              if (preserveBlankLines) {
                if (i === iz - 1) {
                  if (!stmt.body[i].trailingComments) {
                    generateBlankLines(stmt.body[i].range[1], stmt.range[1], result);
                  }
                }
              }
            }
          });
          result.push(addIndent('}'));
          return result;
        },
        BreakStatement: function (stmt, flags) {
          if (stmt.label) {
            return 'break ' + stmt.label.name + this.semicolon(flags);
          }
          return 'break' + this.semicolon(flags);
        },
        ContinueStatement: function (stmt, flags) {
          if (stmt.label) {
            return 'continue ' + stmt.label.name + this.semicolon(flags);
          }
          return 'continue' + this.semicolon(flags);
        },
        ClassBody: function (stmt, flags) {
          var result = [
              '{',
              newline
            ], that = this;
          withIndent(function (indent) {
            var i, iz;
            for (i = 0, iz = stmt.body.length; i < iz; ++i) {
              result.push(indent);
              result.push(that.generateExpression(stmt.body[i], Precedence.Sequence, E_TTT));
              if (i + 1 < iz) {
                result.push(newline);
              }
            }
          });
          if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
            result.push(newline);
          }
          result.push(base);
          result.push('}');
          return result;
        },
        ClassDeclaration: function (stmt, flags) {
          var result, fragment;
          result = ['class'];
          if (stmt.id) {
            result = join(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
          }
          if (stmt.superClass) {
            fragment = join('extends', this.generateExpression(stmt.superClass, Precedence.Assignment, E_TTT));
            result = join(result, fragment);
          }
          result.push(space);
          result.push(this.generateStatement(stmt.body, S_TFFT));
          return result;
        },
        DirectiveStatement: function (stmt, flags) {
          if (extra.raw && stmt.raw) {
            return stmt.raw + this.semicolon(flags);
          }
          return escapeDirective(stmt.directive) + this.semicolon(flags);
        },
        DoWhileStatement: function (stmt, flags) {
          var result = join('do', this.maybeBlock(stmt.body, S_TFFF));
          result = this.maybeBlockSuffix(stmt.body, result);
          return join(result, [
            'while' + space + '(',
            this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
            ')' + this.semicolon(flags)
          ]);
        },
        CatchClause: function (stmt, flags) {
          var result, that = this;
          withIndent(function () {
            var guard;
            result = [
              'catch' + space + '(',
              that.generateExpression(stmt.param, Precedence.Sequence, E_TTT),
              ')'
            ];
            if (stmt.guard) {
              guard = that.generateExpression(stmt.guard, Precedence.Sequence, E_TTT);
              result.splice(2, 0, ' if ', guard);
            }
          });
          result.push(this.maybeBlock(stmt.body, S_TFFF));
          return result;
        },
        DebuggerStatement: function (stmt, flags) {
          return 'debugger' + this.semicolon(flags);
        },
        EmptyStatement: function (stmt, flags) {
          return ';';
        },
        ExportDefaultDeclaration: function (stmt, flags) {
          var result = ['export'], bodyFlags;
          bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
          result = join(result, 'default');
          if (isStatement(stmt.declaration)) {
            result = join(result, this.generateStatement(stmt.declaration, bodyFlags));
          } else {
            result = join(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
          }
          return result;
        },
        ExportNamedDeclaration: function (stmt, flags) {
          var result = ['export'], bodyFlags, that = this;
          bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
          if (stmt.declaration) {
            return join(result, this.generateStatement(stmt.declaration, bodyFlags));
          }
          if (stmt.specifiers) {
            if (stmt.specifiers.length === 0) {
              result = join(result, '{' + space + '}');
            } else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
              result = join(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
            } else {
              result = join(result, '{');
              withIndent(function (indent) {
                var i, iz;
                result.push(newline);
                for (i = 0, iz = stmt.specifiers.length; i < iz; ++i) {
                  result.push(indent);
                  result.push(that.generateExpression(stmt.specifiers[i], Precedence.Sequence, E_TTT));
                  if (i + 1 < iz) {
                    result.push(',' + newline);
                  }
                }
              });
              if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
                result.push(newline);
              }
              result.push(base + '}');
            }
            if (stmt.source) {
              result = join(result, [
                'from' + space,
                this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
                this.semicolon(flags)
              ]);
            } else {
              result.push(this.semicolon(flags));
            }
          }
          return result;
        },
        ExportAllDeclaration: function (stmt, flags) {
          return [
            'export' + space,
            '*' + space,
            'from' + space,
            this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
            this.semicolon(flags)
          ];
        },
        ExpressionStatement: function (stmt, flags) {
          var result, fragment;
          function isClassPrefixed(fragment) {
            var code;
            if (fragment.slice(0, 5) !== 'class') {
              return false;
            }
            code = fragment.charCodeAt(5);
            return code === 123 || esutils.code.isWhiteSpace(code) || esutils.code.isLineTerminator(code);
          }
          function isFunctionPrefixed(fragment) {
            var code;
            if (fragment.slice(0, 8) !== 'function') {
              return false;
            }
            code = fragment.charCodeAt(8);
            return code === 40 || esutils.code.isWhiteSpace(code) || code === 42 || esutils.code.isLineTerminator(code);
          }
          function isAsyncPrefixed(fragment) {
            var code, i, iz;
            if (fragment.slice(0, 5) !== 'async') {
              return false;
            }
            if (!esutils.code.isWhiteSpace(fragment.charCodeAt(5))) {
              return false;
            }
            for (i = 6, iz = fragment.length; i < iz; ++i) {
              if (!esutils.code.isWhiteSpace(fragment.charCodeAt(i))) {
                break;
              }
            }
            if (i === iz) {
              return false;
            }
            if (fragment.slice(i, i + 8) !== 'function') {
              return false;
            }
            code = fragment.charCodeAt(i + 8);
            return code === 40 || esutils.code.isWhiteSpace(code) || code === 42 || esutils.code.isLineTerminator(code);
          }
          result = [this.generateExpression(stmt.expression, Precedence.Sequence, E_TTT | F_XJS_NOINDENT)];
          fragment = toSourceNodeWhenNeeded(result).toString();
          if (fragment.charCodeAt(0) === 123 || isClassPrefixed(fragment) || isFunctionPrefixed(fragment) || isAsyncPrefixed(fragment) || directive && flags & F_DIRECTIVE_CTX && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string') {
            result = [
              '(',
              result,
              ')' + this.semicolon(flags)
            ];
          } else {
            result.push(this.semicolon(flags));
          }
          return result;
        },
        ImportDeclaration: function (stmt, flags) {
          var result, cursor, that = this;
          if (stmt.specifiers.length === 0) {
            return [
              'import',
              space,
              this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
              this.semicolon(flags)
            ];
          }
          result = ['import'];
          cursor = 0;
          if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
            result = join(result, [this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)]);
            ++cursor;
          }
          if (stmt.specifiers[cursor]) {
            if (cursor !== 0) {
              result.push(',');
            }
            if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
              result = join(result, [
                space,
                this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
              ]);
            } else {
              result.push(space + '{');
              if (stmt.specifiers.length - cursor === 1) {
                result.push(space);
                result.push(this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT));
                result.push(space + '}' + space);
              } else {
                withIndent(function (indent) {
                  var i, iz;
                  result.push(newline);
                  for (i = cursor, iz = stmt.specifiers.length; i < iz; ++i) {
                    result.push(indent);
                    result.push(that.generateExpression(stmt.specifiers[i], Precedence.Sequence, E_TTT));
                    if (i + 1 < iz) {
                      result.push(',' + newline);
                    }
                  }
                });
                if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
                  result.push(newline);
                }
                result.push(base + '}' + space);
              }
            }
          }
          result = join(result, [
            'from' + space,
            this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
            this.semicolon(flags)
          ]);
          return result;
        },
        VariableDeclarator: function (stmt, flags) {
          var itemFlags = flags & F_ALLOW_IN ? E_TTT : E_FTT;
          if (stmt.init) {
            return [
              this.generateExpression(stmt.id, Precedence.Assignment, itemFlags),
              space,
              '=',
              space,
              this.generateExpression(stmt.init, Precedence.Assignment, itemFlags)
            ];
          }
          return this.generatePattern(stmt.id, Precedence.Assignment, itemFlags);
        },
        VariableDeclaration: function (stmt, flags) {
          var result, i, iz, node, bodyFlags, that = this;
          result = [stmt.kind];
          bodyFlags = flags & F_ALLOW_IN ? S_TFFF : S_FFFF;
          function block() {
            node = stmt.declarations[0];
            if (extra.comment && node.leadingComments) {
              result.push('\n');
              result.push(addIndent(that.generateStatement(node, bodyFlags)));
            } else {
              result.push(noEmptySpace());
              result.push(that.generateStatement(node, bodyFlags));
            }
            for (i = 1, iz = stmt.declarations.length; i < iz; ++i) {
              node = stmt.declarations[i];
              if (extra.comment && node.leadingComments) {
                result.push(',' + newline);
                result.push(addIndent(that.generateStatement(node, bodyFlags)));
              } else {
                result.push(',' + space);
                result.push(that.generateStatement(node, bodyFlags));
              }
            }
          }
          if (stmt.declarations.length > 1) {
            withIndent(block);
          } else {
            block();
          }
          result.push(this.semicolon(flags));
          return result;
        },
        ThrowStatement: function (stmt, flags) {
          return [
            join('throw', this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)),
            this.semicolon(flags)
          ];
        },
        TryStatement: function (stmt, flags) {
          var result, i, iz, guardedHandlers;
          result = [
            'try',
            this.maybeBlock(stmt.block, S_TFFF)
          ];
          result = this.maybeBlockSuffix(stmt.block, result);
          if (stmt.handlers) {
            for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {
              result = join(result, this.generateStatement(stmt.handlers[i], S_TFFF));
              if (stmt.finalizer || i + 1 !== iz) {
                result = this.maybeBlockSuffix(stmt.handlers[i].body, result);
              }
            }
          } else {
            guardedHandlers = stmt.guardedHandlers || [];
            for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {
              result = join(result, this.generateStatement(guardedHandlers[i], S_TFFF));
              if (stmt.finalizer || i + 1 !== iz) {
                result = this.maybeBlockSuffix(guardedHandlers[i].body, result);
              }
            }
            if (stmt.handler) {
              if (isArray(stmt.handler)) {
                for (i = 0, iz = stmt.handler.length; i < iz; ++i) {
                  result = join(result, this.generateStatement(stmt.handler[i], S_TFFF));
                  if (stmt.finalizer || i + 1 !== iz) {
                    result = this.maybeBlockSuffix(stmt.handler[i].body, result);
                  }
                }
              } else {
                result = join(result, this.generateStatement(stmt.handler, S_TFFF));
                if (stmt.finalizer) {
                  result = this.maybeBlockSuffix(stmt.handler.body, result);
                }
              }
            }
          }
          if (stmt.finalizer) {
            result = join(result, [
              'finally',
              this.maybeBlock(stmt.finalizer, S_TFFF)
            ]);
          }
          return result;
        },
        SwitchStatement: function (stmt, flags) {
          var result, fragment, i, iz, bodyFlags, that = this;
          withIndent(function () {
            result = [
              'switch' + space + '(',
              that.generateExpression(stmt.discriminant, Precedence.Sequence, E_TTT),
              ')' + space + '{' + newline
            ];
          });
          if (stmt.cases) {
            bodyFlags = S_TFFF;
            for (i = 0, iz = stmt.cases.length; i < iz; ++i) {
              if (i === iz - 1) {
                bodyFlags |= F_SEMICOLON_OPT;
              }
              fragment = addIndent(this.generateStatement(stmt.cases[i], bodyFlags));
              result.push(fragment);
              if (!endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
                result.push(newline);
              }
            }
          }
          result.push(addIndent('}'));
          return result;
        },
        SwitchCase: function (stmt, flags) {
          var result, fragment, i, iz, bodyFlags, that = this;
          withIndent(function () {
            if (stmt.test) {
              result = [
                join('case', that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
                ':'
              ];
            } else {
              result = ['default:'];
            }
            i = 0;
            iz = stmt.consequent.length;
            if (iz && stmt.consequent[0].type === Syntax.BlockStatement) {
              fragment = that.maybeBlock(stmt.consequent[0], S_TFFF);
              result.push(fragment);
              i = 1;
            }
            if (i !== iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
              result.push(newline);
            }
            bodyFlags = S_TFFF;
            for (; i < iz; ++i) {
              if (i === iz - 1 && flags & F_SEMICOLON_OPT) {
                bodyFlags |= F_SEMICOLON_OPT;
              }
              fragment = addIndent(that.generateStatement(stmt.consequent[i], bodyFlags));
              result.push(fragment);
              if (i + 1 !== iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
                result.push(newline);
              }
            }
          });
          return result;
        },
        IfStatement: function (stmt, flags) {
          var result, bodyFlags, semicolonOptional, that = this;
          withIndent(function () {
            result = [
              'if' + space + '(',
              that.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
              ')'
            ];
          });
          semicolonOptional = flags & F_SEMICOLON_OPT;
          bodyFlags = S_TFFF;
          if (semicolonOptional) {
            bodyFlags |= F_SEMICOLON_OPT;
          }
          if (stmt.alternate) {
            result.push(this.maybeBlock(stmt.consequent, S_TFFF));
            result = this.maybeBlockSuffix(stmt.consequent, result);
            if (stmt.alternate.type === Syntax.IfStatement) {
              result = join(result, [
                'else ',
                this.generateStatement(stmt.alternate, bodyFlags)
              ]);
            } else {
              result = join(result, join('else', this.maybeBlock(stmt.alternate, bodyFlags)));
            }
          } else {
            result.push(this.maybeBlock(stmt.consequent, bodyFlags));
          }
          return result;
        },
        ForStatement: function (stmt, flags) {
          var result, that = this;
          withIndent(function () {
            result = ['for' + space + '('];
            if (stmt.init) {
              if (stmt.init.type === Syntax.VariableDeclaration) {
                result.push(that.generateStatement(stmt.init, S_FFFF));
              } else {
                result.push(that.generateExpression(stmt.init, Precedence.Sequence, E_FTT));
                result.push(';');
              }
            } else {
              result.push(';');
            }
            if (stmt.test) {
              result.push(space);
              result.push(that.generateExpression(stmt.test, Precedence.Sequence, E_TTT));
              result.push(';');
            } else {
              result.push(';');
            }
            if (stmt.update) {
              result.push(space);
              result.push(that.generateExpression(stmt.update, Precedence.Sequence, E_TTT));
              result.push(')');
            } else {
              result.push(')');
            }
          });
          result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF));
          return result;
        },
        ForInStatement: function (stmt, flags) {
          return this.generateIterationForStatement('in', stmt, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF);
        },
        ForOfStatement: function (stmt, flags) {
          return this.generateIterationForStatement('of', stmt, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF);
        },
        LabeledStatement: function (stmt, flags) {
          return [
            stmt.label.name + ':',
            this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF)
          ];
        },
        Program: function (stmt, flags) {
          var result, fragment, i, iz, bodyFlags;
          iz = stmt.body.length;
          result = [safeConcatenation && iz > 0 ? '\n' : ''];
          bodyFlags = S_TFTF;
          for (i = 0; i < iz; ++i) {
            if (!safeConcatenation && i === iz - 1) {
              bodyFlags |= F_SEMICOLON_OPT;
            }
            if (preserveBlankLines) {
              if (i === 0) {
                if (!stmt.body[0].leadingComments) {
                  generateBlankLines(stmt.range[0], stmt.body[i].range[0], result);
                }
              }
              if (i > 0) {
                if (!stmt.body[i - 1].trailingComments && !stmt.body[i].leadingComments) {
                  generateBlankLines(stmt.body[i - 1].range[1], stmt.body[i].range[0], result);
                }
              }
            }
            fragment = addIndent(this.generateStatement(stmt.body[i], bodyFlags));
            result.push(fragment);
            if (i + 1 < iz && !endsWithLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
              if (preserveBlankLines) {
                if (!stmt.body[i + 1].leadingComments) {
                  result.push(newline);
                }
              } else {
                result.push(newline);
              }
            }
            if (preserveBlankLines) {
              if (i === iz - 1) {
                if (!stmt.body[i].trailingComments) {
                  generateBlankLines(stmt.body[i].range[1], stmt.range[1], result);
                }
              }
            }
          }
          return result;
        },
        FunctionDeclaration: function (stmt, flags) {
          return [
            generateAsyncPrefix(stmt, true),
            'function',
            generateStarSuffix(stmt) || noEmptySpace(),
            stmt.id ? generateIdentifier(stmt.id) : '',
            this.generateFunctionBody(stmt)
          ];
        },
        ReturnStatement: function (stmt, flags) {
          if (stmt.argument) {
            return [
              join('return', this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)),
              this.semicolon(flags)
            ];
          }
          return ['return' + this.semicolon(flags)];
        },
        WhileStatement: function (stmt, flags) {
          var result, that = this;
          withIndent(function () {
            result = [
              'while' + space + '(',
              that.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
              ')'
            ];
          });
          result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF));
          return result;
        },
        WithStatement: function (stmt, flags) {
          var result, that = this;
          withIndent(function () {
            result = [
              'with' + space + '(',
              that.generateExpression(stmt.object, Precedence.Sequence, E_TTT),
              ')'
            ];
          });
          result.push(this.maybeBlock(stmt.body, flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF));
          return result;
        }
      };
      merge(CodeGenerator.prototype, CodeGenerator.Statement);
      CodeGenerator.Expression = {
        SequenceExpression: function (expr, precedence, flags) {
          var result, i, iz;
          if (Precedence.Sequence < precedence) {
            flags |= F_ALLOW_IN;
          }
          result = [];
          for (i = 0, iz = expr.expressions.length; i < iz; ++i) {
            result.push(this.generateExpression(expr.expressions[i], Precedence.Assignment, flags));
            if (i + 1 < iz) {
              result.push(',' + space);
            }
          }
          return parenthesize(result, Precedence.Sequence, precedence);
        },
        AssignmentExpression: function (expr, precedence, flags) {
          return this.generateAssignment(expr.left, expr.right, expr.operator, precedence, flags);
        },
        ArrowFunctionExpression: function (expr, precedence, flags) {
          return parenthesize(this.generateFunctionBody(expr), Precedence.ArrowFunction, precedence);
        },
        ConditionalExpression: function (expr, precedence, flags) {
          if (Precedence.Conditional < precedence) {
            flags |= F_ALLOW_IN;
          }
          return parenthesize([
            this.generateExpression(expr.test, Precedence.LogicalOR, flags),
            space + '?' + space,
            this.generateExpression(expr.consequent, Precedence.Assignment, flags),
            space + ':' + space,
            this.generateExpression(expr.alternate, Precedence.Assignment, flags)
          ], Precedence.Conditional, precedence);
        },
        LogicalExpression: function (expr, precedence, flags) {
          return this.BinaryExpression(expr, precedence, flags);
        },
        BinaryExpression: function (expr, precedence, flags) {
          var result, currentPrecedence, fragment, leftSource;
          currentPrecedence = BinaryPrecedence[expr.operator];
          if (currentPrecedence < precedence) {
            flags |= F_ALLOW_IN;
          }
          fragment = this.generateExpression(expr.left, currentPrecedence, flags);
          leftSource = fragment.toString();
          if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
            result = [
              fragment,
              noEmptySpace(),
              expr.operator
            ];
          } else {
            result = join(fragment, expr.operator);
          }
          fragment = this.generateExpression(expr.right, currentPrecedence + 1, flags);
          if (expr.operator === '/' && fragment.toString().charAt(0) === '/' || expr.operator.slice(-1) === '<' && fragment.toString().slice(0, 3) === '!--') {
            result.push(noEmptySpace());
            result.push(fragment);
          } else {
            result = join(result, fragment);
          }
          if (expr.operator === 'in' && !(flags & F_ALLOW_IN)) {
            return [
              '(',
              result,
              ')'
            ];
          }
          return parenthesize(result, currentPrecedence, precedence);
        },
        CallExpression: function (expr, precedence, flags) {
          var result, i, iz;
          result = [this.generateExpression(expr.callee, Precedence.Call, E_TTF)];
          result.push('(');
          for (i = 0, iz = expr['arguments'].length; i < iz; ++i) {
            result.push(this.generateExpression(expr['arguments'][i], Precedence.Assignment, E_TTT | F_XJS_NOPAREN));
            if (i + 1 < iz) {
              result.push(',' + space);
            }
          }
          result.push(')');
          if (!(flags & F_ALLOW_CALL)) {
            return [
              '(',
              result,
              ')'
            ];
          }
          return parenthesize(result, Precedence.Call, precedence);
        },
        NewExpression: function (expr, precedence, flags) {
          var result, length, i, iz, itemFlags;
          length = expr['arguments'].length;
          itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
          result = join('new', this.generateExpression(expr.callee, Precedence.New, itemFlags));
          if (!(flags & F_ALLOW_UNPARATH_NEW) || parentheses || length > 0) {
            result.push('(');
            for (i = 0, iz = length; i < iz; ++i) {
              result.push(this.generateExpression(expr['arguments'][i], Precedence.Assignment, E_TTT));
              if (i + 1 < iz) {
                result.push(',' + space);
              }
            }
            result.push(')');
          }
          return parenthesize(result, Precedence.New, precedence);
        },
        MemberExpression: function (expr, precedence, flags) {
          var result, fragment;
          result = [this.generateExpression(expr.object, Precedence.Call, flags & F_ALLOW_CALL ? E_TTF : E_TFF)];
          if (expr.computed) {
            result.push('[');
            result.push(this.generateExpression(expr.property, Precedence.Sequence, flags & F_ALLOW_CALL ? E_TTT : E_TFT));
            result.push(']');
          } else {
            if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
              fragment = toSourceNodeWhenNeeded(result).toString();
              if (fragment.indexOf('.') < 0 && !/[eExX]/.test(fragment) && esutils.code.isDecimalDigit(fragment.charCodeAt(fragment.length - 1)) && !(fragment.length >= 2 && fragment.charCodeAt(0) === 48)) {
                result.push('.');
              }
            }
            result.push('.');
            result.push(generateIdentifier(expr.property));
          }
          return parenthesize(result, Precedence.Member, precedence);
        },
        MetaProperty: function (expr, precedence, flags) {
          var result, meta, property;
          meta = expr.meta && typeof expr.meta.type === 'string' && expr.meta.type === Syntax.Identifier ? expr.meta.name : expr.meta;
          property = expr.property && typeof expr.property.type === 'string' && expr.property.type === Syntax.Identifier ? expr.property.name : expr.property;
          result = [
            meta,
            '.',
            property
          ];
          return parenthesize(result, Precedence.Member, precedence);
        },
        UnaryExpression: function (expr, precedence, flags) {
          var result, fragment, rightCharCode, leftSource, leftCharCode;
          fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
          if (space === '') {
            result = join(expr.operator, fragment);
          } else {
            result = [expr.operator];
            if (expr.operator.length > 2) {
              result = join(result, fragment);
            } else {
              leftSource = toSourceNodeWhenNeeded(result).toString();
              leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
              rightCharCode = fragment.toString().charCodeAt(0);
              if ((leftCharCode === 43 || leftCharCode === 45) && leftCharCode === rightCharCode || esutils.code.isIdentifierPartES5(leftCharCode) && esutils.code.isIdentifierPartES5(rightCharCode)) {
                result.push(noEmptySpace());
                result.push(fragment);
              } else {
                result.push(fragment);
              }
            }
          }
          return parenthesize(result, Precedence.Unary, precedence);
        },
        YieldExpression: function (expr, precedence, flags) {
          var result;
          if (expr.delegate) {
            result = 'yield*';
          } else {
            result = 'yield';
          }
          if (expr.argument) {
            result = join(result, this.generateExpression(expr.argument, Precedence.Yield, E_TTT));
          }
          return parenthesize(result, Precedence.Yield, precedence);
        },
        AwaitExpression: function (expr, precedence, flags) {
          var result = join(expr.all ? 'await*' : 'await', this.generateExpression(expr.argument, Precedence.Await, E_TTT));
          return parenthesize(result, Precedence.Await, precedence);
        },
        UpdateExpression: function (expr, precedence, flags) {
          if (expr.prefix) {
            return parenthesize([
              expr.operator,
              this.generateExpression(expr.argument, Precedence.Unary, E_TTT)
            ], Precedence.Unary, precedence);
          }
          return parenthesize([
            this.generateExpression(expr.argument, Precedence.Postfix, E_TTT),
            expr.operator
          ], Precedence.Postfix, precedence);
        },
        FunctionExpression: function (expr, precedence, flags) {
          var result = [
              generateAsyncPrefix(expr, true),
              'function'
            ];
          if (expr.id) {
            result.push(generateStarSuffix(expr) || noEmptySpace());
            result.push(generateIdentifier(expr.id));
          } else {
            result.push(generateStarSuffix(expr) || space);
          }
          result.push(this.generateFunctionBody(expr));
          return result;
        },
        ArrayPattern: function (expr, precedence, flags) {
          return this.ArrayExpression(expr, precedence, flags, true);
        },
        ArrayExpression: function (expr, precedence, flags, isPattern) {
          var result, multiline, that = this;
          if (!expr.elements.length) {
            return '[]';
          }
          multiline = isPattern ? false : expr.elements.length > 1;
          result = [
            '[',
            multiline ? newline : ''
          ];
          withIndent(function (indent) {
            var i, iz;
            for (i = 0, iz = expr.elements.length; i < iz; ++i) {
              if (!expr.elements[i]) {
                if (multiline) {
                  result.push(indent);
                }
                if (i + 1 === iz) {
                  result.push(',');
                }
              } else {
                result.push(multiline ? indent : '');
                result.push(that.generateExpression(expr.elements[i], Precedence.Assignment, E_TTT | F_XJS_NOINDENT | F_XJS_NOPAREN));
              }
              if (i + 1 < iz) {
                result.push(',' + (multiline ? newline : space));
              }
            }
          });
          if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
            result.push(newline);
          }
          result.push(multiline ? base : '');
          result.push(']');
          return result;
        },
        ClassExpression: function (expr, precedence, flags) {
          var result, fragment;
          result = ['class'];
          if (expr.id) {
            result = join(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
          }
          if (expr.superClass) {
            fragment = join('extends', this.generateExpression(expr.superClass, Precedence.Assignment, E_TTT));
            result = join(result, fragment);
          }
          result.push(space);
          result.push(this.generateStatement(expr.body, S_TFFT));
          return result;
        },
        MethodDefinition: function (expr, precedence, flags) {
          var result, fragment;
          if (expr['static']) {
            result = ['static' + space];
          } else {
            result = [];
          }
          if (expr.kind === 'get' || expr.kind === 'set') {
            fragment = [
              join(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
              this.generateFunctionBody(expr.value)
            ];
          } else {
            fragment = [
              generateMethodPrefix(expr),
              this.generatePropertyKey(expr.key, expr.computed),
              this.generateFunctionBody(expr.value)
            ];
          }
          return join(result, fragment);
        },
        Property: function (expr, precedence, flags) {
          if (expr.kind === 'get' || expr.kind === 'set') {
            return [
              expr.kind,
              noEmptySpace(),
              this.generatePropertyKey(expr.key, expr.computed),
              this.generateFunctionBody(expr.value)
            ];
          }
          if (expr.kind === 'init' && !expr.method && expr.shorthand) {
            return this.generatePattern(expr.value, Precedence.Assignment, E_TTT);
          }
          if (expr.shorthand) {
            return this.generatePropertyKey(expr.key, expr.computed);
          }
          if (expr.method) {
            return [
              generateMethodPrefix(expr),
              this.generatePropertyKey(expr.key, expr.computed),
              this.generateFunctionBody(expr.value)
            ];
          }
          return [
            this.generatePropertyKey(expr.key, expr.computed),
            ':' + space,
            this.generateExpression(expr.value, Precedence.Assignment, E_TTT)
          ];
        },
        ObjectExpression: function (expr, precedence, flags) {
          var multiline, result, fragment, that = this;
          if (!expr.properties.length) {
            return '{}';
          }
          multiline = expr.properties.length > 1;
          withIndent(function () {
            fragment = that.generateExpression(expr.properties[0], Precedence.Sequence, E_TTT);
          });
          if (!multiline) {
            if (!hasLineTerminator(toSourceNodeWhenNeeded(fragment).toString())) {
              return [
                '{',
                space,
                fragment,
                space,
                '}'
              ];
            }
          }
          withIndent(function (indent) {
            var i, iz;
            result = [
              '{',
              newline,
              indent,
              fragment
            ];
            if (multiline) {
              result.push(',' + newline);
              for (i = 1, iz = expr.properties.length; i < iz; ++i) {
                result.push(indent);
                result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT));
                if (i + 1 < iz) {
                  result.push(',' + newline);
                }
              }
            }
          });
          if (!endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
            result.push(newline);
          }
          result.push(base);
          result.push('}');
          return result;
        },
        AssignmentPattern: function (expr, precedence, flags) {
          return this.generateAssignment(expr.left, expr.right, '=', precedence, flags);
        },
        ObjectPattern: function (expr, precedence, flags) {
          var result, i, iz, multiline, property, that = this;
          if (!expr.properties.length) {
            return '{}';
          }
          multiline = false;
          if (expr.properties.length === 1) {
            property = expr.properties[0];
            if (property.value && property.value.type !== Syntax.Identifier) {
              multiline = true;
            }
          } else {
            for (i = 0, iz = expr.properties.length; i < iz; ++i) {
              property = expr.properties[i];
              if (!property.shorthand) {
                multiline = true;
                break;
              }
            }
          }
          result = [
            '{',
            multiline ? newline : ''
          ];
          withIndent(function (indent) {
            var i, iz;
            for (i = 0, iz = expr.properties.length; i < iz; ++i) {
              result.push(multiline ? indent : '');
              result.push(that.generateExpression(expr.properties[i], Precedence.Sequence, E_TTT));
              if (i + 1 < iz) {
                result.push(',' + (multiline ? newline : space));
              }
            }
          });
          if (multiline && !endsWithLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
            result.push(newline);
          }
          result.push(multiline ? base : '');
          result.push('}');
          return result;
        },
        ThisExpression: function (expr, precedence, flags) {
          return 'this';
        },
        Super: function (expr, precedence, flags) {
          return 'super';
        },
        Identifier: function (expr, precedence, flags) {
          return generateIdentifier(expr);
        },
        Import: function (expr, precedence, flags) {
          return 'import';
        },
        ImportDefaultSpecifier: function (expr, precedence, flags) {
          return generateIdentifier(expr.id || expr.local);
        },
        ImportNamespaceSpecifier: function (expr, precedence, flags) {
          var result = ['*'];
          var id = expr.id || expr.local;
          if (id) {
            result.push(space + 'as' + noEmptySpace() + generateIdentifier(id));
          }
          return result;
        },
        ImportSpecifier: function (expr, precedence, flags) {
          var imported = expr.imported;
          var result = [imported.name];
          var local = expr.local;
          if (local && local.name !== imported.name) {
            result.push(noEmptySpace() + 'as' + noEmptySpace() + generateIdentifier(local));
          }
          return result;
        },
        ExportSpecifier: function (expr, precedence, flags) {
          var local = expr.local;
          var result = [local.name];
          var exported = expr.exported;
          if (exported && exported.name !== local.name) {
            result.push(noEmptySpace() + 'as' + noEmptySpace() + generateIdentifier(exported));
          }
          return result;
        },
        Literal: function (expr, precedence, flags) {
          var raw;
          if (expr.hasOwnProperty('raw') && parse && extra.raw) {
            try {
              raw = parse(expr.raw).body[0].expression;
              if (raw.type === Syntax.Literal) {
                if (raw.value === expr.value) {
                  return expr.raw;
                }
              }
            } catch (e) {
            }
          }
          if (expr.value === null) {
            return 'null';
          }
          if (typeof expr.value === 'string') {
            return escapeString(expr.value);
          }
          if (typeof expr.value === 'number') {
            return generateNumber(expr.value);
          }
          if (typeof expr.value === 'boolean') {
            return expr.value ? 'true' : 'false';
          }
          return generateRegExp(expr.value);
        },
        GeneratorExpression: function (expr, precedence, flags) {
          return this.ComprehensionExpression(expr, precedence, flags);
        },
        ComprehensionExpression: function (expr, precedence, flags) {
          var result, i, iz, fragment, that = this;
          result = expr.type === Syntax.GeneratorExpression ? ['('] : ['['];
          if (extra.moz.comprehensionExpressionStartsWithAssignment) {
            fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
            result.push(fragment);
          }
          if (expr.blocks) {
            withIndent(function () {
              for (i = 0, iz = expr.blocks.length; i < iz; ++i) {
                fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);
                if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
                  result = join(result, fragment);
                } else {
                  result.push(fragment);
                }
              }
            });
          }
          if (expr.filter) {
            result = join(result, 'if' + space);
            fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
            result = join(result, [
              '(',
              fragment,
              ')'
            ]);
          }
          if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
            fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
            result = join(result, fragment);
          }
          result.push(expr.type === Syntax.GeneratorExpression ? ')' : ']');
          return result;
        },
        ComprehensionBlock: function (expr, precedence, flags) {
          var fragment;
          if (expr.left.type === Syntax.VariableDeclaration) {
            fragment = [
              expr.left.kind,
              noEmptySpace(),
              this.generateStatement(expr.left.declarations[0], S_FFFF)
            ];
          } else {
            fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
          }
          fragment = join(fragment, expr.of ? 'of' : 'in');
          fragment = join(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
          return [
            'for' + space + '(',
            fragment,
            ')'
          ];
        },
        SpreadElement: function (expr, precedence, flags) {
          return [
            '...',
            this.generateExpression(expr.argument, Precedence.Assignment, E_TTT)
          ];
        },
        RestElement: function (expr, precedence, flags) {
          return [
            '...',
            this.generatePattern(expr.argument, Precedence.Assignment, E_TTT)
          ];
        },
        SpreadProperty: function (expr, precedence, flags) {
          return [
            '...',
            this.generateExpression(expr.argument, Precedence.Assignment, E_TTT)
          ];
        },
        RestProperty: function (expr, precedence, flags) {
          return [
            '...',
            this.generatePattern(expr.argument, Precedence.Assignment, E_TTT)
          ];
        },
        TaggedTemplateExpression: function (expr, precedence, flags) {
          var itemFlags = E_TTF;
          if (!(flags & F_ALLOW_CALL)) {
            itemFlags = E_TFF;
          }
          var result = [
              this.generateExpression(expr.tag, Precedence.Call, itemFlags),
              this.generateExpression(expr.quasi, Precedence.Primary, E_FFT)
            ];
          return parenthesize(result, Precedence.TaggedTemplate, precedence);
        },
        TemplateElement: function (expr, precedence, flags) {
          return expr.value.raw;
        },
        TemplateLiteral: function (expr, precedence, flags) {
          var result, i, iz;
          result = ['`'];
          for (i = 0, iz = expr.quasis.length; i < iz; ++i) {
            result.push(this.generateExpression(expr.quasis[i], Precedence.Primary, E_TTT));
            if (i + 1 < iz) {
              result.push('${' + space);
              result.push(this.generateExpression(expr.expressions[i], Precedence.Sequence, E_TTT));
              result.push(space + '}');
            }
          }
          result.push('`');
          return result;
        },
        ModuleSpecifier: function (expr, precedence, flags) {
          return this.Literal(expr, precedence, flags);
        },
        JSXText: function (expr, precedence, flags) {
          if (expr.hasOwnProperty('raw')) {
            return expr.raw;
          }
          return String(expr.value);
        },
        JSXAttribute: function (expr, precedence, flags) {
          var result = [];
          var fragment = this.generateExpression(expr.name, Precedence.Sequence, {
              allowIn: true,
              allowCall: true
            });
          result.push(fragment);
          if (expr.value) {
            result.push('=');
            if (expr.value.type === Syntax.Literal) {
              fragment = xjsEscapeAttr(expr.value.value, expr.value.raw);
            } else {
              fragment = this.generateExpression(expr.value, Precedence.Sequence, {
                allowIn: true,
                allowCall: true
              });
            }
            result.push(fragment);
          }
          return result;
        },
        JSXClosingElement: function (expr, precedence, flags) {
          return [
            '</',
            this.generateExpression(expr.name, Precedence.Sequence, 0),
            '>'
          ];
        },
        JSXElement: function (expr, precedence, flags) {
          var result = [], that = this;
          if (!(flags & F_XJS_NOINDENT)) {
            base += indent;
          }
          var fragment = this.generateExpression(expr.openingElement, Precedence.JSXElement, {
              allowIn: true,
              allowCall: true
            });
          result.push(fragment);
          var xjsFragments = [];
          var i, len;
          withIndent(function (indent) {
            for (i = 0, len = expr.children.length; i < len; ++i) {
              if (expr.children[i].type === Syntax.Literal) {
                fragment = expr.children[i].raw;
                if (fragment) {
                  xjsFragments.push(fragment);
                }
                continue;
              }
              fragment = that.generateExpression(expr.children[i], Precedence.JSXElement, E_TTF | F_XJS_NOINDENT);
              xjsFragments.push(fragment);
            }
            for (i = 0, len = xjsFragments.length; i < len; ++i) {
              result.push(xjsFragments[i]);
            }
          });
          if (expr.closingElement) {
            fragment = that.generateExpression(expr.closingElement, Precedence.JSXElement, 0);
            result.push(fragment);
          }
          if (!(flags & F_XJS_NOINDENT)) {
            base = base.slice(0, base.length - indent.length);
            if (hasLineTerminator(toSourceNodeWhenNeeded(result).toString())) {
              if (flags & F_XJS_NOPAREN) {
                result = [
                  newline + base + indent,
                  result
                ];
              } else {
                result = [
                  '(' + newline + base + indent,
                  result,
                  newline + base + ')'
                ];
              }
            }
          }
          return result;
        },
        JSXExpressionContainer: function (expr, precedence, flags) {
          return [
            '{',
            this.generateExpression(expr.expression, Precedence.Sequence, E_TTF),
            '}'
          ];
        },
        JSXIdentifier: function (expr, precedence, flags) {
          return expr.name;
        },
        JSXMemberExpression: function (expr, precedence, flags) {
          return [
            this.generateExpression(expr.object, Precedence.Sequence, E_TFF),
            '.',
            this.generateExpression(expr.property, Precedence.Sequence, 0)
          ];
        },
        JSXNamespacedName: function (expr, precedence, flags) {
          return [
            this.generateExpression(expr.namespace, Precedence.Sequence, 0),
            ':',
            this.generateExpression(expr.name, Precedence.Sequence, 0)
          ];
        },
        JSXOpeningElement: function (expr, precedence, flags) {
          var result = ['<'], that = this;
          var fragment = this.generateExpression(expr.name, Precedence.Sequence, 0);
          result.push(fragment);
          var xjsFragments = [];
          for (var i = 0, len = expr.attributes.length; i < len; ++i) {
            fragment = that.generateExpression(expr.attributes[i], Precedence.Sequence, E_TTF);
            xjsFragments.push({
              expr: expr.attributes[i],
              name: expr.attributes[i].name && expr.attributes[i].name.name,
              fragment: fragment,
              multiline: hasLineTerminator(toSourceNodeWhenNeeded(fragment).toString())
            });
            if (expr.attributes.length > 3 && expr.attributes[i].value && expr.attributes[i].value.type !== Syntax.Literal) {
              xjsFragments[xjsFragments.length - 1].multiline = true;
            }
          }
          withIndent(function (indent) {
            for (var i = 0, len = xjsFragments.length; i < len; ++i) {
              if (i > 0 && i % 3 === 0 || xjsFragments[i].multiline) {
                result.push(newline + indent);
              } else {
                result.push(' ');
              }
              result.push(that.generateExpression(xjsFragments[i].expr, Precedence.Sequence, E_TTF));
            }
          });
          result.push(expr.selfClosing ? '/>' : '>');
          return result;
        },
        JSXSpreadAttribute: function (expr, precedence, flags) {
          return [
            '{...',
            this.generateExpression(expr.argument, Precedence.Sequence, {
              allowIn: true,
              allowCall: true
            }),
            '}'
          ];
        }
      };
      merge(CodeGenerator.prototype, CodeGenerator.Expression);
      CodeGenerator.prototype.generateExpression = function (expr, precedence, flags) {
        var result, type;
        type = expr.type || Syntax.Property;
        if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) {
          return generateVerbatim(expr, precedence);
        }
        result = this[type](expr, precedence, flags);
        if (extra.comment) {
          result = addComments(expr, result);
        }
        return toSourceNodeWhenNeeded(result, expr);
      };
      CodeGenerator.prototype.generateStatement = function (stmt, flags) {
        var result, fragment;
        result = this[stmt.type](stmt, flags);
        if (extra.comment) {
          result = addComments(stmt, result);
        }
        fragment = toSourceNodeWhenNeeded(result).toString();
        if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') {
          result = sourceMap ? toSourceNodeWhenNeeded(result).replaceRight(/\s+$/, '') : fragment.replace(/\s+$/, '');
        }
        return toSourceNodeWhenNeeded(result, stmt);
      };
      function generateInternal(node) {
        var codegen;
        codegen = new CodeGenerator;
        if (isStatement(node)) {
          return codegen.generateStatement(node, S_TFFF);
        }
        if (isExpression(node)) {
          return codegen.generateExpression(node, Precedence.Sequence, E_TTT);
        }
        throw new Error('Unknown node type: ' + node.type);
      }
      function generate(node, options) {
        var defaultOptions = getDefaultOptions(), result, pair;
        if (options != null) {
          if (typeof options.indent === 'string') {
            defaultOptions.format.indent.style = options.indent;
          }
          if (typeof options.base === 'number') {
            defaultOptions.format.indent.base = options.base;
          }
          options = updateDeeply(defaultOptions, options);
          indent = options.format.indent.style;
          if (typeof options.base === 'string') {
            base = options.base;
          } else {
            base = stringRepeat(indent, options.format.indent.base);
          }
        } else {
          options = defaultOptions;
          indent = options.format.indent.style;
          base = stringRepeat(indent, options.format.indent.base);
        }
        json = options.format.json;
        renumber = options.format.renumber;
        hexadecimal = json ? false : options.format.hexadecimal;
        quotes = json ? 'double' : options.format.quotes;
        escapeless = options.format.escapeless;
        newline = options.format.newline;
        space = options.format.space;
        if (options.format.compact) {
          newline = space = indent = base = '';
        }
        parentheses = options.format.parentheses;
        semicolons = options.format.semicolons;
        safeConcatenation = options.format.safeConcatenation;
        directive = options.directive;
        parse = json ? null : options.parse;
        sourceMap = options.sourceMap;
        sourceCode = options.sourceCode;
        preserveBlankLines = options.format.preserveBlankLines && sourceCode !== null;
        extra = options;
        if (sourceMap) {
          if (!exports.browser) {
            SourceNode = require('/node_modules/source-map/lib/source-map.js', module).SourceNode;
          } else {
            SourceNode = global.sourceMap.SourceNode;
          }
        }
        result = generateInternal(node);
        if (!sourceMap) {
          pair = {
            code: result.toString(),
            map: null
          };
          return options.sourceMapWithCode ? pair : pair.code;
        }
        pair = result.toStringWithSourceMap({
          file: options.file,
          sourceRoot: options.sourceMapRoot
        });
        if (options.sourceContent) {
          pair.map.setSourceContent(options.sourceMap, options.sourceContent);
        }
        if (options.sourceMapWithCode) {
          return pair;
        }
        return pair.map.toString();
      }
      function xjsEscapeAttr(s, raw) {
        if (s.indexOf('"') >= 0 || s.indexOf("'") >= 0) {
          return raw;
        }
        return quotes === 'double' ? '"' + s + '"' : "'" + s + "'";
      }
      FORMAT_MINIFY = {
        indent: {
          style: '',
          base: 0
        },
        renumber: true,
        hexadecimal: true,
        quotes: 'auto',
        escapeless: true,
        compact: true,
        parentheses: false,
        semicolons: false
      };
      FORMAT_DEFAULTS = getDefaultOptions().format;
      exports.version = require('/package.json', module).version;
      exports.generate = generate;
      exports.attachComments = estraverse.attachComments;
      exports.Precedence = updateDeeply({}, Precedence);
      exports.browser = false;
      exports.FORMAT_MINIFY = FORMAT_MINIFY;
      exports.FORMAT_DEFAULTS = FORMAT_DEFAULTS;
    }());
  });
  require.define('/package.json', function (module, exports, __dirname, __filename) {
    module.exports = {
      'name': 'escodegen-wallaby',
      'description': 'ECMAScript code generator with JSX support',
      'homepage': 'http://github.com/wallabyjs/escodegen',
      'main': 'escodegen.js',
      'bin': {
        'esgenerate': './bin/esgenerate.js',
        'escodegen': './bin/escodegen.js'
      },
      'files': [
        'LICENSE.BSD',
        'LICENSE.source-map',
        'README.md',
        'bin',
        'escodegen.js',
        'package.json'
      ],
      'version': '1.6.12',
      'engines': { 'node': '>=0.10.0' },
      'maintainers': [{
          'name': 'Artem Govorov',
          'email': 'artem.govorov@gmail.com',
          'web': 'http://dm.gl'
        }],
      'repository': {
        'type': 'git',
        'url': 'http://github.com/wallabyjs/escodegen.git'
      },
      'dependencies': {
        'estraverse': '^1.9.1',
        'esutils': '^2.0.2',
        'esprima': '^2.7.1',
        'optionator': '^0.8.1'
      },
      'optionalDependencies': { 'source-map': '~0.2.0' },
      'devDependencies': {
        'acorn': '^2.7.0',
        'acorn-babel': '^0.11.1-38',
        'bluebird': '^2.3.11',
        'bower-registry-client': '^0.2.1',
        'chai': '^1.10.0',
        'commonjs-everywhere': '^0.9.7',
        'gulp': '^3.8.10',
        'gulp-eslint': '^0.2.0',
        'gulp-mocha': '^2.0.0',
        'semver': '^5.1.0'
      },
      'licenses': [{
          'type': 'BSD',
          'url': 'http://github.com/wallabyjs/escodegen/raw/master/LICENSE.BSD'
        }],
      'scripts': {
        'test': 'gulp travis',
        'unit-test': 'gulp test',
        'lint': 'gulp lint',
        'release': 'node tools/release.js',
        'build-min': './node_modules/.bin/cjsify -ma path: tools/entry-point.js > escodegen.browser.min.js',
        'build': './node_modules/.bin/cjsify -a path: tools/entry-point.js > escodegen.browser.js'
      }
    };
  });
  require.define('/node_modules/source-map/lib/source-map.js', function (module, exports, __dirname, __filename) {
    exports.SourceMapGenerator = require('/node_modules/source-map/lib/source-map/source-map-generator.js', module).SourceMapGenerator;
    exports.SourceMapConsumer = require('/node_modules/source-map/lib/source-map/source-map-consumer.js', module).SourceMapConsumer;
    exports.SourceNode = require('/node_modules/source-map/lib/source-map/source-node.js', module).SourceNode;
  });
  require.define('/node_modules/source-map/lib/source-map/source-node.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var SourceMapGenerator = require('/node_modules/source-map/lib/source-map/source-map-generator.js', module).SourceMapGenerator;
      var util = require('/node_modules/source-map/lib/source-map/util.js', module);
      var REGEX_NEWLINE = /(\r?\n)/;
      var NEWLINE_CODE = 10;
      var isSourceNode = '$$$isSourceNode$$$';
      function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
        this.children = [];
        this.sourceContents = {};
        this.line = aLine == null ? null : aLine;
        this.column = aColumn == null ? null : aColumn;
        this.source = aSource == null ? null : aSource;
        this.name = aName == null ? null : aName;
        this[isSourceNode] = true;
        if (aChunks != null)
          this.add(aChunks);
      }
      SourceNode.fromStringWithSourceMap = function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
        var node = new SourceNode;
        var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
        var shiftNextLine = function () {
          var lineContents = remainingLines.shift();
          var newLine = remainingLines.shift() || '';
          return lineContents + newLine;
        };
        var lastGeneratedLine = 1, lastGeneratedColumn = 0;
        var lastMapping = null;
        aSourceMapConsumer.eachMapping(function (mapping) {
          if (lastMapping !== null) {
            if (lastGeneratedLine < mapping.generatedLine) {
              var code = '';
              addMappingWithCode(lastMapping, shiftNextLine());
              lastGeneratedLine++;
              lastGeneratedColumn = 0;
            } else {
              var nextLine = remainingLines[0];
              var code = nextLine.substr(0, mapping.generatedColumn - lastGeneratedColumn);
              remainingLines[0] = nextLine.substr(mapping.generatedColumn - lastGeneratedColumn);
              lastGeneratedColumn = mapping.generatedColumn;
              addMappingWithCode(lastMapping, code);
              lastMapping = mapping;
              return;
            }
          }
          while (lastGeneratedLine < mapping.generatedLine) {
            node.add(shiftNextLine());
            lastGeneratedLine++;
          }
          if (lastGeneratedColumn < mapping.generatedColumn) {
            var nextLine = remainingLines[0];
            node.add(nextLine.substr(0, mapping.generatedColumn));
            remainingLines[0] = nextLine.substr(mapping.generatedColumn);
            lastGeneratedColumn = mapping.generatedColumn;
          }
          lastMapping = mapping;
        }, this);
        if (remainingLines.length > 0) {
          if (lastMapping) {
            addMappingWithCode(lastMapping, shiftNextLine());
          }
          node.add(remainingLines.join(''));
        }
        aSourceMapConsumer.sources.forEach(function (sourceFile) {
          var content = aSourceMapConsumer.sourceContentFor(sourceFile);
          if (content != null) {
            if (aRelativePath != null) {
              sourceFile = util.join(aRelativePath, sourceFile);
            }
            node.setSourceContent(sourceFile, content);
          }
        });
        return node;
        function addMappingWithCode(mapping, code) {
          if (mapping === null || mapping.source === undefined) {
            node.add(code);
          } else {
            var source = aRelativePath ? util.join(aRelativePath, mapping.source) : mapping.source;
            node.add(new SourceNode(mapping.originalLine, mapping.originalColumn, source, code, mapping.name));
          }
        }
      };
      SourceNode.prototype.add = function SourceNode_add(aChunk) {
        if (Array.isArray(aChunk)) {
          aChunk.forEach(function (chunk) {
            this.add(chunk);
          }, this);
        } else if (aChunk[isSourceNode] || typeof aChunk === 'string') {
          if (aChunk) {
            this.children.push(aChunk);
          }
        } else {
          throw new TypeError('Expected a SourceNode, string, or an array of SourceNodes and strings. Got ' + aChunk);
        }
        return this;
      };
      SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
        if (Array.isArray(aChunk)) {
          for (var i = aChunk.length - 1; i >= 0; i--) {
            this.prepend(aChunk[i]);
          }
        } else if (aChunk[isSourceNode] || typeof aChunk === 'string') {
          this.children.unshift(aChunk);
        } else {
          throw new TypeError('Expected a SourceNode, string, or an array of SourceNodes and strings. Got ' + aChunk);
        }
        return this;
      };
      SourceNode.prototype.walk = function SourceNode_walk(aFn) {
        var chunk;
        for (var i = 0, len = this.children.length; i < len; i++) {
          chunk = this.children[i];
          if (chunk[isSourceNode]) {
            chunk.walk(aFn);
          } else {
            if (chunk !== '') {
              aFn(chunk, {
                source: this.source,
                line: this.line,
                column: this.column,
                name: this.name
              });
            }
          }
        }
      };
      SourceNode.prototype.join = function SourceNode_join(aSep) {
        var newChildren;
        var i;
        var len = this.children.length;
        if (len > 0) {
          newChildren = [];
          for (i = 0; i < len - 1; i++) {
            newChildren.push(this.children[i]);
            newChildren.push(aSep);
          }
          newChildren.push(this.children[i]);
          this.children = newChildren;
        }
        return this;
      };
      SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
        var lastChild = this.children[this.children.length - 1];
        if (lastChild[isSourceNode]) {
          lastChild.replaceRight(aPattern, aReplacement);
        } else if (typeof lastChild === 'string') {
          this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
        } else {
          this.children.push(''.replace(aPattern, aReplacement));
        }
        return this;
      };
      SourceNode.prototype.setSourceContent = function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
        this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
      };
      SourceNode.prototype.walkSourceContents = function SourceNode_walkSourceContents(aFn) {
        for (var i = 0, len = this.children.length; i < len; i++) {
          if (this.children[i][isSourceNode]) {
            this.children[i].walkSourceContents(aFn);
          }
        }
        var sources = Object.keys(this.sourceContents);
        for (var i = 0, len = sources.length; i < len; i++) {
          aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
        }
      };
      SourceNode.prototype.toString = function SourceNode_toString() {
        var str = '';
        this.walk(function (chunk) {
          str += chunk;
        });
        return str;
      };
      SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
        var generated = {
            code: '',
            line: 1,
            column: 0
          };
        var map = new SourceMapGenerator(aArgs);
        var sourceMappingActive = false;
        var lastOriginalSource = null;
        var lastOriginalLine = null;
        var lastOriginalColumn = null;
        var lastOriginalName = null;
        this.walk(function (chunk, original) {
          generated.code += chunk;
          if (original.source !== null && original.line !== null && original.column !== null) {
            if (lastOriginalSource !== original.source || lastOriginalLine !== original.line || lastOriginalColumn !== original.column || lastOriginalName !== original.name) {
              map.addMapping({
                source: original.source,
                original: {
                  line: original.line,
                  column: original.column
                },
                generated: {
                  line: generated.line,
                  column: generated.column
                },
                name: original.name
              });
            }
            lastOriginalSource = original.source;
            lastOriginalLine = original.line;
            lastOriginalColumn = original.column;
            lastOriginalName = original.name;
            sourceMappingActive = true;
          } else if (sourceMappingActive) {
            map.addMapping({
              generated: {
                line: generated.line,
                column: generated.column
              }
            });
            lastOriginalSource = null;
            sourceMappingActive = false;
          }
          for (var idx = 0, length = chunk.length; idx < length; idx++) {
            if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
              generated.line++;
              generated.column = 0;
              if (idx + 1 === length) {
                lastOriginalSource = null;
                sourceMappingActive = false;
              } else if (sourceMappingActive) {
                map.addMapping({
                  source: original.source,
                  original: {
                    line: original.line,
                    column: original.column
                  },
                  generated: {
                    line: generated.line,
                    column: generated.column
                  },
                  name: original.name
                });
              }
            } else {
              generated.column++;
            }
          }
        });
        this.walkSourceContents(function (sourceFile, sourceContent) {
          map.setSourceContent(sourceFile, sourceContent);
        });
        return {
          code: generated.code,
          map: map
        };
      };
      exports.SourceNode = SourceNode;
    });
  });
  require.define('/node_modules/source-map/lib/source-map/util.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      function getArg(aArgs, aName, aDefaultValue) {
        if (aName in aArgs) {
          return aArgs[aName];
        } else if (arguments.length === 3) {
          return aDefaultValue;
        } else {
          throw new Error('"' + aName + '" is a required argument.');
        }
      }
      exports.getArg = getArg;
      var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/;
      var dataUrlRegexp = /^data:.+\,.+$/;
      function urlParse(aUrl) {
        var match = aUrl.match(urlRegexp);
        if (!match) {
          return null;
        }
        return {
          scheme: match[1],
          auth: match[2],
          host: match[3],
          port: match[4],
          path: match[5]
        };
      }
      exports.urlParse = urlParse;
      function urlGenerate(aParsedUrl) {
        var url = '';
        if (aParsedUrl.scheme) {
          url += aParsedUrl.scheme + ':';
        }
        url += '//';
        if (aParsedUrl.auth) {
          url += aParsedUrl.auth + '@';
        }
        if (aParsedUrl.host) {
          url += aParsedUrl.host;
        }
        if (aParsedUrl.port) {
          url += ':' + aParsedUrl.port;
        }
        if (aParsedUrl.path) {
          url += aParsedUrl.path;
        }
        return url;
      }
      exports.urlGenerate = urlGenerate;
      function normalize(aPath) {
        var path = aPath;
        var url = urlParse(aPath);
        if (url) {
          if (!url.path) {
            return aPath;
          }
          path = url.path;
        }
        var isAbsolute = path.charAt(0) === '/';
        var parts = path.split(/\/+/);
        for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
          part = parts[i];
          if (part === '.') {
            parts.splice(i, 1);
          } else if (part === '..') {
            up++;
          } else if (up > 0) {
            if (part === '') {
              parts.splice(i + 1, up);
              up = 0;
            } else {
              parts.splice(i, 2);
              up--;
            }
          }
        }
        path = parts.join('/');
        if (path === '') {
          path = isAbsolute ? '/' : '.';
        }
        if (url) {
          url.path = path;
          return urlGenerate(url);
        }
        return path;
      }
      exports.normalize = normalize;
      function join(aRoot, aPath) {
        if (aRoot === '') {
          aRoot = '.';
        }
        if (aPath === '') {
          aPath = '.';
        }
        var aPathUrl = urlParse(aPath);
        var aRootUrl = urlParse(aRoot);
        if (aRootUrl) {
          aRoot = aRootUrl.path || '/';
        }
        if (aPathUrl && !aPathUrl.scheme) {
          if (aRootUrl) {
            aPathUrl.scheme = aRootUrl.scheme;
          }
          return urlGenerate(aPathUrl);
        }
        if (aPathUrl || aPath.match(dataUrlRegexp)) {
          return aPath;
        }
        if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
          aRootUrl.host = aPath;
          return urlGenerate(aRootUrl);
        }
        var joined = aPath.charAt(0) === '/' ? aPath : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
        if (aRootUrl) {
          aRootUrl.path = joined;
          return urlGenerate(aRootUrl);
        }
        return joined;
      }
      exports.join = join;
      function relative(aRoot, aPath) {
        if (aRoot === '') {
          aRoot = '.';
        }
        aRoot = aRoot.replace(/\/$/, '');
        var url = urlParse(aRoot);
        if (aPath.charAt(0) == '/' && url && url.path == '/') {
          return aPath.slice(1);
        }
        return aPath.indexOf(aRoot + '/') === 0 ? aPath.substr(aRoot.length + 1) : aPath;
      }
      exports.relative = relative;
      function toSetString(aStr) {
        return '$' + aStr;
      }
      exports.toSetString = toSetString;
      function fromSetString(aStr) {
        return aStr.substr(1);
      }
      exports.fromSetString = fromSetString;
      function strcmp(aStr1, aStr2) {
        var s1 = aStr1 || '';
        var s2 = aStr2 || '';
        return (s1 > s2) - (s1 < s2);
      }
      function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
        var cmp;
        cmp = strcmp(mappingA.source, mappingB.source);
        if (cmp) {
          return cmp;
        }
        cmp = mappingA.originalLine - mappingB.originalLine;
        if (cmp) {
          return cmp;
        }
        cmp = mappingA.originalColumn - mappingB.originalColumn;
        if (cmp || onlyCompareOriginal) {
          return cmp;
        }
        cmp = strcmp(mappingA.name, mappingB.name);
        if (cmp) {
          return cmp;
        }
        cmp = mappingA.generatedLine - mappingB.generatedLine;
        if (cmp) {
          return cmp;
        }
        return mappingA.generatedColumn - mappingB.generatedColumn;
      }
      ;
      exports.compareByOriginalPositions = compareByOriginalPositions;
      function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) {
        var cmp;
        cmp = mappingA.generatedLine - mappingB.generatedLine;
        if (cmp) {
          return cmp;
        }
        cmp = mappingA.generatedColumn - mappingB.generatedColumn;
        if (cmp || onlyCompareGenerated) {
          return cmp;
        }
        cmp = strcmp(mappingA.source, mappingB.source);
        if (cmp) {
          return cmp;
        }
        cmp = mappingA.originalLine - mappingB.originalLine;
        if (cmp) {
          return cmp;
        }
        cmp = mappingA.originalColumn - mappingB.originalColumn;
        if (cmp) {
          return cmp;
        }
        return strcmp(mappingA.name, mappingB.name);
      }
      ;
      exports.compareByGeneratedPositions = compareByGeneratedPositions;
    });
  });
  require.define('/node_modules/amdefine/amdefine.js', function (module, exports, __dirname, __filename) {
    'use strict';
    function amdefine(module, requireFn) {
      'use strict';
      var defineCache = {}, loaderCache = {}, alreadyCalled = false, path = require('path', module), makeRequire, stringRequire;
      function trimDots(ary) {
        var i, part;
        for (i = 0; ary[i]; i += 1) {
          part = ary[i];
          if (part === '.') {
            ary.splice(i, 1);
            i -= 1;
          } else if (part === '..') {
            if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
              break;
            } else if (i > 0) {
              ary.splice(i - 1, 2);
              i -= 2;
            }
          }
        }
      }
      function normalize(name, baseName) {
        var baseParts;
        if (name && name.charAt(0) === '.') {
          if (baseName) {
            baseParts = baseName.split('/');
            baseParts = baseParts.slice(0, baseParts.length - 1);
            baseParts = baseParts.concat(name.split('/'));
            trimDots(baseParts);
            name = baseParts.join('/');
          }
        }
        return name;
      }
      function makeNormalize(relName) {
        return function (name) {
          return normalize(name, relName);
        };
      }
      function makeLoad(id) {
        function load(value) {
          loaderCache[id] = value;
        }
        load.fromText = function (id, text) {
          throw new Error('amdefine does not implement load.fromText');
        };
        return load;
      }
      makeRequire = function (systemRequire, exports, module, relId) {
        function amdRequire(deps, callback) {
          if (typeof deps === 'string') {
            return stringRequire(systemRequire, exports, module, deps, relId);
          } else {
            deps = deps.map(function (depName) {
              return stringRequire(systemRequire, exports, module, depName, relId);
            });
            if (callback) {
              process.nextTick(function () {
                callback.apply(null, deps);
              });
            }
          }
        }
        amdRequire.toUrl = function (filePath) {
          if (filePath.indexOf('.') === 0) {
            return normalize(filePath, path.dirname(module.filename));
          } else {
            return filePath;
          }
        };
        return amdRequire;
      };
      requireFn = requireFn || function req() {
        return module.require.apply(module, arguments);
      };
      function runFactory(id, deps, factory) {
        var r, e, m, result;
        if (id) {
          e = loaderCache[id] = {};
          m = {
            id: id,
            uri: __filename,
            exports: e
          };
          r = makeRequire(requireFn, e, m, id);
        } else {
          if (alreadyCalled) {
            throw new Error('amdefine with no module ID cannot be called more than once per file.');
          }
          alreadyCalled = true;
          e = module.exports;
          m = module;
          r = makeRequire(requireFn, e, m, module.id);
        }
        if (deps) {
          deps = deps.map(function (depName) {
            return r(depName);
          });
        }
        if (typeof factory === 'function') {
          result = factory.apply(m.exports, deps);
        } else {
          result = factory;
        }
        if (result !== undefined) {
          m.exports = result;
          if (id) {
            loaderCache[id] = m.exports;
          }
        }
      }
      stringRequire = function (systemRequire, exports, module, id, relId) {
        var index = id.indexOf('!'), originalId = id, prefix, plugin;
        if (index === -1) {
          id = normalize(id, relId);
          if (id === 'require') {
            return makeRequire(systemRequire, exports, module, relId);
          } else if (id === 'exports') {
            return exports;
          } else if (id === 'module') {
            return module;
          } else if (loaderCache.hasOwnProperty(id)) {
            return loaderCache[id];
          } else if (defineCache[id]) {
            runFactory.apply(null, defineCache[id]);
            return loaderCache[id];
          } else {
            if (systemRequire) {
              return systemRequire(originalId);
            } else {
              throw new Error('No module with ID: ' + id);
            }
          }
        } else {
          prefix = id.substring(0, index);
          id = id.substring(index + 1, id.length);
          plugin = stringRequire(systemRequire, exports, module, prefix, relId);
          if (plugin.normalize) {
            id = plugin.normalize(id, makeNormalize(relId));
          } else {
            id = normalize(id, relId);
          }
          if (loaderCache[id]) {
            return loaderCache[id];
          } else {
            plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {});
            return loaderCache[id];
          }
        }
      };
      function define(id, deps, factory) {
        if (Array.isArray(id)) {
          factory = deps;
          deps = id;
          id = undefined;
        } else if (typeof id !== 'string') {
          factory = id;
          id = deps = undefined;
        }
        if (deps && !Array.isArray(deps)) {
          factory = deps;
          deps = undefined;
        }
        if (!deps) {
          deps = [
            'require',
            'exports',
            'module'
          ];
        }
        if (id) {
          defineCache[id] = [
            id,
            deps,
            factory
          ];
        } else {
          runFactory(id, deps, factory);
        }
      }
      define.require = function (id) {
        if (loaderCache[id]) {
          return loaderCache[id];
        }
        if (defineCache[id]) {
          runFactory.apply(null, defineCache[id]);
          return loaderCache[id];
        }
      };
      define.amd = {};
      return define;
    }
    module.exports = amdefine;
  });
  require.define('/node_modules/source-map/lib/source-map/source-map-generator.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var base64VLQ = require('/node_modules/source-map/lib/source-map/base64-vlq.js', module);
      var util = require('/node_modules/source-map/lib/source-map/util.js', module);
      var ArraySet = require('/node_modules/source-map/lib/source-map/array-set.js', module).ArraySet;
      var MappingList = require('/node_modules/source-map/lib/source-map/mapping-list.js', module).MappingList;
      function SourceMapGenerator(aArgs) {
        if (!aArgs) {
          aArgs = {};
        }
        this._file = util.getArg(aArgs, 'file', null);
        this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
        this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
        this._sources = new ArraySet;
        this._names = new ArraySet;
        this._mappings = new MappingList;
        this._sourcesContents = null;
      }
      SourceMapGenerator.prototype._version = 3;
      SourceMapGenerator.fromSourceMap = function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
        var sourceRoot = aSourceMapConsumer.sourceRoot;
        var generator = new SourceMapGenerator({
            file: aSourceMapConsumer.file,
            sourceRoot: sourceRoot
          });
        aSourceMapConsumer.eachMapping(function (mapping) {
          var newMapping = {
              generated: {
                line: mapping.generatedLine,
                column: mapping.generatedColumn
              }
            };
          if (mapping.source != null) {
            newMapping.source = mapping.source;
            if (sourceRoot != null) {
              newMapping.source = util.relative(sourceRoot, newMapping.source);
            }
            newMapping.original = {
              line: mapping.originalLine,
              column: mapping.originalColumn
            };
            if (mapping.name != null) {
              newMapping.name = mapping.name;
            }
          }
          generator.addMapping(newMapping);
        });
        aSourceMapConsumer.sources.forEach(function (sourceFile) {
          var content = aSourceMapConsumer.sourceContentFor(sourceFile);
          if (content != null) {
            generator.setSourceContent(sourceFile, content);
          }
        });
        return generator;
      };
      SourceMapGenerator.prototype.addMapping = function SourceMapGenerator_addMapping(aArgs) {
        var generated = util.getArg(aArgs, 'generated');
        var original = util.getArg(aArgs, 'original', null);
        var source = util.getArg(aArgs, 'source', null);
        var name = util.getArg(aArgs, 'name', null);
        if (!this._skipValidation) {
          this._validateMapping(generated, original, source, name);
        }
        if (source != null && !this._sources.has(source)) {
          this._sources.add(source);
        }
        if (name != null && !this._names.has(name)) {
          this._names.add(name);
        }
        this._mappings.add({
          generatedLine: generated.line,
          generatedColumn: generated.column,
          originalLine: original != null && original.line,
          originalColumn: original != null && original.column,
          source: source,
          name: name
        });
      };
      SourceMapGenerator.prototype.setSourceContent = function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
        var source = aSourceFile;
        if (this._sourceRoot != null) {
          source = util.relative(this._sourceRoot, source);
        }
        if (aSourceContent != null) {
          if (!this._sourcesContents) {
            this._sourcesContents = {};
          }
          this._sourcesContents[util.toSetString(source)] = aSourceContent;
        } else if (this._sourcesContents) {
          delete this._sourcesContents[util.toSetString(source)];
          if (Object.keys(this._sourcesContents).length === 0) {
            this._sourcesContents = null;
          }
        }
      };
      SourceMapGenerator.prototype.applySourceMap = function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
        var sourceFile = aSourceFile;
        if (aSourceFile == null) {
          if (aSourceMapConsumer.file == null) {
            throw new Error('SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + 'or the source map\'s "file" property. Both were omitted.');
          }
          sourceFile = aSourceMapConsumer.file;
        }
        var sourceRoot = this._sourceRoot;
        if (sourceRoot != null) {
          sourceFile = util.relative(sourceRoot, sourceFile);
        }
        var newSources = new ArraySet;
        var newNames = new ArraySet;
        this._mappings.unsortedForEach(function (mapping) {
          if (mapping.source === sourceFile && mapping.originalLine != null) {
            var original = aSourceMapConsumer.originalPositionFor({
                line: mapping.originalLine,
                column: mapping.originalColumn
              });
            if (original.source != null) {
              mapping.source = original.source;
              if (aSourceMapPath != null) {
                mapping.source = util.join(aSourceMapPath, mapping.source);
              }
              if (sourceRoot != null) {
                mapping.source = util.relative(sourceRoot, mapping.source);
              }
              mapping.originalLine = original.line;
              mapping.originalColumn = original.column;
              if (original.name != null) {
                mapping.name = original.name;
              }
            }
          }
          var source = mapping.source;
          if (source != null && !newSources.has(source)) {
            newSources.add(source);
          }
          var name = mapping.name;
          if (name != null && !newNames.has(name)) {
            newNames.add(name);
          }
        }, this);
        this._sources = newSources;
        this._names = newNames;
        aSourceMapConsumer.sources.forEach(function (sourceFile) {
          var content = aSourceMapConsumer.sourceContentFor(sourceFile);
          if (content != null) {
            if (aSourceMapPath != null) {
              sourceFile = util.join(aSourceMapPath, sourceFile);
            }
            if (sourceRoot != null) {
              sourceFile = util.relative(sourceRoot, sourceFile);
            }
            this.setSourceContent(sourceFile, content);
          }
        }, this);
      };
      SourceMapGenerator.prototype._validateMapping = function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, aName) {
        if (aGenerated && 'line' in aGenerated && 'column' in aGenerated && aGenerated.line > 0 && aGenerated.column >= 0 && !aOriginal && !aSource && !aName) {
          return;
        } else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated && aOriginal && 'line' in aOriginal && 'column' in aOriginal && aGenerated.line > 0 && aGenerated.column >= 0 && aOriginal.line > 0 && aOriginal.column >= 0 && aSource) {
          return;
        } else {
          throw new Error('Invalid mapping: ' + JSON.stringify({
            generated: aGenerated,
            source: aSource,
            original: aOriginal,
            name: aName
          }));
        }
      };
      SourceMapGenerator.prototype._serializeMappings = function SourceMapGenerator_serializeMappings() {
        var previousGeneratedColumn = 0;
        var previousGeneratedLine = 1;
        var previousOriginalColumn = 0;
        var previousOriginalLine = 0;
        var previousName = 0;
        var previousSource = 0;
        var result = '';
        var mapping;
        var mappings = this._mappings.toArray();
        for (var i = 0, len = mappings.length; i < len; i++) {
          mapping = mappings[i];
          if (mapping.generatedLine !== previousGeneratedLine) {
            previousGeneratedColumn = 0;
            while (mapping.generatedLine !== previousGeneratedLine) {
              result += ';';
              previousGeneratedLine++;
            }
          } else {
            if (i > 0) {
              if (!util.compareByGeneratedPositions(mapping, mappings[i - 1])) {
                continue;
              }
              result += ',';
            }
          }
          result += base64VLQ.encode(mapping.generatedColumn - previousGeneratedColumn);
          previousGeneratedColumn = mapping.generatedColumn;
          if (mapping.source != null) {
            result += base64VLQ.encode(this._sources.indexOf(mapping.source) - previousSource);
            previousSource = this._sources.indexOf(mapping.source);
            result += base64VLQ.encode(mapping.originalLine - 1 - previousOriginalLine);
            previousOriginalLine = mapping.originalLine - 1;
            result += base64VLQ.encode(mapping.originalColumn - previousOriginalColumn);
            previousOriginalColumn = mapping.originalColumn;
            if (mapping.name != null) {
              result += base64VLQ.encode(this._names.indexOf(mapping.name) - previousName);
              previousName = this._names.indexOf(mapping.name);
            }
          }
        }
        return result;
      };
      SourceMapGenerator.prototype._generateSourcesContent = function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
        return aSources.map(function (source) {
          if (!this._sourcesContents) {
            return null;
          }
          if (aSourceRoot != null) {
            source = util.relative(aSourceRoot, source);
          }
          var key = util.toSetString(source);
          return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) ? this._sourcesContents[key] : null;
        }, this);
      };
      SourceMapGenerator.prototype.toJSON = function SourceMapGenerator_toJSON() {
        var map = {
            version: this._version,
            sources: this._sources.toArray(),
            names: this._names.toArray(),
            mappings: this._serializeMappings()
          };
        if (this._file != null) {
          map.file = this._file;
        }
        if (this._sourceRoot != null) {
          map.sourceRoot = this._sourceRoot;
        }
        if (this._sourcesContents) {
          map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
        }
        return map;
      };
      SourceMapGenerator.prototype.toString = function SourceMapGenerator_toString() {
        return JSON.stringify(this);
      };
      exports.SourceMapGenerator = SourceMapGenerator;
    });
  });
  require.define('/node_modules/source-map/lib/source-map/mapping-list.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var util = require('/node_modules/source-map/lib/source-map/util.js', module);
      function generatedPositionAfter(mappingA, mappingB) {
        var lineA = mappingA.generatedLine;
        var lineB = mappingB.generatedLine;
        var columnA = mappingA.generatedColumn;
        var columnB = mappingB.generatedColumn;
        return lineB > lineA || lineB == lineA && columnB >= columnA || util.compareByGeneratedPositions(mappingA, mappingB) <= 0;
      }
      function MappingList() {
        this._array = [];
        this._sorted = true;
        this._last = {
          generatedLine: -1,
          generatedColumn: 0
        };
      }
      MappingList.prototype.unsortedForEach = function MappingList_forEach(aCallback, aThisArg) {
        this._array.forEach(aCallback, aThisArg);
      };
      MappingList.prototype.add = function MappingList_add(aMapping) {
        var mapping;
        if (generatedPositionAfter(this._last, aMapping)) {
          this._last = aMapping;
          this._array.push(aMapping);
        } else {
          this._sorted = false;
          this._array.push(aMapping);
        }
      };
      MappingList.prototype.toArray = function MappingList_toArray() {
        if (!this._sorted) {
          this._array.sort(util.compareByGeneratedPositions);
          this._sorted = true;
        }
        return this._array;
      };
      exports.MappingList = MappingList;
    });
  });
  require.define('/node_modules/source-map/lib/source-map/array-set.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var util = require('/node_modules/source-map/lib/source-map/util.js', module);
      function ArraySet() {
        this._array = [];
        this._set = {};
      }
      ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
        var set = new ArraySet;
        for (var i = 0, len = aArray.length; i < len; i++) {
          set.add(aArray[i], aAllowDuplicates);
        }
        return set;
      };
      ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
        var isDuplicate = this.has(aStr);
        var idx = this._array.length;
        if (!isDuplicate || aAllowDuplicates) {
          this._array.push(aStr);
        }
        if (!isDuplicate) {
          this._set[util.toSetString(aStr)] = idx;
        }
      };
      ArraySet.prototype.has = function ArraySet_has(aStr) {
        return Object.prototype.hasOwnProperty.call(this._set, util.toSetString(aStr));
      };
      ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
        if (this.has(aStr)) {
          return this._set[util.toSetString(aStr)];
        }
        throw new Error('"' + aStr + '" is not in the set.');
      };
      ArraySet.prototype.at = function ArraySet_at(aIdx) {
        if (aIdx >= 0 && aIdx < this._array.length) {
          return this._array[aIdx];
        }
        throw new Error('No element indexed by ' + aIdx);
      };
      ArraySet.prototype.toArray = function ArraySet_toArray() {
        return this._array.slice();
      };
      exports.ArraySet = ArraySet;
    });
  });
  require.define('/node_modules/source-map/lib/source-map/base64-vlq.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var base64 = require('/node_modules/source-map/lib/source-map/base64.js', module);
      var VLQ_BASE_SHIFT = 5;
      var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
      var VLQ_BASE_MASK = VLQ_BASE - 1;
      var VLQ_CONTINUATION_BIT = VLQ_BASE;
      function toVLQSigned(aValue) {
        return aValue < 0 ? (-aValue << 1) + 1 : (aValue << 1) + 0;
      }
      function fromVLQSigned(aValue) {
        var isNegative = (aValue & 1) === 1;
        var shifted = aValue >> 1;
        return isNegative ? -shifted : shifted;
      }
      exports.encode = function base64VLQ_encode(aValue) {
        var encoded = '';
        var digit;
        var vlq = toVLQSigned(aValue);
        do {
          digit = vlq & VLQ_BASE_MASK;
          vlq >>>= VLQ_BASE_SHIFT;
          if (vlq > 0) {
            digit |= VLQ_CONTINUATION_BIT;
          }
          encoded += base64.encode(digit);
        } while (vlq > 0);
        return encoded;
      };
      exports.decode = function base64VLQ_decode(aStr, aOutParam) {
        var i = 0;
        var strLen = aStr.length;
        var result = 0;
        var shift = 0;
        var continuation, digit;
        do {
          if (i >= strLen) {
            throw new Error('Expected more digits in base 64 VLQ value.');
          }
          digit = base64.decode(aStr.charAt(i++));
          continuation = !!(digit & VLQ_CONTINUATION_BIT);
          digit &= VLQ_BASE_MASK;
          result = result + (digit << shift);
          shift += VLQ_BASE_SHIFT;
        } while (continuation);
        aOutParam.value = fromVLQSigned(result);
        aOutParam.rest = aStr.slice(i);
      };
    });
  });
  require.define('/node_modules/source-map/lib/source-map/base64.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var charToIntMap = {};
      var intToCharMap = {};
      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('').forEach(function (ch, index) {
        charToIntMap[ch] = index;
        intToCharMap[index] = ch;
      });
      exports.encode = function base64_encode(aNumber) {
        if (aNumber in intToCharMap) {
          return intToCharMap[aNumber];
        }
        throw new TypeError('Must be between 0 and 63: ' + aNumber);
      };
      exports.decode = function base64_decode(aChar) {
        if (aChar in charToIntMap) {
          return charToIntMap[aChar];
        }
        throw new TypeError('Not a valid base 64 digit: ' + aChar);
      };
    });
  });
  require.define('/node_modules/source-map/lib/source-map/source-map-consumer.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var util = require('/node_modules/source-map/lib/source-map/util.js', module);
      function SourceMapConsumer(aSourceMap) {
        var sourceMap = aSourceMap;
        if (typeof aSourceMap === 'string') {
          sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
        }
        if (sourceMap.sections != null) {
          var indexedSourceMapConsumer = require('/node_modules/source-map/lib/source-map/indexed-source-map-consumer.js', module);
          return new indexedSourceMapConsumer.IndexedSourceMapConsumer(sourceMap);
        } else {
          var basicSourceMapConsumer = require('/node_modules/source-map/lib/source-map/basic-source-map-consumer.js', module);
          return new basicSourceMapConsumer.BasicSourceMapConsumer(sourceMap);
        }
      }
      SourceMapConsumer.fromSourceMap = function (aSourceMap) {
        var basicSourceMapConsumer = require('/node_modules/source-map/lib/source-map/basic-source-map-consumer.js', module);
        return basicSourceMapConsumer.BasicSourceMapConsumer.fromSourceMap(aSourceMap);
      };
      SourceMapConsumer.prototype._version = 3;
      SourceMapConsumer.prototype.__generatedMappings = null;
      Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {
        get: function () {
          if (!this.__generatedMappings) {
            this.__generatedMappings = [];
            this.__originalMappings = [];
            this._parseMappings(this._mappings, this.sourceRoot);
          }
          return this.__generatedMappings;
        }
      });
      SourceMapConsumer.prototype.__originalMappings = null;
      Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {
        get: function () {
          if (!this.__originalMappings) {
            this.__generatedMappings = [];
            this.__originalMappings = [];
            this._parseMappings(this._mappings, this.sourceRoot);
          }
          return this.__originalMappings;
        }
      });
      SourceMapConsumer.prototype._nextCharIsMappingSeparator = function SourceMapConsumer_nextCharIsMappingSeparator(aStr) {
        var c = aStr.charAt(0);
        return c === ';' || c === ',';
      };
      SourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
        throw new Error('Subclasses must implement _parseMappings');
      };
      SourceMapConsumer.GENERATED_ORDER = 1;
      SourceMapConsumer.ORIGINAL_ORDER = 2;
      SourceMapConsumer.prototype.eachMapping = function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
        var context = aContext || null;
        var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
        var mappings;
        switch (order) {
        case SourceMapConsumer.GENERATED_ORDER:
          mappings = this._generatedMappings;
          break;
        case SourceMapConsumer.ORIGINAL_ORDER:
          mappings = this._originalMappings;
          break;
        default:
          throw new Error('Unknown order of iteration.');
        }
        var sourceRoot = this.sourceRoot;
        mappings.map(function (mapping) {
          var source = mapping.source;
          if (source != null && sourceRoot != null) {
            source = util.join(sourceRoot, source);
          }
          return {
            source: source,
            generatedLine: mapping.generatedLine,
            generatedColumn: mapping.generatedColumn,
            originalLine: mapping.originalLine,
            originalColumn: mapping.originalColumn,
            name: mapping.name
          };
        }).forEach(aCallback, context);
      };
      SourceMapConsumer.prototype.allGeneratedPositionsFor = function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {
        var needle = {
            source: util.getArg(aArgs, 'source'),
            originalLine: util.getArg(aArgs, 'line'),
            originalColumn: Infinity
          };
        if (this.sourceRoot != null) {
          needle.source = util.relative(this.sourceRoot, needle.source);
        }
        var mappings = [];
        var index = this._findMapping(needle, this._originalMappings, 'originalLine', 'originalColumn', util.compareByOriginalPositions);
        if (index >= 0) {
          var mapping = this._originalMappings[index];
          while (mapping && mapping.originalLine === needle.originalLine) {
            mappings.push({
              line: util.getArg(mapping, 'generatedLine', null),
              column: util.getArg(mapping, 'generatedColumn', null),
              lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
            });
            mapping = this._originalMappings[--index];
          }
        }
        return mappings.reverse();
      };
      exports.SourceMapConsumer = SourceMapConsumer;
    });
  });
  require.define('/node_modules/source-map/lib/source-map/basic-source-map-consumer.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var util = require('/node_modules/source-map/lib/source-map/util.js', module);
      var binarySearch = require('/node_modules/source-map/lib/source-map/binary-search.js', module);
      var ArraySet = require('/node_modules/source-map/lib/source-map/array-set.js', module).ArraySet;
      var base64VLQ = require('/node_modules/source-map/lib/source-map/base64-vlq.js', module);
      var SourceMapConsumer = require('/node_modules/source-map/lib/source-map/source-map-consumer.js', module).SourceMapConsumer;
      function BasicSourceMapConsumer(aSourceMap) {
        var sourceMap = aSourceMap;
        if (typeof aSourceMap === 'string') {
          sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
        }
        var version = util.getArg(sourceMap, 'version');
        var sources = util.getArg(sourceMap, 'sources');
        var names = util.getArg(sourceMap, 'names', []);
        var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
        var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
        var mappings = util.getArg(sourceMap, 'mappings');
        var file = util.getArg(sourceMap, 'file', null);
        if (version != this._version) {
          throw new Error('Unsupported version: ' + version);
        }
        sources = sources.map(util.normalize);
        this._names = ArraySet.fromArray(names, true);
        this._sources = ArraySet.fromArray(sources, true);
        this.sourceRoot = sourceRoot;
        this.sourcesContent = sourcesContent;
        this._mappings = mappings;
        this.file = file;
      }
      BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
      BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;
      BasicSourceMapConsumer.fromSourceMap = function SourceMapConsumer_fromSourceMap(aSourceMap) {
        var smc = Object.create(BasicSourceMapConsumer.prototype);
        smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
        smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
        smc.sourceRoot = aSourceMap._sourceRoot;
        smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), smc.sourceRoot);
        smc.file = aSourceMap._file;
        smc.__generatedMappings = aSourceMap._mappings.toArray().slice();
        smc.__originalMappings = aSourceMap._mappings.toArray().slice().sort(util.compareByOriginalPositions);
        return smc;
      };
      BasicSourceMapConsumer.prototype._version = 3;
      Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {
        get: function () {
          return this._sources.toArray().map(function (s) {
            return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;
          }, this);
        }
      });
      BasicSourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
        var generatedLine = 1;
        var previousGeneratedColumn = 0;
        var previousOriginalLine = 0;
        var previousOriginalColumn = 0;
        var previousSource = 0;
        var previousName = 0;
        var str = aStr;
        var temp = {};
        var mapping;
        while (str.length > 0) {
          if (str.charAt(0) === ';') {
            generatedLine++;
            str = str.slice(1);
            previousGeneratedColumn = 0;
          } else if (str.charAt(0) === ',') {
            str = str.slice(1);
          } else {
            mapping = {};
            mapping.generatedLine = generatedLine;
            base64VLQ.decode(str, temp);
            mapping.generatedColumn = previousGeneratedColumn + temp.value;
            previousGeneratedColumn = mapping.generatedColumn;
            str = temp.rest;
            if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
              base64VLQ.decode(str, temp);
              mapping.source = this._sources.at(previousSource + temp.value);
              previousSource += temp.value;
              str = temp.rest;
              if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
                throw new Error('Found a source, but no line and column');
              }
              base64VLQ.decode(str, temp);
              mapping.originalLine = previousOriginalLine + temp.value;
              previousOriginalLine = mapping.originalLine;
              mapping.originalLine += 1;
              str = temp.rest;
              if (str.length === 0 || this._nextCharIsMappingSeparator(str)) {
                throw new Error('Found a source and line, but no column');
              }
              base64VLQ.decode(str, temp);
              mapping.originalColumn = previousOriginalColumn + temp.value;
              previousOriginalColumn = mapping.originalColumn;
              str = temp.rest;
              if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) {
                base64VLQ.decode(str, temp);
                mapping.name = this._names.at(previousName + temp.value);
                previousName += temp.value;
                str = temp.rest;
              }
            }
            this.__generatedMappings.push(mapping);
            if (typeof mapping.originalLine === 'number') {
              this.__originalMappings.push(mapping);
            }
          }
        }
        this.__generatedMappings.sort(util.compareByGeneratedPositions);
        this.__originalMappings.sort(util.compareByOriginalPositions);
      };
      BasicSourceMapConsumer.prototype._findMapping = function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, aColumnName, aComparator) {
        if (aNeedle[aLineName] <= 0) {
          throw new TypeError('Line must be greater than or equal to 1, got ' + aNeedle[aLineName]);
        }
        if (aNeedle[aColumnName] < 0) {
          throw new TypeError('Column must be greater than or equal to 0, got ' + aNeedle[aColumnName]);
        }
        return binarySearch.search(aNeedle, aMappings, aComparator);
      };
      BasicSourceMapConsumer.prototype.computeColumnSpans = function SourceMapConsumer_computeColumnSpans() {
        for (var index = 0; index < this._generatedMappings.length; ++index) {
          var mapping = this._generatedMappings[index];
          if (index + 1 < this._generatedMappings.length) {
            var nextMapping = this._generatedMappings[index + 1];
            if (mapping.generatedLine === nextMapping.generatedLine) {
              mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
              continue;
            }
          }
          mapping.lastGeneratedColumn = Infinity;
        }
      };
      BasicSourceMapConsumer.prototype.originalPositionFor = function SourceMapConsumer_originalPositionFor(aArgs) {
        var needle = {
            generatedLine: util.getArg(aArgs, 'line'),
            generatedColumn: util.getArg(aArgs, 'column')
          };
        var index = this._findMapping(needle, this._generatedMappings, 'generatedLine', 'generatedColumn', util.compareByGeneratedPositions);
        if (index >= 0) {
          var mapping = this._generatedMappings[index];
          if (mapping.generatedLine === needle.generatedLine) {
            var source = util.getArg(mapping, 'source', null);
            if (source != null && this.sourceRoot != null) {
              source = util.join(this.sourceRoot, source);
            }
            return {
              source: source,
              line: util.getArg(mapping, 'originalLine', null),
              column: util.getArg(mapping, 'originalColumn', null),
              name: util.getArg(mapping, 'name', null)
            };
          }
        }
        return {
          source: null,
          line: null,
          column: null,
          name: null
        };
      };
      BasicSourceMapConsumer.prototype.sourceContentFor = function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
        if (!this.sourcesContent) {
          return null;
        }
        if (this.sourceRoot != null) {
          aSource = util.relative(this.sourceRoot, aSource);
        }
        if (this._sources.has(aSource)) {
          return this.sourcesContent[this._sources.indexOf(aSource)];
        }
        var url;
        if (this.sourceRoot != null && (url = util.urlParse(this.sourceRoot))) {
          var fileUriAbsPath = aSource.replace(/^file:\/\//, '');
          if (url.scheme == 'file' && this._sources.has(fileUriAbsPath)) {
            return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)];
          }
          if ((!url.path || url.path == '/') && this._sources.has('/' + aSource)) {
            return this.sourcesContent[this._sources.indexOf('/' + aSource)];
          }
        }
        if (nullOnMissing) {
          return null;
        } else {
          throw new Error('"' + aSource + '" is not in the SourceMap.');
        }
      };
      BasicSourceMapConsumer.prototype.generatedPositionFor = function SourceMapConsumer_generatedPositionFor(aArgs) {
        var needle = {
            source: util.getArg(aArgs, 'source'),
            originalLine: util.getArg(aArgs, 'line'),
            originalColumn: util.getArg(aArgs, 'column')
          };
        if (this.sourceRoot != null) {
          needle.source = util.relative(this.sourceRoot, needle.source);
        }
        var index = this._findMapping(needle, this._originalMappings, 'originalLine', 'originalColumn', util.compareByOriginalPositions);
        if (index >= 0) {
          var mapping = this._originalMappings[index];
          return {
            line: util.getArg(mapping, 'generatedLine', null),
            column: util.getArg(mapping, 'generatedColumn', null),
            lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
          };
        }
        return {
          line: null,
          column: null,
          lastColumn: null
        };
      };
      exports.BasicSourceMapConsumer = BasicSourceMapConsumer;
    });
  });
  require.define('/node_modules/source-map/lib/source-map/binary-search.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {
        var mid = Math.floor((aHigh - aLow) / 2) + aLow;
        var cmp = aCompare(aNeedle, aHaystack[mid], true);
        if (cmp === 0) {
          return mid;
        } else if (cmp > 0) {
          if (aHigh - mid > 1) {
            return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare);
          }
          return mid;
        } else {
          if (mid - aLow > 1) {
            return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare);
          }
          return aLow < 0 ? -1 : aLow;
        }
      }
      exports.search = function search(aNeedle, aHaystack, aCompare) {
        if (aHaystack.length === 0) {
          return -1;
        }
        return recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare);
      };
    });
  });
  require.define('/node_modules/source-map/lib/source-map/indexed-source-map-consumer.js', function (module, exports, __dirname, __filename) {
    if (typeof define !== 'function') {
      var define = require('/node_modules/amdefine/amdefine.js', module)(module, require);
    }
    define(function (require, exports, module) {
      var util = require('/node_modules/source-map/lib/source-map/util.js', module);
      var binarySearch = require('/node_modules/source-map/lib/source-map/binary-search.js', module);
      var SourceMapConsumer = require('/node_modules/source-map/lib/source-map/source-map-consumer.js', module).SourceMapConsumer;
      var BasicSourceMapConsumer = require('/node_modules/source-map/lib/source-map/basic-source-map-consumer.js', module).BasicSourceMapConsumer;
      function IndexedSourceMapConsumer(aSourceMap) {
        var sourceMap = aSourceMap;
        if (typeof aSourceMap === 'string') {
          sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
        }
        var version = util.getArg(sourceMap, 'version');
        var sections = util.getArg(sourceMap, 'sections');
        if (version != this._version) {
          throw new Error('Unsupported version: ' + version);
        }
        var lastOffset = {
            line: -1,
            column: 0
          };
        this._sections = sections.map(function (s) {
          if (s.url) {
            throw new Error('Support for url field in sections not implemented.');
          }
          var offset = util.getArg(s, 'offset');
          var offsetLine = util.getArg(offset, 'line');
          var offsetColumn = util.getArg(offset, 'column');
          if (offsetLine < lastOffset.line || offsetLine === lastOffset.line && offsetColumn < lastOffset.column) {
            throw new Error('Section offsets must be ordered and non-overlapping.');
          }
          lastOffset = offset;
          return {
            generatedOffset: {
              generatedLine: offsetLine + 1,
              generatedColumn: offsetColumn + 1
            },
            consumer: new SourceMapConsumer(util.getArg(s, 'map'))
          };
        });
      }
      IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
      IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;
      IndexedSourceMapConsumer.prototype._version = 3;
      Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {
        get: function () {
          var sources = [];
          for (var i = 0; i < this._sections.length; i++) {
            for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {
              sources.push(this._sections[i].consumer.sources[j]);
            }
          }
          ;
          return sources;
        }
      });
      IndexedSourceMapConsumer.prototype.originalPositionFor = function IndexedSourceMapConsumer_originalPositionFor(aArgs) {
        var needle = {
            generatedLine: util.getArg(aArgs, 'line'),
            generatedColumn: util.getArg(aArgs, 'column')
          };
        var sectionIndex = binarySearch.search(needle, this._sections, function (needle, section) {
            var cmp = needle.generatedLine - section.generatedOffset.generatedLine;
            if (cmp) {
              return cmp;
            }
            return needle.generatedColumn - section.generatedOffset.generatedColumn;
          });
        var section = this._sections[sectionIndex];
        if (!section) {
          return {
            source: null,
            line: null,
            column: null,
            name: null
          };
        }
        return section.consumer.originalPositionFor({
          line: needle.generatedLine - (section.generatedOffset.generatedLine - 1),
          column: needle.generatedColumn - (section.generatedOffset.generatedLine === needle.generatedLine ? section.generatedOffset.generatedColumn - 1 : 0)
        });
      };
      IndexedSourceMapConsumer.prototype.sourceContentFor = function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
        for (var i = 0; i < this._sections.length; i++) {
          var section = this._sections[i];
          var content = section.consumer.sourceContentFor(aSource, true);
          if (content) {
            return content;
          }
        }
        if (nullOnMissing) {
          return null;
        } else {
          throw new Error('"' + aSource + '" is not in the SourceMap.');
        }
      };
      IndexedSourceMapConsumer.prototype.generatedPositionFor = function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {
        for (var i = 0; i < this._sections.length; i++) {
          var section = this._sections[i];
          if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {
            continue;
          }
          var generatedPosition = section.consumer.generatedPositionFor(aArgs);
          if (generatedPosition) {
            var ret = {
                line: generatedPosition.line + (section.generatedOffset.generatedLine - 1),
                column: generatedPosition.column + (section.generatedOffset.generatedLine === generatedPosition.line ? section.generatedOffset.generatedColumn - 1 : 0)
              };
            return ret;
          }
        }
        return {
          line: null,
          column: null
        };
      };
      IndexedSourceMapConsumer.prototype._parseMappings = function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {
        this.__generatedMappings = [];
        this.__originalMappings = [];
        for (var i = 0; i < this._sections.length; i++) {
          var section = this._sections[i];
          var sectionMappings = section.consumer._generatedMappings;
          for (var j = 0; j < sectionMappings.length; j++) {
            var mapping = sectionMappings[i];
            var source = mapping.source;
            var sourceRoot = section.consumer.sourceRoot;
            if (source != null && sourceRoot != null) {
              source = util.join(sourceRoot, source);
            }
            var adjustedMapping = {
                source: source,
                generatedLine: mapping.generatedLine + (section.generatedOffset.generatedLine - 1),
                generatedColumn: mapping.column + (section.generatedOffset.generatedLine === mapping.generatedLine) ? section.generatedOffset.generatedColumn - 1 : 0,
                originalLine: mapping.originalLine,
                originalColumn: mapping.originalColumn,
                name: mapping.name
              };
            this.__generatedMappings.push(adjustedMapping);
            if (typeof adjustedMapping.originalLine === 'number') {
              this.__originalMappings.push(adjustedMapping);
            }
          }
          ;
        }
        ;
        this.__generatedMappings.sort(util.compareByGeneratedPositions);
        this.__originalMappings.sort(util.compareByOriginalPositions);
      };
      exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
    });
  });
  require.define('/node_modules/esutils/lib/utils.js', function (module, exports, __dirname, __filename) {
    (function () {
      'use strict';
      exports.ast = require('/node_modules/esutils/lib/ast.js', module);
      exports.code = require('/node_modules/esutils/lib/code.js', module);
      exports.keyword = require('/node_modules/esutils/lib/keyword.js', module);
    }());
  });
  require.define('/node_modules/esutils/lib/keyword.js', function (module, exports, __dirname, __filename) {
    (function () {
      'use strict';
      var code = require('/node_modules/esutils/lib/code.js', module);
      function isStrictModeReservedWordES6(id) {
        switch (id) {
        case 'implements':
        case 'interface':
        case 'package':
        case 'private':
        case 'protected':
        case 'public':
        case 'static':
        case 'let':
          return true;
        default:
          return false;
        }
      }
      function isKeywordES5(id, strict) {
        if (!strict && id === 'yield') {
          return false;
        }
        return isKeywordES6(id, strict);
      }
      function isKeywordES6(id, strict) {
        if (strict && isStrictModeReservedWordES6(id)) {
          return true;
        }
        switch (id.length) {
        case 2:
          return id === 'if' || id === 'in' || id === 'do';
        case 3:
          return id === 'var' || id === 'for' || id === 'new' || id === 'try';
        case 4:
          return id === 'this' || id === 'else' || id === 'case' || id === 'void' || id === 'with' || id === 'enum';
        case 5:
          return id === 'while' || id === 'break' || id === 'catch' || id === 'throw' || id === 'const' || id === 'yield' || id === 'class' || id === 'super';
        case 6:
          return id === 'return' || id === 'typeof' || id === 'delete' || id === 'switch' || id === 'export' || id === 'import';
        case 7:
          return id === 'default' || id === 'finally' || id === 'extends';
        case 8:
          return id === 'function' || id === 'continue' || id === 'debugger';
        case 10:
          return id === 'instanceof';
        default:
          return false;
        }
      }
      function isReservedWordES5(id, strict) {
        return id === 'null' || id === 'true' || id === 'false' || isKeywordES5(id, strict);
      }
      function isReservedWordES6(id, strict) {
        return id === 'null' || id === 'true' || id === 'false' || isKeywordES6(id, strict);
      }
      function isRestrictedWord(id) {
        return id === 'eval' || id === 'arguments';
      }
      function isIdentifierNameES5(id) {
        var i, iz, ch;
        if (id.length === 0) {
          return false;
        }
        ch = id.charCodeAt(0);
        if (!code.isIdentifierStartES5(ch)) {
          return false;
        }
        for (i = 1, iz = id.length; i < iz; ++i) {
          ch = id.charCodeAt(i);
          if (!code.isIdentifierPartES5(ch)) {
            return false;
          }
        }
        return true;
      }
      function decodeUtf16(lead, trail) {
        return (lead - 55296) * 1024 + (trail - 56320) + 65536;
      }
      function isIdentifierNameES6(id) {
        var i, iz, ch, lowCh, check;
        if (id.length === 0) {
          return false;
        }
        check = code.isIdentifierStartES6;
        for (i = 0, iz = id.length; i < iz; ++i) {
          ch = id.charCodeAt(i);
          if (55296 <= ch && ch <= 56319) {
            ++i;
            if (i >= iz) {
              return false;
            }
            lowCh = id.charCodeAt(i);
            if (!(56320 <= lowCh && lowCh <= 57343)) {
              return false;
            }
            ch = decodeUtf16(ch, lowCh);
          }
          if (!check(ch)) {
            return false;
          }
          check = code.isIdentifierPartES6;
        }
        return true;
      }
      function isIdentifierES5(id, strict) {
        return isIdentifierNameES5(id) && !isReservedWordES5(id, strict);
      }
      function isIdentifierES6(id, strict) {
        return isIdentifierNameES6(id) && !isReservedWordES6(id, strict);
      }
      module.exports = {
        isKeywordES5: isKeywordES5,
        isKeywordES6: isKeywordES6,
        isReservedWordES5: isReservedWordES5,
        isReservedWordES6: isReservedWordES6,
        isRestrictedWord: isRestrictedWord,
        isIdentifierNameES5: isIdentifierNameES5,
        isIdentifierNameES6: isIdentifierNameES6,
        isIdentifierES5: isIdentifierES5,
        isIdentifierES6: isIdentifierES6
      };
    }());
  });
  require.define('/node_modules/esutils/lib/code.js', function (module, exports, __dirname, __filename) {
    (function () {
      'use strict';
      var ES6Regex, ES5Regex, NON_ASCII_WHITESPACES, IDENTIFIER_START, IDENTIFIER_PART, ch;
      ES5Regex = {
        NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/,
        NonAsciiIdentifierPart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/
      };
      ES6Regex = {
        NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/,
        NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
      };
      function isDecimalDigit(ch) {
        return 48 <= ch && ch <= 57;
      }
      function isHexDigit(ch) {
        return 48 <= ch && ch <= 57 || 97 <= ch && ch <= 102 || 65 <= ch && ch <= 70;
      }
      function isOctalDigit(ch) {
        return ch >= 48 && ch <= 55;
      }
      NON_ASCII_WHITESPACES = [
        5760,
        6158,
        8192,
        8193,
        8194,
        8195,
        8196,
        8197,
        8198,
        8199,
        8200,
        8201,
        8202,
        8239,
        8287,
        12288,
        65279
      ];
      function isWhiteSpace(ch) {
        return ch === 32 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch >= 5760 && NON_ASCII_WHITESPACES.indexOf(ch) >= 0;
      }
      function isLineTerminator(ch) {
        return ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
      }
      function fromCodePoint(cp) {
        if (cp <= 65535) {
          return String.fromCharCode(cp);
        }
        var cu1 = String.fromCharCode(Math.floor((cp - 65536) / 1024) + 55296);
        var cu2 = String.fromCharCode((cp - 65536) % 1024 + 56320);
        return cu1 + cu2;
      }
      IDENTIFIER_START = new Array(128);
      for (ch = 0; ch < 128; ++ch) {
        IDENTIFIER_START[ch] = ch >= 97 && ch <= 122 || ch >= 65 && ch <= 90 || ch === 36 || ch === 95;
      }
      IDENTIFIER_PART = new Array(128);
      for (ch = 0; ch < 128; ++ch) {
        IDENTIFIER_PART[ch] = ch >= 97 && ch <= 122 || ch >= 65 && ch <= 90 || ch >= 48 && ch <= 57 || ch === 36 || ch === 95;
      }
      function isIdentifierStartES5(ch) {
        return ch < 128 ? IDENTIFIER_START[ch] : ES5Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch));
      }
      function isIdentifierPartES5(ch) {
        return ch < 128 ? IDENTIFIER_PART[ch] : ES5Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch));
      }
      function isIdentifierStartES6(ch) {
        return ch < 128 ? IDENTIFIER_START[ch] : ES6Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch));
      }
      function isIdentifierPartES6(ch) {
        return ch < 128 ? IDENTIFIER_PART[ch] : ES6Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch));
      }
      module.exports = {
        isDecimalDigit: isDecimalDigit,
        isHexDigit: isHexDigit,
        isOctalDigit: isOctalDigit,
        isWhiteSpace: isWhiteSpace,
        isLineTerminator: isLineTerminator,
        isIdentifierStartES5: isIdentifierStartES5,
        isIdentifierPartES5: isIdentifierPartES5,
        isIdentifierStartES6: isIdentifierStartES6,
        isIdentifierPartES6: isIdentifierPartES6
      };
    }());
  });
  require.define('/node_modules/esutils/lib/ast.js', function (module, exports, __dirname, __filename) {
    (function () {
      'use strict';
      function isExpression(node) {
        if (node == null) {
          return false;
        }
        switch (node.type) {
        case 'ArrayExpression':
        case 'AssignmentExpression':
        case 'BinaryExpression':
        case 'CallExpression':
        case 'ConditionalExpression':
        case 'FunctionExpression':
        case 'Identifier':
        case 'Literal':
        case 'LogicalExpression':
        case 'MemberExpression':
        case 'NewExpression':
        case 'ObjectExpression':
        case 'SequenceExpression':
        case 'ThisExpression':
        case 'UnaryExpression':
        case 'UpdateExpression':
          return true;
        }
        return false;
      }
      function isIterationStatement(node) {
        if (node == null) {
          return false;
        }
        switch (node.type) {
        case 'DoWhileStatement':
        case 'ForInStatement':
        case 'ForStatement':
        case 'WhileStatement':
          return true;
        }
        return false;
      }
      function isStatement(node) {
        if (node == null) {
          return false;
        }
        switch (node.type) {
        case 'BlockStatement':
        case 'BreakStatement':
        case 'ContinueStatement':
        case 'DebuggerStatement':
        case 'DoWhileStatement':
        case 'EmptyStatement':
        case 'ExpressionStatement':
        case 'ForInStatement':
        case 'ForStatement':
        case 'IfStatement':
        case 'LabeledStatement':
        case 'ReturnStatement':
        case 'SwitchStatement':
        case 'ThrowStatement':
        case 'TryStatement':
        case 'VariableDeclaration':
        case 'WhileStatement':
        case 'WithStatement':
          return true;
        }
        return false;
      }
      function isSourceElement(node) {
        return isStatement(node) || node != null && node.type === 'FunctionDeclaration';
      }
      function trailingStatement(node) {
        switch (node.type) {
        case 'IfStatement':
          if (node.alternate != null) {
            return node.alternate;
          }
          return node.consequent;
        case 'LabeledStatement':
        case 'ForStatement':
        case 'ForInStatement':
        case 'WhileStatement':
        case 'WithStatement':
          return node.body;
        }
        return null;
      }
      function isProblematicIfStatement(node) {
        var current;
        if (node.type !== 'IfStatement') {
          return false;
        }
        if (node.alternate == null) {
          return false;
        }
        current = node.consequent;
        do {
          if (current.type === 'IfStatement') {
            if (current.alternate == null) {
              return true;
            }
          }
          current = trailingStatement(current);
        } while (current);
        return false;
      }
      module.exports = {
        isExpression: isExpression,
        isStatement: isStatement,
        isIterationStatement: isIterationStatement,
        isSourceElement: isSourceElement,
        isProblematicIfStatement: isProblematicIfStatement,
        trailingStatement: trailingStatement
      };
    }());
  });
  require.define('/node_modules/estraverse/estraverse.js', function (module, exports, __dirname, __filename) {
    (function (root, factory) {
      'use strict';
      if (typeof define === 'function' && define.amd) {
        define(['exports'], factory);
      } else if (typeof exports !== 'undefined') {
        factory(exports);
      } else {
        factory(root.estraverse = {});
      }
    }(this, function clone(exports) {
      'use strict';
      var Syntax, isArray, VisitorOption, VisitorKeys, objectCreate, objectKeys, BREAK, SKIP, REMOVE;
      function ignoreJSHintError() {
      }
      isArray = Array.isArray;
      if (!isArray) {
        isArray = function isArray(array) {
          return Object.prototype.toString.call(array) === '[object Array]';
        };
      }
      function deepCopy(obj) {
        var ret = {}, key, val;
        for (key in obj) {
          if (obj.hasOwnProperty(key)) {
            val = obj[key];
            if (typeof val === 'object' && val !== null) {
              ret[key] = deepCopy(val);
            } else {
              ret[key] = val;
            }
          }
        }
        return ret;
      }
      function shallowCopy(obj) {
        var ret = {}, key;
        for (key in obj) {
          if (obj.hasOwnProperty(key)) {
            ret[key] = obj[key];
          }
        }
        return ret;
      }
      ignoreJSHintError(shallowCopy);
      function upperBound(array, func) {
        var diff, len, i, current;
        len = array.length;
        i = 0;
        while (len) {
          diff = len >>> 1;
          current = i + diff;
          if (func(array[current])) {
            len = diff;
          } else {
            i = current + 1;
            len -= diff + 1;
          }
        }
        return i;
      }
      function lowerBound(array, func) {
        var diff, len, i, current;
        len = array.length;
        i = 0;
        while (len) {
          diff = len >>> 1;
          current = i + diff;
          if (func(array[current])) {
            i = current + 1;
            len -= diff + 1;
          } else {
            len = diff;
          }
        }
        return i;
      }
      ignoreJSHintError(lowerBound);
      objectCreate = Object.create || function () {
        function F() {
        }
        return function (o) {
          F.prototype = o;
          return new F;
        };
      }();
      objectKeys = Object.keys || function (o) {
        var keys = [], key;
        for (key in o) {
          keys.push(key);
        }
        return keys;
      };
      function extend(to, from) {
        var keys = objectKeys(from), key, i, len;
        for (i = 0, len = keys.length; i < len; i += 1) {
          key = keys[i];
          to[key] = from[key];
        }
        return to;
      }
      Syntax = {
        AssignmentExpression: 'AssignmentExpression',
        ArrayExpression: 'ArrayExpression',
        ArrayPattern: 'ArrayPattern',
        ArrowFunctionExpression: 'ArrowFunctionExpression',
        AwaitExpression: 'AwaitExpression',
        BlockStatement: 'BlockStatement',
        BinaryExpression: 'BinaryExpression',
        BreakStatement: 'BreakStatement',
        CallExpression: 'CallExpression',
        CatchClause: 'CatchClause',
        ClassBody: 'ClassBody',
        ClassDeclaration: 'ClassDeclaration',
        ClassExpression: 'ClassExpression',
        ComprehensionBlock: 'ComprehensionBlock',
        ComprehensionExpression: 'ComprehensionExpression',
        ConditionalExpression: 'ConditionalExpression',
        ContinueStatement: 'ContinueStatement',
        DebuggerStatement: 'DebuggerStatement',
        DirectiveStatement: 'DirectiveStatement',
        DoWhileStatement: 'DoWhileStatement',
        EmptyStatement: 'EmptyStatement',
        ExportBatchSpecifier: 'ExportBatchSpecifier',
        ExportDeclaration: 'ExportDeclaration',
        ExportSpecifier: 'ExportSpecifier',
        ExpressionStatement: 'ExpressionStatement',
        ForStatement: 'ForStatement',
        ForInStatement: 'ForInStatement',
        ForOfStatement: 'ForOfStatement',
        FunctionDeclaration: 'FunctionDeclaration',
        FunctionExpression: 'FunctionExpression',
        GeneratorExpression: 'GeneratorExpression',
        Identifier: 'Identifier',
        IfStatement: 'IfStatement',
        ImportDeclaration: 'ImportDeclaration',
        ImportDefaultSpecifier: 'ImportDefaultSpecifier',
        ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
        ImportSpecifier: 'ImportSpecifier',
        Literal: 'Literal',
        LabeledStatement: 'LabeledStatement',
        LogicalExpression: 'LogicalExpression',
        MemberExpression: 'MemberExpression',
        MethodDefinition: 'MethodDefinition',
        ModuleSpecifier: 'ModuleSpecifier',
        NewExpression: 'NewExpression',
        ObjectExpression: 'ObjectExpression',
        ObjectPattern: 'ObjectPattern',
        Program: 'Program',
        Property: 'Property',
        ReturnStatement: 'ReturnStatement',
        SequenceExpression: 'SequenceExpression',
        SpreadElement: 'SpreadElement',
        SwitchStatement: 'SwitchStatement',
        SwitchCase: 'SwitchCase',
        TaggedTemplateExpression: 'TaggedTemplateExpression',
        TemplateElement: 'TemplateElement',
        TemplateLiteral: 'TemplateLiteral',
        ThisExpression: 'ThisExpression',
        ThrowStatement: 'ThrowStatement',
        TryStatement: 'TryStatement',
        UnaryExpression: 'UnaryExpression',
        UpdateExpression: 'UpdateExpression',
        VariableDeclaration: 'VariableDeclaration',
        VariableDeclarator: 'VariableDeclarator',
        WhileStatement: 'WhileStatement',
        WithStatement: 'WithStatement',
        YieldExpression: 'YieldExpression'
      };
      VisitorKeys = {
        AssignmentExpression: [
          'left',
          'right'
        ],
        ArrayExpression: ['elements'],
        ArrayPattern: ['elements'],
        ArrowFunctionExpression: [
          'params',
          'defaults',
          'rest',
          'body'
        ],
        AwaitExpression: ['argument'],
        BlockStatement: ['body'],
        BinaryExpression: [
          'left',
          'right'
        ],
        BreakStatement: ['label'],
        CallExpression: [
          'callee',
          'arguments'
        ],
        CatchClause: [
          'param',
          'body'
        ],
        ClassBody: ['body'],
        ClassDeclaration: [
          'id',
          'body',
          'superClass'
        ],
        ClassExpression: [
          'id',
          'body',
          'superClass'
        ],
        ComprehensionBlock: [
          'left',
          'right'
        ],
        ComprehensionExpression: [
          'blocks',
          'filter',
          'body'
        ],
        ConditionalExpression: [
          'test',
          'consequent',
          'alternate'
        ],
        ContinueStatement: ['label'],
        DebuggerStatement: [],
        DirectiveStatement: [],
        DoWhileStatement: [
          'body',
          'test'
        ],
        EmptyStatement: [],
        ExportBatchSpecifier: [],
        ExportDeclaration: [
          'declaration',
          'specifiers',
          'source'
        ],
        ExportSpecifier: [
          'id',
          'name'
        ],
        ExpressionStatement: ['expression'],
        ForStatement: [
          'init',
          'test',
          'update',
          'body'
        ],
        ForInStatement: [
          'left',
          'right',
          'body'
        ],
        ForOfStatement: [
          'left',
          'right',
          'body'
        ],
        FunctionDeclaration: [
          'id',
          'params',
          'defaults',
          'rest',
          'body'
        ],
        FunctionExpression: [
          'id',
          'params',
          'defaults',
          'rest',
          'body'
        ],
        GeneratorExpression: [
          'blocks',
          'filter',
          'body'
        ],
        Identifier: [],
        IfStatement: [
          'test',
          'consequent',
          'alternate'
        ],
        ImportDeclaration: [
          'specifiers',
          'source'
        ],
        ImportDefaultSpecifier: ['id'],
        ImportNamespaceSpecifier: ['id'],
        ImportSpecifier: [
          'id',
          'name'
        ],
        Literal: [],
        LabeledStatement: [
          'label',
          'body'
        ],
        LogicalExpression: [
          'left',
          'right'
        ],
        MemberExpression: [
          'object',
          'property'
        ],
        MethodDefinition: [
          'key',
          'value'
        ],
        ModuleSpecifier: [],
        NewExpression: [
          'callee',
          'arguments'
        ],
        ObjectExpression: ['properties'],
        ObjectPattern: ['properties'],
        Program: ['body'],
        Property: [
          'key',
          'value'
        ],
        ReturnStatement: ['argument'],
        SequenceExpression: ['expressions'],
        SpreadElement: ['argument'],
        SwitchStatement: [
          'discriminant',
          'cases'
        ],
        SwitchCase: [
          'test',
          'consequent'
        ],
        TaggedTemplateExpression: [
          'tag',
          'quasi'
        ],
        TemplateElement: [],
        TemplateLiteral: [
          'quasis',
          'expressions'
        ],
        ThisExpression: [],
        ThrowStatement: ['argument'],
        TryStatement: [
          'block',
          'handlers',
          'handler',
          'guardedHandlers',
          'finalizer'
        ],
        UnaryExpression: ['argument'],
        UpdateExpression: ['argument'],
        VariableDeclaration: ['declarations'],
        VariableDeclarator: [
          'id',
          'init'
        ],
        WhileStatement: [
          'test',
          'body'
        ],
        WithStatement: [
          'object',
          'body'
        ],
        YieldExpression: ['argument']
      };
      BREAK = {};
      SKIP = {};
      REMOVE = {};
      VisitorOption = {
        Break: BREAK,
        Skip: SKIP,
        Remove: REMOVE
      };
      function Reference(parent, key) {
        this.parent = parent;
        this.key = key;
      }
      Reference.prototype.replace = function replace(node) {
        this.parent[this.key] = node;
      };
      Reference.prototype.remove = function remove() {
        if (isArray(this.parent)) {
          this.parent.splice(this.key, 1);
          return true;
        } else {
          this.replace(null);
          return false;
        }
      };
      function Element(node, path, wrap, ref) {
        this.node = node;
        this.path = path;
        this.wrap = wrap;
        this.ref = ref;
      }
      function Controller() {
      }
      Controller.prototype.path = function path() {
        var i, iz, j, jz, result, element;
        function addToPath(result, path) {
          if (isArray(path)) {
            for (j = 0, jz = path.length; j < jz; ++j) {
              result.push(path[j]);
            }
          } else {
            result.push(path);
          }
        }
        if (!this.__current.path) {
          return null;
        }
        result = [];
        for (i = 2, iz = this.__leavelist.length; i < iz; ++i) {
          element = this.__leavelist[i];
          addToPath(result, element.path);
        }
        addToPath(result, this.__current.path);
        return result;
      };
      Controller.prototype.type = function () {
        var node = this.current();
        return node.type || this.__current.wrap;
      };
      Controller.prototype.parents = function parents() {
        var i, iz, result;
        result = [];
        for (i = 1, iz = this.__leavelist.length; i < iz; ++i) {
          result.push(this.__leavelist[i].node);
        }
        return result;
      };
      Controller.prototype.current = function current() {
        return this.__current.node;
      };
      Controller.prototype.__execute = function __execute(callback, element) {
        var previous, result;
        result = undefined;
        previous = this.__current;
        this.__current = element;
        this.__state = null;
        if (callback) {
          result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node);
        }
        this.__current = previous;
        return result;
      };
      Controller.prototype.notify = function notify(flag) {
        this.__state = flag;
      };
      Controller.prototype.skip = function () {
        this.notify(SKIP);
      };
      Controller.prototype['break'] = function () {
        this.notify(BREAK);
      };
      Controller.prototype.remove = function () {
        this.notify(REMOVE);
      };
      Controller.prototype.__initialize = function (root, visitor) {
        this.visitor = visitor;
        this.root = root;
        this.__worklist = [];
        this.__leavelist = [];
        this.__current = null;
        this.__state = null;
        this.__fallback = visitor.fallback === 'iteration';
        this.__keys = VisitorKeys;
        if (visitor.keys) {
          this.__keys = extend(objectCreate(this.__keys), visitor.keys);
        }
      };
      function isNode(node) {
        if (node == null) {
          return false;
        }
        return typeof node === 'object' && typeof node.type === 'string';
      }
      function isProperty(nodeType, key) {
        return (nodeType === Syntax.ObjectExpression || nodeType === Syntax.ObjectPattern) && 'properties' === key;
      }
      Controller.prototype.traverse = function traverse(root, visitor) {
        var worklist, leavelist, element, node, nodeType, ret, key, current, current2, candidates, candidate, sentinel;
        this.__initialize(root, visitor);
        sentinel = {};
        worklist = this.__worklist;
        leavelist = this.__leavelist;
        worklist.push(new Element(root, null, null, null));
        leavelist.push(new Element(null, null, null, null));
        while (worklist.length) {
          element = worklist.pop();
          if (element === sentinel) {
            element = leavelist.pop();
            ret = this.__execute(visitor.leave, element);
            if (this.__state === BREAK || ret === BREAK) {
              return;
            }
            continue;
          }
          if (element.node) {
            ret = this.__execute(visitor.enter, element);
            if (this.__state === BREAK || ret === BREAK) {
              return;
            }
            worklist.push(sentinel);
            leavelist.push(element);
            if (this.__state === SKIP || ret === SKIP) {
              continue;
            }
            node = element.node;
            nodeType = element.wrap || node.type;
            candidates = this.__keys[nodeType];
            if (!candidates) {
              if (this.__fallback) {
                candidates = objectKeys(node);
              } else {
                throw new Error('Unknown node type ' + nodeType + '.');
              }
            }
            current = candidates.length;
            while ((current -= 1) >= 0) {
              key = candidates[current];
              candidate = node[key];
              if (!candidate) {
                continue;
              }
              if (isArray(candidate)) {
                current2 = candidate.length;
                while ((current2 -= 1) >= 0) {
                  if (!candidate[current2]) {
                    continue;
                  }
                  if (isProperty(nodeType, candidates[current])) {
                    element = new Element(candidate[current2], [
                      key,
                      current2
                    ], 'Property', null);
                  } else if (isNode(candidate[current2])) {
                    element = new Element(candidate[current2], [
                      key,
                      current2
                    ], null, null);
                  } else {
                    continue;
                  }
                  worklist.push(element);
                }
              } else if (isNode(candidate)) {
                worklist.push(new Element(candidate, key, null, null));
              }
            }
          }
        }
      };
      Controller.prototype.replace = function replace(root, visitor) {
        function removeElem(element) {
          var i, key, nextElem, parent;
          if (element.ref.remove()) {
            key = element.ref.key;
            parent = element.ref.parent;
            i = worklist.length;
            while (i--) {
              nextElem = worklist[i];
              if (nextElem.ref && nextElem.ref.parent === parent) {
                if (nextElem.ref.key < key) {
                  break;
                }
                --nextElem.ref.key;
              }
            }
          }
        }
        var worklist, leavelist, node, nodeType, target, element, current, current2, candidates, candidate, sentinel, outer, key;
        this.__initialize(root, visitor);
        sentinel = {};
        worklist = this.__worklist;
        leavelist = this.__leavelist;
        outer = { root: root };
        element = new Element(root, null, null, new Reference(outer, 'root'));
        worklist.push(element);
        leavelist.push(element);
        while (worklist.length) {
          element = worklist.pop();
          if (element === sentinel) {
            element = leavelist.pop();
            target = this.__execute(visitor.leave, element);
            if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
              element.ref.replace(target);
            }
            if (this.__state === REMOVE || target === REMOVE) {
              removeElem(element);
            }
            if (this.__state === BREAK || target === BREAK) {
              return outer.root;
            }
            continue;
          }
          target = this.__execute(visitor.enter, element);
          if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
            element.ref.replace(target);
            element.node = target;
          }
          if (this.__state === REMOVE || target === REMOVE) {
            removeElem(element);
            element.node = null;
          }
          if (this.__state === BREAK || target === BREAK) {
            return outer.root;
          }
          node = element.node;
          if (!node) {
            continue;
          }
          worklist.push(sentinel);
          leavelist.push(element);
          if (this.__state === SKIP || target === SKIP) {
            continue;
          }
          nodeType = element.wrap || node.type;
          candidates = this.__keys[nodeType];
          if (!candidates) {
            if (this.__fallback) {
              candidates = objectKeys(node);
            } else {
              throw new Error('Unknown node type ' + nodeType + '.');
            }
          }
          current = candidates.length;
          while ((current -= 1) >= 0) {
            key = candidates[current];
            candidate = node[key];
            if (!candidate) {
              continue;
            }
            if (isArray(candidate)) {
              current2 = candidate.length;
              while ((current2 -= 1) >= 0) {
                if (!candidate[current2]) {
                  continue;
                }
                if (isProperty(nodeType, candidates[current])) {
                  element = new Element(candidate[current2], [
                    key,
                    current2
                  ], 'Property', new Reference(candidate, current2));
                } else if (isNode(candidate[current2])) {
                  element = new Element(candidate[current2], [
                    key,
                    current2
                  ], null, new Reference(candidate, current2));
                } else {
                  continue;
                }
                worklist.push(element);
              }
            } else if (isNode(candidate)) {
              worklist.push(new Element(candidate, key, null, new Reference(node, key)));
            }
          }
        }
        return outer.root;
      };
      function traverse(root, visitor) {
        var controller = new Controller;
        return controller.traverse(root, visitor);
      }
      function replace(root, visitor) {
        var controller = new Controller;
        return controller.replace(root, visitor);
      }
      function extendCommentRange(comment, tokens) {
        var target;
        target = upperBound(tokens, function search(token) {
          return token.range[0] > comment.range[0];
        });
        comment.extendedRange = [
          comment.range[0],
          comment.range[1]
        ];
        if (target !== tokens.length) {
          comment.extendedRange[1] = tokens[target].range[0];
        }
        target -= 1;
        if (target >= 0) {
          comment.extendedRange[0] = tokens[target].range[1];
        }
        return comment;
      }
      function attachComments(tree, providedComments, tokens) {
        var comments = [], comment, len, i, cursor;
        if (!tree.range) {
          throw new Error('attachComments needs range information');
        }
        if (!tokens.length) {
          if (providedComments.length) {
            for (i = 0, len = providedComments.length; i < len; i += 1) {
              comment = deepCopy(providedComments[i]);
              comment.extendedRange = [
                0,
                tree.range[0]
              ];
              comments.push(comment);
            }
            tree.leadingComments = comments;
          }
          return tree;
        }
        for (i = 0, len = providedComments.length; i < len; i += 1) {
          comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
        }
        cursor = 0;
        traverse(tree, {
          enter: function (node) {
            var comment;
            while (cursor < comments.length) {
              comment = comments[cursor];
              if (comment.extendedRange[1] > node.range[0]) {
                break;
              }
              if (comment.extendedRange[1] === node.range[0]) {
                if (!node.leadingComments) {
                  node.leadingComments = [];
                }
                node.leadingComments.push(comment);
                comments.splice(cursor, 1);
              } else {
                cursor += 1;
              }
            }
            if (cursor === comments.length) {
              return VisitorOption.Break;
            }
            if (comments[cursor].extendedRange[0] > node.range[1]) {
              return VisitorOption.Skip;
            }
          }
        });
        cursor = 0;
        traverse(tree, {
          leave: function (node) {
            var comment;
            while (cursor < comments.length) {
              comment = comments[cursor];
              if (node.range[1] < comment.extendedRange[0]) {
                break;
              }
              if (node.range[1] === comment.extendedRange[0]) {
                if (!node.trailingComments) {
                  node.trailingComments = [];
                }
                node.trailingComments.push(comment);
                comments.splice(cursor, 1);
              } else {
                cursor += 1;
              }
            }
            if (cursor === comments.length) {
              return VisitorOption.Break;
            }
            if (comments[cursor].extendedRange[0] > node.range[1]) {
              return VisitorOption.Skip;
            }
          }
        });
        return tree;
      }
      exports.version = '1.8.1-dev';
      exports.Syntax = Syntax;
      exports.traverse = traverse;
      exports.replace = replace;
      exports.attachComments = attachComments;
      exports.VisitorKeys = VisitorKeys;
      exports.VisitorOption = VisitorOption;
      exports.Controller = Controller;
      exports.cloneEnvironment = function () {
        return clone({});
      };
      return exports;
    }));
  });
  require('/tools/entry-point.js');
}.call(GLOBAL, GLOBAL));

})(typeof window !== "undefined" ? window :
    typeof global!=="undefined" ? global :
      typeof self!=="undefined" ? self : this);
;
  })();
  (function() {
    this.lively = this.lively || {};
(function (exports,lively_lang,escodegen,acorn$1) {
'use strict';

// <<<<<<<<<<<<< BEGIN OF AUTO GENERATED CODE <<<<<<<<<<<<<
// Generated on 17-11-28 13:01 PST
function Visitor() {}
Visitor.prototype.accept = function accept(node, state, path) {
  if (!node) throw new Error("Undefined AST node in Visitor.accept:\n  " + path.join(".") + "\n  " + node);
  if (!node.type) throw new Error("Strangee AST node without type in Visitor.accept:\n  " + path.join(".") + "\n  " + JSON.stringify(node));
  switch (node.type) {
    case "Node":
      return this.visitNode(node, state, path);
    case "SourceLocation":
      return this.visitSourceLocation(node, state, path);
    case "Position":
      return this.visitPosition(node, state, path);
    case "Program":
      return this.visitProgram(node, state, path);
    case "Function":
      return this.visitFunction(node, state, path);
    case "Statement":
      return this.visitStatement(node, state, path);
    case "Directive":
      return this.visitDirective(node, state, path);
    case "SwitchCase":
      return this.visitSwitchCase(node, state, path);
    case "CatchClause":
      return this.visitCatchClause(node, state, path);
    case "VariableDeclarator":
      return this.visitVariableDeclarator(node, state, path);
    case "Expression":
      return this.visitExpression(node, state, path);
    case "Property":
      return this.visitProperty(node, state, path);
    case "Pattern":
      return this.visitPattern(node, state, path);
    case "Super":
      return this.visitSuper(node, state, path);
    case "SpreadElement":
      return this.visitSpreadElement(node, state, path);
    case "TemplateElement":
      return this.visitTemplateElement(node, state, path);
    case "Class":
      return this.visitClass(node, state, path);
    case "ClassBody":
      return this.visitClassBody(node, state, path);
    case "MethodDefinition":
      return this.visitMethodDefinition(node, state, path);
    case "ModuleDeclaration":
      return this.visitModuleDeclaration(node, state, path);
    case "ModuleSpecifier":
      return this.visitModuleSpecifier(node, state, path);
    case "JSXEmptyExpression":
      return this.visitJSXEmptyExpression(node, state, path);
    case "JSXExpressionContainer":
      return this.visitJSXExpressionContainer(node, state, path);
    case "JSXSpreadChild":
      return this.visitJSXSpreadChild(node, state, path);
    case "JSXBoundaryElement":
      return this.visitJSXBoundaryElement(node, state, path);
    case "JSXAttribute":
      return this.visitJSXAttribute(node, state, path);
    case "JSXText":
      return this.visitJSXText(node, state, path);
    case "JSXOpeningFragment":
      return this.visitJSXOpeningFragment(node, state, path);
    case "JSXClosingFragment":
      return this.visitJSXClosingFragment(node, state, path);
    case "Identifier":
      return this.visitIdentifier(node, state, path);
    case "Literal":
      return this.visitLiteral(node, state, path);
    case "ExpressionStatement":
      return this.visitExpressionStatement(node, state, path);
    case "BlockStatement":
      return this.visitBlockStatement(node, state, path);
    case "EmptyStatement":
      return this.visitEmptyStatement(node, state, path);
    case "DebuggerStatement":
      return this.visitDebuggerStatement(node, state, path);
    case "WithStatement":
      return this.visitWithStatement(node, state, path);
    case "ReturnStatement":
      return this.visitReturnStatement(node, state, path);
    case "LabeledStatement":
      return this.visitLabeledStatement(node, state, path);
    case "BreakStatement":
      return this.visitBreakStatement(node, state, path);
    case "ContinueStatement":
      return this.visitContinueStatement(node, state, path);
    case "IfStatement":
      return this.visitIfStatement(node, state, path);
    case "SwitchStatement":
      return this.visitSwitchStatement(node, state, path);
    case "ThrowStatement":
      return this.visitThrowStatement(node, state, path);
    case "TryStatement":
      return this.visitTryStatement(node, state, path);
    case "WhileStatement":
      return this.visitWhileStatement(node, state, path);
    case "DoWhileStatement":
      return this.visitDoWhileStatement(node, state, path);
    case "ForStatement":
      return this.visitForStatement(node, state, path);
    case "ForInStatement":
      return this.visitForInStatement(node, state, path);
    case "Declaration":
      return this.visitDeclaration(node, state, path);
    case "ThisExpression":
      return this.visitThisExpression(node, state, path);
    case "ArrayExpression":
      return this.visitArrayExpression(node, state, path);
    case "ObjectExpression":
      return this.visitObjectExpression(node, state, path);
    case "FunctionExpression":
      return this.visitFunctionExpression(node, state, path);
    case "UnaryExpression":
      return this.visitUnaryExpression(node, state, path);
    case "UpdateExpression":
      return this.visitUpdateExpression(node, state, path);
    case "BinaryExpression":
      return this.visitBinaryExpression(node, state, path);
    case "AssignmentExpression":
      return this.visitAssignmentExpression(node, state, path);
    case "LogicalExpression":
      return this.visitLogicalExpression(node, state, path);
    case "MemberExpression":
      return this.visitMemberExpression(node, state, path);
    case "ConditionalExpression":
      return this.visitConditionalExpression(node, state, path);
    case "CallExpression":
      return this.visitCallExpression(node, state, path);
    case "NewExpression":
      return this.visitNewExpression(node, state, path);
    case "SequenceExpression":
      return this.visitSequenceExpression(node, state, path);
    case "ArrowFunctionExpression":
      return this.visitArrowFunctionExpression(node, state, path);
    case "YieldExpression":
      return this.visitYieldExpression(node, state, path);
    case "TemplateLiteral":
      return this.visitTemplateLiteral(node, state, path);
    case "TaggedTemplateExpression":
      return this.visitTaggedTemplateExpression(node, state, path);
    case "AssignmentProperty":
      return this.visitAssignmentProperty(node, state, path);
    case "ObjectPattern":
      return this.visitObjectPattern(node, state, path);
    case "ArrayPattern":
      return this.visitArrayPattern(node, state, path);
    case "RestElement":
      return this.visitRestElement(node, state, path);
    case "AssignmentPattern":
      return this.visitAssignmentPattern(node, state, path);
    case "ClassExpression":
      return this.visitClassExpression(node, state, path);
    case "MetaProperty":
      return this.visitMetaProperty(node, state, path);
    case "ImportDeclaration":
      return this.visitImportDeclaration(node, state, path);
    case "ImportSpecifier":
      return this.visitImportSpecifier(node, state, path);
    case "ImportDefaultSpecifier":
      return this.visitImportDefaultSpecifier(node, state, path);
    case "ImportNamespaceSpecifier":
      return this.visitImportNamespaceSpecifier(node, state, path);
    case "ExportNamedDeclaration":
      return this.visitExportNamedDeclaration(node, state, path);
    case "ExportSpecifier":
      return this.visitExportSpecifier(node, state, path);
    case "ExportDefaultDeclaration":
      return this.visitExportDefaultDeclaration(node, state, path);
    case "ExportAllDeclaration":
      return this.visitExportAllDeclaration(node, state, path);
    case "AwaitExpression":
      return this.visitAwaitExpression(node, state, path);
    case "JSXMemberExpression":
      return this.visitJSXMemberExpression(node, state, path);
    case "JSXNamespacedName":
      return this.visitJSXNamespacedName(node, state, path);
    case "JSXOpeningElement":
      return this.visitJSXOpeningElement(node, state, path);
    case "JSXClosingElement":
      return this.visitJSXClosingElement(node, state, path);
    case "JSXSpreadAttribute":
      return this.visitJSXSpreadAttribute(node, state, path);
    case "JSXElement":
      return this.visitJSXElement(node, state, path);
    case "JSXFragment":
      return this.visitJSXFragment(node, state, path);
    case "RegExpLiteral":
      return this.visitRegExpLiteral(node, state, path);
    case "FunctionBody":
      return this.visitFunctionBody(node, state, path);
    case "FunctionDeclaration":
      return this.visitFunctionDeclaration(node, state, path);
    case "VariableDeclaration":
      return this.visitVariableDeclaration(node, state, path);
    case "ForOfStatement":
      return this.visitForOfStatement(node, state, path);
    case "ClassDeclaration":
      return this.visitClassDeclaration(node, state, path);
    case "JSXIdentifier":
      return this.visitJSXIdentifier(node, state, path);
  }
  throw new Error("No visit function in AST visitor Visitor for:\n  " + path.join(".") + "\n  " + JSON.stringify(node));
};
Visitor.prototype.visitNode = function visitNode(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitSourceLocation = function visitSourceLocation(node, state, path) {
  var visitor = this;
  // start is of types Position
  node["start"] = visitor.accept(node["start"], state, path.concat(["start"]));
  // end is of types Position
  node["end"] = visitor.accept(node["end"], state, path.concat(["end"]));
  return node;
};
Visitor.prototype.visitPosition = function visitPosition(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitProgram = function visitProgram(node, state, path) {
  var visitor = this;
  // body is a list with types Statement, ModuleDeclaration
  var newElements = [];
  for (var i = 0; i < node["body"].length; i++) {
    var ea = node["body"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["body", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["body"] = newElements;
  return node;
};
Visitor.prototype.visitFunction = function visitFunction(node, state, path) {
  var visitor = this;
  // id is of types Identifier
  if (node["id"]) {
    node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  }
  // params is a list with types Pattern
  var newElements = [];
  for (var i = 0; i < node["params"].length; i++) {
    var ea = node["params"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["params", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["params"] = newElements;
  // body is of types FunctionBody
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitStatement = function visitStatement(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitDirective = function visitDirective(node, state, path) {
  var visitor = this;
  // expression is of types Literal
  node["expression"] = visitor.accept(node["expression"], state, path.concat(["expression"]));
  return node;
};
Visitor.prototype.visitSwitchCase = function visitSwitchCase(node, state, path) {
  var visitor = this;
  // test is of types Expression
  if (node["test"]) {
    node["test"] = visitor.accept(node["test"], state, path.concat(["test"]));
  }
  // consequent is a list with types Statement
  var newElements = [];
  for (var i = 0; i < node["consequent"].length; i++) {
    var ea = node["consequent"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["consequent", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["consequent"] = newElements;
  return node;
};
Visitor.prototype.visitCatchClause = function visitCatchClause(node, state, path) {
  var visitor = this;
  // param is of types Pattern
  node["param"] = visitor.accept(node["param"], state, path.concat(["param"]));
  // body is of types BlockStatement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitVariableDeclarator = function visitVariableDeclarator(node, state, path) {
  var visitor = this;
  // id is of types Pattern
  node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  // init is of types Expression
  if (node["init"]) {
    node["init"] = visitor.accept(node["init"], state, path.concat(["init"]));
  }
  return node;
};
Visitor.prototype.visitExpression = function visitExpression(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitProperty = function visitProperty(node, state, path) {
  var visitor = this;
  // key is of types Expression
  node["key"] = visitor.accept(node["key"], state, path.concat(["key"]));
  // value is of types Expression
  node["value"] = visitor.accept(node["value"], state, path.concat(["value"]));
  return node;
};
Visitor.prototype.visitPattern = function visitPattern(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitSuper = function visitSuper(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitSpreadElement = function visitSpreadElement(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  return node;
};
Visitor.prototype.visitTemplateElement = function visitTemplateElement(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitClass = function visitClass(node, state, path) {
  var visitor = this;
  // id is of types Identifier
  if (node["id"]) {
    node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  }
  // superClass is of types Expression
  if (node["superClass"]) {
    node["superClass"] = visitor.accept(node["superClass"], state, path.concat(["superClass"]));
  }
  // body is of types ClassBody
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitClassBody = function visitClassBody(node, state, path) {
  var visitor = this;
  // body is a list with types MethodDefinition
  var newElements = [];
  for (var i = 0; i < node["body"].length; i++) {
    var ea = node["body"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["body", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["body"] = newElements;
  return node;
};
Visitor.prototype.visitMethodDefinition = function visitMethodDefinition(node, state, path) {
  var visitor = this;
  // key is of types Expression
  node["key"] = visitor.accept(node["key"], state, path.concat(["key"]));
  // value is of types FunctionExpression
  node["value"] = visitor.accept(node["value"], state, path.concat(["value"]));
  return node;
};
Visitor.prototype.visitModuleDeclaration = function visitModuleDeclaration(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitModuleSpecifier = function visitModuleSpecifier(node, state, path) {
  var visitor = this;
  // local is of types Identifier
  node["local"] = visitor.accept(node["local"], state, path.concat(["local"]));
  return node;
};
Visitor.prototype.visitJSXEmptyExpression = function visitJSXEmptyExpression(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitJSXExpressionContainer = function visitJSXExpressionContainer(node, state, path) {
  var visitor = this;
  // expression is of types Expression, JSXEmptyExpression
  node["expression"] = visitor.accept(node["expression"], state, path.concat(["expression"]));
  return node;
};
Visitor.prototype.visitJSXSpreadChild = function visitJSXSpreadChild(node, state, path) {
  var visitor = this;
  // expression is of types Expression
  node["expression"] = visitor.accept(node["expression"], state, path.concat(["expression"]));
  return node;
};
Visitor.prototype.visitJSXBoundaryElement = function visitJSXBoundaryElement(node, state, path) {
  var visitor = this;
  // name is of types JSXIdentifier, JSXMemberExpression, JSXNamespacedName
  node["name"] = visitor.accept(node["name"], state, path.concat(["name"]));
  return node;
};
Visitor.prototype.visitJSXAttribute = function visitJSXAttribute(node, state, path) {
  var visitor = this;
  // name is of types JSXIdentifier, JSXNamespacedName
  node["name"] = visitor.accept(node["name"], state, path.concat(["name"]));
  // value is of types Literal, JSXExpressionContainer, JSXElement, JSXFragment
  if (node["value"]) {
    node["value"] = visitor.accept(node["value"], state, path.concat(["value"]));
  }
  return node;
};
Visitor.prototype.visitJSXText = function visitJSXText(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitJSXOpeningFragment = function visitJSXOpeningFragment(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitJSXClosingFragment = function visitJSXClosingFragment(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitIdentifier = function visitIdentifier(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitLiteral = function visitLiteral(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitExpressionStatement = function visitExpressionStatement(node, state, path) {
  var visitor = this;
  // expression is of types Expression
  node["expression"] = visitor.accept(node["expression"], state, path.concat(["expression"]));
  return node;
};
Visitor.prototype.visitBlockStatement = function visitBlockStatement(node, state, path) {
  var visitor = this;
  // body is a list with types Statement
  var newElements = [];
  for (var i = 0; i < node["body"].length; i++) {
    var ea = node["body"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["body", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["body"] = newElements;
  return node;
};
Visitor.prototype.visitEmptyStatement = function visitEmptyStatement(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitDebuggerStatement = function visitDebuggerStatement(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitWithStatement = function visitWithStatement(node, state, path) {
  var visitor = this;
  // object is of types Expression
  node["object"] = visitor.accept(node["object"], state, path.concat(["object"]));
  // body is of types Statement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitReturnStatement = function visitReturnStatement(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  if (node["argument"]) {
    node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  }
  return node;
};
Visitor.prototype.visitLabeledStatement = function visitLabeledStatement(node, state, path) {
  var visitor = this;
  // label is of types Identifier
  node["label"] = visitor.accept(node["label"], state, path.concat(["label"]));
  // body is of types Statement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitBreakStatement = function visitBreakStatement(node, state, path) {
  var visitor = this;
  // label is of types Identifier
  if (node["label"]) {
    node["label"] = visitor.accept(node["label"], state, path.concat(["label"]));
  }
  return node;
};
Visitor.prototype.visitContinueStatement = function visitContinueStatement(node, state, path) {
  var visitor = this;
  // label is of types Identifier
  if (node["label"]) {
    node["label"] = visitor.accept(node["label"], state, path.concat(["label"]));
  }
  return node;
};
Visitor.prototype.visitIfStatement = function visitIfStatement(node, state, path) {
  var visitor = this;
  // test is of types Expression
  node["test"] = visitor.accept(node["test"], state, path.concat(["test"]));
  // consequent is of types Statement
  node["consequent"] = visitor.accept(node["consequent"], state, path.concat(["consequent"]));
  // alternate is of types Statement
  if (node["alternate"]) {
    node["alternate"] = visitor.accept(node["alternate"], state, path.concat(["alternate"]));
  }
  return node;
};
Visitor.prototype.visitSwitchStatement = function visitSwitchStatement(node, state, path) {
  var visitor = this;
  // discriminant is of types Expression
  node["discriminant"] = visitor.accept(node["discriminant"], state, path.concat(["discriminant"]));
  // cases is a list with types SwitchCase
  var newElements = [];
  for (var i = 0; i < node["cases"].length; i++) {
    var ea = node["cases"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["cases", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["cases"] = newElements;
  return node;
};
Visitor.prototype.visitThrowStatement = function visitThrowStatement(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  return node;
};
Visitor.prototype.visitTryStatement = function visitTryStatement(node, state, path) {
  var visitor = this;
  // block is of types BlockStatement
  node["block"] = visitor.accept(node["block"], state, path.concat(["block"]));
  // handler is of types CatchClause
  if (node["handler"]) {
    node["handler"] = visitor.accept(node["handler"], state, path.concat(["handler"]));
  }
  // finalizer is of types BlockStatement
  if (node["finalizer"]) {
    node["finalizer"] = visitor.accept(node["finalizer"], state, path.concat(["finalizer"]));
  }
  return node;
};
Visitor.prototype.visitWhileStatement = function visitWhileStatement(node, state, path) {
  var visitor = this;
  // test is of types Expression
  node["test"] = visitor.accept(node["test"], state, path.concat(["test"]));
  // body is of types Statement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitDoWhileStatement = function visitDoWhileStatement(node, state, path) {
  var visitor = this;
  // body is of types Statement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  // test is of types Expression
  node["test"] = visitor.accept(node["test"], state, path.concat(["test"]));
  return node;
};
Visitor.prototype.visitForStatement = function visitForStatement(node, state, path) {
  var visitor = this;
  // init is of types VariableDeclaration, Expression
  if (node["init"]) {
    node["init"] = visitor.accept(node["init"], state, path.concat(["init"]));
  }
  // test is of types Expression
  if (node["test"]) {
    node["test"] = visitor.accept(node["test"], state, path.concat(["test"]));
  }
  // update is of types Expression
  if (node["update"]) {
    node["update"] = visitor.accept(node["update"], state, path.concat(["update"]));
  }
  // body is of types Statement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitForInStatement = function visitForInStatement(node, state, path) {
  var visitor = this;
  // left is of types VariableDeclaration, Pattern
  node["left"] = visitor.accept(node["left"], state, path.concat(["left"]));
  // right is of types Expression
  node["right"] = visitor.accept(node["right"], state, path.concat(["right"]));
  // body is of types Statement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitDeclaration = function visitDeclaration(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitThisExpression = function visitThisExpression(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitArrayExpression = function visitArrayExpression(node, state, path) {
  var visitor = this;
  // elements is a list with types Expression, SpreadElement
  if (node["elements"]) {
    var newElements = [];
    for (var i = 0; i < node["elements"].length; i++) {
      var ea = node["elements"][i];
      var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["elements", i])) : ea;
      if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
    }
    node["elements"] = newElements;
  }
  return node;
};
Visitor.prototype.visitObjectExpression = function visitObjectExpression(node, state, path) {
  var visitor = this;
  // properties is a list with types Property, SpreadElement
  var newElements = [];
  for (var i = 0; i < node["properties"].length; i++) {
    var ea = node["properties"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["properties", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["properties"] = newElements;
  return node;
};
Visitor.prototype.visitFunctionExpression = function visitFunctionExpression(node, state, path) {
  var visitor = this;
  // id is of types Identifier
  if (node["id"]) {
    node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  }
  // params is a list with types Pattern
  var newElements = [];
  for (var i = 0; i < node["params"].length; i++) {
    var ea = node["params"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["params", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["params"] = newElements;
  // body is of types FunctionBody
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitUnaryExpression = function visitUnaryExpression(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  return node;
};
Visitor.prototype.visitUpdateExpression = function visitUpdateExpression(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  return node;
};
Visitor.prototype.visitBinaryExpression = function visitBinaryExpression(node, state, path) {
  var visitor = this;
  // left is of types Expression
  node["left"] = visitor.accept(node["left"], state, path.concat(["left"]));
  // right is of types Expression
  node["right"] = visitor.accept(node["right"], state, path.concat(["right"]));
  return node;
};
Visitor.prototype.visitAssignmentExpression = function visitAssignmentExpression(node, state, path) {
  var visitor = this;
  // left is of types Pattern
  node["left"] = visitor.accept(node["left"], state, path.concat(["left"]));
  // right is of types Expression
  node["right"] = visitor.accept(node["right"], state, path.concat(["right"]));
  return node;
};
Visitor.prototype.visitLogicalExpression = function visitLogicalExpression(node, state, path) {
  var visitor = this;
  // left is of types Expression
  node["left"] = visitor.accept(node["left"], state, path.concat(["left"]));
  // right is of types Expression
  node["right"] = visitor.accept(node["right"], state, path.concat(["right"]));
  return node;
};
Visitor.prototype.visitMemberExpression = function visitMemberExpression(node, state, path) {
  var visitor = this;
  // object is of types Expression, Super
  node["object"] = visitor.accept(node["object"], state, path.concat(["object"]));
  // property is of types Expression
  node["property"] = visitor.accept(node["property"], state, path.concat(["property"]));
  return node;
};
Visitor.prototype.visitConditionalExpression = function visitConditionalExpression(node, state, path) {
  var visitor = this;
  // test is of types Expression
  node["test"] = visitor.accept(node["test"], state, path.concat(["test"]));
  // alternate is of types Expression
  node["alternate"] = visitor.accept(node["alternate"], state, path.concat(["alternate"]));
  // consequent is of types Expression
  node["consequent"] = visitor.accept(node["consequent"], state, path.concat(["consequent"]));
  return node;
};
Visitor.prototype.visitCallExpression = function visitCallExpression(node, state, path) {
  var visitor = this;
  // callee is of types Expression, Super
  node["callee"] = visitor.accept(node["callee"], state, path.concat(["callee"]));
  // arguments is a list with types Expression, SpreadElement
  var newElements = [];
  for (var i = 0; i < node["arguments"].length; i++) {
    var ea = node["arguments"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["arguments", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["arguments"] = newElements;
  return node;
};
Visitor.prototype.visitNewExpression = function visitNewExpression(node, state, path) {
  var visitor = this;
  // callee is of types Expression
  node["callee"] = visitor.accept(node["callee"], state, path.concat(["callee"]));
  // arguments is a list with types Expression
  var newElements = [];
  for (var i = 0; i < node["arguments"].length; i++) {
    var ea = node["arguments"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["arguments", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["arguments"] = newElements;
  return node;
};
Visitor.prototype.visitSequenceExpression = function visitSequenceExpression(node, state, path) {
  var visitor = this;
  // expressions is a list with types Expression
  var newElements = [];
  for (var i = 0; i < node["expressions"].length; i++) {
    var ea = node["expressions"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["expressions", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["expressions"] = newElements;
  return node;
};
Visitor.prototype.visitArrowFunctionExpression = function visitArrowFunctionExpression(node, state, path) {
  var visitor = this;
  // body is of types FunctionBody, Expression
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  // id is of types Identifier
  if (node["id"]) {
    node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  }
  // params is a list with types Pattern
  var newElements = [];
  for (var i = 0; i < node["params"].length; i++) {
    var ea = node["params"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["params", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["params"] = newElements;
  return node;
};
Visitor.prototype.visitYieldExpression = function visitYieldExpression(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  if (node["argument"]) {
    node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  }
  return node;
};
Visitor.prototype.visitTemplateLiteral = function visitTemplateLiteral(node, state, path) {
  var visitor = this;
  // quasis is a list with types TemplateElement
  var newElements = [];
  for (var i = 0; i < node["quasis"].length; i++) {
    var ea = node["quasis"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["quasis", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["quasis"] = newElements;
  // expressions is a list with types Expression
  var newElements = [];
  for (var i = 0; i < node["expressions"].length; i++) {
    var ea = node["expressions"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["expressions", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["expressions"] = newElements;
  return node;
};
Visitor.prototype.visitTaggedTemplateExpression = function visitTaggedTemplateExpression(node, state, path) {
  var visitor = this;
  // tag is of types Expression
  node["tag"] = visitor.accept(node["tag"], state, path.concat(["tag"]));
  // quasi is of types TemplateLiteral
  node["quasi"] = visitor.accept(node["quasi"], state, path.concat(["quasi"]));
  return node;
};
Visitor.prototype.visitAssignmentProperty = function visitAssignmentProperty(node, state, path) {
  var visitor = this;
  // value is of types Pattern, Expression
  node["value"] = visitor.accept(node["value"], state, path.concat(["value"]));
  // key is of types Expression
  node["key"] = visitor.accept(node["key"], state, path.concat(["key"]));
  return node;
};
Visitor.prototype.visitObjectPattern = function visitObjectPattern(node, state, path) {
  var visitor = this;
  // properties is a list with types AssignmentProperty, RestElement
  var newElements = [];
  for (var i = 0; i < node["properties"].length; i++) {
    var ea = node["properties"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["properties", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["properties"] = newElements;
  return node;
};
Visitor.prototype.visitArrayPattern = function visitArrayPattern(node, state, path) {
  var visitor = this;
  // elements is a list with types Pattern
  if (node["elements"]) {
    var newElements = [];
    for (var i = 0; i < node["elements"].length; i++) {
      var ea = node["elements"][i];
      var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["elements", i])) : ea;
      if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
    }
    node["elements"] = newElements;
  }
  return node;
};
Visitor.prototype.visitRestElement = function visitRestElement(node, state, path) {
  var visitor = this;
  // argument is of types Pattern
  node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  return node;
};
Visitor.prototype.visitAssignmentPattern = function visitAssignmentPattern(node, state, path) {
  var visitor = this;
  // left is of types Pattern
  node["left"] = visitor.accept(node["left"], state, path.concat(["left"]));
  // right is of types Expression
  node["right"] = visitor.accept(node["right"], state, path.concat(["right"]));
  return node;
};
Visitor.prototype.visitClassExpression = function visitClassExpression(node, state, path) {
  var visitor = this;
  // id is of types Identifier
  if (node["id"]) {
    node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  }
  // superClass is of types Expression
  if (node["superClass"]) {
    node["superClass"] = visitor.accept(node["superClass"], state, path.concat(["superClass"]));
  }
  // body is of types ClassBody
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitMetaProperty = function visitMetaProperty(node, state, path) {
  var visitor = this;
  // meta is of types Identifier
  node["meta"] = visitor.accept(node["meta"], state, path.concat(["meta"]));
  // property is of types Identifier
  node["property"] = visitor.accept(node["property"], state, path.concat(["property"]));
  return node;
};
Visitor.prototype.visitImportDeclaration = function visitImportDeclaration(node, state, path) {
  var visitor = this;
  // specifiers is a list with types ImportSpecifier, ImportDefaultSpecifier, ImportNamespaceSpecifier
  var newElements = [];
  for (var i = 0; i < node["specifiers"].length; i++) {
    var ea = node["specifiers"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["specifiers", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["specifiers"] = newElements;
  // source is of types Literal
  node["source"] = visitor.accept(node["source"], state, path.concat(["source"]));
  return node;
};
Visitor.prototype.visitImportSpecifier = function visitImportSpecifier(node, state, path) {
  var visitor = this;
  // imported is of types Identifier
  node["imported"] = visitor.accept(node["imported"], state, path.concat(["imported"]));
  // local is of types Identifier
  node["local"] = visitor.accept(node["local"], state, path.concat(["local"]));
  return node;
};
Visitor.prototype.visitImportDefaultSpecifier = function visitImportDefaultSpecifier(node, state, path) {
  var visitor = this;
  // local is of types Identifier
  node["local"] = visitor.accept(node["local"], state, path.concat(["local"]));
  return node;
};
Visitor.prototype.visitImportNamespaceSpecifier = function visitImportNamespaceSpecifier(node, state, path) {
  var visitor = this;
  // local is of types Identifier
  node["local"] = visitor.accept(node["local"], state, path.concat(["local"]));
  return node;
};
Visitor.prototype.visitExportNamedDeclaration = function visitExportNamedDeclaration(node, state, path) {
  var visitor = this;
  // declaration is of types Declaration
  if (node["declaration"]) {
    node["declaration"] = visitor.accept(node["declaration"], state, path.concat(["declaration"]));
  }
  // specifiers is a list with types ExportSpecifier
  var newElements = [];
  for (var i = 0; i < node["specifiers"].length; i++) {
    var ea = node["specifiers"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["specifiers", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["specifiers"] = newElements;
  // source is of types Literal
  if (node["source"]) {
    node["source"] = visitor.accept(node["source"], state, path.concat(["source"]));
  }
  return node;
};
Visitor.prototype.visitExportSpecifier = function visitExportSpecifier(node, state, path) {
  var visitor = this;
  // exported is of types Identifier
  node["exported"] = visitor.accept(node["exported"], state, path.concat(["exported"]));
  // local is of types Identifier
  node["local"] = visitor.accept(node["local"], state, path.concat(["local"]));
  return node;
};
Visitor.prototype.visitExportDefaultDeclaration = function visitExportDefaultDeclaration(node, state, path) {
  var visitor = this;
  // declaration is of types Declaration, Expression
  node["declaration"] = visitor.accept(node["declaration"], state, path.concat(["declaration"]));
  return node;
};
Visitor.prototype.visitExportAllDeclaration = function visitExportAllDeclaration(node, state, path) {
  var visitor = this;
  // source is of types Literal
  node["source"] = visitor.accept(node["source"], state, path.concat(["source"]));
  return node;
};
Visitor.prototype.visitAwaitExpression = function visitAwaitExpression(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  return node;
};
Visitor.prototype.visitJSXMemberExpression = function visitJSXMemberExpression(node, state, path) {
  var visitor = this;
  // object is of types JSXMemberExpression, JSXIdentifier
  node["object"] = visitor.accept(node["object"], state, path.concat(["object"]));
  // property is of types JSXIdentifier
  node["property"] = visitor.accept(node["property"], state, path.concat(["property"]));
  return node;
};
Visitor.prototype.visitJSXNamespacedName = function visitJSXNamespacedName(node, state, path) {
  var visitor = this;
  // namespace is of types JSXIdentifier
  node["namespace"] = visitor.accept(node["namespace"], state, path.concat(["namespace"]));
  // name is of types JSXIdentifier
  node["name"] = visitor.accept(node["name"], state, path.concat(["name"]));
  return node;
};
Visitor.prototype.visitJSXOpeningElement = function visitJSXOpeningElement(node, state, path) {
  var visitor = this;
  // attributes is a list with types JSXAttribute, JSXSpreadAttribute
  var newElements = [];
  for (var i = 0; i < node["attributes"].length; i++) {
    var ea = node["attributes"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["attributes", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["attributes"] = newElements;
  // name is of types JSXIdentifier, JSXMemberExpression, JSXNamespacedName
  node["name"] = visitor.accept(node["name"], state, path.concat(["name"]));
  return node;
};
Visitor.prototype.visitJSXClosingElement = function visitJSXClosingElement(node, state, path) {
  var visitor = this;
  // name is of types JSXIdentifier, JSXMemberExpression, JSXNamespacedName
  node["name"] = visitor.accept(node["name"], state, path.concat(["name"]));
  return node;
};
Visitor.prototype.visitJSXSpreadAttribute = function visitJSXSpreadAttribute(node, state, path) {
  var visitor = this;
  // argument is of types Expression
  node["argument"] = visitor.accept(node["argument"], state, path.concat(["argument"]));
  return node;
};
Visitor.prototype.visitJSXElement = function visitJSXElement(node, state, path) {
  var visitor = this;
  // openingElement is of types JSXOpeningElement
  node["openingElement"] = visitor.accept(node["openingElement"], state, path.concat(["openingElement"]));
  // children is a list with types JSXText, JSXExpressionContainer, JSXSpreadChild, JSXElement, JSXFragment
  var newElements = [];
  for (var i = 0; i < node["children"].length; i++) {
    var ea = node["children"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["children", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["children"] = newElements;
  // closingElement is of types JSXClosingElement
  if (node["closingElement"]) {
    node["closingElement"] = visitor.accept(node["closingElement"], state, path.concat(["closingElement"]));
  }
  return node;
};
Visitor.prototype.visitJSXFragment = function visitJSXFragment(node, state, path) {
  var visitor = this;
  // openingFragment is of types JSXOpeningFragment
  node["openingFragment"] = visitor.accept(node["openingFragment"], state, path.concat(["openingFragment"]));
  // children is a list with types JSXText, JSXExpressionContainer, JSXSpreadChild, JSXElement, JSXFragment
  var newElements = [];
  for (var i = 0; i < node["children"].length; i++) {
    var ea = node["children"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["children", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["children"] = newElements;
  // closingFragment is of types JSXClosingFragment
  node["closingFragment"] = visitor.accept(node["closingFragment"], state, path.concat(["closingFragment"]));
  return node;
};
Visitor.prototype.visitRegExpLiteral = function visitRegExpLiteral(node, state, path) {
  var visitor = this;
  return node;
};
Visitor.prototype.visitFunctionBody = function visitFunctionBody(node, state, path) {
  var visitor = this;
  // body is a list with types Directive, Statement
  var newElements = [];
  for (var i = 0; i < node["body"].length; i++) {
    var ea = node["body"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["body", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["body"] = newElements;
  return node;
};
Visitor.prototype.visitFunctionDeclaration = function visitFunctionDeclaration(node, state, path) {
  var visitor = this;
  // id is of types Identifier
  if (node["id"]) {
    node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  }
  // params is a list with types Pattern
  var newElements = [];
  for (var i = 0; i < node["params"].length; i++) {
    var ea = node["params"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["params", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["params"] = newElements;
  // body is of types FunctionBody
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitVariableDeclaration = function visitVariableDeclaration(node, state, path) {
  var visitor = this;
  // declarations is a list with types VariableDeclarator
  var newElements = [];
  for (var i = 0; i < node["declarations"].length; i++) {
    var ea = node["declarations"][i];
    var acceptedNodes = ea ? visitor.accept(ea, state, path.concat(["declarations", i])) : ea;
    if (Array.isArray(acceptedNodes)) newElements.push.apply(newElements, acceptedNodes);else newElements.push(acceptedNodes);
  }
  node["declarations"] = newElements;
  return node;
};
Visitor.prototype.visitForOfStatement = function visitForOfStatement(node, state, path) {
  var visitor = this;
  // left is of types VariableDeclaration, Pattern
  node["left"] = visitor.accept(node["left"], state, path.concat(["left"]));
  // right is of types Expression
  node["right"] = visitor.accept(node["right"], state, path.concat(["right"]));
  // body is of types Statement
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitClassDeclaration = function visitClassDeclaration(node, state, path) {
  var visitor = this;
  // id is of types Identifier
  if (node["id"]) {
    node["id"] = visitor.accept(node["id"], state, path.concat(["id"]));
  }
  // superClass is of types Expression
  if (node["superClass"]) {
    node["superClass"] = visitor.accept(node["superClass"], state, path.concat(["superClass"]));
  }
  // body is of types ClassBody
  node["body"] = visitor.accept(node["body"], state, path.concat(["body"]));
  return node;
};
Visitor.prototype.visitJSXIdentifier = function visitJSXIdentifier(node, state, path) {
  var visitor = this;
  return node;
};

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj$$1) {
  return typeof obj$$1;
} : function (obj$$1) {
  return obj$$1 && typeof Symbol === "function" && obj$$1.constructor === Symbol && obj$$1 !== Symbol.prototype ? "symbol" : typeof obj$$1;
};











var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

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;
  };
}();





var defineProperty = function (obj$$1, key, value) {
  if (key in obj$$1) {
    Object.defineProperty(obj$$1, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj$$1[key] = value;
  }

  return obj$$1;
};

var _extends = Object.assign || function (target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];

    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }

  return target;
};

var get = function get(object, property, receiver) {
  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(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);
  }
};

var inherits = function (subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};











var possibleConstructorReturn = function (self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return call && (typeof call === "object" || typeof call === "function") ? call : self;
};



var set = function set(object, property, value, receiver) {
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent !== null) {
      set(parent, property, value, receiver);
    }
  } else if ("value" in desc && desc.writable) {
    desc.value = value;
  } else {
    var setter = desc.set;

    if (setter !== undefined) {
      setter.call(receiver, value);
    }
  }

  return value;
};

var slicedToArray = function () {
  function sliceIterator(arr$$1, i) {
    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;

    try {
      for (var _i = arr$$1[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);

        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"]) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  return function (arr$$1, i) {
    if (Array.isArray(arr$$1)) {
      return arr$$1;
    } else if (Symbol.iterator in Object(arr$$1)) {
      return sliceIterator(arr$$1, i);
    } else {
      throw new TypeError("Invalid attempt to destructure non-iterable instance");
    }
  };
}();











var toArray = function (arr$$1) {
  return Array.isArray(arr$$1) ? arr$$1 : Array.from(arr$$1);
};

var toConsumableArray = function (arr$$1) {
  if (Array.isArray(arr$$1)) {
    for (var i = 0, arr2 = Array(arr$$1.length); i < arr$$1.length; i++) arr2[i] = arr$$1[i];

    return arr2;
  } else {
    return Array.from(arr$$1);
  }
};

/*global process, global, exports*/

var PrinterVisitor = function (_Visitor) {
  inherits(PrinterVisitor, _Visitor);

  function PrinterVisitor() {
    classCallCheck(this, PrinterVisitor);
    return possibleConstructorReturn(this, (PrinterVisitor.__proto__ || Object.getPrototypeOf(PrinterVisitor)).apply(this, arguments));
  }

  createClass(PrinterVisitor, [{
    key: "accept",
    value: function accept(node, state, path) {
      var pathString = path.map(function (ea) {
        return typeof ea === 'string' ? "." + ea : "[" + ea + "]";
      }).join(''),
          myChildren = [],
          result = get(PrinterVisitor.prototype.__proto__ || Object.getPrototypeOf(PrinterVisitor.prototype), "accept", this).call(this, node, { index: state.index, tree: myChildren }, path);
      state.tree.push({
        node: node,
        path: pathString,
        index: state.index++,
        children: myChildren
      });
      return result;
    }
  }]);
  return PrinterVisitor;
}(Visitor);

var ComparisonVisitor = function (_Visitor2) {
  inherits(ComparisonVisitor, _Visitor2);

  function ComparisonVisitor() {
    classCallCheck(this, ComparisonVisitor);
    return possibleConstructorReturn(this, (ComparisonVisitor.__proto__ || Object.getPrototypeOf(ComparisonVisitor)).apply(this, arguments));
  }

  createClass(ComparisonVisitor, [{
    key: "recordNotEqual",
    value: function recordNotEqual(node1, node2, state, msg) {
      state.comparisons.errors.push({
        node1: node1, node2: node2,
        path: state.completePath, msg: msg
      });
    }
  }, {
    key: "compareType",
    value: function compareType(node1, node2, state) {
      return this.compareField('type', node1, node2, state);
    }
  }, {
    key: "compareField",
    value: function compareField(field, node1, node2, state) {
      node2 = lively.lang.Path(state.completePath.join('.')).get(node2);
      if (node1 && node2 && node1[field] === node2[field]) return true;
      if (node1 && node1[field] === '*' || node2 && node2[field] === '*') return true;
      var fullPath = state.completePath.join('.') + '.' + field,
          msg;
      if (!node1) msg = "node1 on " + fullPath + " not defined";else if (!node2) msg = 'node2 not defined but node1 (' + fullPath + ') is: ' + node1[field];else msg = fullPath + ' is not equal: ' + node1[field] + ' vs. ' + node2[field];
      this.recordNotEqual(node1, node2, state, msg);
      return false;
    }
  }, {
    key: "accept",
    value: function accept(node1, node2, state, path) {
      var patternNode = lively.lang.Path(path.join('.')).get(node2);
      if (node1 === '*' || patternNode === '*') return;
      var nextState = {
        completePath: path,
        comparisons: state.comparisons
      };
      if (this.compareType(node1, node2, nextState)) this['visit' + node1.type](node1, node2, nextState, path);
    }
  }, {
    key: "visitFunction",
    value: function visitFunction(node1, node2, state, path) {
      // node1.generator has a specific type that is boolean
      if (node1.generator) {
        this.compareField("generator", node1, node2, state);
      }

      // node1.expression has a specific type that is boolean
      if (node1.expression) {
        this.compareField("expression", node1, node2, state);
      }

      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitFunction", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitSwitchStatement",
    value: function visitSwitchStatement(node1, node2, state, path) {
      // node1.lexical has a specific type that is boolean
      if (node1.lexical) {
        this.compareField("lexical", node1, node2, state);
      }

      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitSwitchStatement", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitForInStatement",
    value: function visitForInStatement(node1, node2, state, path) {
      // node1.each has a specific type that is boolean
      if (node1.each) {
        this.compareField("each", node1, node2, state);
      }

      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitForInStatement", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitFunctionDeclaration",
    value: function visitFunctionDeclaration(node1, node2, state, path) {
      // node1.generator has a specific type that is boolean
      if (node1.generator) {
        this.compareField("generator", node1, node2, state);
      }

      // node1.expression has a specific type that is boolean
      if (node1.expression) {
        this.compareField("expression", node1, node2, state);
      }

      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitFunctionDeclaration", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitVariableDeclaration",
    value: function visitVariableDeclaration(node1, node2, state, path) {
      // node1.kind is "var" or "let" or "const"
      this.compareField("kind", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitVariableDeclaration", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitUnaryExpression",
    value: function visitUnaryExpression(node1, node2, state, path) {
      // node1.operator is an UnaryOperator enum:
      // "-" | "+" | "!" | "~" | "typeof" | "void" | "delete"
      this.compareField("operator", node1, node2, state);

      // node1.prefix has a specific type that is boolean
      if (node1.prefix) {
        this.compareField("prefix", node1, node2, state);
      }

      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitUnaryExpression", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitBinaryExpression",
    value: function visitBinaryExpression(node1, node2, state, path) {
      // node1.operator is an BinaryOperator enum:
      // "==" | "!=" | "===" | "!==" | | "<" | "<=" | ">" | ">=" | | "<<" | ">>" | ">>>" | | "+" | "-" | "*" | "/" | "%" | | "|" | "^" | "&" | "in" | | "instanceof" | ".."
      this.compareField("operator", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitBinaryExpression", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitAssignmentExpression",
    value: function visitAssignmentExpression(node1, node2, state, path) {
      // node1.operator is an AssignmentOperator enum:
      // "=" | "+=" | "-=" | "*=" | "/=" | "%=" | | "<<=" | ">>=" | ">>>=" | | "|=" | "^=" | "&="
      this.compareField("operator", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitAssignmentExpression", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitUpdateExpression",
    value: function visitUpdateExpression(node1, node2, state, path) {
      // node1.operator is an UpdateOperator enum:
      // "++" | "--"
      this.compareField("operator", node1, node2, state);
      // node1.prefix has a specific type that is boolean
      if (node1.prefix) {
        this.compareField("prefix", node1, node2, state);
      }
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitUpdateExpression", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitLogicalExpression",
    value: function visitLogicalExpression(node1, node2, state, path) {
      // node1.operator is an LogicalOperator enum:
      // "||" | "&&"
      this.compareField("operator", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitLogicalExpression", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitMemberExpression",
    value: function visitMemberExpression(node1, node2, state, path) {
      // node1.computed has a specific type that is boolean
      if (node1.computed) {
        this.compareField("computed", node1, node2, state);
      }
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitMemberExpression", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitComprehensionBlock",
    value: function visitComprehensionBlock(node1, node2, state, path) {
      // node1.each has a specific type that is boolean
      if (node1.each) {
        this.compareField("each", node1, node2, state);
      }
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitComprehensionBlock", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitIdentifier",
    value: function visitIdentifier(node1, node2, state, path) {
      // node1.name has a specific type that is string
      this.compareField("name", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitIdentifier", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitLiteral",
    value: function visitLiteral(node1, node2, state, path) {
      this.compareField("value", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitLiteral", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitClassDeclaration",
    value: function visitClassDeclaration(node1, node2, state, path) {
      this.compareField("id", node1, node2, state);
      if (node1.superClass) {
        this.compareField("superClass", node1, node2, state);
      }
      this.compareField("body", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitClassDeclaration", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitClassBody",
    value: function visitClassBody(node1, node2, state, path) {
      this.compareField("body", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitClassBody", this).call(this, node1, node2, state, path);
    }
  }, {
    key: "visitMethodDefinition",
    value: function visitMethodDefinition(node1, node2, state, path) {
      this.compareField("static", node1, node2, state);
      this.compareField("computed", node1, node2, state);
      this.compareField("kind", node1, node2, state);
      this.compareField("key", node1, node2, state);
      this.compareField("value", node1, node2, state);
      return get(ComparisonVisitor.prototype.__proto__ || Object.getPrototypeOf(ComparisonVisitor.prototype), "visitMethodDefinition", this).call(this, node1, node2, state, path);
    }
  }]);
  return ComparisonVisitor;
}(Visitor);

var ScopeVisitor = function (_Visitor3) {
  inherits(ScopeVisitor, _Visitor3);

  function ScopeVisitor() {
    classCallCheck(this, ScopeVisitor);
    return possibleConstructorReturn(this, (ScopeVisitor.__proto__ || Object.getPrototypeOf(ScopeVisitor)).apply(this, arguments));
  }

  createClass(ScopeVisitor, [{
    key: "newScope",
    value: function newScope(scopeNode, parentScope) {
      var scope = {
        node: scopeNode,
        varDecls: [],
        varDeclPaths: [],
        funcDecls: [],
        funcDeclPaths: [],
        classDecls: [],
        classDeclPaths: [],
        classExprs: [],
        classExprPaths: [],
        methodDecls: [],
        methodDeclPaths: [],
        importSpecifiers: [],
        importSpecifierPaths: [],
        exportDecls: [],
        exportDeclPaths: [],
        refs: [],
        thisRefs: [],
        params: [],
        catches: [],
        subScopes: [],
        resolvedRefMap: new Map()
      };
      if (parentScope) parentScope.subScopes.push(scope);
      return scope;
    }
  }, {
    key: "visitVariableDeclaration",
    value: function visitVariableDeclaration(node, scope, path) {
      scope.varDecls.push(node);
      scope.varDeclPaths.push(path);
      return get(ScopeVisitor.prototype.__proto__ || Object.getPrototypeOf(ScopeVisitor.prototype), "visitVariableDeclaration", this).call(this, node, scope, path);
    }
  }, {
    key: "visitVariableDeclarator",
    value: function visitVariableDeclarator(node, scope, path) {
      var visitor = this;
      // ignore id
      // // id is of types Pattern
      // node["id"] = visitor.accept(node["id"], scope, path.concat(["id"]));
      // init is of types Expression
      if (node["init"]) {
        node["init"] = visitor.accept(node["init"], scope, path.concat(["init"]));
      }
      return node;
    }
  }, {
    key: "visitFunction",
    value: function visitFunction(node, scope, path) {
      var visitor = this;
      var newScope = this.newScope(node, scope);

      // AssignmentPattern = default params
      // only visit the right side of a default param, we track the declarations
      // in newScope.params specificially
      node.params.forEach(function (param, i) {
        if (param.type === "AssignmentPattern") visitor.accept(param.right, newScope, path.concat("params", i, "right"));
      });

      newScope.params = Array.prototype.slice.call(node.params);
      return newScope;
    }
  }, {
    key: "visitFunctionDeclaration",
    value: function visitFunctionDeclaration(node, scope, path) {
      var newScope = this.visitFunction(node, scope, path);
      scope.funcDecls.push(node);
      scope.funcDeclPaths.push(path);

      // don't visit id and params  
      var visitor = this;

      if (node.defaults) {
        node["defaults"] = node["defaults"].reduce(function (results, ea, i) {
          var result = visitor.accept(ea, newScope, path.concat(["defaults", i]));
          if (Array.isArray(result)) results.push.apply(results, result);else results.push(result);
          return results;
        }, []);
      }

      if (node.rest) {
        node["rest"] = visitor.accept(node["rest"], newScope, path.concat(["rest"]));
      }

      node["body"] = visitor.accept(node["body"], newScope, path.concat(["body"]));

      // loc is of types SourceLocation
      if (node["loc"]) {
        node["loc"] = visitor.accept(node["loc"], newScope, path.concat(["loc"]));
      }
      return node;
    }
  }, {
    key: "visitFunctionExpression",
    value: function visitFunctionExpression(node, scope, path) {
      var newScope = this.visitFunction(node, scope, path);

      // don't visit id and params  
      var visitor = this;

      if (node.defaults) {
        node["defaults"] = node["defaults"].reduce(function (results, ea, i) {
          var result = visitor.accept(ea, newScope, path.concat(["defaults", i]));
          if (Array.isArray(result)) results.push.apply(results, result);else results.push(result);
          return results;
        }, []);
      }

      if (node.rest) {
        node["rest"] = visitor.accept(node["rest"], newScope, path.concat(["rest"]));
      }

      node["body"] = visitor.accept(node["body"], newScope, path.concat(["body"]));

      // loc is of types SourceLocation
      if (node["loc"]) {
        node["loc"] = visitor.accept(node["loc"], newScope, path.concat(["loc"]));
      }
      return node;
    }
  }, {
    key: "visitArrowFunctionExpression",
    value: function visitArrowFunctionExpression(node, scope, path) {
      var newScope = this.visitFunction(node, scope, path);
      var visitor = this;

      if (node.defaults) {
        node["defaults"] = node["defaults"].reduce(function (results, ea, i) {
          var result = visitor.accept(ea, newScope, path.concat(["defaults", i]));
          if (Array.isArray(result)) results.push.apply(results, result);else results.push(result);
          return results;
        }, []);
      }

      if (node.rest) {
        node["rest"] = visitor.accept(node["rest"], newScope, path.concat(["rest"]));
      }

      // body is of types BlockStatement, Expression
      node["body"] = visitor.accept(node["body"], newScope, path.concat(["body"]));

      // loc is of types SourceLocation
      if (node["loc"]) {
        node["loc"] = visitor.accept(node["loc"], newScope, path.concat(["loc"]));
      }
      // node.generator has a specific type that is boolean
      if (node.generator) {} /*do stuff*/

      // node.expression has a specific type that is boolean
      if (node.expression) {/*do stuff*/}
      return node;
    }
  }, {
    key: "visitIdentifier",
    value: function visitIdentifier(node, scope, path) {
      scope.refs.push(node);
      return get(ScopeVisitor.prototype.__proto__ || Object.getPrototypeOf(ScopeVisitor.prototype), "visitIdentifier", this).call(this, node, scope, path);
    }
  }, {
    key: "visitMemberExpression",
    value: function visitMemberExpression(node, scope, path) {
      // only visit property part when prop is computed so we don't gather
      // prop ids

      var visitor = this;
      // object is of types Expression, Super
      node["object"] = visitor.accept(node["object"], scope, path.concat(["object"]));
      // property is of types Expression
      if (node.computed) {
        node["property"] = visitor.accept(node["property"], scope, path.concat(["property"]));
      }
      return node;
    }
  }, {
    key: "visitProperty",
    value: function visitProperty(node, scope, path) {
      var visitor = this;
      // key is of types Expression
      if (node.computed) node["key"] = visitor.accept(node["key"], scope, path.concat(["key"]));
      // value is of types Expression
      node["value"] = visitor.accept(node["value"], scope, path.concat(["value"]));
      return node;
    }
  }, {
    key: "visitThisExpression",
    value: function visitThisExpression(node, scope, path) {
      scope.thisRefs.push(node);
      return get(ScopeVisitor.prototype.__proto__ || Object.getPrototypeOf(ScopeVisitor.prototype), "visitThisExpression", this).call(this, node, scope, path);
    }
  }, {
    key: "visitTryStatement",
    value: function visitTryStatement(node, scope, path) {
      var visitor = this;
      // block is of types BlockStatement
      node["block"] = visitor.accept(node["block"], scope, path.concat(["block"]));
      // handler is of types CatchClause
      if (node["handler"]) {
        node["handler"] = visitor.accept(node["handler"], scope, path.concat(["handler"]));
        scope.catches.push(node.handler.param);
      }

      // finalizer is of types BlockStatement
      if (node["finalizer"]) {
        node["finalizer"] = visitor.accept(node["finalizer"], scope, path.concat(["finalizer"]));
      }
      return node;
    }
  }, {
    key: "visitLabeledStatement",
    value: function visitLabeledStatement(node, scope, path) {
      var visitor = this;
      // ignore label
      // // label is of types Identifier
      // node["label"] = visitor.accept(node["label"], scope, path.concat(["label"]));
      // body is of types Statement
      node["body"] = visitor.accept(node["body"], scope, path.concat(["body"]));
      return node;
    }
  }, {
    key: "visitClassDeclaration",
    value: function visitClassDeclaration(node, scope, path) {
      scope.classDecls.push(node);
      scope.classDeclPaths.push(path);

      var visitor = this;
      // ignore id
      // // id is of types Identifier
      // node["id"] = visitor.accept(node["id"], scope, path.concat(["id"]));
      // superClass is of types Expression
      if (node["superClass"]) {
        node["superClass"] = visitor.accept(node["superClass"], scope, path.concat(["superClass"]));
      }
      // body is of types ClassBody
      node["body"] = visitor.accept(node["body"], scope, path.concat(["body"]));
      return node;
    }
  }, {
    key: "visitClassExpression",
    value: function visitClassExpression(node, scope, path) {
      if (node.id) {
        scope.classExprs.push(node);
        scope.classExprPaths.push(path);
      }

      var visitor = this;
      // ignore id
      // // id is of types Identifier
      // node["id"] = visitor.accept(node["id"], scope, path.concat(["id"]));
      // superClass is of types Expression
      if (node["superClass"]) {
        node["superClass"] = visitor.accept(node["superClass"], scope, path.concat(["superClass"]));
      }
      // body is of types ClassBody
      node["body"] = visitor.accept(node["body"], scope, path.concat(["body"]));
      return node;
    }
  }, {
    key: "visitMethodDefinition",
    value: function visitMethodDefinition(node, scope, path) {
      var visitor = this;
      // don't visit key Identifier for now
      // // key is of types Expression
      // node["key"] = visitor.accept(node["key"], scope, path.concat(["key"]));
      // value is of types FunctionExpression
      node["value"] = visitor.accept(node["value"], scope, path.concat(["value"]));
      return node;
    }
  }, {
    key: "visitMetaProperty",
    value: function visitMetaProperty(node, scope, path) {
      // this is the new.target thing
      var visitor = this;
      // node['meta'] = visitor.accept(node['meta'], scope, path.concat(['meta']));
      // node['property'] = visitor.accept(node['property'],scope, path.concat(['property']));
      return node;
    }
  }, {
    key: "visitBreakStatement",
    value: function visitBreakStatement(node, scope, path) {
      return node;
    }
  }, {
    key: "visitContinueStatement",
    value: function visitContinueStatement(node, scope, path) {
      return node;
    }

    // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    // es6 modules

  }, {
    key: "visitImportSpecifier",
    value: function visitImportSpecifier(node, scope, path) {
      scope.importSpecifiers.push(node.local);
      scope.importSpecifierPaths.push(path);

      var visitor = this;
      // imported is of types Identifier
      // node["imported"] = visitor.accept(node["imported"], scope, path.concat(["imported"]));
      // local is of types Identifier
      // node["local"] = visitor.accept(node["local"], scope, path.concat(["local"]));
      return node;
    }
  }, {
    key: "visitImportDefaultSpecifier",
    value: function visitImportDefaultSpecifier(node, scope, path) {
      scope.importSpecifiers.push(node.local);
      scope.importSpecifierPaths.push(path);
      var visitor = this;
      // // local is of types Identifier
      // node["local"] = visitor.accept(node["local"], scope, path.concat(["local"]));
      return node;
    }
  }, {
    key: "visitImportNamespaceSpecifier",
    value: function visitImportNamespaceSpecifier(node, scope, path) {
      scope.importSpecifiers.push(node.local);
      scope.importSpecifierPaths.push(path);
      var visitor = this;
      // // local is of types Identifier
      // node["local"] = visitor.accept(node["local"], scope, path.concat(["local"]));
      return node;
    }
  }, {
    key: "visitExportSpecifier",
    value: function visitExportSpecifier(node, scope, path) {
      var visitor = this;
      // // exported is of types Identifier
      // node["exported"] = visitor.accept(node["exported"], scope, path.concat(["exported"]));
      // local is of types Identifier
      node["local"] = visitor.accept(node["local"], scope, path.concat(["local"]));
      return node;
    }
  }, {
    key: "visitExportNamedDeclaration",
    value: function visitExportNamedDeclaration(node, scope, path) {
      scope.exportDecls.push(node);
      scope.exportDeclPaths.push(path);
      // only descend if it's not an export {...} from "..."
      if (!node.source) get(ScopeVisitor.prototype.__proto__ || Object.getPrototypeOf(ScopeVisitor.prototype), "visitExportNamedDeclaration", this).call(this, node, scope, path);
      return node;
    }
  }, {
    key: "visitExportDefaultDeclaration",
    value: function visitExportDefaultDeclaration(node, scope, path) {
      scope.exportDecls.push(node);
      scope.exportDeclPaths.push(path);
      return get(ScopeVisitor.prototype.__proto__ || Object.getPrototypeOf(ScopeVisitor.prototype), "visitExportDefaultDeclaration", this).call(this, node, scope, path);
    }
  }, {
    key: "visitExportAllDeclaration",
    value: function visitExportAllDeclaration(node, scope, path) {
      scope.exportDecls.push(node);
      scope.exportDeclPaths.push(path);
      return get(ScopeVisitor.prototype.__proto__ || Object.getPrototypeOf(ScopeVisitor.prototype), "visitExportAllDeclaration", this).call(this, node, scope, path);
    }
  }]);
  return ScopeVisitor;
}(Visitor);

var es = escodegen.escodegen || escodegen;

function stringify(node) {
  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  var optsIndent = opts && opts.format && opts.format.indent || {};
  var indent = {
    style: "  ",
    base: 0,
    adjustMultilineComment: false,
    optsIndent: optsIndent
  };

  var optsFormat = opts && opts.format || {};
  var format = _extends({
    indent: indent,
    quotes: "double"
  }, lively_lang.obj.dissoc(optsFormat, ["indent"]));

  opts = _extends({
    format: format,
    comment: false
  }, lively_lang.obj.dissoc(opts, ["format"]));

  return es.generate(node, opts);
}

/*global acorn*/
var walk = acorn.walk;
var loose = acorn.loose;
// rk 2016-05-17 FIXME: the current version of acorn.walk doesn't support async
// await. We patch the walker here until it does
if (!walk.base.AwaitExpression) {
  walk.base.AwaitExpression = function (node, st, c) {
    if (node.argument) c(node.argument, st, 'Expression');
  };
}

// FIXME, don't add to walk object, that's our own stuff!
walk.forEachNode = forEachNode;
walk.matchNodes = matchNodes;
walk.findNodesIncluding = findNodesIncluding;
walk.withParentInfo = withParentInfo;
walk.copy = copy;
walk.findSiblings = findSiblings;

walk.findNodeByAstIndex = findNodeByAstIndex;
walk.findStatementOfNode = findStatementOfNode;
walk.addAstIndex = addAstIndex;

// -=-=-=-=-=-=-=-=-=-=-=-
// from lively.ast.acorn
// -=-=-=-=-=-=-=-=-=-=-=-
function forEachNode(parsed, func, state, options) {
  // note: func can get called with the same node for different
  // visitor callbacks!
  // func args: node, state, depth, type
  options = options || {};
  var traversal = options.traversal || 'preorder'; // also: postorder

  var visitors = lively_lang.obj.clone(options.visitors ? options.visitors : walk.make(walk.visitors.withMemberExpression));
  var iterator = traversal === 'preorder' ? function (orig, type, node, depth, cont) {
    func(node, state, depth, type);return orig(node, depth + 1, cont);
  } : function (orig, type, node, depth, cont) {
    var result = orig(node, depth + 1, cont);func(node, state, depth, type);return result;
  };
  Object.keys(visitors).forEach(function (type) {
    var orig = visitors[type];
    visitors[type] = function (node, depth, cont) {
      return iterator(orig, type, node, depth, cont);
    };
  });
  walk.recursive(parsed, 0, null, visitors);
  return parsed;
}

function matchNodes(parsed, visitor, state, options) {
  function visit(node, state, depth, type) {
    if (visitor[node.type]) visitor[node.type](node, state, depth, type);
  }
  return forEachNode(parsed, visit, state, options);
}

// findNodesIncluding: function(ast, pos, test, base) {
//   var nodes = [];
//   base = base || acorn.walk.make({});
//   Object.keys(base).forEach(function(name) {
//       var orig = base[name];
//       base[name] = function(node, state, cont) {
//           nodes.pushIfNotIncluded(node);
//           return orig(node, state, cont);
//       }
//   });
//   acorn.walk.findNodeAround(ast, pos, test, base);
//   return nodes;
// }

function findNodesIncluding(parsed, pos, test, base) {
  var nodes = [];
  base = base || walk.make(walk.visitors.withMemberExpression);
  Object.keys(walk.base).forEach(function (name) {
    var orig = base[name];
    base[name] = function (node, state, cont) {
      lively_lang.arr.pushIfNotIncluded(nodes, node);
      return orig(node, state, cont);
    };
  });
  base["Property"] = function (node, st, c) {
    lively_lang.arr.pushIfNotIncluded(nodes, node);
    c(node.key, st, "Expression");
    c(node.value, st, "Expression");
  };
  base["LabeledStatement"] = function (node, st, c) {
    node.label && c(node.label, st, "Expression");
    c(node.body, st, "Statement");
  };
  walk.findNodeAround(parsed, pos, test, base);
  return nodes;
}

function withParentInfo(parsed, iterator, options) {
  // options = {visitAllNodes: BOOL}
  options = options || {};
  function makeScope(parentScope) {
    var scope = { id: lively_lang.string.newUUID(), parentScope: parentScope, containingScopes: [] };
    parentScope && parentScope.containingScopes.push(scope);
    return scope;
  }
  var visitors = walk.make({
    Function: function Function(node, st, c) {
      if (st && st.scope) st.scope = makeScope(st.scope);
      c(node.body, st, "ScopeBody");
    },
    VariableDeclarator: function VariableDeclarator(node, st, c) {
      // node.id && c(node.id, st, 'Identifier');
      node.init && c(node.init, st, 'Expression');
    },
    VariableDeclaration: function VariableDeclaration(node, st, c) {
      for (var i = 0; i < node.declarations.length; ++i) {
        var decl = node.declarations[i];
        if (decl) c(decl, st, "VariableDeclarator");
      }
    },
    ObjectExpression: function ObjectExpression(node, st, c) {
      for (var i = 0; i < node.properties.length; ++i) {
        var prop = node.properties[i];
        c(prop.key, st, "Expression");
        c(prop.value, st, "Expression");
      }
    },
    MemberExpression: function MemberExpression(node, st, c) {
      c(node.object, st, "Expression");
      c(node.property, st, "Expression");
    }
  }, walk.base);
  var lastActiveProp,
      getters = [];
  forEachNode(parsed, function (node) {
    lively_lang.arr.withoutAll(Object.keys(node), ['end', 'start', 'type', 'source', 'raw']).forEach(function (propName) {
      if (node.__lookupGetter__(propName)) return; // already defined
      var val = node[propName];
      node.__defineGetter__(propName, function () {
        lastActiveProp = propName;return val;
      });
      getters.push([node, propName, node[propName]]);
    });
  }, null, { visitors: visitors });
  var result = [];
  Object.keys(visitors).forEach(function (type) {
    var orig = visitors[type];
    visitors[type] = function (node, state, cont) {
      if (type === node.type || options.visitAllNodes) {
        result.push(iterator.call(null, node, { scope: state.scope, depth: state.depth, parent: state.parent, type: type, propertyInParent: lastActiveProp }));
        return orig(node, { scope: state.scope, parent: node, depth: state.depth + 1 }, cont);
      } else {
        return orig(node, state, cont);
      }
    };
  });
  walk.recursive(parsed, { scope: makeScope(), parent: null, propertyInParent: '', depth: 0 }, null, visitors);
  getters.forEach(function (nodeNameVal) {
    delete nodeNameVal[0][nodeNameVal[1]];
    nodeNameVal[0][nodeNameVal[1]] = nodeNameVal[2];
  });
  return result;
}

function copy(ast, override) {
  var visitors = lively_lang.obj.extend({
    Program: function Program(n, c) {
      return {
        start: n.start, end: n.end, type: 'Program',
        body: n.body.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    FunctionDeclaration: function FunctionDeclaration(n, c) {
      return {
        start: n.start, end: n.end, type: 'FunctionDeclaration',
        id: c(n.id), params: n.params.map(c), body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    BlockStatement: function BlockStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'BlockStatement',
        body: n.body.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    ExpressionStatement: function ExpressionStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'ExpressionStatement',
        expression: c(n.expression),
        source: n.source, astIndex: n.astIndex
      };
    },
    CallExpression: function CallExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'CallExpression',
        callee: c(n.callee), arguments: n.arguments.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    MemberExpression: function MemberExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'MemberExpression',
        object: c(n.object), property: c(n.property), computed: n.computed,
        source: n.source, astIndex: n.astIndex
      };
    },
    NewExpression: function NewExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'NewExpression',
        callee: c(n.callee), arguments: n.arguments.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    VariableDeclaration: function VariableDeclaration(n, c) {
      return {
        start: n.start, end: n.end, type: 'VariableDeclaration',
        declarations: n.declarations.map(c), kind: n.kind,
        source: n.source, astIndex: n.astIndex
      };
    },
    VariableDeclarator: function VariableDeclarator(n, c) {
      return {
        start: n.start, end: n.end, type: 'VariableDeclarator',
        id: c(n.id), init: c(n.init),
        source: n.source, astIndex: n.astIndex
      };
    },
    FunctionExpression: function FunctionExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'FunctionExpression',
        id: c(n.id), params: n.params.map(c), body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    IfStatement: function IfStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'IfStatement',
        test: c(n.test), consequent: c(n.consequent),
        alternate: c(n.alternate),
        source: n.source, astIndex: n.astIndex
      };
    },
    ConditionalExpression: function ConditionalExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'ConditionalExpression',
        test: c(n.test), consequent: c(n.consequent),
        alternate: c(n.alternate),
        source: n.source, astIndex: n.astIndex
      };
    },
    SwitchStatement: function SwitchStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'SwitchStatement',
        discriminant: c(n.discriminant), cases: n.cases.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    SwitchCase: function SwitchCase(n, c) {
      return {
        start: n.start, end: n.end, type: 'SwitchCase',
        test: c(n.test), consequent: n.consequent.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    BreakStatement: function BreakStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'BreakStatement',
        label: n.label,
        source: n.source, astIndex: n.astIndex
      };
    },
    ContinueStatement: function ContinueStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'ContinueStatement',
        label: n.label,
        source: n.source, astIndex: n.astIndex
      };
    },
    TryStatement: function TryStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'TryStatement',
        block: c(n.block), handler: c(n.handler), finalizer: c(n.finalizer),
        guardedHandlers: n.guardedHandlers.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    CatchClause: function CatchClause(n, c) {
      return {
        start: n.start, end: n.end, type: 'CatchClause',
        param: c(n.param), guard: c(n.guard), body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    ThrowStatement: function ThrowStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'ThrowStatement',
        argument: c(n.argument),
        source: n.source, astIndex: n.astIndex
      };
    },
    ForStatement: function ForStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'ForStatement',
        init: c(n.init), test: c(n.test), update: c(n.update),
        body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    ForInStatement: function ForInStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'ForInStatement',
        left: c(n.left), right: c(n.right), body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    WhileStatement: function WhileStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'WhileStatement',
        test: c(n.test), body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    DoWhileStatement: function DoWhileStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'DoWhileStatement',
        test: c(n.test), body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    WithStatement: function WithStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'WithStatement',
        object: c(n.object), body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    },
    UnaryExpression: function UnaryExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'UnaryExpression',
        argument: c(n.argument), operator: n.operator, prefix: n.prefix,
        source: n.source, astIndex: n.astIndex
      };
    },
    BinaryExpression: function BinaryExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'BinaryExpression',
        left: c(n.left), operator: n.operator, right: c(n.right),
        source: n.source, astIndex: n.astIndex
      };
    },
    LogicalExpression: function LogicalExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'LogicalExpression',
        left: c(n.left), operator: n.operator, right: c(n.right),
        source: n.source, astIndex: n.astIndex
      };
    },
    AssignmentExpression: function AssignmentExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'AssignmentExpression',
        left: c(n.left), operator: n.operator, right: c(n.right),
        source: n.source, astIndex: n.astIndex
      };
    },
    UpdateExpression: function UpdateExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'UpdateExpression',
        argument: c(n.argument), operator: n.operator, prefix: n.prefix,
        source: n.source, astIndex: n.astIndex
      };
    },
    ReturnStatement: function ReturnStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'ReturnStatement',
        argument: c(n.argument),
        source: n.source, astIndex: n.astIndex
      };
    },
    Identifier: function Identifier(n, c) {
      return {
        start: n.start, end: n.end, type: 'Identifier',
        name: n.name,
        source: n.source, astIndex: n.astIndex
      };
    },
    Literal: function Literal(n, c) {
      return {
        start: n.start, end: n.end, type: 'Literal',
        value: n.value, raw: n.raw /* Acorn-specific */
        , source: n.source, astIndex: n.astIndex
      };
    },
    ObjectExpression: function ObjectExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'ObjectExpression',
        properties: n.properties.map(function (prop) {
          return {
            key: c(prop.key), value: c(prop.value), kind: prop.kind
          };
        }),
        source: n.source, astIndex: n.astIndex
      };
    },
    ArrayExpression: function ArrayExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'ArrayExpression',
        elements: n.elements.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    SequenceExpression: function SequenceExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'SequenceExpression',
        expressions: n.expressions.map(c),
        source: n.source, astIndex: n.astIndex
      };
    },
    EmptyStatement: function EmptyStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'EmptyStatement',
        source: n.source, astIndex: n.astIndex
      };
    },
    ThisExpression: function ThisExpression(n, c) {
      return {
        start: n.start, end: n.end, type: 'ThisExpression',
        source: n.source, astIndex: n.astIndex
      };
    },
    DebuggerStatement: function DebuggerStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'DebuggerStatement',
        source: n.source, astIndex: n.astIndex
      };
    },
    LabeledStatement: function LabeledStatement(n, c) {
      return {
        start: n.start, end: n.end, type: 'LabeledStatement',
        label: n.label, body: c(n.body),
        source: n.source, astIndex: n.astIndex
      };
    }
  }, override || {});

  function c(node) {
    if (node === null) return null;
    return visitors[node.type](node, c);
  }
  return c(ast);
}

function findSiblings(parsed, node, beforeOrAfter) {
  if (!node) return [];
  var nodes = findNodesIncluding(parsed, node.start),
      idx = nodes.indexOf(node),
      parents = nodes.slice(0, idx),
      parentWithBody = lively_lang.arr.detect(parents.reverse(), function (p) {
    return Array.isArray(p.body);
  }),
      siblingsWithNode = parentWithBody.body;
  if (!beforeOrAfter) return lively_lang.arr.without(siblingsWithNode, node);
  var nodeIdxInSiblings = siblingsWithNode.indexOf(node);
  return beforeOrAfter === 'before' ? siblingsWithNode.slice(0, nodeIdxInSiblings) : siblingsWithNode.slice(nodeIdxInSiblings + 1);
}

// // cached visitors that are used often
walk.visitors = {
  stopAtFunctions: walk.make({
    'Function': function Function() {/* stop descent */}
  }, walk.base),

  withMemberExpression: walk.make({
    MemberExpression: function MemberExpression(node, st, c) {
      c(node.object, st, "Expression");
      c(node.property, st, "Expression");
    }
  }, walk.base)

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-
  // from lively.ast.AstHelper
  // -=-=-=-=-=-=-=-=-=-=-=-=-=-
};function findNodeByAstIndex(parsed, astIndexToFind, addIndex) {
  addIndex = addIndex == null ? true : !!addIndex;
  if (!parsed.astIndex && addIndex) addAstIndex(parsed);
  // we need to visit every node, forEachNode is highly
  // inefficient, the compilled Mozilla visitors are a better fit
  var found = null;
  withMozillaAstDo(parsed, null, function (next, node, state) {
    if (found) return;
    var idx = node.astIndex;
    if (idx < astIndexToFind) return;
    if (node.astIndex === astIndexToFind) {
      found = node;return;
    }
    next();
  });
  return found;
}

// FIXME: global (and temporary) findNodeByAstIndex is used by __getClosure and defined in Rewriting.js
// Global.findNodeByAstIndex = findNodeByAstIndex;

function findStatementOfNode(options, parsed, target) {
  // DEPRECATED in favor of query.statementOf(parsed, node)
  // Can also be called with just ast and target. options can be {asPath: BOOLEAN}.
  // Find the statement that a target node is in. Example:
  // let source be "var x = 1; x + 1;" and we are looking for the
  // Identifier "x" in "x+1;". The second statement is what will be found.
  if (!target) {
    target = parsed;parsed = options;options = null;
  }
  if (!options) options = {};
  if (!parsed.astIndex) addAstIndex(parsed);
  var found,
      targetReached = false;
  var statements = [
  // ES5
  'EmptyStatement', 'BlockStatement', 'ExpressionStatement', 'IfStatement', 'LabeledStatement', 'BreakStatement', 'ContinueStatement', 'WithStatement', 'SwitchStatement', 'ReturnStatement', 'ThrowStatement', 'TryStatement', 'WhileStatement', 'DoWhileStatement', 'ForStatement', 'ForInStatement', 'DebuggerStatement', 'FunctionDeclaration', 'VariableDeclaration',
  // ES2015:
  'ClassDeclaration'];
  withMozillaAstDo(parsed, {}, function (next, node, state, path) {
    if (targetReached || node.astIndex < target.astIndex) return;
    if (node === target || node.astIndex === target.astIndex) {
      targetReached = true;
      if (options.asPath) found = path;else {
        var p = lively_lang.Path(path);
        do {
          found = p.get(parsed);
          p = p.slice(0, p.size() - 1);
        } while (statements.indexOf(found.type) == -1 && p.size() > 0);
      }
    }
    !targetReached && next();
  });
  return found;
}

function addAstIndex(parsed) {
  // we need to visit every node, forEachNode is highly
  // inefficient, the compilled Mozilla visitors are a better fit
  withMozillaAstDo(parsed, { index: 0 }, function (next, node, state) {
    next();node.astIndex = state.index++;
  });
  return parsed;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// simple ast traversing
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var AllNodesVisitor = function (_Visitor) {
  inherits(AllNodesVisitor, _Visitor);

  function AllNodesVisitor() {
    classCallCheck(this, AllNodesVisitor);
    return possibleConstructorReturn(this, (AllNodesVisitor.__proto__ || Object.getPrototypeOf(AllNodesVisitor)).apply(this, arguments));
  }

  createClass(AllNodesVisitor, [{
    key: "accept",
    value: function accept(node, state, path) {
      this.doFunc(node, state, path);
      return get(AllNodesVisitor.prototype.__proto__ || Object.getPrototypeOf(AllNodesVisitor.prototype), "accept", this).call(this, node, state, path);
    }
  }], [{
    key: "run",
    value: function run(parsed, doFunc, state) {
      var v = new this();
      v.doFunc = doFunc;
      v.accept(parsed, state, []);
      return state;
    }
  }]);
  return AllNodesVisitor;
}(Visitor);

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// scoping
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var FindToplevelFuncDeclVisitor = function (_Visitor2) {
  inherits(FindToplevelFuncDeclVisitor, _Visitor2);

  function FindToplevelFuncDeclVisitor() {
    classCallCheck(this, FindToplevelFuncDeclVisitor);
    return possibleConstructorReturn(this, (FindToplevelFuncDeclVisitor.__proto__ || Object.getPrototypeOf(FindToplevelFuncDeclVisitor)).apply(this, arguments));
  }

  createClass(FindToplevelFuncDeclVisitor, [{
    key: "accept",
    value: function accept(node, funcDecls, path) {
      switch (node.type) {
        case "ArrowFunctionExpression":
          return node;
        case "FunctionExpression":
          return node;
        case "FunctionDeclaration":
          funcDecls.unshift({ node: node, path: path });return node;
        default:
          return get(FindToplevelFuncDeclVisitor.prototype.__proto__ || Object.getPrototypeOf(FindToplevelFuncDeclVisitor.prototype), "accept", this).call(this, node, funcDecls, path);
      }
    }
  }], [{
    key: "run",
    value: function run(parsed) {
      var state = [];
      new this().accept(parsed, state, []);
      return state;
    }
  }]);
  return FindToplevelFuncDeclVisitor;
}(Visitor);

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// replacement
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var canBeInlinedSym = Symbol("canBeInlined");

function blockInliner(node) {
  // FIXME what about () => x kind of functions?
  if (Array.isArray(node.body)) {
    for (var i = node.body.length - 1; i >= 0; i--) {
      var stmt = node.body[i];
      if (stmt.type === "BlockStatement" && stmt[canBeInlinedSym]) {
        node.body.splice.apply(node.body, [i, 1].concat(stmt.body));
      }
    }
  }
  return node;
}

function block(nodes) {
  return { type: "BlockStatement", body: nodes };
}

var ReplaceManyVisitor = function (_Visitor3) {
  inherits(ReplaceManyVisitor, _Visitor3);

  function ReplaceManyVisitor() {
    classCallCheck(this, ReplaceManyVisitor);
    return possibleConstructorReturn(this, (ReplaceManyVisitor.__proto__ || Object.getPrototypeOf(ReplaceManyVisitor)).apply(this, arguments));
  }

  createClass(ReplaceManyVisitor, [{
    key: "accept",
    value: function accept(node, state, path) {
      return this.replacer(get(ReplaceManyVisitor.prototype.__proto__ || Object.getPrototypeOf(ReplaceManyVisitor.prototype), "accept", this).call(this, node, state, path));
      var replaced = this.replacer(get(ReplaceManyVisitor.prototype.__proto__ || Object.getPrototypeOf(ReplaceManyVisitor.prototype), "accept", this).call(this, node, state, path), path);
      return !Array.isArray(replaced) ? replaced : replaced.length === 1 ? replaced[0] : Object.assign(block(replaced), defineProperty({}, canBeInlinedSym, true));
    }
  }, {
    key: "visitBlockStatement",
    value: function visitBlockStatement(node, state, path) {
      return blockInliner(get(ReplaceManyVisitor.prototype.__proto__ || Object.getPrototypeOf(ReplaceManyVisitor.prototype), "visitBlockStatement", this).call(this, node, state, path));
    }
  }, {
    key: "visitProgram",
    value: function visitProgram(node, state, path) {
      return blockInliner(get(ReplaceManyVisitor.prototype.__proto__ || Object.getPrototypeOf(ReplaceManyVisitor.prototype), "visitProgram", this).call(this, node, state, path));
    }
  }], [{
    key: "run",
    value: function run(parsed, replacer) {
      var v = new this();
      v.replacer = replacer;
      return v.accept(parsed, null, []);
    }
  }]);
  return ReplaceManyVisitor;
}(Visitor);

var ReplaceVisitor = function (_Visitor4) {
  inherits(ReplaceVisitor, _Visitor4);

  function ReplaceVisitor() {
    classCallCheck(this, ReplaceVisitor);
    return possibleConstructorReturn(this, (ReplaceVisitor.__proto__ || Object.getPrototypeOf(ReplaceVisitor)).apply(this, arguments));
  }

  createClass(ReplaceVisitor, [{
    key: "accept",
    value: function accept(node, state, path) {
      return this.replacer(get(ReplaceVisitor.prototype.__proto__ || Object.getPrototypeOf(ReplaceVisitor.prototype), "accept", this).call(this, node, state, path), path);
    }
  }], [{
    key: "run",
    value: function run(parsed, replacer) {
      var v = new this();
      v.replacer = replacer;
      return v.accept(parsed, null, []);
    }
  }]);
  return ReplaceVisitor;
}(Visitor);

acorn.walk.addSource = addSource;

function addSource(parsed, source) {
  if (typeof parsed === "string") {
    source = parsed;
    parsed = parse(parsed);
  }
  source && AllNodesVisitor.run(parsed, function (node, state, path) {
    return !node.source && (node.source = source.slice(node.start, node.end));
  });
  return parsed;
}

function nodesAt(pos, ast) {
  ast = typeof ast === 'string' ? this.parse(ast) : ast;
  return findNodesIncluding(ast, pos);
}

function parseFunction(source) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  var src = '(' + source + ')',
      offset = -1,
      parsed = parse(src, options);

  AllNodesVisitor.run(parsed, function (node, state, path) {
    if (node._positionFixed) return;
    node._positionFixed = true;
    if (node.start || node.start === 0) {
      node.start += offset;
      node.end += offset;
    }
    if (options.addSource && !node.source) {
      node.source = source.slice(node.start, node.end);
    }
  });

  return parsed.body[0].expression;
}

function fuzzyParse(source, options) {
  // options: verbose, addSource, type
  options = options || {};
  options.ecmaVersion = options.ecmaVersion || 8;
  options.sourceType = options.sourceType || "module";
  options.plugins = options.plugins || {};
  // if (options.plugins.hasOwnProperty("jsx")) options.plugins.jsx = options.plugins.jsx;
  options.plugins.jsx = options.plugins.hasOwnProperty("jsx") ? options.plugins.jsx : true;
  options.plugins.asyncawait = options.plugins.hasOwnProperty("asyncawait") ? options.plugins.asyncawait : { inAsyncFunction: true };
  options.plugins.objectSpread = options.plugins.hasOwnProperty("objectSpread") ? options.plugins.objectSpread : true;

  var ast, safeSource, err;
  if (options.type === 'LabeledStatement') {
    safeSource = '$={' + source + '}';
  }
  try {
    // we only parse to find errors
    ast = parse(safeSource || source, options);
    if (safeSource) ast = null; // we parsed only for finding errors
    else if (options.addSource) addSource(ast, source);
  } catch (e) {
    err = e;
  }
  if (err && err.raisedAt !== undefined) {
    if (safeSource) {
      // fix error pos
      err.pos -= 3;err.raisedAt -= 3;err.loc.column -= 3;
    }
    var parseErrorSource = '';
    parseErrorSource += source.slice(err.raisedAt - 20, err.raisedAt);
    parseErrorSource += '<-error->';
    parseErrorSource += source.slice(err.raisedAt, err.raisedAt + 20);
    options.verbose && show('parse error: ' + parseErrorSource);
    err.parseErrorSource = parseErrorSource;
  } else if (err && options.verbose) {
    show('' + err + err.stack);
  }
  if (!ast) {
    ast = loose.parse_dammit(source, options);
    if (options.addSource) addSource(ast, source);
    ast.isFuzzy = true;
    ast.parseError = err;
  }
  return ast;
}

function parse(source, options) {
  // proxy function to acorn.parse.
  // Note that we will implement useful functionality on top of the pure
  // acorn interface and make it available here (such as more convenient
  // comment parsing). For using the pure acorn interface use the acorn
  // global.
  // See https://github.com/marijnh/acorn for full acorn doc and parse options.
  // options: {
  //   addSource: BOOL, -- add source property to each node
  //   addAstIndex: BOOL, -- each node gets an index  number
  //   withComments: BOOL, -- adds comment objects to Program/BlockStatements:
  //              {isBlock: BOOL, text: STRING, node: NODE,
  //               start: INTEGER, end: INTEGER, line: INTEGER, column: INTEGER}
  //   ecmaVersion: 3|5|6,
  //   allowReturnOutsideFunction: BOOL, -- Default is false
  //   locations: BOOL -- Default is false
  // }

  options = options || {};
  options.ecmaVersion = options.ecmaVersion || 8;
  options.sourceType = options.sourceType || "module";
  if (!options.hasOwnProperty("allowImportExportEverywhere")) options.allowImportExportEverywhere = true;
  options.plugins = options.plugins || {};
  options.plugins.jsx = options.plugins.hasOwnProperty("jsx") ? options.plugins.jsx : true;
  options.plugins.asyncawait = options.plugins.hasOwnProperty("asyncawait") ? options.plugins.asyncawait : { inAsyncFunction: true };
  options.plugins.objectSpread = options.plugins.hasOwnProperty("objectSpread") ? options.plugins.objectSpread : true;

  if (options.withComments) {
    // record comments
    delete options.withComments;
    var comments = [];
    options.onComment = function (isBlock, text, start, end, line, column) {
      comments.push({
        isBlock: isBlock,
        text: text, node: null,
        start: start, end: end,
        line: line, column: column
      });
    };
  }

  try {
    var parsed = acorn.parse(source, options);
  } catch (err) {
    if (typeof SyntaxError !== "undefined" && err instanceof SyntaxError && err.loc) {
      var lines = source.split("\n"),
          message = err.message,
          _err$loc = err.loc,
          row = _err$loc.line,
          column = _err$loc.column,
          pos = err.pos,
          line = lines[row - 1],
          newMessage = "Syntax error at line " + row + " column " + column + " (index " + pos + ") \"" + message + "\"\nsource: " + line.slice(0, column) + "<--SyntaxError-->" + line.slice(column),
          betterErr = new SyntaxError(newMessage);

      betterErr.loc = { line: row, column: column };
      betterErr.pos = pos;
      throw betterErr;
    } else throw err;
  }

  if (options.addSource) addSource(parsed, source);

  if (options.addAstIndex && !parsed.hasOwnProperty('astIndex')) addAstIndex(parsed);

  if (parsed && comments) attachCommentsToAST({ ast: parsed, comments: comments, nodesWithComments: [] });

  return parsed;

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  function attachCommentsToAST(commentData) {
    // for each comment: assign the comment to a block-level AST node
    commentData = mergeComments(assignCommentsToBlockNodes(commentData));
    parsed.allComments = commentData.comments;
  }

  function assignCommentsToBlockNodes(commentData) {
    comments.forEach(function (comment) {
      var node = lively_lang.arr.detect(nodesAt(comment.start, parsed).reverse(), function (node) {
        return node.type === 'BlockStatement' || node.type === 'Program';
      });
      if (!node) node = parsed;
      if (!node.comments) node.comments = [];
      node.comments.push(comment);
      commentData.nodesWithComments.push(node);
    });
    return commentData;
  }

  function mergeComments(commentData) {
    // coalesce non-block comments (multiple following lines of "// ...") into one comment.
    // This only happens if line comments aren't seperated by newlines
    commentData.nodesWithComments.forEach(function (blockNode) {
      lively_lang.arr.clone(blockNode.comments).reduce(function (coalesceData, comment) {
        if (comment.isBlock) {
          coalesceData.lastComment = null;
          return coalesceData;
        }

        if (!coalesceData.lastComment) {
          coalesceData.lastComment = comment;
          return coalesceData;
        }

        // if the comments are seperated by a statement, don't merge
        var last = coalesceData.lastComment;
        var nodeInbetween = lively_lang.arr.detect(blockNode.body, function (node) {
          return node.start >= last.end && node.end <= comment.start;
        });
        if (nodeInbetween) {
          coalesceData.lastComment = comment;
          return coalesceData;
        }

        // if the comments are seperated by a newline, don't merge
        var codeInBetween = source.slice(last.end, comment.start);
        if (/[\n\r][\n\r]+/.test(codeInBetween)) {
          coalesceData.lastComment = comment;
          return coalesceData;
        }

        // merge comments into one
        last.text += "\n" + comment.text;
        last.end = comment.end;
        lively_lang.arr.remove(blockNode.comments, comment);
        lively_lang.arr.remove(commentData.comments, comment);
        return coalesceData;
      }, { lastComment: null });
    });
    return commentData;
  }
}

/*global process, global, exports*/

var methods = {

  withMozillaAstDo: function withMozillaAstDo(parsed, state, func) {
    // simple interface to mozilla AST visitor. function gets passed three
    // arguments:
    // acceptNext, -- continue visiting
    // node, -- current node being visited
    // state -- state variable that is passed along
    var vis = new Visitor(),
        origAccept = vis.accept;
    vis.accept = function (node, st, path) {
      var next = function next() {
        origAccept.call(vis, node, st, path);
      };
      state = func(next, node, st, path);
      return node;
    };
    vis.accept(parsed, state, []);
    return state;
  },

  printAst: function printAst(astOrSource, options) {
    options = options || {};
    var printSource = options.printSource || false,
        printPositions = options.printPositions || false,
        printIndex = options.printIndex || false,
        source,
        parsed,
        tree$$1 = [];

    if (typeof astOrSource === "string") {
      source = astOrSource;
      parsed = parse(astOrSource);
    } else {
      parsed = astOrSource;source = options.source || parsed.source;
    }

    if (printSource && !parsed.source) {
      // ensure that nodes have source attached
      if (!source) {
        source = stringify(parsed);
        parsed = parse(source);
      }
      addSource(parsed, source);
    }

    function printFunc(ea) {
      var line = ea.path + ':' + ea.node.type,
          additional = [];
      if (printIndex) {
        additional.push(ea.index);
      }
      if (printPositions) {
        additional.push(ea.node.start + '-' + ea.node.end);
      }
      if (printSource) {
        var src = ea.node.source || source.slice(ea.node.start, ea.node.end),
            printed = lively_lang.string.print(src.truncate(60).replace(/\n/g, '').replace(/\s+/g, ' '));
        additional.push(printed);
      }
      if (additional.length) {
        line += '(' + additional.join(',') + ')';
      }
      return line;
    }

    new PrinterVisitor().accept(parsed, { index: 0, tree: tree$$1 }, []);
    return lively_lang.string.printTree(tree$$1[0], printFunc, function (ea) {
      return ea.children;
    }, '  ');
  },

  compareAst: function compareAst(node1, node2) {
    if (!node1 || !node2) throw new Error('node' + (node1 ? '1' : '2') + ' not defined');
    var state = { completePath: [], comparisons: { errors: [] } };
    new ComparisonVisitor().accept(node1, node2, state, []);
    return !state.comparisons.errors.length ? null : state.comparisons.errors.pluck('msg');
  },

  pathToNode: function pathToNode(parsed, index, options) {
    options = options || {};
    if (!parsed.astIndex) addAstIndex(parsed);
    var vis = new Visitor(),
        found = null;
    (vis.accept = function (node, pathToHere, state, path) {
      if (found) return;
      var fullPath = pathToHere.concat(path);
      if (node.astIndex === index) {
        var pathString = fullPath.map(function (ea) {
          return typeof ea === 'string' ? '.' + ea : '[' + ea + ']';
        }).join('');
        found = { pathString: pathString, path: fullPath, node: node };
      }
      return this['visit' + node.type](node, fullPath, state, path);
    }).call(vis, parsed, [], {}, []);
    return found;
  },

  rematchAstWithSource: function rematchAstWithSource(parsed, source, addLocations, subTreePath) {
    addLocations = !!addLocations;
    var parsed2 = parse(source, addLocations ? { locations: true } : undefined),
        visitor = new Visitor();
    if (subTreePath) parsed2 = lively_lang.Path(subTreePath).get(parsed2);
    visitor.accept = function (node, state, path) {
      path = path || [];
      var node2 = path.reduce(function (node, pathElem) {
        return node[pathElem];
      }, parsed);
      node2.start = node.start;
      node2.end = node.end;
      if (addLocations) node2.loc = node.loc;
      return this['visit' + node.type](node, state, path);
    };

    visitor.accept(parsed2);
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

};var withMozillaAstDo = methods.withMozillaAstDo; var printAst = methods.printAst; var compareAst = methods.compareAst; var pathToNode = methods.pathToNode; var rematchAstWithSource = methods.rematchAstWithSource;



// obj.extend(ast, methods);

// FIXME! Don't extend acorn object!
// obj.extend(ast.acorn, methods);

var identifierRe = /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/;
function isIdentifier(string$$1) {
  // Note: It's not so easy...
  // http://wiki.ecmascript.org/doku.php?id=strawman:identifier_identification
  // https://mathiasbynens.be/notes/javascript-identifiers-es6
  return identifierRe.test(string$$1) && string$$1.indexOf("-") === -1;
}

function id(name) {
  return name === "this" ? { type: "ThisExpression" } : { name: String(name), type: "Identifier" };
}

function literal(value) {
  return { type: "Literal", value: value };
}

function exprStmt(expression) {
  return { type: "ExpressionStatement", expression: expression };
}

function returnStmt(expr) {
  return { type: "ReturnStatement", argument: expr };
}

function empty() {
  return { type: "EmptyStatement" };
}

function binaryExpr(left, op, right) {
  return {
    left: left, right: right, operator: op,
    type: "BinaryExpression"
  };
}

function funcExpr(_ref) {
  for (var _len = arguments.length, statements = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
    statements[_key - 2] = arguments[_key];
  }

  var arrow = _ref.arrow,
      funcId = _ref.id,
      expression = _ref.expression,
      generator = _ref.generator;
  var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

  // lively.ast.stringify(funcExpr({id: "foo"}, ["a"], exprStmt(id("3"))))
  // // => "function foo(a) { 3; }"
  params = params.map(function (ea) {
    return typeof ea === "string" ? id(ea) : ea;
  });
  return {
    type: (arrow ? "Arrow" : "") + "FunctionExpression",
    id: funcId ? typeof funcId === "string" ? id(funcId) : funcId : undefined,
    params: params,
    body: expression && statements.length === 1 ? statements[0] : { body: statements, type: "BlockStatement" },
    expression: expression || false,
    generator: generator || false
  };
}

function funcCall(callee) {
  for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
    args[_key2 - 1] = arguments[_key2];
  }

  if (typeof callee === "string") callee = id(callee);
  return {
    type: "CallExpression",
    callee: callee,
    arguments: args
  };
}

function varDecl(id, init, kind) {
  if (typeof id === "string") id = { name: id, type: "Identifier" };
  return {
    type: "VariableDeclaration", kind: kind || "var",
    declarations: [{ type: "VariableDeclarator", id: id, init: init }]
  };
}

function member(obj$$1, prop, computed) {
  // Example:
  // lively.ast.stringify(member("foo", "bar"))
  // // => "foo.bar"
  // lively.ast.stringify(member("foo", "b-a-r"))
  // // => "foo['b-a-r']"
  // lively.ast.stringify(member("foo", "zork", true))
  // // => "foo['zork']"
  // lively.ast.stringify(member("foo", 0))
  // // => "foo[0]"
  if (typeof obj$$1 === "string") obj$$1 = id(obj$$1);
  if (typeof prop === "string") {
    if (!computed && !isIdentifier(prop)) computed = true;
    prop = computed ? literal(prop) : id(prop);
  } else if (typeof prop === "number") {
    prop = literal(prop);
    computed = true;
  } else if (prop.type === "Literal") {
    computed = true;
  }
  return {
    type: "MemberExpression",
    computed: !!computed,
    object: obj$$1, property: prop
  };
}

function memberChain(first) {
  for (var _len3 = arguments.length, rest = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
    rest[_key3 - 1] = arguments[_key3];
  }

  // lively.ast.stringify(memberChain("foo", "bar", 0, "baz-zork"));
  // // => "foo.bar[0]['baz-zork']"
  return rest.reduce(function (memberExpr, key) {
    return member(memberExpr, key);
  }, (typeof first === "undefined" ? "undefined" : _typeof(first)) === "object" ? first : id(first));
}

function assign(left, right) {
  // lively.ast.stringify(assign("a", "x"))
  // // => "a = x"
  // lively.ast.stringify(assign(member("a", "x"), literal(23)))
  // // => "a.x = 23"
  return {
    type: "AssignmentExpression", operator: "=",
    right: right ? typeof right === "string" ? id(right) : right : id("undefined"),
    left: typeof left === "string" ? id(left) : left
  };
}

function block$1() {
  for (var _len4 = arguments.length, body = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
    body[_key4] = arguments[_key4];
  }

  return { body: Array.isArray(body[0]) ? body[0] : body, type: "BlockStatement" };
}

function program() {
  return Object.assign(block$1.apply(undefined, arguments), { sourceType: "module", type: "Program" });
}

function tryStmt(exName, handlerBody, finalizerBody) {
  for (var _len5 = arguments.length, body = Array(_len5 > 3 ? _len5 - 3 : 0), _key5 = 3; _key5 < _len5; _key5++) {
    body[_key5 - 3] = arguments[_key5];
  }

  // Example:
  // var stmt = exprStmt(binaryExpr(literal(3), "+", literal(2)));
  // lively.ast.stringify(tryStmt("err", [stmt], [stmt], stmt, stmt))
  // // => "try { 3 + 2; 3 + 2; } catch (err) { 3 + 2; } finally { 3 + 2; }"
  if (!Array.isArray(finalizerBody)) {
    body.unshift(finalizerBody);
    finalizerBody = null;
  }
  return {
    block: block$1(body),
    finalizer: finalizerBody ? block$1(finalizerBody) : null,
    handler: {
      body: block$1(handlerBody),
      param: id(exName),
      type: "CatchClause"
    },
    type: "TryStatement"
  };
}

function prop(key, value) {
  return {
    type: "Property",
    key: key,
    computed: key.type !== "Identifier",
    shorthand: false,
    value: value
  };
}

function objectLiteral(keysAndValues) {
  var props = [];
  for (var i = 0; i < keysAndValues.length; i += 2) {
    var key = keysAndValues[i];
    if (typeof key === "string") key = id(key);
    props.push(prop(key, keysAndValues[i + 1]));
  }
  return {
    properties: props,
    type: "ObjectExpression"
  };
}

function ifStmt(test) {
  var consequent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : block$1();
  var alternate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : block$1();

  return {
    consequent: consequent, alternate: alternate, test: test,
    type: "IfStatement"
  };
}

function forIn(varDeclOrName, objExprOrName, body) {
  return {
    type: "ForInStatement",
    left: typeof varDeclOrName === "string" ? varDecl(varDeclOrName) : varDeclOrName,
    right: typeof objExprOrName === "string" ? id(objExprOrName) : objExprOrName,
    body: body
  };
}

function conditional(test) {
  var consequent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : id("undefined");
  var alternate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : id("undefined");

  return {
    consequent: consequent, alternate: alternate, test: test,
    type: "ConditionalExpression"
  };
}

function logical(op, left, right) {
  return {
    operator: op, left: left, right: right,
    type: "LogicalExpression"
  };
}



var nodes = Object.freeze({
	isIdentifier: isIdentifier,
	id: id,
	literal: literal,
	objectLiteral: objectLiteral,
	prop: prop,
	exprStmt: exprStmt,
	returnStmt: returnStmt,
	empty: empty,
	binaryExpr: binaryExpr,
	funcExpr: funcExpr,
	funcCall: funcCall,
	varDecl: varDecl,
	member: member,
	memberChain: memberChain,
	assign: assign,
	block: block$1,
	program: program,
	tryStmt: tryStmt,
	ifStmt: ifStmt,
	forIn: forIn,
	conditional: conditional,
	logical: logical
});

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var helpers = {
  declIds: function declIds(nodes) {
    var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

    for (var i = 0; i < nodes.length; i++) {
      var node = nodes[i];
      if (!node) continue;else if (node.type === "Identifier") result.push(node);else if (node.type === "RestElement") result.push(node.argument);
      // AssignmentPattern: default arg like function(local = defaultVal) {}
      else if (node.type === "AssignmentPattern") helpers.declIds([node.left], result);else if (node.type === "ObjectPattern") {
          for (var j = 0; j < node.properties.length; j++) {
            var prop = node.properties[j];
            helpers.declIds([prop.value || prop], result);
          }
        } else if (node.type === "ArrayPattern") helpers.declIds(node.elements, result);
    }
    return result;
  },
  varDecls: function varDecls(scope) {
    var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;

    try {
      for (var _iterator = scope.varDecls[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        var varDecl = _step.value;
        var _iteratorNormalCompletion2 = true;
        var _didIteratorError2 = false;
        var _iteratorError2 = undefined;

        try {
          for (var _iterator2 = varDecl.declarations[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
            var decl = _step2.value;
            var _iteratorNormalCompletion3 = true;
            var _didIteratorError3 = false;
            var _iteratorError3 = undefined;

            try {
              for (var _iterator3 = helpers.declIds([decl.id])[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
                var id = _step3.value;

                result.push([decl, id]);
              }
            } catch (err) {
              _didIteratorError3 = true;
              _iteratorError3 = err;
            } finally {
              try {
                if (!_iteratorNormalCompletion3 && _iterator3.return) {
                  _iterator3.return();
                }
              } finally {
                if (_didIteratorError3) {
                  throw _iteratorError3;
                }
              }
            }
          }
        } catch (err) {
          _didIteratorError2 = true;
          _iteratorError2 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion2 && _iterator2.return) {
              _iterator2.return();
            }
          } finally {
            if (_didIteratorError2) {
              throw _iteratorError2;
            }
          }
        }
      }
    } catch (err) {
      _didIteratorError = true;
      _iteratorError = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion && _iterator.return) {
          _iterator.return();
        }
      } finally {
        if (_didIteratorError) {
          throw _iteratorError;
        }
      }
    }

    return result;
  },
  varDeclIds: function varDeclIds(scope) {
    var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    var _iteratorNormalCompletion4 = true;
    var _didIteratorError4 = false;
    var _iteratorError4 = undefined;

    try {
      for (var _iterator4 = scope.varDecls[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
        var varDecl = _step4.value;
        var _iteratorNormalCompletion5 = true;
        var _didIteratorError5 = false;
        var _iteratorError5 = undefined;

        try {
          for (var _iterator5 = varDecl.declarations[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
            var decl = _step5.value;

            helpers.declIds([decl.id], result);
          }
        } catch (err) {
          _didIteratorError5 = true;
          _iteratorError5 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion5 && _iterator5.return) {
              _iterator5.return();
            }
          } finally {
            if (_didIteratorError5) {
              throw _iteratorError5;
            }
          }
        }
      }
    } catch (err) {
      _didIteratorError4 = true;
      _iteratorError4 = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion4 && _iterator4.return) {
          _iterator4.return();
        }
      } finally {
        if (_didIteratorError4) {
          throw _iteratorError4;
        }
      }
    }

    return result;
  },
  objPropertiesAsList: function objPropertiesAsList(objExpr, path, onlyLeafs) {
    var result = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];

    // takes an obj expr like {x: 23, y: [{z: 4}]} an returns the key and value
    // nodes as a list
    var _iteratorNormalCompletion6 = true;
    var _didIteratorError6 = false;
    var _iteratorError6 = undefined;

    try {
      for (var _iterator6 = objExpr.properties[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
        var prop = _step6.value;

        var key = prop.key.name,
            thisNode = { key: path.concat([key]), value: prop.value };
        switch (prop.value.type) {
          case "ArrayExpression":case "ArrayPattern":
            if (!onlyLeafs) result.push(thisNode);
            for (var i = 0; i < prop.value.elements.length; i++) {
              var el = prop.value.elements[i];
              helpers.objPropertiesAsList(el, path.concat([key, i]), onlyLeafs, result);
            }
            break;
          case "ObjectExpression":case "ObjectPattern":
            if (!onlyLeafs) result.push(thisNode);
            helpers.objPropertiesAsList(prop.value, path.concat([key]), onlyLeafs, result);
            break;
          case "AssignmentPattern":
            if (!onlyLeafs) result.push(thisNode);
            helpers.objPropertiesAsList(prop.left, path.concat([key]), onlyLeafs, result);
            break;
          default:
            result.push(thisNode);
        }
      }
    } catch (err) {
      _didIteratorError6 = true;
      _iteratorError6 = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion6 && _iterator6.return) {
          _iterator6.return();
        }
      } finally {
        if (_didIteratorError6) {
          throw _iteratorError6;
        }
      }
    }

    return result;
  },
  isDeclaration: function isDeclaration(node) {
    return node.type === "FunctionDeclaration" || node.type === "VariableDeclaration" || node.type === "ClassDeclaration";
  }
};

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var knownGlobals = ["true", "false", "null", "undefined", "arguments", "Object", "Function", "Array", "Number", "parseFloat", "parseInt", "Infinity", "NaN", "Boolean", "String", "Symbol", "Date", "Promise", "RegExp", "Error", "EvalError", "RangeError", "ReferenceError", "SyntaxError", "TypeError", "URIError", "JSON", "Math", "console", "ArrayBuffer", "Uint8Array", "Int8Array", "Uint16Array", "Int16Array", "Uint32Array", "Int32Array", "Float32Array", "Float64Array", "Uint8ClampedArray", "DataView", "Map", "Set", "WeakMap", "WeakSet", "Proxy", "Reflect", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "escape", "unescape", "eval", "isFinite", "isNaN", "Intl", "navigator", "window", "document", "Blob", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "requestAnimationFrame", "cancelAnimationFrame", "btoa", "atob", "sessionStorage", "localStorage", "$world", "lively"];

function scopes(parsed) {
  var vis = new ScopeVisitor(),
      scope = vis.newScope(parsed, null);
  vis.accept(parsed, scope, []);
  return scope;
}

function nodesAtIndex(parsed, index) {
  return withMozillaAstDo(parsed, [], function (next, node, found) {
    if (node.start <= index && index <= node.end) {
      found.push(node);next();
    }
    return found;
  });
}

function scopesAtIndex(parsed, index) {
  return lively_lang.tree.filter(scopes(parsed), function (scope) {
    var n = scope.node;
    var start = n.start,
        end = n.end;
    if (n.type === 'FunctionDeclaration') {
      start = n.params.length ? n.params[0].start : n.body.start;
      end = n.body.end;
    }
    return start <= index && index <= end;
  }, function (s) {
    return s.subScopes;
  });
}

function scopeAtIndex(parsed, index) {
  return lively_lang.arr.last(scopesAtIndex(parsed, index));
}

function scopesAtPos(pos, parsed) {
  // DEPRECATED
  // FIXME "scopes" should actually not referer to a node but to a scope
  // object, see exports.scopes!
  return nodesAt$1(pos, parsed).filter(function (node) {
    return node.type === 'Program' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression';
  });
}

function nodesInScopeOf(node) {
  // DEPRECATED
  // FIXME "scopes" should actually not referer to a node but to a scope
  // object, see exports.scopes!
  return withMozillaAstDo(node, { root: node, result: [] }, function (next, node, state) {
    state.result.push(node);
    if (node !== state.root && (node.type === 'Program' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression')) return state;
    next();
    return state;
  }).result;
}

function declarationsOfScope(scope, includeOuter) {
  var result = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];

  // returns Identifier nodes
  if (includeOuter && scope.node.id && scope.node.id.name) result.push(scope.node.id);
  helpers.declIds(scope.params, result);
  for (var i = 0; i < scope.funcDecls.length; i++) {
    var id = scope.funcDecls[i].id;
    if (id) result.push(id);
  }
  helpers.varDeclIds(scope, result);
  result.push.apply(result, toConsumableArray(scope.catches));
  for (var i = 0; i < scope.classDecls.length; i++) {
    var id = scope.classDecls[i].id;
    if (id) result.push(id);
  }
  result.push.apply(result, toConsumableArray(scope.importSpecifiers));
  return result;
}

function declarationsWithIdsOfScope(scope) {
  // returns a list of pairs [(DeclarationNode,IdentifierNode)]
  var bareIds = helpers.declIds(scope.params).concat(scope.catches),
      declNodes = (scope.node.id && scope.node.id.name ? [scope.node] : []).concat(scope.funcDecls.filter(function (ea) {
    return ea.id;
  })).concat(scope.classDecls.filter(function (ea) {
    return ea.id;
  }));
  return bareIds.map(function (ea) {
    return [ea, ea];
  }).concat(declNodes.map(function (ea) {
    return [ea, ea.id];
  })).concat(helpers.varDecls(scope)).concat(scope.importSpecifiers.map(function (im) {
    return [statementOf(scope.node, im), im];
  }));
}

function _declaredVarNames(scope, useComments) {
  var result = [];
  var _iteratorNormalCompletion7 = true;
  var _didIteratorError7 = false;
  var _iteratorError7 = undefined;

  try {
    for (var _iterator7 = declarationsOfScope(scope, true)[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
      var decl = _step7.value;

      result.push(decl.name);
    }
  } catch (err) {
    _didIteratorError7 = true;
    _iteratorError7 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion7 && _iterator7.return) {
        _iterator7.return();
      }
    } finally {
      if (_didIteratorError7) {
        throw _iteratorError7;
      }
    }
  }

  if (useComments) {
    _findJsLintGlobalDeclarations(scope.node.type === 'Program' ? scope.node : scope.node.body, result);
  }
  return result;
}

var globalDeclRe = /^\s*global\s*/;
function _findJsLintGlobalDeclarations(node) {
  var result = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

  if (!node || !node.comments) return result;
  var _iteratorNormalCompletion8 = true;
  var _didIteratorError8 = false;
  var _iteratorError8 = undefined;

  try {
    for (var _iterator8 = node.comments[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
      var comment = _step8.value;

      var text = comment.text.trim();
      if (!text.startsWith("global")) continue;
      var _iteratorNormalCompletion9 = true;
      var _didIteratorError9 = false;
      var _iteratorError9 = undefined;

      try {
        for (var _iterator9 = text.replace(globalDeclRe, '').split(',')[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
          var globalDecl = _step9.value;

          result.push(globalDecl.trim());
        }
      } catch (err) {
        _didIteratorError9 = true;
        _iteratorError9 = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion9 && _iterator9.return) {
            _iterator9.return();
          }
        } finally {
          if (_didIteratorError9) {
            throw _iteratorError9;
          }
        }
      }
    }
  } catch (err) {
    _didIteratorError8 = true;
    _iteratorError8 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion8 && _iterator8.return) {
        _iterator8.return();
      }
    } finally {
      if (_didIteratorError8) {
        throw _iteratorError8;
      }
    }
  }

  return result;
}

function topLevelFuncDecls(parsed) {
  return FindToplevelFuncDeclVisitor.run(parsed);
}

function resolveReference(ref, scopePath) {
  if (scopePath.length == 0) return [null, null];

  var _scopePath = toArray(scopePath),
      scope = _scopePath[0],
      outer = _scopePath.slice(1);

  var decls = scope.decls || declarationsWithIdsOfScope(scope);
  scope.decls = decls;
  var decl = decls.find(function (_ref) {
    var _ref2 = slicedToArray(_ref, 2),
        _ = _ref2[0],
        id = _ref2[1];

    return id.name == ref;
  });
  return decl || resolveReference(ref, outer);
}

function resolveReferences(scope) {
  function rec(scope, outerScopes) {
    var path = [scope].concat(outerScopes);
    scope.refs.forEach(function (ref) {
      var _resolveReference = resolveReference(ref.name, path),
          _resolveReference2 = slicedToArray(_resolveReference, 2),
          decl = _resolveReference2[0],
          id = _resolveReference2[1];

      map.set(ref, { decl: decl, declId: id, ref: ref });
    });
    scope.subScopes.forEach(function (s) {
      return rec(s, path);
    });
  }
  if (scope.referencesResolvedSafely) return scope;
  var map = scope.resolvedRefMap || (scope.resolvedRefMap = new Map());
  rec(scope, []);
  scope.referencesResolvedSafely = true;
  return scope;
}

function refWithDeclAt(pos, scope) {
  var _iteratorNormalCompletion10 = true;
  var _didIteratorError10 = false;
  var _iteratorError10 = undefined;

  try {
    for (var _iterator10 = scope.resolvedRefMap.values()[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
      var ref = _step10.value;
      var _ref$ref = ref.ref,
          start = _ref$ref.start,
          end = _ref$ref.end;

      if (start <= pos && pos <= end) return ref;
    }
  } catch (err) {
    _didIteratorError10 = true;
    _iteratorError10 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion10 && _iterator10.return) {
        _iterator10.return();
      }
    } finally {
      if (_didIteratorError10) {
        throw _iteratorError10;
      }
    }
  }
}

function topLevelDeclsAndRefs(parsed, options) {
  options = options || {};
  options.withComments = true;

  if (typeof parsed === "string") parsed = parse(parsed, options);

  var scope = scopes(parsed),
      useComments = !!options.jslintGlobalComment,
      declared = _declaredVarNames(scope, useComments),
      refs = scope.refs.concat(lively_lang.arr.flatten(scope.subScopes.map(findUndeclaredReferences))),
      undeclared = lively_lang.arr.withoutAll(refs.map(function (ea) {
    return ea.name;
  }), declared);

  return {
    scope: scope,
    varDecls: scope.varDecls,
    funcDecls: scope.funcDecls.filter(function (ea) {
      return ea.id;
    }),
    classDecls: scope.classDecls.filter(function (ea) {
      return ea.id;
    }),
    declaredNames: declared,
    undeclaredNames: undeclared,
    refs: refs,
    thisRefs: scope.thisRefs

    // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  };function findUndeclaredReferences(scope) {
    var names = _declaredVarNames(scope, useComments);
    return scope.subScopes.map(findUndeclaredReferences).reduce(function (refs, ea) {
      return refs.concat(ea);
    }, scope.refs).filter(function (ref) {
      return names.indexOf(ref.name) === -1;
    });
  }
}

function findGlobalVarRefs(parsed, options) {
  var topLevel = topLevelDeclsAndRefs(parsed, options),
      noGlobals = topLevel.declaredNames.concat(knownGlobals);
  return topLevel.refs.filter(function (ea) {
    return noGlobals.indexOf(ea.name) === -1;
  });
}

function findNodesIncludingLines(parsed, code, lines, options) {
  if (!code && !parsed) throw new Error("Need at least ast or code");
  code = code ? code : stringify(parsed);
  parsed = parsed && parsed.loc ? parsed : parse(code, { locations: true });
  return withMozillaAstDo(parsed, [], function (next, node, found) {
    if (lines.every(function (line) {
      return lively_lang.num.between(line, node.loc.start.line, node.loc.end.line);
    })) {
      lively_lang.arr.pushIfNotIncluded(found, node);next();
    }
    return found;
  });
}

function __varDeclIdsFor(scope, name) {
  var result = [];
  var _iteratorNormalCompletion11 = true;
  var _didIteratorError11 = false;
  var _iteratorError11 = undefined;

  try {
    for (var _iterator11 = scope.params[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
      var ea = _step11.value;
      if (ea.name === name) result.push(ea);
    }
  } catch (err) {
    _didIteratorError11 = true;
    _iteratorError11 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion11 && _iterator11.return) {
        _iterator11.return();
      }
    } finally {
      if (_didIteratorError11) {
        throw _iteratorError11;
      }
    }
  }

  var _iteratorNormalCompletion12 = true;
  var _didIteratorError12 = false;
  var _iteratorError12 = undefined;

  try {
    for (var _iterator12 = scope.funcDecls[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
      var ea = _step12.value;
      if (ea.id && ea.id.name === name) result.push(ea.id);
    }
  } catch (err) {
    _didIteratorError12 = true;
    _iteratorError12 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion12 && _iterator12.return) {
        _iterator12.return();
      }
    } finally {
      if (_didIteratorError12) {
        throw _iteratorError12;
      }
    }
  }

  var _iteratorNormalCompletion13 = true;
  var _didIteratorError13 = false;
  var _iteratorError13 = undefined;

  try {
    for (var _iterator13 = scope.classDecls[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
      var ea = _step13.value;
      if (ea.id && ea.id.name === name) result.push(ea.id);
    }
  } catch (err) {
    _didIteratorError13 = true;
    _iteratorError13 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion13 && _iterator13.return) {
        _iterator13.return();
      }
    } finally {
      if (_didIteratorError13) {
        throw _iteratorError13;
      }
    }
  }

  var _iteratorNormalCompletion14 = true;
  var _didIteratorError14 = false;
  var _iteratorError14 = undefined;

  try {
    for (var _iterator14 = scope.importSpecifiers[Symbol.iterator](), _step14; !(_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done); _iteratorNormalCompletion14 = true) {
      var ea = _step14.value;
      if (ea.name === name) result.push(ea);
    }
  } catch (err) {
    _didIteratorError14 = true;
    _iteratorError14 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion14 && _iterator14.return) {
        _iterator14.return();
      }
    } finally {
      if (_didIteratorError14) {
        throw _iteratorError14;
      }
    }
  }

  var _iteratorNormalCompletion15 = true;
  var _didIteratorError15 = false;
  var _iteratorError15 = undefined;

  try {
    for (var _iterator15 = helpers.varDeclIds(scope)[Symbol.iterator](), _step15; !(_iteratorNormalCompletion15 = (_step15 = _iterator15.next()).done); _iteratorNormalCompletion15 = true) {
      var ea = _step15.value;
      if (ea.name === name) result.push(ea);
    }
  } catch (err) {
    _didIteratorError15 = true;
    _iteratorError15 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion15 && _iterator15.return) {
        _iterator15.return();
      }
    } finally {
      if (_didIteratorError15) {
        throw _iteratorError15;
      }
    }
  }

  return result;
}

function findReferencesAndDeclsInScope(scope, name) {
  var _result$decls;

  var startingScope = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  var result = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { refs: [], decls: [] };

  if (name === "this") {
    var _result$refs;

    (_result$refs = result.refs).push.apply(_result$refs, toConsumableArray(scope.thisRefs));
    return result;
  }

  var decls = __varDeclIdsFor(scope, name);
  if (!startingScope && decls.length) return result; // name shadowed in sub-scope

  var _iteratorNormalCompletion16 = true;
  var _didIteratorError16 = false;
  var _iteratorError16 = undefined;

  try {
    for (var _iterator16 = scope.refs[Symbol.iterator](), _step16; !(_iteratorNormalCompletion16 = (_step16 = _iterator16.next()).done); _iteratorNormalCompletion16 = true) {
      var ref = _step16.value;
      if (ref.name === name) result.refs.push(ref);
    }
  } catch (err) {
    _didIteratorError16 = true;
    _iteratorError16 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion16 && _iterator16.return) {
        _iterator16.return();
      }
    } finally {
      if (_didIteratorError16) {
        throw _iteratorError16;
      }
    }
  }

  (_result$decls = result.decls).push.apply(_result$decls, toConsumableArray(decls));

  var _iteratorNormalCompletion17 = true;
  var _didIteratorError17 = false;
  var _iteratorError17 = undefined;

  try {
    for (var _iterator17 = scope.subScopes[Symbol.iterator](), _step17; !(_iteratorNormalCompletion17 = (_step17 = _iterator17.next()).done); _iteratorNormalCompletion17 = true) {
      var subScope = _step17.value;

      findReferencesAndDeclsInScope(subScope, name, false, result);
    }
  } catch (err) {
    _didIteratorError17 = true;
    _iteratorError17 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion17 && _iterator17.return) {
        _iterator17.return();
      }
    } finally {
      if (_didIteratorError17) {
        throw _iteratorError17;
      }
    }
  }

  return result;
}

function findDeclarationClosestToIndex(parsed, name, index) {
  var found = null;
  lively_lang.arr.detect(scopesAtIndex(parsed, index).reverse(), function (scope) {
    var decls = declarationsOfScope(scope, true),
        idx = lively_lang.arr.pluck(decls, 'name').indexOf(name);
    if (idx === -1) return false;
    found = decls[idx];return true;
  });
  return found;
}

function nodesAt$1(pos, ast) {
  ast = typeof ast === 'string' ? parse(ast) : ast;
  return acorn.walk.findNodesIncluding(ast, pos);
}

var _stmtTypes = ["EmptyStatement", "BlockStatement", "ExpressionStatement", "IfStatement", "BreakStatement", "ContinueStatement", "WithStatement", "ReturnStatement", "ThrowStatement", "TryStatement", "WhileStatement", "DoWhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DebuggerStatement", "FunctionDeclaration", "VariableDeclaration", "ClassDeclaration", "ImportDeclaration", "ImportDeclaration", "ExportNamedDeclaration", "ExportDefaultDeclaration", "ExportAllDeclaration"];

function statementOf(parsed, node, options) {
  // Find the statement that a target node is in. Example:
  // let source be "var x = 1; x + 1;" and we are looking for the
  // Identifier "x" in "x+1;". The second statement is what will be found.
  var nodes = nodesAt$1(node.start, parsed),
      found = nodes.reverse().find(function (node) {
    return lively_lang.arr.include(_stmtTypes, node.type);
  });
  if (options && options.asPath) {
    var v = new Visitor(),
        foundPath = void 0;
    v.accept = lively_lang.fun.wrap(v.accept, function (proceed, node, state, path) {
      if (node === found) {
        foundPath = path;throw new Error("stop search");
      }
      return proceed(node, state, path);
    });
    try {
      v.accept(parsed, {}, []);
    } catch (e) {}
    return foundPath;
  }
  return found;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// imports and exports
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function imports(scope) {

  // like import "fooo";
  var imports = [],
      stmts = scope.node.body || [];

  for (var i = 0; i < stmts.length; i++) {
    var stmt = stmts[i];
    if (stmt.type !== "ImportDeclaration") continue;
    if (stmt.specifiers.length === 0) {
      imports.push({ local: null, imported: null, fromModule: stmt.source.value, node: stmt });
      continue;
    }

    // like import { x as y } from "fooo"; import * as x from "fooo"; import x from "fooo";
    var from = stmt.source ? stmt.source.value : "unknown module";

    imports.push.apply(imports, toConsumableArray(stmt.specifiers.map(function (importSpec) {
      var imported;
      if (importSpec.type === "ImportNamespaceSpecifier") imported = "*";else if (importSpec.type === "ImportDefaultSpecifier") imported = "default";else if (importSpec.type === "ImportSpecifier") imported = importSpec.imported.name;else imported = null;
      return {
        local: importSpec.local ? importSpec.local.name : null,
        imported: imported,
        fromModule: from,
        node: stmt
      };
    })));
  }

  return imports;
}

function exports$1(scope) {
  var resolve = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;

  if (resolve) resolveReferences(scope);

  var exports = [];
  var _iteratorNormalCompletion18 = true;
  var _didIteratorError18 = false;
  var _iteratorError18 = undefined;

  try {
    var _loop = function _loop() {
      var node = _step18.value;
      exportsStmt = statementOf(scope.node, node);

      if (!exportsStmt) return "continue";

      from = exportsStmt.source ? exportsStmt.source.value : null;


      if (exportsStmt.type === "ExportAllDeclaration") {
        exports.push({
          local: null,
          exported: "*",
          imported: "*",
          fromModule: from,
          node: node,
          type: "all"
        });
        return "continue";
      }

      if (exportsStmt.type === "ExportDefaultDeclaration") {

        if (helpers.isDeclaration(exportsStmt.declaration)) {
          exports.push({
            local: exportsStmt.declaration.id ? exportsStmt.declaration.id.name : null,
            exported: "default",
            type: exportsStmt.declaration.type === "FunctionDeclaration" ? "function" : exportsStmt.declaration.type === "ClassDeclaration" ? "class" : null,
            fromModule: null,
            node: node,
            decl: exportsStmt.declaration,
            declId: exportsStmt.declaration.id
          });
          return "continue";
        }

        if (exportsStmt.declaration.type === "Identifier") {
          var _ref3 = scope.resolvedRefMap.get(exportsStmt.declaration) || {};

          decl = _ref3.decl;
          declId = _ref3.declId;

          exports.push({
            local: exportsStmt.declaration.name,
            exported: "default",
            fromModule: null,
            node: node,
            type: "id",
            decl: decl,
            declId: declId
          });
          return "continue";
        }

        // exportsStmt.declaration is an expression
        exports.push({
          local: null,
          exported: "default",
          fromModule: null,
          node: node,
          type: "expr",
          decl: exportsStmt.declaration,
          declId: exportsStmt.declaration
        });
        return "continue";
      }

      if (exportsStmt.specifiers && exportsStmt.specifiers.length) {

        exports.push.apply(exports, toConsumableArray(exportsStmt.specifiers.map(function (exportSpec) {
          var decl, declId;
          if (from) {
            // "export { x as y } from 'foo'" is the only case where export
            // creates a (non-local) declaration itself
            decl = node;declId = exportSpec.exported;
          } else if (exportSpec.local) {
            var resolved = scope.resolvedRefMap.get(exportSpec.local);
            decl = resolved ? resolved.decl : null;
            declId = resolved ? resolved.declId : null;
          }

          return {
            local: !from && exportSpec.local ? exportSpec.local.name : null,
            exported: exportSpec.exported ? exportSpec.exported.name : null,
            imported: from && exportSpec.local ? exportSpec.local.name : null,
            fromModule: from || null,
            type: "id",
            node: node,
            decl: decl,
            declId: declId
          };
        })));
        return "continue";
      }

      if (exportsStmt.declaration && exportsStmt.declaration.declarations) {
        exports.push.apply(exports, toConsumableArray(exportsStmt.declaration.declarations.map(function (decl) {
          return {
            local: decl.id ? decl.id.name : "default",
            exported: decl.id ? decl.id.name : "default",
            type: exportsStmt.declaration.kind,
            fromModule: null,
            node: node,
            decl: decl,
            declId: decl.id
          };
        })));
        return "continue";
      }

      if (exportsStmt.declaration) {
        exports.push({
          local: exportsStmt.declaration.id ? exportsStmt.declaration.id.name : "default",
          exported: exportsStmt.declaration.id ? exportsStmt.declaration.id.name : "default",
          type: exportsStmt.declaration.type === "FunctionDeclaration" ? "function" : exportsStmt.declaration.type === "ClassDeclaration" ? "class" : null,
          fromModule: null,
          node: node,
          decl: exportsStmt.declaration,
          declId: exportsStmt.declaration.id
        });
        return "continue";
      }
    };

    for (var _iterator18 = scope.exportDecls[Symbol.iterator](), _step18; !(_iteratorNormalCompletion18 = (_step18 = _iterator18.next()).done); _iteratorNormalCompletion18 = true) {
      var exportsStmt;
      var from;
      var decl, declId;

      var _ret = _loop();

      if (_ret === "continue") continue;
    }
  } catch (err) {
    _didIteratorError18 = true;
    _iteratorError18 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion18 && _iterator18.return) {
        _iterator18.return();
      }
    } finally {
      if (_didIteratorError18) {
        throw _iteratorError18;
      }
    }
  }

  return lively_lang.arr.uniqBy(exports, function (a, b) {
    return a.local == b.local && a.exported == b.exported && a.fromModule == b.fromModule;
  });
}



var query = Object.freeze({
	helpers: helpers,
	knownGlobals: knownGlobals,
	scopes: scopes,
	nodesAtIndex: nodesAtIndex,
	scopesAtIndex: scopesAtIndex,
	scopeAtIndex: scopeAtIndex,
	scopesAtPos: scopesAtPos,
	nodesInScopeOf: nodesInScopeOf,
	declarationsOfScope: declarationsOfScope,
	_declaredVarNames: _declaredVarNames,
	_findJsLintGlobalDeclarations: _findJsLintGlobalDeclarations,
	topLevelDeclsAndRefs: topLevelDeclsAndRefs,
	topLevelFuncDecls: topLevelFuncDecls,
	findGlobalVarRefs: findGlobalVarRefs,
	findNodesIncludingLines: findNodesIncludingLines,
	findReferencesAndDeclsInScope: findReferencesAndDeclsInScope,
	findDeclarationClosestToIndex: findDeclarationClosestToIndex,
	nodesAt: nodesAt$1,
	statementOf: statementOf,
	resolveReferences: resolveReferences,
	refWithDeclAt: refWithDeclAt,
	imports: imports,
	exports: exports$1
});

var ObjectSpreadTransformer = function (_Visitor) {
  inherits(ObjectSpreadTransformer, _Visitor);

  function ObjectSpreadTransformer() {
    classCallCheck(this, ObjectSpreadTransformer);
    return possibleConstructorReturn(this, (ObjectSpreadTransformer.__proto__ || Object.getPrototypeOf(ObjectSpreadTransformer)).apply(this, arguments));
  }

  createClass(ObjectSpreadTransformer, [{
    key: "accept",
    value: function accept(node, state, path) {
      if (node.type === "ObjectExpression") {
        node = this.transformSpreadElement(node);
      }
      return get(ObjectSpreadTransformer.prototype.__proto__ || Object.getPrototypeOf(ObjectSpreadTransformer.prototype), "accept", this).call(this, node, state, path);
    }
  }, {
    key: "transformSpreadElement",
    value: function transformSpreadElement(node) {
      var currentGroup = [],
          propGroups = [currentGroup];

      node.properties.forEach(function (prop$$1) {
        if (prop$$1.type !== "SpreadElement") currentGroup.push(prop$$1);else {
          propGroups.push(prop$$1);
          currentGroup = [];
          propGroups.push(currentGroup);
        }
      });

      if (propGroups.length === 1) return node;

      if (!currentGroup.length) propGroups.pop();

      return funcCall.apply(undefined, [member("Object", "assign")].concat(toConsumableArray(propGroups.map(function (group) {
        return group.type === "SpreadElement" ? group.argument : {
          properties: group,
          type: 'ObjectExpression'
        };
      }))));
    }
  }]);
  return ObjectSpreadTransformer;
}(Visitor);

function objectSpreadTransform(parsed) {
  // "var x = {y, ...z}" => "var x = Object.assign({ y }, z);"
  return new ObjectSpreadTransformer().accept(parsed, {}, []);
}

/*global process, global, exports*/

function _node2string(node) {
  return node.source || stringify(node);
}

function _findIndentAt(s, pos) {
  var bol = lively_lang.string.peekLeft(s, pos, /\s+$/),
      indent = typeof bol === 'number' ? s.slice(bol, pos) : '';
  if (indent[0] === '\n') indent = indent.slice(1);
  return indent;
}

function _applyChanges(changes, source) {
  for (var i = 0; i < changes.length; i++) {
    var change = changes[i];
    if (change.type === 'del') {
      source = source.slice(0, change.pos) + source.slice(change.pos + change.length);
    } else if (change.type === 'add') {
      source = source.slice(0, change.pos) + change.string + source.slice(change.pos);
    } else {
      throw new Error('Unexpected change ' + lively_lang.obj.inspect(change));
    }
  }
  return source;
}

function _compareNodesForReplacement(nodeA, nodeB) {
  // equals
  if (nodeA.start === nodeB.start && nodeA.end === nodeB.end) return 0;
  // a "left" of b
  if (nodeA.end <= nodeB.start) return -1;
  // a "right" of b
  if (nodeA.start >= nodeB.end) return 1;
  // a contains b
  if (nodeA.start <= nodeB.start && nodeA.end >= nodeB.end) return 1;
  // b contains a
  if (nodeB.start <= nodeA.start && nodeB.end >= nodeA.end) return -1;
  throw new Error('Comparing nodes');
}

function replaceNode(target, replacementFunc, sourceOrChanges) {
  // parameters:
  //   - target: ast node
  //   - replacementFunc that gets this node and its source snippet
  //     handed and should produce a new ast node or source code.
  //   - sourceOrChanges: If its a string -- the source code to rewrite
  //                      If its and object -- {changes: ARRAY, source: STRING}

  var sourceChanges = (typeof sourceOrChanges === "undefined" ? "undefined" : _typeof(sourceOrChanges)) === 'object' ? sourceOrChanges : { changes: [], source: sourceOrChanges },
      insideChangedBefore = false,
      pos = sourceChanges.changes.reduce(function (pos, change) {
    // fixup the start and end indices of target using the del/add
    // changes already applied
    if (pos.end < change.pos) return pos;

    var isInFront = change.pos < pos.start;
    insideChangedBefore = insideChangedBefore || change.pos >= pos.start && change.pos <= pos.end;

    if (change.type === 'add') return {
      start: isInFront ? pos.start + change.string.length : pos.start,
      end: pos.end + change.string.length
    };

    if (change.type === 'del') return {
      start: isInFront ? pos.start - change.length : pos.start,
      end: pos.end - change.length
    };

    throw new Error('Cannot deal with change ' + lively_lang.obj.inspect(change));
  }, { start: target.start, end: target.end });

  var source = sourceChanges.source,
      replacement = replacementFunc(target, source.slice(pos.start, pos.end), insideChangedBefore),
      replacementSource = typeof replacement === "string" ? replacement : Array.isArray(replacement) ? replacement.map(_node2string).join('\n' + _findIndentAt(source, pos.start)) : replacementSource = _node2string(replacement);

  var changes = [{ type: 'del', pos: pos.start, length: pos.end - pos.start }, { type: 'add', pos: pos.start, string: replacementSource }];

  return {
    changes: sourceChanges.changes.concat(changes),
    source: _applyChanges(changes, source)
  };
}

function replaceNodes(targetAndReplacementFuncs, sourceOrChanges) {
  // replace multiple AST nodes, order rewriting from inside out and
  // top to bottom so that nodes to rewrite can overlap or be contained
  // in each other
  var sorted = targetAndReplacementFuncs.sort(function (a, b) {
    return _compareNodesForReplacement(a.target, b.target);
  }),
      sourceChanges = (typeof sourceOrChanges === "undefined" ? "undefined" : _typeof(sourceOrChanges)) === 'object' ? sourceOrChanges : { changes: [], source: sourceOrChanges };
  for (var i = 0; i < sorted.length; i++) {
    var _sorted$i = sorted[i],
        target = _sorted$i.target,
        replacementFunc = _sorted$i.replacementFunc;

    sourceChanges = replaceNode(target, replacementFunc, sourceChanges);
  }
  return sourceChanges;
}

function replace(astOrSource, targetNode, replacementFunc, options) {
  // replaces targetNode in astOrSource with what replacementFunc returns
  // (one or multiple ast nodes)
  // Example:
  // var ast = exports.parse('foo.bar("hello");')
  // exports.transform.replace(
  //     ast, ast.body[0].expression,
  //     function(node, source) {
  //         return {type: "CallExpression",
  //             callee: {name: node.arguments[0].value, type: "Identifier"},
  //             arguments: [{value: "world", type: "Literal"}]
  //         }
  //     });
  // => {
  //      source: "hello('world');",
  //      changes: [{pos: 0,length: 16,type: "del"},{pos: 0,string: "hello('world')",type: "add"}]
  //    }

  var parsed = (typeof astOrSource === "undefined" ? "undefined" : _typeof(astOrSource)) === 'object' ? astOrSource : null,
      source = typeof astOrSource === 'string' ? astOrSource : parsed.source || _node2string(parsed);
  return replaceNode(targetNode, replacementFunc, source);
}

function __findVarDecls(scope) {
  var varDecls = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

  varDecls.push.apply(varDecls, toConsumableArray(scope.varDecls));
  var _iteratorNormalCompletion = true;
  var _didIteratorError = false;
  var _iteratorError = undefined;

  try {
    for (var _iterator = scope.subScopes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
      var subScope = _step.value;

      __findVarDecls(subScope, varDecls);
    }
  } catch (err) {
    _didIteratorError = true;
    _iteratorError = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion && _iterator.return) {
        _iterator.return();
      }
    } finally {
      if (_didIteratorError) {
        throw _iteratorError;
      }
    }
  }

  return varDecls;
}

function oneDeclaratorPerVarDecl(astOrSource) {
  // exports.transform.oneDeclaratorPerVarDecl(
  //    "var x = 3, y = (function() { var y = 3, x = 2; })(); ").source

  var parsed = (typeof astOrSource === "undefined" ? "undefined" : _typeof(astOrSource)) === 'object' ? astOrSource : parse(astOrSource),
      source = typeof astOrSource === 'string' ? astOrSource : parsed.source || _node2string(parsed),
      scope = scopes(parsed),
      varDecls = __findVarDecls(scope);

  var targetsAndReplacements = [];
  var _iteratorNormalCompletion2 = true;
  var _didIteratorError2 = false;
  var _iteratorError2 = undefined;

  try {
    for (var _iterator2 = varDecls[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
      var decl = _step2.value;

      targetsAndReplacements.push({
        target: decl,
        replacementFunc: function replacementFunc(declNode, s, wasChanged) {
          if (wasChanged) {
            // reparse node if necessary, e.g. if init was changed before like in
            // var x = (function() { var y = ... })();
            declNode = parse(s).body[0];
          }

          return declNode.declarations.map(function (ea) {
            return {
              type: "VariableDeclaration",
              kind: "var", declarations: [ea]
            };
          });
        }
      });
    }
  } catch (err) {
    _didIteratorError2 = true;
    _iteratorError2 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion2 && _iterator2.return) {
        _iterator2.return();
      }
    } finally {
      if (_didIteratorError2) {
        throw _iteratorError2;
      }
    }
  }

  return replaceNodes(targetsAndReplacements, source);
}

function oneDeclaratorForVarsInDestructoring(astOrSource) {
  var parsed = (typeof astOrSource === "undefined" ? "undefined" : _typeof(astOrSource)) === 'object' ? astOrSource : parse(astOrSource),
      source = typeof astOrSource === 'string' ? astOrSource : parsed.source || _node2string(parsed),
      scope = scopes(parsed),
      varDecls = __findVarDecls(scope),
      targetsAndReplacements = [];

  var _iteratorNormalCompletion3 = true;
  var _didIteratorError3 = false;
  var _iteratorError3 = undefined;

  try {
    for (var _iterator3 = varDecls[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
      var decl = _step3.value;

      targetsAndReplacements.push({
        target: decl,
        replacementFunc: function replacementFunc(declNode, s, wasChanged) {
          if (wasChanged) {
            // reparse node if necessary, e.g. if init was changed before like in
            // var x = (function() { var y = ... })();
            declNode = parse(s).body[0];
          }

          var nodes = [];
          var _iteratorNormalCompletion4 = true;
          var _didIteratorError4 = false;
          var _iteratorError4 = undefined;

          try {
            for (var _iterator4 = declNode.declarations[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
              var _declNode = _step4.value;

              var extractedId = { type: "Identifier", name: "__temp" },
                  extractedInit = {
                type: "VariableDeclaration", kind: "var",
                declarations: [{ type: "VariableDeclarator", id: extractedId, init: _declNode.init }]
              };
              nodes.push(extractedInit);

              var _iteratorNormalCompletion5 = true;
              var _didIteratorError5 = false;
              var _iteratorError5 = undefined;

              try {
                for (var _iterator5 = helpers.objPropertiesAsList(_declNode.id, [], false)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
                  var _ref2 = _step5.value;
                  var keyPath = _ref2.key;

                  nodes.push(varDecl(keyPath[keyPath.length - 2], memberChain.apply(undefined, [extractedId.name].concat(toConsumableArray(keyPath))), "var"));
                }
              } catch (err) {
                _didIteratorError5 = true;
                _iteratorError5 = err;
              } finally {
                try {
                  if (!_iteratorNormalCompletion5 && _iterator5.return) {
                    _iterator5.return();
                  }
                } finally {
                  if (_didIteratorError5) {
                    throw _iteratorError5;
                  }
                }
              }
            }
          } catch (err) {
            _didIteratorError4 = true;
            _iteratorError4 = err;
          } finally {
            try {
              if (!_iteratorNormalCompletion4 && _iterator4.return) {
                _iterator4.return();
              }
            } finally {
              if (_didIteratorError4) {
                throw _iteratorError4;
              }
            }
          }

          return nodes;
        }
      });
    }
  } catch (err) {
    _didIteratorError3 = true;
    _iteratorError3 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion3 && _iterator3.return) {
        _iterator3.return();
      }
    } finally {
      if (_didIteratorError3) {
        throw _iteratorError3;
      }
    }
  }

  return replaceNodes(targetsAndReplacements, source);
}

function returnLastStatement(source, opts) {
  opts = opts || {};

  var parsed = parse(source, opts),
      last = lively_lang.arr.last(parsed.body);
  if (last.type !== "ExpressionStatement") return opts.asAST ? parsed : source;

  parsed.body.splice(parsed.body.length - 1, 1, returnStmt(last.expression));
  return opts.asAST ? parsed : stringify(parsed);
}

function wrapInFunction(code, opts) {
  opts = opts || {};
  var transformed = returnLastStatement(code, opts);
  return opts.asAST ? program(funcExpr.apply(undefined, [{ id: opts.id || undefined }, []].concat(toConsumableArray(transformed.body)))) : "function" + (opts.id ? " " + opts.id : "") + "() {\n" + transformed + "\n}";
}

function wrapInStartEndCall(parsed, options) {
  // Wraps a piece of code into two function calls: One before the first
  // statement and one after the last. Also wraps the entire thing into a try /
  // catch block. The end call gets the result of the last statement (if it is
  // something that returns a value, i.e. an expression) passed as the second
  // argument. If an error occurs the end function is called with an error as
  // first parameter
  // Why? This allows to easily track execution of code, especially for
  // asynchronus / await code!
  // Example:
  // stringify(wrapInStartEndCall("var y = x + 23; y"))
  // // generates code
  // try {
  //     __start_execution();
  //     __lvVarRecorder.y = x + 23;
  //     return __end_execution(null, __lvVarRecorder.y);
  // } catch (err) {
  //     return __end_execution(err, undefined);
  // }

  if (typeof parsed === "string") parsed = parse(parsed);
  options = options || {};

  var isProgram = parsed.type === "Program",
      startFuncNode = options.startFuncNode || id("__start_execution"),
      endFuncNode = options.endFuncNode || id("__end_execution"),
      funcDecls = topLevelFuncDecls(parsed),
      innerBody = parsed.body,
      outerBody = [];

  // 1. Hoist func decls outside the actual eval start - end code. The async /
  // generator transforms require this!
  funcDecls.forEach(function (_ref3) {
    var node = _ref3.node,
        path = _ref3.path;

    lively_lang.Path(path).set(parsed, exprStmt(node.id));
    outerBody.push(node);
  });

  // 2. add start-eval call
  innerBody.unshift(exprStmt(funcCall(startFuncNode)));

  // 3. if last statement is an expression, transform it so we can pass it to
  // the end-eval call, replacing the original expression. If it's a
  // non-expression we record undefined as the eval result
  var last = lively_lang.arr.last(innerBody);
  if (last.type === "ExpressionStatement") {
    innerBody.pop();
    innerBody.push(exprStmt(funcCall(endFuncNode, id("null"), last.expression)));
  } else if (last.type === "VariableDeclaration" && lively_lang.arr.last(last.declarations).id.type === "Identifier") {
    innerBody.push(exprStmt(funcCall(endFuncNode, id("null"), lively_lang.arr.last(last.declarations).id)));
  } else {
    innerBody.push(exprStmt(funcCall(endFuncNode, id("null"), id("undefined"))));
  }

  // 4. Wrap that stuff in a try stmt
  outerBody.push(tryStmt.apply(undefined, ["err", [exprStmt(funcCall(endFuncNode, id("err"), id("undefined")))]].concat(toConsumableArray(innerBody))));

  return isProgram ? program.apply(undefined, outerBody) : block$1.apply(undefined, outerBody);
}

var isProbablySingleExpressionRe = /^\s*(\{|function\s*\()/;

function transformSingleExpression(code) {
  // evaling certain expressions such as single functions or object
  // literals will fail or not work as intended. When the code being
  // evaluated consists just out of a single expression we will wrap it in
  // parens to allow for those cases
  // Example:
  // transformSingleExpression("{foo: 23}") // => "({foo: 23})"

  if (!isProbablySingleExpressionRe.test(code) || code.split("\n").length > 30) return code;

  try {
    var parsed = fuzzyParse(code);
    if (parsed.body.length === 1 && (parsed.body[0].type === 'FunctionDeclaration' || parsed.body[0].type === 'BlockStatement' && parsed.body[0].body[0].type === 'LabeledStatement')) {
      code = '(' + code.replace(/;\s*$/, '') + ')';
    }
  } catch (e) {
    if (typeof $world !== "undefined") $world.logError(e);else console.error("Eval preprocess error: %s", e.stack || e);
  }
  return code;
}



var transform = Object.freeze({
	replaceNode: replaceNode,
	replaceNodes: replaceNodes,
	replace: replace,
	_compareNodesForReplacement: _compareNodesForReplacement,
	oneDeclaratorPerVarDecl: oneDeclaratorPerVarDecl,
	oneDeclaratorForVarsInDestructoring: oneDeclaratorForVarsInDestructoring,
	returnLastStatement: returnLastStatement,
	wrapInFunction: wrapInFunction,
	wrapInStartEndCall: wrapInStartEndCall,
	transformSingleExpression: transformSingleExpression,
	objectSpreadTransform: objectSpreadTransform
});

/*global process, global, exports*/

function getCommentPrecedingNode(parsed, node) {
  var statementPath = statementOf(parsed, node, { asPath: true }),
      blockPath = statementPath.slice(0, -2),
      block = lively_lang.Path(blockPath).get(parsed);

  return !block.comments || !block.comments.length ? null : lively_lang.chain(extractComments(parsed)).reversed().detect(function (ea) {
    return ea.followingNode === node;
  }).value();
}

function extractComments(astOrCode, optCode) {
  var parsed = typeof astOrCode === "string" ? parse(astOrCode, { withComments: true }) : astOrCode,
      code = optCode ? optCode : typeof astOrCode === "string" ? astOrCode : stringify(astOrCode),
      parsedComments = lively_lang.arr.sortBy(commentsWithPathsAndNodes(parsed), function (c) {
    return c.comment.start;
  });

  return parsedComments.map(function (c, i) {

    // 1. a method comment like "x: function() {\n//foo\n ...}"?
    if (isInObjectMethod(c)) {
      return lively_lang.obj.merge([c, c.comment, { type: 'method', comment: c.comment.text }, methodAttributesOf(c)]);
    }

    if (isInComputedMethod(c)) {
      return lively_lang.obj.merge([c, c.comment, { type: 'method', comment: c.comment.text }, computedMethodAttributesOf(c)]);
    }

    // 2. function statement comment like "function foo() {\n//foo\n ...}"?
    if (isInFunctionStatement(c)) {
      return lively_lang.obj.merge([c, c.comment, { type: 'function', comment: c.comment.text }, functionAttributesOf(c)]);
    }

    // 3. assigned method like "foo.bar = function(x) {/*comment*/};"
    if (isInAssignedMethod(c)) {
      return lively_lang.obj.merge([c, c.comment, { type: 'method', comment: c.comment.text }, methodAttributesOfAssignment(c)]);
    }

    // 4. comment preceding another node?
    var followingNode = followingNodeOf(c);
    if (!followingNode) return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, unknownComment(c)]);

    // is there another comment in front of the node>
    var followingComment = parsedComments[i + 1];
    if (followingComment && followingComment.comment.start <= followingNode.start) return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, unknownComment(c)]);

    // 3. an obj var comment like "// foo\nvar obj = {...}"?
    if (isSingleObjVarDeclaration(followingNode)) {
      return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, { type: 'object', comment: c.comment.text }, objAttributesOf(followingNode)]);
    }

    // 4. Is it a simple var declaration like "// foo\nvar obj = 23"?
    if (isSingleVarDeclaration(followingNode)) {
      return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, { type: 'var', comment: c.comment.text }, objAttributesOf(followingNode)]);
    }

    return lively_lang.obj.merge([c, c.comment, { followingNode: followingNode }, unknownComment(c)]);
  });

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  function commentsWithPathsAndNodes(parsed) {
    var comments = [],
        v = new Visitor();
    v.accept = lively_lang.fun.wrap(v.accept, function (proceed, node, state, path) {
      if (node.comments) {
        lively_lang.arr.pushAll(comments, node.comments.map(function (comment) {
          return { path: path, comment: comment, node: node };
        }));
      }
      return proceed(node, state, path);
    });
    v.accept(parsed, comments, []);
    return comments;
  }

  function followingNodeOf(comment) {
    return lively_lang.arr.detect(comment.node.body, function (node) {
      return node.start > comment.comment.end;
    });
  }

  function unknownComment(comment) {
    return { type: "unknown", comment: comment.comment.text };
  }
  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  function isInFunctionStatement(comment) {
    var node = lively_lang.Path(comment.path.slice(0, -1)).get(parsed);
    return node && node.type === "FunctionDeclaration";
  }

  function functionAttributesOf(comment) {
    var funcNode = lively_lang.Path(comment.path.slice(0, -1)).get(parsed),
        name = funcNode.id ? funcNode.id.name : "<error: no name for function>";
    return { name: name, args: lively_lang.arr.pluck(funcNode.params, "name") };
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  function isInObjectMethod(comment) {
    return lively_lang.arr.equals(comment.path.slice(-2), ["value", "body"]); // obj expr
  }

  function isInAssignedMethod(comment) {
    return lively_lang.arr.equals(comment.path.slice(-2), ["right", "body"]); // asignment
  }

  function methodAttributesOf(comment) {
    var methodNode = lively_lang.Path(comment.path.slice(0, -2)).get(parsed),
        name = methodNode.key ? methodNode.key.name : "<error: no name for method>";

    // if it's someting like "var obj = {foo: function() {...}};"
    var p = comment.path.slice(),
        objectName = "<error: no object found for method>";

    while (p.length && lively_lang.arr.last(p) !== 'init') {
      p.pop();
    }if (p.length) {
      objectName = lively_lang.Path(p.slice(0, -1).concat(["id", "name"])).get(parsed);
    }

    // if it's someting like "exports.obj = {foo: function() {...}};"
    if (lively_lang.string.startsWith(objectName, "<error")) {
      p = comment.path.slice();
      while (p.length && lively_lang.arr.last(p) !== 'right') {
        p.pop();
      }if (p.length) {
        var assignNode = lively_lang.Path(p.slice(0, -1).concat(["left"])).get(parsed);
        objectName = code.slice(assignNode.start, assignNode.end);
      }
    }

    // if it's someting like "Object.extend(Foo.prototype, {m: function() {/*some comment*/ return 23; }})"
    if (lively_lang.string.startsWith(objectName, "<error")) {
      p = comment.path.slice();
      var callExpr = lively_lang.Path(p.slice(0, -6)).get(parsed),
          isCall = callExpr && callExpr.type === "CallExpression",
          firstArg = isCall && callExpr.arguments[0];
      if (firstArg) objectName = code.slice(firstArg.start, firstArg.end);
    }

    return {
      name: name,
      args: lively_lang.arr.pluck(methodNode.value.params, "name"),
      objectName: objectName
    };
  }

  function methodAttributesOfAssignment(comment) {

    var node = lively_lang.Path(comment.path.slice(0, -1)).get(parsed);
    if (node.type !== "FunctionExpression" && node.type !== "FunctionDeclaration") return {};

    var statement = statementOf(parsed, node);
    if (statement.type !== "ExpressionStatement" || statement.expression.type !== "AssignmentExpression") return {};

    var objName = code.slice(statement.expression.left.object.start, statement.expression.left.object.end);

    var methodName = code.slice(statement.expression.left.property.start, statement.expression.left.property.end);

    return {
      name: methodName,
      objectName: objName,
      args: lively_lang.arr.pluck(node.params, "name")
    };
  }

  function isInComputedMethod(comment) {
    var path = comment.path.slice(-5);
    lively_lang.arr.removeAt(path, 1);
    return lively_lang.arr.equals(path, ["properties", "value", "callee", "body"]);
  }

  function computedMethodAttributesOf(comment) {
    var name, args, pathToProp;

    pathToProp = comment.path.slice(0, -3);
    var propertyNode = lively_lang.Path(pathToProp).get(parsed);
    if (propertyNode && propertyNode.type === "Property") {
      // if it is a function immediatelly called
      args = lively_lang.arr.pluck(propertyNode.value.callee.params, "name");
      name = propertyNode.key ? propertyNode.key.name : "<error: no name for method>";
    }

    if (!name) {
      // if it is an object member function
      pathToProp = comment.path.slice(0, -2);
      propertyNode = lively_lang.Path(pathToProp).get(parsed);
      if (propertyNode && propertyNode.type === "Property") {
        args = lively_lang.arr.pluck(propertyNode.value.params, "name");
        name = propertyNode.key ? propertyNode.key.name : "<error: no name for method>";
      }
    }

    if (!name) {
      name = "<error: no name for method>";
      args = [];
      pathToProp = comment.path;
    }

    // if it's someting like "var obj = {foo: function() {...}};"
    var p = lively_lang.arr.clone(pathToProp);
    var objectName = "<error: no object found for method>";

    while (p.length && lively_lang.arr.last(p) !== 'init') {
      p.pop();
    }if (p.length) {
      objectName = lively_lang.Path(p.slice(0, -1).concat(["id", "name"])).get(parsed);
    }

    // if it's someting like "exports.obj = {foo: function() {...}};"
    if (lively_lang.string.startsWith(objectName, "<error")) {
      var p = lively_lang.arr.clone(pathToProp);
      while (p.length && lively_lang.arr.last(p) !== 'right') {
        p.pop();
      }if (p.length) {
        var assignNode = lively_lang.Path(p.slice(0, -1).concat(["left"])).get(parsed);
        objectName = code.slice(assignNode.start, assignNode.end);
      }
    }

    // if it's someting like "Object.extend(Foo.prototype, {m: function() {/*some comment*/ return 23; }})"
    if (lively_lang.string.startsWith(objectName, "<error")) {
      var p = lively_lang.arr.clone(pathToProp);
      var callExpr = lively_lang.Path(p.slice(0, -4)).get(parsed),
          isCall = callExpr && callExpr.type === "CallExpression",
          firstArg = isCall && callExpr.arguments[0];
      if (firstArg) objectName = code.slice(firstArg.start, firstArg.end);
    }

    return { name: name, args: args, objectName: objectName };
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  // like "var foo = {/*...*/}" or  "var foo = bar = {/*...*/};"
  function isSingleObjVarDeclaration(node) {
    // should be a var declaration with one declarator with a value
    // being an JS object
    return isSingleVarDeclaration(node) && (node.declarations[0].init.type === "ObjectExpression" || isObjectAssignment(node.declarations[0].init));
  }

  function isSingleVarDeclaration(node) {
    return node && node.type === 'VariableDeclaration' && node.declarations.length === 1;
  }

  function objAttributesOf(node) {
    return { name: node.declarations[0].id.name };
  }

  // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  // like "foo = {/*...*/}"
  function isObjectAssignment(node) {
    if (node.type !== "AssignmentExpression") return false;
    if (node.right.type === "ObjectExpression") return true;
    if (node.right.type === "AssignmentExpression") return isObjectAssignment(node.right);
    return false;
  }
}



var comments = Object.freeze({
	getCommentPrecedingNode: getCommentPrecedingNode,
	extractComments: extractComments
});

/*

types found:

The def data structure:
  {type, name, node, children?, parent?}

class-decl
  class-constructor
  class-instance-method
  class-class-method
  class-instance-getter
  class-instance-setter
  class-class-getter
  class-class-setter

function-decl

var-decl

object-decl
  object-method
  object-property

*/

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// main method
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
function findDecls(parsed, options) {
  // lively.debugNextMethodCall(lively.ast.codeCategorizer, "findDecls")

  options = options || lively_lang.obj.merge({ hideOneLiners: false }, options);

  if (typeof parsed === "string") parsed = parse(parsed, { addSource: true });

  var topLevelNodes = parsed.type === "Program" ? parsed.body : parsed.body.body,
      defs = [],
      hideOneLiners = options.hideOneLiners && parsed.source;

  var _iteratorNormalCompletion = true;
  var _didIteratorError = false;
  var _iteratorError = undefined;

  try {
    for (var _iterator = topLevelNodes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
      var node = _step.value;

      node = unwrapExport(node);
      var found = functionWrapper(node, options) || varDefs(node) || funcDef(node) || es6ClassDef(node) || someObjectExpressionCall(node);

      if (!found) continue;

      if (options.hideOneLiners) {
        if (parsed.loc) {
          found = found.filter(function (def) {
            return !def.node.loc || def.node.loc.start.line !== def.node.loc.end.line;
          });
        } else if (parsed.source) {
          var filtered = [];
          var _iteratorNormalCompletion2 = true;
          var _didIteratorError2 = false;
          var _iteratorError2 = undefined;

          try {
            for (var _iterator2 = found[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
              var def = _step2.value;

              if (def.parent && filtered.includes(def.parent) || // parent is in
              (def.node.source || "").includes("\n") // more than one line
              ) filtered.push(def);
            }
          } catch (err) {
            _didIteratorError2 = true;
            _iteratorError2 = err;
          } finally {
            try {
              if (!_iteratorNormalCompletion2 && _iterator2.return) {
                _iterator2.return();
              }
            } finally {
              if (_didIteratorError2) {
                throw _iteratorError2;
              }
            }
          }

          found = filtered;
        }
      }

      defs.push.apply(defs, toConsumableArray(found));
    }
  } catch (err) {
    _didIteratorError = true;
    _iteratorError = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion && _iterator.return) {
        _iterator.return();
      }
    } finally {
      if (_didIteratorError) {
        throw _iteratorError;
      }
    }
  }

  return defs;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// defs
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-


function es6ClassDef(node) {
  var _def$children;

  if (node.type !== "ClassDeclaration") return null;
  var def = {
    type: "class-decl",
    name: node.id.name,
    node: node,
    children: []
  };
  (_def$children = def.children).push.apply(_def$children, toConsumableArray(node.body.body.map(function (node, i) {
    return es6ClassMethod(node, def, i);
  }).filter(Boolean)));
  return [def].concat(toConsumableArray(def.children));
}

function es6ClassMethod(node, parent, i) {
  if (node.type !== "MethodDefinition") return null;
  var type;
  if (node.kind === "constructor") type = "class-constructor";else if (node.kind === "method") type = node.static ? "class-class-method" : "class-instance-method";else if (node.kind === "get") type = node.static ? "class-class-getter" : "class-instance-getter";else if (node.kind === "set") type = node.static ? "class-class-setter" : "class-instance-setter";
  return type ? {
    type: type, parent: parent, node: node,
    name: node.key.name
  } : null;
}

function varDefs(varDeclNode) {
  if (varDeclNode.type !== "VariableDeclaration") return null;
  var result = [];

  var _iteratorNormalCompletion3 = true;
  var _didIteratorError3 = false;
  var _iteratorError3 = undefined;

  try {
    var _loop = function _loop() {
      var _ref = _step3.value;
      var id = _ref.id,
          node = _ref.node;

      var def = { name: id.name, node: node, type: "var-decl" };
      result.push(def);
      if (!def.node.init) return "continue";

      var initNode = def.node.init;
      while (initNode.type === "AssignmentExpression") {
        initNode = initNode.right;
      }if (initNode.type === "ObjectExpression") {
        def.type = "object-decl";
        def.children = objectKeyValsAsDefs(initNode).map(function (ea) {
          return _extends({}, ea, { type: "object-" + ea.type, parent: def });
        });
        result.push.apply(result, toConsumableArray(def.children));
        return "continue";
      }

      objDefs = someObjectExpressionCall(initNode, def);

      if (objDefs) {
        def.children = objDefs.map(function (d) {
          return _extends({}, d, { parent: def });
        });
        result.push.apply(result, toConsumableArray(def.children));
      }
    };

    for (var _iterator3 = withVarDeclIds(varDeclNode)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
      var objDefs;

      var _ret = _loop();

      if (_ret === "continue") continue;
    }
  } catch (err) {
    _didIteratorError3 = true;
    _iteratorError3 = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion3 && _iterator3.return) {
        _iterator3.return();
      }
    } finally {
      if (_didIteratorError3) {
        throw _iteratorError3;
      }
    }
  }

  return result;
}

function funcDef(node) {
  if (node.type !== "FunctionStatement" && node.type !== "FunctionDeclaration") return null;
  return [{ name: node.id.name, node: node, type: "function-decl" }];
}

function someObjectExpressionCall(node, parentDef) {
  // like Foo({....})
  if (node.type === "ExpressionStatement") node = node.expression;
  if (node.type !== "CallExpression") return null;
  var objArg = node.arguments.find(function (a) {
    return a.type === "ObjectExpression";
  });
  if (!objArg) return null;
  return objectKeyValsAsDefs(objArg, parentDef);
}

function functionWrapper(node, options) {
  if (!isFunctionWrapper(node)) return null;
  var decls;
  // Is it a function wrapper passed as arg?
  // like ;(function(run) {... })(function(exports) {...})
  var argFunc = lively_lang.Path("expression.arguments.0").get(node);
  if (argFunc && argFunc.type === "FunctionExpression" && lively_lang.string.lines(argFunc.source || "").length > 5) {
    // lively.debugNextMethodCall(lively.ast.CodeCategorizer, "findDecls");
    decls = findDecls(argFunc, options);
  } else {
    decls = findDecls(lively_lang.Path("expression.callee").get(node), options);
  }
  var parent = { node: node, name: lively_lang.Path("expression.callee.id.name").get(node) };
  decls.forEach(function (decl) {
    return decl.parent || (decl.parent = parent);
  });
  return decls;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// helpers
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function unwrapExport(node) {
  return (node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration") && node.declaration ? node.declaration : node;
}

function objectKeyValsAsDefs(objectExpression, parent) {
  return objectExpression.properties.map(function (node) {
    return {
      name: node.key.name || node.key.value,
      type: node.value.type === "FunctionExpression" ? "method" : "property",
      node: node, parent: parent
    };
  });
}

function isFunctionWrapper(node) {
  return lively_lang.Path("expression.type").get(node) === "CallExpression" && lively_lang.Path("expression.callee.type").get(node) === "FunctionExpression";
}

function withVarDeclIds(varNode) {
  return varNode.declarations.map(function (declNode) {
    if (!declNode.source && declNode.init) declNode.source = declNode.id.name + " = " + declNode.init.source;
    return { node: declNode, id: declNode.id };
  });
}



var codeCategorizer = Object.freeze({
	findDecls: findDecls
});

// ignore-in-doc
// As defined in the Ecmascript standard (http://www.ecma-international.org/ecma-262/5.1/#sec-7.6)
// JS identifiers can consist out of several unicode character classes.
// The code below was generated using the MIT licensed CSET library, see http://inimino.org/~inimino/blog/javascript_cset
var isValidIdentifierRe = /^(?!(?:do|if|in|for|let|new|try|var|case|default|else|enum|eval|false|null|this|true|void|with|break|catch|class|const|super|throw|while|yield|delete|export|import|public|return|static|switch|typeof|extends|finally|package|private|continue|debugger|function|arguments|interface|protected|implements|instanceof)$)[$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc][$A-Z\_a-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc0-9\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u08fe\u0900-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d02\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19d9\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1dc0-\u1de6\u1dfc-\u1dff\u200c\u200d\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f]*$/;
function isValidIdentifier(string$$1) {
  return isValidIdentifierRe.test(string$$1);
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// serialization extension for ast nodes
var Node = parse("").constructor;
Object.defineProperty(Node.prototype, "__serialize__", {
  configurable: true,
  value: function value() {
    return {
      __expr__: "(" + JSON.stringify(this) + ")"
    };
  }
});

exports.escodegen = es;
exports.acorn = acorn;
exports.query = query;
exports.transform = transform;
exports.comments = comments;
exports.categorizer = codeCategorizer;
exports.stringify = stringify;
exports.nodes = nodes;
exports.isValidIdentifier = isValidIdentifier;
exports.BaseVisitor = Visitor;
exports.withMozillaAstDo = withMozillaAstDo;
exports.printAst = printAst;
exports.compareAst = compareAst;
exports.pathToNode = pathToNode;
exports.rematchAstWithSource = rematchAstWithSource;
exports.ReplaceManyVisitor = ReplaceManyVisitor;
exports.ReplaceVisitor = ReplaceVisitor;
exports.parse = parse;
exports.parseFunction = parseFunction;
exports.fuzzyParse = fuzzyParse;

}((this.lively.ast = this.lively.ast || {}),lively.lang,GLOBAL.escodegen,acorn));

  }).call(GLOBAL);
  if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.ast;
  if (__define_suckz__) { GLOBAL.define = __define_suckz__; }
})();

// INLINED END /Users/user/git/lively.vm/node_modules/lively.ast/dist/lively.ast.js

// INLINED /Users/user/git/lively.vm/node_modules/lively.classes/dist/lively.classes.js

;(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  if (typeof lively.lang === "undefined") GLOBAL.livey.lang = {};
})();
(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  this.lively = this.lively || {};
(function (exports,lively_lang,lively_ast) {
'use strict';

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj$$1) {
  return typeof obj$$1;
} : function (obj$$1) {
  return obj$$1 && typeof Symbol === "function" && obj$$1.constructor === Symbol && obj$$1 !== Symbol.prototype ? "symbol" : typeof obj$$1;
};











var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

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;
  };
}();





var defineProperty = function (obj$$1, key, value) {
  if (key in obj$$1) {
    Object.defineProperty(obj$$1, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj$$1[key] = value;
  }

  return obj$$1;
};

var _extends = Object.assign || function (target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];

    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }

  return target;
};

var get = function get(object, property, receiver) {
  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(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);
  }
};

var inherits = function (subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};











var possibleConstructorReturn = function (self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return call && (typeof call === "object" || typeof call === "function") ? call : self;
};



var set = function set(object, property, value, receiver) {
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent !== null) {
      set(parent, property, value, receiver);
    }
  } else if ("value" in desc && desc.writable) {
    desc.value = value;
  } else {
    var setter = desc.set;

    if (setter !== undefined) {
      setter.call(receiver, value);
    }
  }

  return value;
};

var slicedToArray = function () {
  function sliceIterator(arr, i) {
    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;

    try {
      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);

        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"]) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  return function (arr, i) {
    if (Array.isArray(arr)) {
      return arr;
    } else if (Symbol.iterator in Object(arr)) {
      return sliceIterator(arr, i);
    } else {
      throw new TypeError("Invalid attempt to destructure non-iterable instance");
    }
  };
}();













var toConsumableArray = function (arr) {
  if (Array.isArray(arr)) {
    for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

    return arr2;
  } else {
    return Array.from(arr);
  }
};

// compactness
// types -> fabrik
// serialization, obscure references
// debugging, more usful inspector
// change system -> synchronization, serialization, debugging
// initialization order, dependencies (ex. btn => label => submoprhs needed)
// declaratively configuring objects


// propertySettings: {
//   valueStoreProperty: STRING|SYMBOL - optional, defaults to _state. This is where the
//                                  actual values of the properties will be stored by default
//   defaultGetter: FUNCTION(STRING) - default getter to be used
//   defaultSetter: FUNCTION(STRING, VALUE) - default setter to be used
// }
// 
// ????????????
//   propertyDescriptorCacheKey: STRING|SYMBOL - where the result of
//                                               initializeProperties() should go
// ????????????


// properties:
// {STRING: DESCRIPTOR, ...}
// properties are merged in the proto chain
// 
// descriptor: {
//   get: FUNCTION       - optional
//   set: FUNCTION       - optional
//   defaultValue: OBJECT   - optional
//   initialize: FUNCTION   - optional, function that when present should
//                            produce a value for the property. Run after object creation
//   autoSetter: BOOL       - optional, true if not specified
//   usePropertyStore: BOOL - optional, true if not specified.
//   priority: NUMBER       - optional, true if not specified.
//   before: [STRING]       - optional, list of property names that depend on
//                            the descriptor's property and that should be
//                            initialized / sorted / ... *after*
//                            it. Think of it as a constraint: "this property
//                            needs to run before that property"
//   after: [STRING]        - optional, list of property names that this property depends on
//   internal: BOOL         - optional, if specified marks property as meant for
//                            internal housekeeping. At this point this is only used
//                            documentation and debugging purposes, it won't affect
//                            how the property works
// }


// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var defaultPropertiesKey = "properties";
var propertiesAndSettingsCacheSym = Symbol.for("lively.classes-properties-and-settings");

var defaultPropertySettings = {
  defaultSetter: null,
  defaultGetter: null,
  valueStoreProperty: "_state"
};

function hasManagedProperties(klass) {
  return klass.hasOwnProperty(defaultPropertiesKey);
}

function prepareClassForManagedPropertiesAfterCreation(klass) {
  if (!hasManagedProperties(klass)) return;

  var _propertiesAndSetting = propertiesAndSettingsInHierarchyOf(klass),
      properties = _propertiesAndSetting.properties,
      propertySettings = _propertiesAndSetting.propertySettings;

  klass[propertiesAndSettingsCacheSym] = { properties: properties, propertySettings: propertySettings };
  if (!properties || (typeof properties === "undefined" ? "undefined" : _typeof(properties)) !== "object") {
    console.warn("Class " + klass.name + " indicates it has managed properties but its " + ("properties accessor (" + defaultPropertiesKey + ") does not return ") + "a valid property descriptor map");
    return;
  }
  prepareClassForProperties(klass, propertySettings, properties);
}

function prepareClassForProperties(klass, propertySettings, properties) {
  ensurePropertyInitializer(klass);

  var valueStoreProperty = propertySettings.valueStoreProperty,
      defaultGetter = propertySettings.defaultGetter,
      defaultSetter = propertySettings.defaultSetter,
      myProto = klass.prototype,
      keys = Object.keys(properties);


  keys.forEach(function (key) {
    var descriptor = properties[key];

    // ... define a getter to the property for the outside world...
    var hasGetter = myProto.hasOwnProperty(key) && myProto.__lookupGetter__(key);
    if (!hasGetter) {
      var getter = descriptor.get || typeof defaultGetter === "function" && function () {
        return defaultGetter.call(this, key);
      } || function () {
        return this[valueStoreProperty][key];
      };
      myProto.__defineGetter__(key, getter);
    }

    // ...define a setter if necessary
    var hasSetter = myProto.hasOwnProperty(key) && myProto.__lookupSetter__(key);
    if (!hasSetter) {
      var descrHasSetter = descriptor.hasOwnProperty("set"),
          setterNeeded = descrHasSetter || !descriptor.readOnly;
      if (setterNeeded) {
        var setter = descriptor.set || typeof defaultSetter === "function" && function (val) {
          defaultSetter.call(this, key, val);
        } || function (val) {
          this[valueStoreProperty][key] = val;
        };
        myProto.__defineSetter__(key, setter);
      }
    }
  });
}

function ensurePropertyInitializer(klass) {
  // when we inherit from "conventional classes" those don't have an
  // initializer method. We install a stub that calls the superclass function
  // itself
  Object.defineProperty(klass.prototype, "propertiesAndPropertySettings", {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function value() {
      var klass = this.constructor;
      return klass[propertiesAndSettingsCacheSym] || propertiesAndSettingsInHierarchyOf(klass);
    }
  });
  Object.defineProperty(klass.prototype, "initializeProperties", {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function value(values) {
      var _propertiesAndPropert = this.propertiesAndPropertySettings(),
          properties = _propertiesAndPropert.properties,
          propertySettings = _propertiesAndPropert.propertySettings;

      prepareInstanceForProperties(this, propertySettings, properties, values);
      return this;
    }
  });
}

function propertiesAndSettingsInHierarchyOf(klass) {
  // walks class proto chain
  var propertySettings = _extends({}, defaultPropertySettings),
      properties = {},
      allPropSettings = lively_lang.obj.valuesInPropertyHierarchy(klass, "propertySettings"),
      allProps = lively_lang.obj.valuesInPropertyHierarchy(klass, "properties");

  for (var i = 0; i < allPropSettings.length; i++) {
    var current = allPropSettings[i];
    current && (typeof current === "undefined" ? "undefined" : _typeof(current)) === "object" && Object.assign(propertySettings, current);
  }

  for (var i = 0; i < allProps.length; i++) {
    var _current = allProps[i];
    if ((typeof _current === "undefined" ? "undefined" : _typeof(_current)) !== "object") {
      console.error("[initializeProperties] " + klass + " encountered property declaration " + ("that is not a JS object: " + _current));
      continue;
    }
    // "deep" merge
    for (var name in _current) {
      if (!properties.hasOwnProperty(name)) properties[name] = _current[name];else Object.assign(properties[name], _current[name]);
    }
  }

  return { properties: properties, propertySettings: propertySettings };
}

function prepareInstanceForProperties(instance, propertySettings, properties, values) {
  var valueStoreProperty = propertySettings.valueStoreProperty,
      sortedKeys = lively_lang.obj.sortKeysWithBeforeAndAfterConstraints(properties),
      propsNeedingInitialize = [],
      initActions = {};

  // 1. this[valueStoreProperty] is were the actual values will be stored
  if (!instance.hasOwnProperty(valueStoreProperty)) instance[valueStoreProperty] = {};

  for (var i = 0; i < sortedKeys.length; i++) {
    var key = sortedKeys[i],
        descriptor = properties[key];

    var derived = descriptor.derived,
        foldable = !!descriptor.foldable,
        defaultValue = descriptor.hasOwnProperty("defaultValue") ? descriptor.defaultValue : undefined;
    if (Array.isArray(defaultValue)) defaultValue = defaultValue.slice();
    if (!derived && !foldable) instance[valueStoreProperty][key] = defaultValue;

    var initAction = void 0;
    if (descriptor.hasOwnProperty("initialize")) {
      initAction = initActions[key] = { initialize: defaultValue };
      propsNeedingInitialize.push(key);
    } else if (derived && defaultValue !== undefined) {
      initAction = initActions[key] = { derived: defaultValue };
      propsNeedingInitialize.push(key);
    } else if (foldable && defaultValue !== undefined) {
      initAction = initActions[key] = { folded: defaultValue };
      propsNeedingInitialize.push(key);
    }

    if (values && key in values) {
      if (descriptor.readOnly) {
        console.warn("Trying to initialize read-only property " + key + " in " + instance + ", " + "skipping setting value");
      } else {
        if (!initAction) {
          initAction = initActions[key] = {};
          propsNeedingInitialize.push(key);
        }
        initAction.value = values[key];
      }
    }
  }

  // 2. Run init code for properties
  // and if we have values we will initialize the properties from it. Values
  // is expected to be a JS object mapping property names to property values
  for (var i = 0; i < propsNeedingInitialize.length; i++) {
    var _key = propsNeedingInitialize[i],
        actions = initActions[_key],
        hasValue = actions.hasOwnProperty("value");

    // if we have an initialize function we call it either with the value from
    // values or with the defaultValue
    if (actions.hasOwnProperty("initialize")) {
      var value = hasValue ? actions.value : actions.initialize;
      properties[_key].initialize.call(instance, value);
      if (hasValue) instance[_key] = actions.value;
    }

    // if we have a derived property we will call the setter with the default
    // value or the value from values
    else if (actions.hasOwnProperty("derived")) {
        instance[_key] = hasValue ? actions.value : actions.derived;
      } else if (actions.hasOwnProperty("folded")) {
        instance[_key] = hasValue ? actions.value : actions.folded;
      }

      // if we only have the value from values we simply call the setter with it
      else if (hasValue) {
          instance[_key] = actions.value;
        }
  }
}

var initializeSymbol = Symbol.for("lively-instance-initialize");
var instanceRestorerSymbol = Symbol.for("lively-instance-restorer");
var superclassSymbol = Symbol.for("lively-instance-superclass");
var moduleMetaSymbol = Symbol.for("lively-module-meta");
var objMetaSymbol = Symbol.for("lively-object-meta");
var moduleSubscribeToToplevelChangesSym = Symbol.for("lively-klass-changes-subscriber");

var constructorArgMatcher = /\([^\\)]*\)/;

var defaultPropertyDescriptorForGetterSetter = {
  enumerable: false,
  configurable: true
};

var defaultPropertyDescriptorForValue = {
  enumerable: false,
  configurable: true,
  writable: true
};

var setPrototypeOf = typeof Object.setPrototypeOf === "function" ? function (obj$$1, proto) {
  return Object.setPrototypeOf(obj$$1, proto);
} : function (obj$$1, proto) {
  return obj$$1.__proto__ = proto;
};

function adoptObject(object, newClass) {
  // change the class of object to newClass
  if (newClass === object.constructor) return;
  object.constructor = newClass;
  setPrototypeOf(object, newClass.prototype);
}

function setSuperclass(klass, superclassOrSpec) {
  // define klass.prototype, klass.prototype[constructor], klass[superclassSymbol]
  var superclass = !superclassOrSpec ? Object : typeof superclassOrSpec === "function" ? superclassOrSpec : superclassOrSpec.value ? superclassOrSpec.value : Object;
  var existingSuperclass = klass && klass[superclassSymbol];
  // set the superclass if necessary and set prototype
  if (!existingSuperclass || existingSuperclass !== superclass) {
    ensureInitializeStub(superclass);
    klass[superclassSymbol] = superclass;
    setPrototypeOf(klass.prototype, superclass.prototype);
    if (superclass !== Object) setPrototypeOf(klass, superclass);
  }
  return superclass;
}

function installValueDescriptor(object, klass, descr) {
  descr = Object.assign(descr, defaultPropertyDescriptorForValue);
  descr.value.displayName = descr.key;
  if (descr.needsDeclaringClass) {
    var orig = descr.value.originalFunction || descr.value;
    descr.value = Object.assign(function declaring_class_wrapper() /*args*/{
      return orig.call.apply(orig, [this, klass].concat(Array.prototype.slice.call(arguments)));
    }, {
      originalFunction: orig,
      toString: function toString() {
        return orig.toString();
      },
      displayName: descr.key
    });
  }
  Object.defineProperty(object, descr.key, descr);
}

function installGetterSetterDescriptor(klass, descr) {
  descr = Object.assign(descr, defaultPropertyDescriptorForGetterSetter);
  Object.defineProperty(klass, descr.key, descr);
}

function installMethods(klass, instanceMethods, classMethods) {
  // install methods from two lists (static + instance) of {key, value} or
  // {key, get/set} descriptors

  classMethods && classMethods.forEach(function (ea) {
    ea.value ? installValueDescriptor(klass, klass, ea) : installGetterSetterDescriptor(klass, ea);
  });

  instanceMethods && instanceMethods.forEach(function (ea) {
    ea.value ? installValueDescriptor(klass.prototype, klass, ea) : installGetterSetterDescriptor(klass.prototype, ea);
  });

  // 4. define initializer method, in our class system the constructor is
  // generic and re-directs to the initializer method. This way we can change
  // the constructor without loosing the identity of the class
  if (!klass.prototype[initializeSymbol]) {
    Object.defineProperty(klass.prototype, initializeSymbol, {
      enumerable: false,
      configurable: true,
      writable: true,
      value: function value() {}
    });
    klass.prototype[initializeSymbol].isDefaultInitializer = true;
    klass.prototype[initializeSymbol].displayName = "lively-initialize";
  } else {
    if (Object.getOwnPropertySymbols(klass.prototype).includes(initializeSymbol)) {
      if (klass.prototype[initializeSymbol].isDefaultInitializer) {
        if (klass[superclassSymbol].prototype[initializeSymbol]) {
          delete klass.prototype[initializeSymbol];
        }
      }
    }
  }

  // 5. undefine properties that were removed form class definition
  var instanceMethodsInClass = instanceMethods.map(function (m) {
    return m.key;
  }).concat(["constructor", "arguments", "caller"]),
      instanceAttributes = Object.getOwnPropertyNames(klass.prototype);
  for (var i = 0; i < instanceAttributes.length; i++) {
    var name = instanceAttributes[i];
    if (!instanceMethodsInClass.includes(name)) delete klass.prototype[name];
  }

  var classMethodsInClass = classMethods.map(function (m) {
    return m.key;
  }).concat(["length", "name", "prototype", "arguments", "caller"]),
      classAttributes = Object.getOwnPropertyNames(klass);
  for (var _i = 0; _i < classAttributes.length; _i++) {
    var _name = classAttributes[_i];
    if (!classMethodsInClass.includes(_name)) delete klass[_name];
  }
}

function ensureInitializeStub(superclass) {
  // when we inherit from "conventional classes" those don't have an
  // initializer method. We install a stub that calls the superclass function
  // itself
  if (superclass === Object || superclass.prototype[initializeSymbol]) return;
  Object.defineProperty(superclass.prototype, initializeSymbol, {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function value() /*args*/{
      superclass.apply(this, arguments);
    }
  });
  superclass.prototype[initializeSymbol].displayName = "lively-initialize-stub";
}

function initializeClass(constructorFunc, superclassSpec) {
  var instanceMethods = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  var classMethods = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
  var classHolder = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  var currentModule = arguments[5];
  var sourceLoc = arguments[6];

  // Given a `classHolder` object as "environment", will try to find a "class"
  // (JS constructor function) inside it. If no class is found it will create a
  // new costructor function object and will attach the methods to it. If a class
  // is found it will be modified.
  // This is being used as the compile target for es6 class syntax by the
  // lively.ast capturing / transform logic
  // Example:
  // var Foo = function(superclass) {
  //   function Foo() {}
  //   return initializeClass(Foo, superclass, [{key: "m", value: function m() { return 23 }}])
  // }();
  // new Foo().m() // => 23

  // 1. create a new constructor function if necessary, re-use an exisiting if the
  // classHolder object has it
  var className = constructorFunc.name,
      klass = className && classHolder.hasOwnProperty(className) && classHolder[className],
      existingSuperclass = klass && klass[superclassSymbol];
  if (!klass || typeof klass !== "function" || !existingSuperclass) klass = constructorFunc;

  // 2. set the superclass if necessary and set prototype
  var superclass = setSuperclass(klass, superclassSpec);

  // 3. Install methods
  installMethods(klass, instanceMethods, classMethods);

  klass[objMetaSymbol] = sourceLoc;

  // 4. If we have a `currentModule` instance (from lively.modules/src/module.js)
  // then we also store some meta data about the module. This allows us to
  // (de)serialize class instances in lively.serializer
  if (currentModule) {
    var p = currentModule.package();
    var prevMeta = klass[moduleMetaSymbol];
    var t = Date.now();
    klass[moduleMetaSymbol] = {
      package: p ? { name: p.name, version: p.version } : {},
      pathInPackage: p ? currentModule.pathInPackage() : currentModule.id,
      lastChange: prevMeta && prevMeta.lastChange && t <= prevMeta.lastChange ? prevMeta.lastChange + 1 : t,
      lastSuperclassChange: 0

      // if we have a module, we can listen to toplevel changes of it in case the
      // superclass binding changes. With that we can keep our class up-to-date
      // even if the superclass binding changes. This is especially useful for
      // situations where modules have a circular dependency and classes in modules
      // won't get defined correctly when loaded first. See
      // https://github.com/LivelyKernel/lively.modules/issues/27 for more details
    };if (superclassSpec && superclassSpec.referencedAs) {
      if (klass.hasOwnProperty(moduleSubscribeToToplevelChangesSym)) {
        currentModule.unsubscribeFromToplevelDefinitionChanges(klass[moduleSubscribeToToplevelChangesSym]);
      }
      klass[moduleSubscribeToToplevelChangesSym] = currentModule.subscribeToToplevelDefinitionChanges(function (name, val) {
        if (name !== superclassSpec.referencedAs) return;
        // console.log(`class ${className}: new superclass ${name} ${name !== superclassSpec.referencedAs ? '(' + superclassSpec.referencedAs + ')' : ''} was defined via module bindings`)

        // Only run through the (expensive) updates if superclass really has changes
        var superMeta = val && val[moduleMetaSymbol],
            myMeta = klass[moduleMetaSymbol];
        if (superMeta) {
          if (superMeta.lastChange === myMeta.lastSuperclassChange) return;
          myMeta.lastSuperclassChange = superMeta.lastChange;
        }
        setSuperclass(klass, val);
        installMethods(klass, instanceMethods, classMethods);
        prepareClassForManagedPropertiesAfterCreation(klass);
      });
    }
  }

  // 6. Add a toString method for the class to allows us to see its constructor arguments
  klass.toString = function () {
    var constructorArgs = String(this.prototype[initializeSymbol]).match(constructorArgMatcher),
        className = this.name,
        superclass = this[superclassSymbol];
    return "class " + className + " " + (superclass ? "extends " + superclass.name : "") + " {\n" + ("  constructor" + (constructorArgs ? constructorArgs[0] : "()") + " { /*...*/ }") + "\n}";
  };

  // 7. If the class allows managed properties (auto getters/setters etc., see
  // managed-properties.js) then setup those
  prepareClassForManagedPropertiesAfterCreation(klass);

  return klass;
}

initializeClass._get = function _get(object, property, receiver) {
  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);
  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);
    return parent === null ? undefined : _get(parent, property, receiver);
  }
  if ("value" in desc) return desc.value;
  var getter = desc.get;
  return getter === undefined ? undefined : getter.call(receiver);
};

initializeClass._set = function _set(object, property, value, receiver) {
  var desc = Object.getOwnPropertyDescriptor(object, property);
  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);
    if (parent !== null) _set(parent, property, value, receiver);
  } else if ("value" in desc && desc.writable) desc.value = value;else {
    var setter = desc.set;
    if (setter !== undefined) setter.call(receiver, value);
  }
  return value;
};

var runtime = Object.freeze({
	initializeSymbol: initializeSymbol,
	instanceRestorerSymbol: instanceRestorerSymbol,
	superclassSymbol: superclassSymbol,
	moduleMetaSymbol: moduleMetaSymbol,
	objMetaSymbol: objMetaSymbol,
	moduleSubscribeToToplevelChangesSym: moduleSubscribeToToplevelChangesSym,
	setPrototypeOf: setPrototypeOf,
	adoptObject: adoptObject,
	setSuperclass: setSuperclass,
	initializeClass: initializeClass
});

var assign = lively_ast.nodes.assign;
var member = lively_ast.nodes.member;
var id = lively_ast.nodes.id;
var exprStmt = lively_ast.nodes.exprStmt;
var funcCall = lively_ast.nodes.funcCall;
var literal = lively_ast.nodes.literal;
var objectLiteral = lively_ast.nodes.objectLiteral;
var varDecl = lively_ast.nodes.varDecl;
var funcExpr = lively_ast.nodes.funcExpr;
var returnStmt = lively_ast.nodes.returnStmt;
var binaryExpr = lively_ast.nodes.binaryExpr;
var ifStmt = lively_ast.nodes.ifStmt;
var block = lively_ast.nodes.block;


function isFunctionNode(node) {
  return node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration";
}

var firstIdRe = /^[^_a-z]/i;
var trailingIdRe = /[^_a-z0-9]/ig;
function ensureIdentifier(name) {
  return name.replace(firstIdRe, "_").replace(trailingIdRe, "_");
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function constructorTemplate(name) {
  // Creates a function like
  // function CLASS() {
  //   var firstArg = arguments[0];
  //   if (firstArg && firstArg[Symbol.for("lively-instance-restorer")]) {
  //     // for deserializing instances just do nothing
  //   } else {
  //     // automatically call the initialize method
  //     this[Symbol.for("lively-instance-initialize")].apply(this, arguments);
  //   }
  // }

  return funcExpr({ id: name ? id(name) : null }, ["__first_arg__"], ifStmt(binaryExpr(id("__first_arg__"), "&&", member("__first_arg__", funcCall(member("Symbol", "for"), literal("lively-instance-restorer")), true)), block(), block(exprStmt(funcCall(member(member("this", funcCall(member("Symbol", "for"), literal("lively-instance-initialize")), true), "apply"), id("this"), id("arguments"))))));
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var isTransformedClassVarDeclSymbol = Symbol();
var methodKindSymbol = Symbol();
var tempLivelyClassVar = "__lively_class__";
var tempLivelyClassHolderVar = "__lively_classholder__";

var ClassReplaceVisitor = function (_Visitor) {
  inherits(ClassReplaceVisitor, _Visitor);

  function ClassReplaceVisitor() {
    classCallCheck(this, ClassReplaceVisitor);
    return possibleConstructorReturn(this, (ClassReplaceVisitor.__proto__ || Object.getPrototypeOf(ClassReplaceVisitor)).apply(this, arguments));
  }

  createClass(ClassReplaceVisitor, [{
    key: "accept",
    value: function accept(node, state, path) {
      if (isFunctionNode(node)) {
        state = _extends({}, state, { classHolder: objectLiteral([]),
          currentMethod: node[methodKindSymbol] ? node : state.currentMethod
        });
      }

      if (node.type === "ClassExpression" || node.type === "ClassDeclaration") node = replaceClass(node, state, path, state.options);

      if (node.type === "Super") node = replaceSuper(node, state, path, state.options);

      if (node.type === "MemberExpression" && node.object && node.object.type === "Super") node = replaceSuperGetter(node, state, path, state.options);

      if (node.type === "AssignmentExpression" && node.left.type === "MemberExpression" && node.left.object.type === "Super") node = replaceSuperSetter(node, state, path, state.options);

      if (node.type === "CallExpression" && node.callee.type === "Super") node = replaceDirectSuperCall(node, state, path, state.options);

      if (node.type === "CallExpression" && node.callee.object && node.callee.object.type === "Super") node = replaceSuperMethodCall(node, state, path, state.options);

      node = get(ClassReplaceVisitor.prototype.__proto__ || Object.getPrototypeOf(ClassReplaceVisitor.prototype), "accept", this).call(this, node, state, path);

      if (node.type === "ExportDefaultDeclaration") return splitExportDefaultWithClass(node, state, path, state.options);

      return node;
    }
  }], [{
    key: "run",
    value: function run(parsed, options) {
      var v = new this(),
          classHolder = options.classHolder || objectLiteral([]);
      return v.accept(parsed, { options: options, classHolder: classHolder }, []);
    }
  }]);
  return ClassReplaceVisitor;
}(lively_ast.BaseVisitor);

function replaceSuper(node, state, path, options) {
  // just super
  console.assert(node.type === "Super");

  var currentMethod = state.currentMethod;

  if (!currentMethod) {
    console.warn("[lively.classes] Trying to transform es6 class but got super call outside a method! " + lively_ast.stringify(node) + " in " + path.join("."));
    // return node;
  }

  var _path$slice = path.slice(-2),
      _path$slice2 = slicedToArray(_path$slice, 2),
      parentReferencedAs = _path$slice2[0],
      referencedAs = _path$slice2[1];

  if (parentReferencedAs === 'callee' && referencedAs === 'object' || referencedAs === 'callee') return node; // deal with this in replaceSuperCall

  var methodHolder = currentMethod && currentMethod[methodKindSymbol] === "static" ? funcCall(member("Object", "getPrototypeOf"), id(tempLivelyClassVar)) : funcCall(member("Object", "getPrototypeOf"), member(id(tempLivelyClassVar), "prototype"));

  return methodHolder;
}

// parse("class Foo extends Bar { get x() { return super.x; }}").body[0]

function replaceSuperMethodCall(node, state, path, options) {
  // like super.foo()
  console.assert(node.type === "CallExpression");
  console.assert(node.callee.object.type === "Super");

  return funcCall.apply(undefined, [member(funcCall(member(options.functionNode, "_get"), replaceSuper(node.callee.object, state, path.concat(["callee", "object"]), options), literal(node.callee.property.value || node.callee.property.name), id("this")), "call"), id("this")].concat(toConsumableArray(node.arguments)));
}

function replaceDirectSuperCall(node, state, path, options) {
  // like super()
  console.assert(node.type === "CallExpression");
  console.assert(node.callee.type === "Super");

  return funcCall.apply(undefined, [member(funcCall(member(options.functionNode, "_get"), replaceSuper(node.callee, state, path.concat(["callee"]), options), funcCall(member("Symbol", "for"), literal("lively-instance-initialize")), id("this")), "call"), id("this")].concat(toConsumableArray(node.arguments)));
}

function replaceSuperGetter(node, state, path, options) {
  console.assert(node.type === "MemberExpression");
  console.assert(node.object.type === "Super");
  return funcCall(member(options.functionNode, "_get"), replaceSuper(node.object, state, path.concat(["object"]), options), literal(node.property.value || node.property.name), id("this"));
}

function replaceSuperSetter(node, state, path, options) {
  console.assert(node.type === "AssignmentExpression");
  console.assert(node.left.object.type === "Super");

  return funcCall(member(options.functionNode, "_set"), replaceSuper(node.left.object, state, path.concat(["left", "object"]), options), literal(node.left.property.value || node.left.property.name), node.right, id("this"));
}

function replaceClass(node, state, path, options) {
  console.assert(node.type === "ClassDeclaration" || node.type === "ClassExpression");

  var body = node.body.body,
      superClass = node.superClass,
      classId = node.id,
      type = node.type,
      start = node.start,
      end = node.end,
      instanceProps = id("undefined"),
      classProps = id("undefined"),
      className = classId ? classId.name : "anonymous_class",
      evalId = options.evalId,
      sourceAccessorName = options.sourceAccessorName,
      loc = node["x-lively-object-meta"] || { start: start, end: end };


  if (body.length) {
    var _body$reduce = body.reduce(function (props, propNode) {
      var decl,
          key = propNode.key,
          kind = propNode.kind,
          value = propNode.value,
          classSide = propNode.static;

      if (key.type !== "Literal" && key.type !== "Identifier") {
        console.warn("Unexpected key in classToFunctionTransform! " + JSON.stringify(key));
      }

      if (kind === "method") {
        // The name is just for debugging purposes when it appears in
        // native debuggers. We have to be careful about it b/c it shadows
        // outer functions / vars, something that is totally not apparent for a user
        // of the class syntax. That's the reason for making it a little cryptic
        var methodId = id(className + "_" + ensureIdentifier(key.name || key.value) + "_"),
            _props = ["key", literal(key.name || key.value), "value", _extends({}, value, defineProperty({ id: methodId }, methodKindSymbol, classSide ? "static" : "proto"))];

        decl = objectLiteral(_props);
      } else if (kind === "get" || kind === "set") {
        decl = objectLiteral(["key", literal(key.name || key.value), kind, Object.assign({}, value, defineProperty({ id: id(kind) }, methodKindSymbol, classSide ? "static" : "proto"))]);
      } else if (kind === "constructor") {
        var _props2 = ["key", funcCall(member("Symbol", "for"), literal("lively-instance-initialize")), "value", _extends({}, value, defineProperty({ id: id(className + "_initialize_") }, methodKindSymbol, "proto"))];
        decl = objectLiteral(_props2);
      } else {
        console.warn("[lively.classes] classToFunctionTransform encountered unknown class property with kind " + kind + ", ignoring it, " + JSON.stringify(propNode));
      }
      (classSide ? props.clazz : props.inst).push(decl);
      return props;
    }, { inst: [], clazz: [] }),
        inst = _body$reduce.inst,
        clazz = _body$reduce.clazz;

    if (inst.length) instanceProps = { type: "ArrayExpression", elements: inst };
    if (clazz.length) classProps = { type: "ArrayExpression", elements: clazz };
  }

  var scope = options.scope,
      superClassReferencedAs,
      superClassRef;

  if (superClass && options.currentModuleAccessor) {
    if (options.classHolder === superClass.object) {
      superClassRef = superClass;
      superClassReferencedAs = superClass.property.name;
    } else {
      var found = scope && scope.resolvedRefMap && scope.resolvedRefMap.get(superClass),
          isTopLevel = found && found.decl && scope.decls && scope.decls.find(function (_ref) {
        var _ref2 = slicedToArray(_ref, 1),
            decl = _ref2[0];

        return decl === found.decl;
      });
      if (isTopLevel) {
        superClassRef = superClass;
        superClassReferencedAs = superClass.name;
      }
    }
  }

  var superClassSpec = superClassRef ? objectLiteral(["referencedAs", literal(superClassReferencedAs), "value", superClassRef]) : superClass || id("undefined");

  // For persistent storage and retrieval of pre-existing classes in "classHolder" object
  var useClassHolder = classId && type === "ClassDeclaration";

  var locKeyVals = ["start", literal(loc.start), "end", literal(loc.end)];
  if (typeof evalId !== "undefined") locKeyVals.push("evalId", literal(evalId));
  if (sourceAccessorName) locKeyVals.push("moduleSource", lively_ast.nodes.id(sourceAccessorName));
  var locNode = objectLiteral(locKeyVals);

  var classCreator = funcCall(funcExpr({}, ["superclass"], varDecl(tempLivelyClassHolderVar, state.classHolder), varDecl(tempLivelyClassVar, useClassHolder ? {
    type: "ConditionalExpression",
    test: binaryExpr(funcCall(member(tempLivelyClassHolderVar, "hasOwnProperty"), literal(classId.name)), "&&", binaryExpr({
      argument: member(tempLivelyClassHolderVar, classId),
      operator: "typeof", prefix: true, type: "UnaryExpression"
    }, "===", literal("function"))),
    consequent: member(tempLivelyClassHolderVar, classId),
    alternate: assign(member(tempLivelyClassHolderVar, classId), constructorTemplate(classId.name))
  } : classId ? constructorTemplate(classId.name) : constructorTemplate(null)), returnStmt(funcCall(options.functionNode, id(tempLivelyClassVar), id("superclass"), instanceProps, classProps, id(tempLivelyClassHolderVar), options.currentModuleAccessor || id("undefined"), locNode))), superClassSpec);

  if (type === "ClassExpression") return classCreator;

  var result = classCreator;

  if (options.declarationWrapper && state.classHolder === options.classHolder /*i.e. toplevel*/) result = funcCall(options.declarationWrapper, literal(classId.name), literal("class"), result, options.classHolder, locNode);

  // since it is a declaration and we removed the class construct we need to add a var-decl
  result = varDecl(classId, result, "var");
  result[isTransformedClassVarDeclSymbol] = true;

  return result;
}

function splitExportDefaultWithClass(node, classHolder, path, options) {
  return !node.declaration || !node.declaration[isTransformedClassVarDeclSymbol] ? node : [node.declaration, {
    declaration: node.declaration.declarations[0].id,
    type: "ExportDefaultDeclaration"
  }];
}

// var opts = {classHolder: {type: "Identifier", name: "_rec"}, functionNode: {type: "Identifier", name: "createOrExtendClass"}};
// stringify(classToFunctionTransform(parse("class Foo extends Bar {m() { super.m(); }}"), opts))
// stringify(classToFunctionTransform(parse("class Foo extends Bar {m() { super.m(arguments[1]); }}"), opts))
// stringify(classToFunctionTransform(parse("class Foo {constructor() {}}"), opts))

function classToFunctionTransform(sourceOrAst, options) {
  // required: options = {functionNode, classHolder}
  // From
  //   class Foo extends SuperFoo { m() { return 2 + super.m() }}
  // produces something like
  //   createOrExtend({}, {referencedAs: "SuperFoo", value: SuperFoo}, "Foo2", [{
  //     key: "m",
  //     value: function m() {
  //       return 2 + this.constructor[superclassSymbol].prototype.m.call(this);
  //     }
  //   }])

  // console.log(typeof sourceOrAst === "string" ? sourceOrAst : stringify(sourceOrAst))

  var parsed = typeof sourceOrAst === "string" ? lively_ast.parse(sourceOrAst) : sourceOrAst;
  options.scope = lively_ast.query.resolveReferences(lively_ast.query.scopes(parsed));

  var replaced = ClassReplaceVisitor.run(parsed, options);

  return replaced;
}

exports.runtime = runtime;
exports.classToFunctionTransform = classToFunctionTransform;

}((this.lively.classes = this.lively.classes || {}),lively.lang,lively.ast));

  if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.classes;
})();
// INLINED END /Users/user/git/lively.vm/node_modules/lively.classes/dist/lively.classes.js

// INLINED /Users/user/git/lively.vm/node_modules/lively.source-transform/dist/lively.source-transform.js

;(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  if (typeof lively.lang === "undefined") GLOBAL.livey.lang = {};
})();
(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  this.lively = this.lively || {};
(function (exports,lively_lang,lively_classes,lively_ast) {
'use strict';

var _extends = Object.assign || function (target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];

    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }

  return target;
};

var get = function get(object, property, receiver) {
  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(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);
  }
};

















var set = function set(object, property, value, receiver) {
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent !== null) {
      set(parent, property, value, receiver);
    }
  } else if ("value" in desc && desc.writable) {
    desc.value = value;
  } else {
    var setter = desc.set;

    if (setter !== undefined) {
      setter.call(receiver, value);
    }
  }

  return value;
};















var toConsumableArray = function (arr$$1) {
  if (Array.isArray(arr$$1)) {
    for (var i = 0, arr2 = Array(arr$$1.length); i < arr$$1.length; i++) arr2[i] = arr$$1[i];

    return arr2;
  } else {
    return Array.from(arr$$1);
  }
};

var member = lively_ast.nodes.member;
var prop = lively_ast.nodes.prop;
var varDecl = lively_ast.nodes.varDecl;
var assign = lively_ast.nodes.assign;
var id = lively_ast.nodes.id;
var literal = lively_ast.nodes.literal;
var exprStmt = lively_ast.nodes.exprStmt;
var conditional = lively_ast.nodes.conditional;
var binaryExpr = lively_ast.nodes.binaryExpr;
var funcCall = lively_ast.nodes.funcCall;
var topLevelDeclsAndRefs = lively_ast.query.topLevelDeclsAndRefs;
var queryHelpers = lively_ast.query.helpers;
function rewriteToCaptureTopLevelVariables(parsed, assignToObj, options) {
  /* replaces var and function declarations with assignment statements.
   * Example:
     stringify(
       rewriteToCaptureTopLevelVariables2(
         parse("var x = 3, y = 2, z = 4"),
         {name: "A", type: "Identifier"}, ['z']));
     // => "A.x = 3; A.y = 2; z = 4"
   */

  if (!assignToObj) assignToObj = { type: "Identifier", name: "__rec" };

  options = _extends({
    ignoreUndeclaredExcept: null,
    includeRefs: null,
    excludeRefs: options && options.exclude || [],
    includeDecls: null,
    excludeDecls: options && options.exclude || [],
    recordDefRanges: false,
    es6ExportFuncId: null,
    es6ImportFuncId: null,
    captureObj: assignToObj,
    moduleExportFunc: { name: options && options.es6ExportFuncId || "_moduleExport", type: "Identifier" },
    moduleImportFunc: { name: options && options.es6ImportFuncId || "_moduleImport", type: "Identifier" },
    declarationWrapper: undefined,
    classToFunction: options && options.hasOwnProperty("classToFunction") ? options.classToFunction : {
      classHolder: assignToObj,
      functionNode: { type: "Identifier", name: "_createOrExtendClass" },
      declarationWrapper: options && options.declarationWrapper,
      evalId: options && options.evalId,
      sourceAccessorName: options && options.sourceAccessorName
    }
  }, options);

  var rewritten = parsed;

  // "ignoreUndeclaredExcept" is null if we want to capture all globals in the toplevel scope
  // if it is a list of names we will capture all refs with those names
  if (options.ignoreUndeclaredExcept) {
    var topLevel = topLevelDeclsAndRefs(parsed);
    options.excludeRefs = lively_lang.arr.withoutAll(topLevel.undeclaredNames, options.ignoreUndeclaredExcept).concat(options.excludeRefs);
    options.excludeDecls = lively_lang.arr.withoutAll(topLevel.undeclaredNames, options.ignoreUndeclaredExcept).concat(options.excludeDecls);
  }

  options.excludeRefs = options.excludeRefs.concat(options.captureObj.name);
  options.excludeDecls = options.excludeDecls.concat(options.captureObj.name);

  // 1. def ranges so that we know at which source code positions the
  // definitions are
  var defRanges = options.recordDefRanges ? computeDefRanges(rewritten, options) : null;

  // 2. find those var declarations that should not be rewritten. we
  // currently ignore var declarations in for loops and the error parameter
  // declaration in catch clauses. Also es6 import / export declaration need
  // a special treatment
  // DO NOT rewrite exports like "export { foo as bar }" => "export { _rec.foo as bar }"
  // as this is not valid syntax. Instead we add a var declaration using the
  // recorder as init for those exports later
  options.excludeRefs = options.excludeRefs.concat(additionalIgnoredRefs(parsed, options));
  options.excludeDecls = options.excludeDecls.concat(additionalIgnoredDecls(parsed, options));

  rewritten = fixDefaultAsyncFunctionExportForRegeneratorBug(rewritten, options);

  // 3. if the es6ExportFuncId options is defined we rewrite the es6 form into an
  // obj assignment, converting es6 code to es5 using the extra
  // options.moduleExportFunc and options.moduleImportFunc as capture / sources
  if (options.es6ExportFuncId) {
    options.excludeRefs.push(options.es6ExportFuncId);
    options.excludeRefs.push(options.es6ImportFuncId);
    rewritten = es6ModuleTransforms(rewritten, options);
  }

  // 4. make all references declared in the toplevel scope into property
  // reads of captureObj
  // Example "var foo = 3; 99 + foo;" -> "var foo = 3; 99 + Global.foo;"
  rewritten = replaceRefs(rewritten, options);

  // 5.a turn var declarations into assignments to captureObj
  // Example: "var foo = 3; 99 + foo;" -> "Global.foo = 3; 99 + foo;"
  // if declarationWrapper is requested:
  //   "var foo = 3;" -> "Global.foo = _define(3, 'foo', _rec, 'var');"
  rewritten = replaceVarDecls(rewritten, options);

  // 5.b record class declarations
  // Example: "class Foo {}" -> "class Foo {}; Global.Foo = Foo;"
  // if declarationWrapper is requested:
  //   "class Foo {}" -> "Global.Foo = _define(class Foo {});"
  rewritten = replaceClassDecls(rewritten, options);

  rewritten = splitExportDeclarations(rewritten, options);

  // 6. es6 export declaration are left untouched but a capturing assignment
  // is added after the export so that we get the value:
  // "export var x = 23;" => "export var x = 23; Global.x = x;"
  rewritten = insertCapturesForExportDeclarations(rewritten, options);

  // 7. es6 import declaration are left untouched but a capturing assignment
  // is added after the import so that we get the value:
  // "import x from './some-es6-module.js';" =>
  //   "import x from './some-es6-module.js';\n_rec.x = x;"
  rewritten = insertCapturesForImportDeclarations(rewritten, options);

  // 8. Since variable declarations like "var x = 23" were transformed to sth
  // like "_rex.x = 23" exports can't simply reference vars anymore and
  // "export { _rec.x }" is invalid syntax. So in front of those exports we add
  // var decls manually
  rewritten = insertDeclarationsForExports(rewritten, options);

  // 9. assignments for function declarations in the top level scope are
  // put in front of everything else to mirror the func hoisting:
  // "return bar(); function bar() { return 23 }" ->
  //   "Global.bar = bar; return bar(); function bar() { return 23 }"
  // if declarationWrapper is requested:
  //   "Global.bar = _define(bar, 'bar', _rec, 'function'); function bar() {}"
  rewritten = putFunctionDeclsInFront(rewritten, options);

  return rewritten;
}

function rewriteToRegisterModuleToCaptureSetters(parsed, assignToObj, options) {
  // for rewriting the setters part in code like
  // ```js
  //   System.register(["a.js"], function (_export, _context) {
  //     var a, _rec;
  //     return {
  //       setters: [function(foo_a_js) { a = foo_a_js.x }],
  //       execute: function () { _rec.x = 23 + _rec.a; }
  //     };
  //   });
  // ```
  // This allows us to capture (and potentially re-export) imports and their
  // changes without actively running the module again.

  options = _extends({
    captureObj: assignToObj || { type: "Identifier", name: "__rec" },
    exclude: [],
    declarationWrapper: undefined
  }, options);

  var registerCall = lively_lang.Path("body.0.expression").get(parsed);
  if (registerCall.callee.object.name !== "System") throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call: " + lively_ast.stringify(parsed).slice(0, 300) + "...");
  if (registerCall.callee.property.name !== "register") throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call: " + lively_ast.stringify(parsed).slice(0, 300) + "...");
  var registerBody = lively_lang.Path("arguments.1.body.body").get(registerCall),
      registerReturn = lively_lang.arr.last(registerBody);
  if (registerReturn.type !== "ReturnStatement") throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call, at return statement: " + lively_ast.stringify(parsed).slice(0, 300) + "...");
  var setters = registerReturn.argument.properties.find(function (prop) {
    return prop.key.name === "setters";
  });
  if (!setters) throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call, at finding setters: " + lively_ast.stringify(parsed).slice(0, 300) + "...");
  var execute = registerReturn.argument.properties.find(function (prop) {
    return prop.key.name === "execute";
  });
  if (!execute) throw new Error("rewriteToRegisterModuleToCaptureSetters: input doesn't seem to be a System.register call, at finding execute: " + lively_ast.stringify(parsed).slice(0, 300) + "...");

  // in each setter function: intercept the assignments to local vars and inject capture object
  setters.value.elements.forEach(function (funcExpr) {
    return funcExpr.body.body = funcExpr.body.body.map(function (stmt) {
      if (stmt.type !== "ExpressionStatement" || stmt.expression.type !== "AssignmentExpression" || stmt.expression.left.type !== "Identifier" || lively_lang.arr.include(options.exclude, stmt.expression.left.name)) return stmt;

      var id = stmt.expression.left,
          rhs = options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, null, literal(id.name), literal("var"), stmt.expression, options.captureObj, options) : stmt.expression;
      return exprStmt(assign(member(options.captureObj, id), rhs));
    });
  });

  var captureInitialize = execute.value.body.body.find(function (stmt) {
    return stmt.type === "ExpressionStatement" && stmt.expression.type == "AssignmentExpression" && stmt.expression.left.name === options.captureObj.name;
  });
  if (!captureInitialize) captureInitialize = execute.value.body.body.find(function (stmt) {
    return stmt.type === "VariableDeclaration" && stmt.declarations[0].id && stmt.declarations[0].id.name === options.captureObj.name;
  });
  if (captureInitialize) {
    lively_lang.arr.remove(execute.value.body.body, captureInitialize);
    lively_lang.arr.pushAt(registerBody, captureInitialize, registerBody.length - 1);
  }

  if (options.sourceAccessorName) {
    var origSourceInitialize = execute.value.body.body.find(function (stmt) {
      return stmt.type === "ExpressionStatement" && stmt.expression.type == "AssignmentExpression" && stmt.expression.left.name === options.sourceAccessorName;
    });
    if (!origSourceInitialize) origSourceInitialize = execute.value.body.body.find(function (stmt) {
      return stmt.type === "VariableDeclaration" && stmt.declarations[0].id && stmt.declarations[0].id.name === options.sourceAccessorName;
    });
    if (origSourceInitialize) {
      lively_lang.arr.remove(execute.value.body.body, origSourceInitialize);
      lively_lang.arr.pushAt(registerBody, origSourceInitialize, registerBody.length - 1);
    }
  }

  return parsed;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// replacement helpers

function replaceRefs(parsed, options) {
  var topLevel = topLevelDeclsAndRefs(parsed),
      refsToReplace = topLevel.refs.filter(function (ref) {
    return shouldRefBeCaptured(ref, topLevel, options);
  }),
      locallyIgnored = [];

  var replaced = lively_ast.ReplaceVisitor.run(parsed, function (node, path) {

    // cs 2016/06/27, 1a4661
    // ensure keys of shorthand properties are not renamed while capturing
    if (node.type === "Property" && refsToReplace.includes(node.key) && node.shorthand) return prop(id(node.key.name), node.value);

    // don't replace var refs in expressions such as "export { x }" or "export var x;"
    // We make sure that those var references are defined in insertDeclarationsForExports()
    if (node.type === "ExportNamedDeclaration") {
      var declaration = node.declaration,
          specifiers = node.specifiers;

      if (declaration) {
        if (declaration.id) locallyIgnored.push(declaration.id);else if (declaration.declarations) locallyIgnored.push.apply(locallyIgnored, toConsumableArray(declaration.declarations.map(function (_ref) {
          var id = _ref.id;
          return id;
        })));
      }
      specifiers && specifiers.forEach(function (_ref2) {
        var local = _ref2.local;
        return locallyIgnored.push(local);
      });
      return node;
    }

    // declaration wrapper function for assignments
    // "a = 3" => "a = _define('a', 'assignment', 3, _rec)"
    if (node.type === "AssignmentExpression" && refsToReplace.includes(node.left) && options.declarationWrapper) return _extends({}, node, {
      right: declarationWrapperCall(options.declarationWrapper, null, literal(node.left.name), literal("assignment"), node.right, options.captureObj, options) });

    return node;
  });

  return lively_ast.ReplaceVisitor.run(replaced, function (node, path, parent) {
    return refsToReplace.includes(node) && !locallyIgnored.includes(node) ? member(options.captureObj, node) : node;
  });
}

function replaceVarDecls(parsed, options) {
  // rewrites var declarations so that they can be captured by
  // `options.captureObj`.
  // For normal vars we will do a transform like
  //   "var x = 23;" => "_rec.x = 23";
  // For patterns (destructuring assignments) we will create assignments for
  // all properties that are being destructured, creating helper vars as needed
  //   "var {x: [y]} = foo" => "var _1 = foo; var _1$x = _1.x; __rec.y = _1$x[0];"

  var topLevel = topLevelDeclsAndRefs(parsed);
  return lively_ast.ReplaceManyVisitor.run(parsed, function (node) {
    if (!topLevel.varDecls.includes(node) || node.declarations.every(function (decl) {
      return !shouldDeclBeCaptured(decl, options);
    })) return node;

    var replaced = [];
    for (var i = 0; i < node.declarations.length; i++) {
      var decl = node.declarations[i];

      if (!shouldDeclBeCaptured(decl, options)) {
        replaced.push({ type: "VariableDeclaration", kind: node.kind || "var", declarations: [decl] });
        continue;
      }

      var init = decl.init || {
        operator: "||",
        type: "LogicalExpression",
        left: { computed: false, object: options.captureObj, property: decl.id, type: "MemberExpression" },
        right: { name: "undefined", type: "Identifier" }
      };

      var initWrapped = options.declarationWrapper && decl.id.name ? declarationWrapperCall(options.declarationWrapper, decl, literal(decl.id.name), literal(node.kind), init, options.captureObj, options) : init;

      // Here we create the object pattern / destructuring replacements
      if (decl.id.type.includes("Pattern")) {
        var declRootName = generateUniqueName(topLevel.declaredNames, "destructured_1"),
            declRoot = { type: "Identifier", name: declRootName },
            state = { parent: declRoot, declaredNames: topLevel.declaredNames },
            extractions = transformPattern(decl.id, state).map(function (decl) {
          return decl[annotationSym] && decl[annotationSym].capture ? assignExpr(options.captureObj, decl.declarations[0].id, options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, null, literal(decl.declarations[0].id.name), literal(node.kind), decl.declarations[0].init, options.captureObj, options) : decl.declarations[0].init, false) : decl;
        });
        topLevel.declaredNames.push(declRootName);
        replaced.push.apply(replaced, toConsumableArray([varDecl(declRoot, initWrapped, node.kind)].concat(extractions)));
        continue;
      }

      // This is rewriting normal vars
      replaced.push(assignExpr(options.captureObj, decl.id, initWrapped, false));
    }

    return replaced;
  });
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// naming
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function generateUniqueName(declaredNames, hint) {
  var unique = hint,
      n = 1;
  while (declaredNames.indexOf(unique) > -1) {
    if (n > 1000) throw new Error("Endless loop searching for unique variable " + unique);
    unique = unique.replace(/_[0-9]+$|$/, "_" + ++n);
  }
  return unique;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// exclude / include helpers
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function additionalIgnoredDecls(parsed, options) {
  var topLevel = topLevelDeclsAndRefs(parsed),
      ignoreDecls = [];
  for (var i = 0; i < topLevel.scope.varDecls.length; i++) {
    var decl = topLevel.scope.varDecls[i],
        path = lively_lang.Path(topLevel.scope.varDeclPaths[i]),
        parent = path.slice(0, -1).get(parsed);
    if (parent.type === "ForStatement" || parent.type === "ForInStatement" || parent.type === "ForOfStatement" || parent.type === "ExportNamedDeclaration") ignoreDecls.push.apply(ignoreDecls, toConsumableArray(decl.declarations));
  }

  return topLevel.scope.catches.map(function (ea) {
    return ea.name;
  }).concat(ignoreDecls.map(function (ea) {
    return ea.id.name;
  }));
}

function additionalIgnoredRefs(parsed, options) {
  // FIXME rk 2016-05-11: in shouldRefBeCaptured we now also test for import
  // decls, this should somehow be consolidated with this function and with the
  // fact that naming based ignores aren't good enough...
  var topLevel = topLevelDeclsAndRefs(parsed);

  var ignoreDecls = [];
  for (var i = 0; i < topLevel.scope.varDecls.length; i++) {
    var decl = topLevel.scope.varDecls[i],
        path = lively_lang.Path(topLevel.scope.varDeclPaths[i]),
        parent = path.slice(0, -1).get(parsed);
    if (parent.type === "ForStatement" || parent.type === "ForInStatement" || parent.type === "ForOfStatement") ignoreDecls.push.apply(ignoreDecls, toConsumableArray(decl.declarations));
  }

  return topLevel.scope.catches.map(function (ea) {
    return ea.name;
  }).concat(queryHelpers.declIds(ignoreDecls.map(function (ea) {
    return ea.id;
  })).map(function (ea) {
    return ea.name;
  }));
}

function shouldDeclBeCaptured(decl, options) {
  return options.excludeDecls.indexOf(decl.id.name) === -1 && (!options.includeDecls || options.includeDecls.indexOf(decl.id.name) > -1);
}

function shouldRefBeCaptured(ref, toplevel, options) {
  if (toplevel.scope.importSpecifiers.includes(ref)) return false;
  for (var i = 0; i < toplevel.scope.exportDecls.length; i++) {
    var ea = toplevel.scope.exportDecls[i];
    if (ea.declarations && ea.declarations.includes(ref)) return false;
    if (ea.declaration === ref) return false;
  }
  if (options.excludeRefs.includes(ref.name)) return false;
  if (options.includeRefs && !options.includeRefs.includes(ref.name)) return false;
  return true;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// capturing specific code
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function replaceClassDecls(parsed, options) {

  if (options.classToFunction) return lively_classes.classToFunctionTransform(parsed, options.classToFunction);

  var topLevel = topLevelDeclsAndRefs(parsed);
  if (!topLevel.classDecls.length) return parsed;

  for (var i = parsed.body.length - 1; i >= 0; i--) {
    var stmt = parsed.body[i];
    if (topLevel.classDecls.includes(stmt)) parsed.body.splice(i + 1, 0, assignExpr(options.captureObj, stmt.id, stmt.id, false));
  }
  return parsed;
}

function splitExportDeclarations(parsed, options) {
  var stmts = parsed.body,
      newNodes = parsed.body = [];
  for (var i = 0; i < stmts.length; i++) {
    var stmt = stmts[i];
    if (stmt.type !== "ExportNamedDeclaration" || !stmt.declaration || stmt.declaration.type !== "VariableDeclaration" || stmt.declaration.declarations.length <= 1) {
      newNodes.push(stmt);continue;
    }

    var decls = stmt.declaration.declarations;
    for (var j = 0; j < decls.length; j++) {
      newNodes.push({
        type: "ExportNamedDeclaration",
        specifiers: [],
        declaration: varDecl(decls[j].id, decls[j].init, stmt.declaration.kind)
      });
    }
  }
  return parsed;
}

function insertCapturesForExportDeclarations(parsed, options) {
  var body = [];
  for (var i = 0; i < parsed.body.length; i++) {
    var stmt = parsed.body[i];
    body.push(stmt);
    // ExportNamedDeclaration can have specifieres = refs, those should already
    // be captured. Only focus on export declarations and only those
    // declarations that are no refs, i.e.
    // ignore: "export default x;"
    // capture: "export default function foo () {};", "export var x = 23, y = 3;"
    if (stmt.type !== "ExportNamedDeclaration" && stmt.type !== "ExportDefaultDeclaration" || !stmt.declaration) {
      /*...*/

    } else if (stmt.declaration.declarations) {
      body.push.apply(body, toConsumableArray(stmt.declaration.declarations.map(function (decl) {
        var assignVal = decl.id;
        if (options.declarationWrapper) {
          var alreadyWrapped = decl.init.callee && decl.init.callee.name === options.declarationWrapper.name;
          if (!alreadyWrapped) assignVal = declarationWrapperCall(options.declarationWrapper, decl, literal(decl.id.name), literal("assignment"), decl.id, options.captureObj, options);
        }
        return assignExpr(options.captureObj, decl.id, assignVal, false);
      })));
    } else if (stmt.declaration.type === "FunctionDeclaration") {
      /*handled by function rewriter as last step*/

    } else if (stmt.declaration.type === "ClassDeclaration") {
      body.push(assignExpr(options.captureObj, stmt.declaration.id, stmt.declaration.id, false));
    }
  }
  parsed.body = body;
  return parsed;
}

function insertCapturesForImportDeclarations(parsed, options) {
  parsed.body = parsed.body.reduce(function (stmts, stmt) {
    return stmts.concat(stmt.type !== "ImportDeclaration" || !stmt.specifiers.length ? [stmt] : [stmt].concat(stmt.specifiers.map(function (specifier) {
      return assignExpr(options.captureObj, specifier.local, specifier.local, false);
    })));
  }, []);
  return parsed;
}

function insertDeclarationsForExports(parsed, options) {
  var topLevel = topLevelDeclsAndRefs(parsed),
      body = [];
  for (var i = 0; i < parsed.body.length; i++) {
    var stmt = parsed.body[i];
    if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration && stmt.declaration.type.indexOf("Declaration") === -1) {
      body = body.concat([varDeclOrAssignment(parsed, {
        type: "VariableDeclarator",
        id: stmt.declaration,
        init: member(options.captureObj, stmt.declaration)
      }), stmt]);
    } else if (stmt.type !== "ExportNamedDeclaration" || !stmt.specifiers.length || stmt.source) {
      body.push(stmt);
    } else {
      body = body.concat(stmt.specifiers.map(function (specifier) {
        return lively_lang.arr.include(topLevel.declaredNames, specifier.local.name) ? null : varDeclOrAssignment(parsed, {
          type: "VariableDeclarator",
          id: specifier.local,
          init: member(options.captureObj, specifier.local)
        });
      }).filter(Boolean)).concat(stmt);
    }
  }

  parsed.body = body;
  return parsed;
}

function fixDefaultAsyncFunctionExportForRegeneratorBug(parsed, options) {
  // rk 2016-06-02: see https://github.com/LivelyKernel/lively.modules/issues/9
  // FIXME this needs to be removed as soon as the cause for the issue is fixed
  var body = [];
  for (var i = 0; i < parsed.body.length; i++) {
    var stmt = parsed.body[i];
    if (stmt.type === "ExportDefaultDeclaration" && stmt.declaration.type === "FunctionDeclaration" && stmt.declaration.id && stmt.declaration.async) {
      body.push(stmt.declaration);
      stmt.declaration = { type: "Identifier", name: stmt.declaration.id.name };
    }
    body.push(stmt);
  }
  parsed.body = body;
  return parsed;
}

function es6ModuleTransforms(parsed, options) {
  parsed.body = parsed.body.reduce(function (stmts, stmt) {
    var nodes$$1;
    if (stmt.type === "ExportNamedDeclaration") {

      if (stmt.source) {
        var key = moduleId = stmt.source;
        nodes$$1 = stmt.specifiers.map(function (specifier) {
          return {
            type: "ExpressionStatement",
            expression: exportFromImport({ type: "Literal", value: specifier.exported.name }, { type: "Literal", value: specifier.local.name }, moduleId, options.moduleExportFunc, options.moduleImportFunc) };
        });
      } else if (stmt.declaration) {
        var decls = stmt.declaration.declarations;
        if (!decls) {
          // func decl or class
          nodes$$1 = [stmt.declaration].concat(exportCallStmt(options.moduleExportFunc, stmt.declaration.id.name, stmt.declaration.id));
        } else {
          nodes$$1 = decls.map(function (decl) {
            options.excludeDecls.push(decl.id);
            return varDecl(decl.id, assignExpr(options.captureObj, decl.id, options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, null, literal(decl.id.name), literal(stmt.declaration.kind), decl, options.captureObj, options) : decl.init, false), stmt.declaration.kind);
          }).concat(decls.map(function (decl) {
            return exportCallStmt(options.moduleExportFunc, decl.id.name, decl.id);
          }));
        }
      } else {
        nodes$$1 = stmt.specifiers.map(function (specifier) {
          return exportCallStmt(options.moduleExportFunc, specifier.exported.name, shouldDeclBeCaptured({ id: specifier.local }, options) ? member(options.captureObj, specifier.local) : specifier.local);
        });
      }
    } else if (stmt.type === "ExportDefaultDeclaration") {
      if (stmt.declaration && stmt.declaration.id) {
        nodes$$1 = [stmt.declaration].concat(exportCallStmt(options.moduleExportFunc, "default", stmt.declaration.id));
      } else {
        nodes$$1 = [exportCallStmt(options.moduleExportFunc, "default", stmt.declaration)];
      }
    } else if (stmt.type === "ExportAllDeclaration") {
      var key = { name: options.es6ExportFuncId + "__iterator__", type: "Identifier" },
          moduleId = stmt.source;
      nodes$$1 = [{
        type: "ForInStatement",
        body: { type: "ExpressionStatement", expression: exportFromImport(key, key, moduleId, options.moduleExportFunc, options.moduleImportFunc) },
        left: { type: "VariableDeclaration", kind: "var", declarations: [{ type: "VariableDeclarator", id: key, init: null }] },
        right: importCall(null, moduleId, options.moduleImportFunc)
      }];
      options.excludeRefs.push(key.name);
      options.excludeDecls.push(key.name);
    } else if (stmt.type === "ImportDeclaration") {
      nodes$$1 = stmt.specifiers.length ? stmt.specifiers.map(function (specifier) {
        var local = specifier.local,
            imported = specifier.type === "ImportSpecifier" && specifier.imported.name || specifier.type === "ImportDefaultSpecifier" && "default" || null;
        return varDeclAndImportCall(parsed, local, imported || null, stmt.source, options.moduleImportFunc);
      }) : importCallStmt(null, stmt.source, options.moduleImportFunc);
    } else nodes$$1 = [stmt];
    return stmts.concat(nodes$$1);
  }, []);

  return parsed;
}

function putFunctionDeclsInFront(parsed, options) {
  var scope = topLevelDeclsAndRefs(parsed).scope,
      funcDecls = scope.funcDecls;
  if (!funcDecls.length) return parsed;

  var putInFront = [];

  for (var i = funcDecls.length; i--;) {
    var decl = funcDecls[i];
    if (!shouldDeclBeCaptured(decl, options)) continue;

    var parentPath = scope.funcDeclPaths[i].slice(0, -1),

    // ge the parent so we can replace the original function:
    parent = lively_lang.Path(parentPath).get(scope.node),
        funcId = { type: "Identifier", name: decl.id.name },

    // what we capture:
    init = options.declarationWrapper ? declarationWrapperCall(options.declarationWrapper, decl, literal(funcId.name), literal("function"), funcId, options.captureObj, options) : funcId,
        declFront = _extends({}, decl);

    if (Array.isArray(parent)) {
      // If the parent is a body array we remove the original func decl from it
      // and replace it with a reference to the function
      parent.splice(parent.indexOf(decl), 1, exprStmt(decl.id));
    } else if (parent.type === "ExportNamedDeclaration") {
      // If the function is exported we change the export declaration into a reference
      var parentIndexInBody = scope.node.body.indexOf(parent);
      if (parentIndexInBody > -1) {
        scope.node.body.splice(parentIndexInBody, 1, { type: "ExportNamedDeclaration", specifiers: [{ type: "ExportSpecifier", exported: decl.id, local: decl.id }] });
      }
    } else if (parent.type === "ExportDefaultDeclaration") {
      parent.declaration = decl.id;
    } else {}
    // ??? just leave it alone...
    // decl.type = "EmptyStatement";


    // hoist the function to the front, also it's capture
    putInFront.unshift(assignExpr(options.captureObj, funcId, init, false));
    putInFront.unshift(declFront);
  }
  parsed.body = putInFront.concat(parsed.body);
  return parsed;
}

function computeDefRanges(parsed, options) {
  var topLevel = topLevelDeclsAndRefs(parsed);
  return lively_lang.chain(topLevel.scope.varDecls).pluck("declarations").flatten().value().concat(topLevel.scope.funcDecls).reduce(function (defs, decl) {
    if (!defs[decl.id.name]) defs[decl.id.name] = [];
    defs[decl.id.name].push({ type: decl.type, start: decl.start, end: decl.end });
    return defs;
  }, {});
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// capturing oobject patters / destructuring
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var annotationSym = Symbol("lively.ast-destructuring-transform");

function transformPattern(pattern, transformState) {
  // For transforming destructuring expressions into plain vars and member access.
  // Takes a var or argument pattern node (of type ArrayPattern or
  // ObjectPattern) and transforms it into a set of var declarations that will
  // "pull out" the nested properties
  // Example:
  // var parsed = parse("var [{b: {c: [a]}}] = foo;");
  // var state = {parent: {type: "Identifier", name: "arg"}, declaredNames: ["foo"]}
  // transformPattern(parsed.body[0].declarations[0].id, state).map(stringify).join("\n");
  // // => "var arg$0 = arg[0];\n"
  // //  + "var arg$0$b = arg$0.b;\n"
  // //  + "var arg$0$b$c = arg$0$b.c;\n"
  // //  + "var a = arg$0$b$c[0];"
  return pattern.type === "ArrayPattern" ? transformArrayPattern(pattern, transformState) : pattern.type === "ObjectPattern" ? transformObjectPattern(pattern, transformState) : [];
}

function transformArrayPattern(pattern, transformState) {
  var declaredNames = transformState.declaredNames,
      p = annotationSym,
      transformed = [];

  for (var i = 0; i < pattern.elements.length; i++) {
    var el = pattern.elements[i];

    // like [a]
    if (el.type === "Identifier") {
      var decl = varDecl(el, member(transformState.parent, id(i), true));
      decl[p] = { capture: true };
      transformed.push(decl);

      // like [...foo]
    } else if (el.type === "RestElement") {
      var decl = varDecl(el.argument, {
        type: "CallExpression",
        arguments: [{ type: "Literal", value: i }],
        callee: member(transformState.parent, id("slice"), false) });
      decl[p] = { capture: true };
      transformed.push(decl);
    } else if (el.type == "AssignmentPattern") {
      // like [x = 23]
      var decl = varDecl(el.left /*id*/
      , conditional(binaryExpr(member(transformState.parent, id(i), true), "===", id("undefined")), el.right, member(transformState.parent, id(i), true)));
      decl[p] = { capture: true };
      transformed.push(decl);

      // like [{x}]
    } else {
      var helperVarId = id(generateUniqueName(declaredNames, transformState.parent.name + "$" + i)),
          helperVar = varDecl(helperVarId, member(transformState.parent, i));
      // helperVar[p] = {capture: true};
      declaredNames.push(helperVarId.name);
      transformed.push(helperVar);
      transformed.push.apply(transformed, toConsumableArray(transformPattern(el, { parent: helperVarId, declaredNames: declaredNames })));
    }
  }
  return transformed;
}

function transformObjectPattern(pattern, transformState) {
  var declaredNames = transformState.declaredNames,
      p = annotationSym,
      transformed = [];

  for (var i = 0; i < pattern.properties.length; i++) {
    var prop = pattern.properties[i];

    if (prop.value.type == "Identifier") {
      // like {x: y}
      var decl = varDecl(prop.value, member(transformState.parent, prop.key));
      decl[p] = { capture: true };
      transformed.push(decl);
    } else if (prop.value.type == "AssignmentPattern") {
      // like {x = 23}
      var decl = varDecl(prop.value.left /*id*/
      , conditional(binaryExpr(member(transformState.parent, prop.key), "===", id("undefined")), prop.value.right, member(transformState.parent, prop.key)));
      decl[p] = { capture: true };
      transformed.push(decl);
    } else {
      // like {x: {z}} or {x: [a]}
      var helperVarId = id(generateUniqueName(declaredNames, transformState.parent.name + "$" + prop.key.name)),
          helperVar = varDecl(helperVarId, member(transformState.parent, prop.key));
      helperVar[p] = { capture: false };
      declaredNames.push(helperVarId.name);
      transformed.push.apply(transformed, toConsumableArray([helperVar].concat(transformPattern(prop.value, { parent: helperVarId, declaredNames: declaredNames }))));
    }
  }

  return transformed;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// code generation helpers
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function varDeclOrAssignment(parsed, declarator, kind) {
  var topLevel = topLevelDeclsAndRefs(parsed),
      name = declarator.id.name;
  return topLevel.declaredNames.indexOf(name) > -1 ?
  // only create a new declaration if necessary
  exprStmt(assign(declarator.id, declarator.init)) : {
    declarations: [declarator],
    kind: kind || "var", type: "VariableDeclaration"
  };
}

function assignExpr(assignee, propId, value, computed) {
  return exprStmt(assign(member(assignee, propId, computed), value || id("undefined")));
}

function exportFromImport(keyLeft, keyRight, moduleId, moduleExportFunc, moduleImportFunc) {
  return exportCall(moduleExportFunc, keyLeft, importCall(keyRight, moduleId, moduleImportFunc));
}

function varDeclAndImportCall(parsed, localId, imported, moduleSource, moduleImportFunc) {
  // return varDeclOrAssignment(parsed, {
  //   type: "VariableDeclarator",
  //   id: localId,
  //   init: importCall(imported, moduleSource, moduleImportFunc)
  // });
  return varDecl(localId, importCall(imported, moduleSource, moduleImportFunc));
}

function importCall(imported, moduleSource, moduleImportFunc) {
  if (typeof imported === "string") imported = literal(imported);
  return {
    arguments: [moduleSource].concat(imported || []),
    callee: moduleImportFunc, type: "CallExpression"
  };
}

function importCallStmt(imported, moduleSource, moduleImportFunc) {
  return exprStmt(importCall(imported, moduleSource, moduleImportFunc));
}

function exportCall(exportFunc, local, exportedObj) {
  if (typeof local === "string") local = literal(local);
  exportedObj = lively_lang.obj.deepCopy(exportedObj);
  return funcCall(exportFunc, local, exportedObj);
}

function exportCallStmt(exportFunc, local, exportedObj) {
  return exprStmt(exportCall(exportFunc, local, exportedObj));
}

function declarationWrapperCall(declarationWrapperNode, declNode, varNameLiteral, varKindLiteral, valueNode, recorder, options) {
  if (declNode) {
    // here we pass compile-time meta data into the runtime
    var keyVals = [];
    var addMeta = false;
    if (declNode["x-lively-object-meta"]) {
      var _declNode$xLivelyOb = declNode["x-lively-object-meta"],
          start = _declNode$xLivelyOb.start,
          end = _declNode$xLivelyOb.end,
          evalId = _declNode$xLivelyOb.evalId,
          sourceAccessorName = _declNode$xLivelyOb.sourceAccessorName;

      addMeta = true;
      keyVals.push("start", lively_ast.nodes.literal(start), "end", lively_ast.nodes.literal(end));
    }
    if (evalId === undefined && options.hasOwnProperty("evalId")) {
      evalId = options.evalId;
      addMeta = true;
    }
    if (sourceAccessorName === undefined && options.hasOwnProperty("sourceAccessorName")) {
      sourceAccessorName = options.sourceAccessorName;
      addMeta = true;
    }
    if (evalId !== undefined) keyVals.push("evalId", lively_ast.nodes.literal(evalId));
    if (sourceAccessorName) keyVals.push("moduleSource", lively_ast.nodes.id(sourceAccessorName));
    if (addMeta) {
      return funcCall(declarationWrapperNode, varNameLiteral, varKindLiteral, valueNode, recorder, lively_ast.nodes.objectLiteral(keyVals) /*meta node*/);
    }
  }

  return funcCall(declarationWrapperNode, varNameLiteral, varKindLiteral, valueNode, recorder);
}



var capturing = Object.freeze({
	rewriteToCaptureTopLevelVariables: rewriteToCaptureTopLevelVariables,
	rewriteToRegisterModuleToCaptureSetters: rewriteToRegisterModuleToCaptureSetters
});

function stringifyFunctionWithoutToplevelRecorder(funcOrSourceOrAst) {
  var varRecorderName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "__lvVarRecorder";

  // stringifyFunctionWithoutToplevelRecorder((x) => hello + x)
  // => x => hello + x
  // instead of String((x) => hello + x) // => x => __lvVarRecorder.hello + x
  // when run in toplevel scope
  if (typeof funcOrSourceOrAst === "function") funcOrSourceOrAst = String(funcOrSourceOrAst);
  var parsed = typeof funcOrSourceOrAst === "string" ? lively_ast.parseFunction(funcOrSourceOrAst) : funcOrSourceOrAst,
      replaced = lively_ast.ReplaceVisitor.run(parsed, function (node) {
    var isVarRecorderMember = node.type === "MemberExpression" && node.object.type === "Identifier" && node.object.name === varRecorderName;
    return isVarRecorderMember ? node.property : node;
  });
  return lively_ast.stringify(replaced);
}

exports.capturing = capturing;
exports.stringifyFunctionWithoutToplevelRecorder = stringifyFunctionWithoutToplevelRecorder;

}((this.lively.sourceTransform = this.lively.sourceTransform || {}),lively.lang,lively.classes,lively.ast));

  if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.sourceTransform;
})();
// INLINED END /Users/user/git/lively.vm/node_modules/lively.source-transform/dist/lively.source-transform.js
(function() {
  var GLOBAL = typeof window !== "undefined" ? window :
      typeof global!=="undefined" ? global :
        typeof self!=="undefined" ? self : this;
  this.lively = this.lively || {};
(function (exports,lively_lang,lively_ast,lively_sourceTransform,lively_classes,lively_notifications) {
'use strict';

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj$$1) {
  return typeof obj$$1;
} : function (obj$$1) {
  return obj$$1 && typeof Symbol === "function" && obj$$1.constructor === Symbol && obj$$1 !== Symbol.prototype ? "symbol" : typeof obj$$1;
};









var asyncToGenerator = function (fn) {
  return function () {
    var gen = fn.apply(this, arguments);
    return new Promise(function (resolve, reject) {
      function step(key, arg) {
        try {
          var info = gen[key](arg);
          var value = info.value;
        } catch (error) {
          reject(error);
          return;
        }

        if (info.done) {
          resolve(value);
        } else {
          return Promise.resolve(value).then(function (value) {
            step("next", value);
          }, function (err) {
            step("throw", err);
          });
        }
      }

      return step("next");
    });
  };
};

var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

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;
  };
}();





var defineProperty = function (obj$$1, key, value) {
  if (key in obj$$1) {
    Object.defineProperty(obj$$1, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj$$1[key] = value;
  }

  return obj$$1;
};

var _extends = Object.assign || function (target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];

    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }

  return target;
};

var get$1 = function get$1(object, property, receiver) {
  if (object === null) object = Function.prototype;
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent === null) {
      return undefined;
    } else {
      return get$1(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);
  }
};

var inherits = function (subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
};











var possibleConstructorReturn = function (self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return call && (typeof call === "object" || typeof call === "function") ? call : self;
};



var set = function set(object, property, value, receiver) {
  var desc = Object.getOwnPropertyDescriptor(object, property);

  if (desc === undefined) {
    var parent = Object.getPrototypeOf(object);

    if (parent !== null) {
      set(parent, property, value, receiver);
    }
  } else if ("value" in desc && desc.writable) {
    desc.value = value;
  } else {
    var setter = desc.set;

    if (setter !== undefined) {
      setter.call(receiver, value);
    }
  }

  return value;
};

var slicedToArray = function () {
  function sliceIterator(arr$$1, i) {
    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;

    try {
      for (var _i = arr$$1[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);

        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"]) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  return function (arr$$1, i) {
    if (Array.isArray(arr$$1)) {
      return arr$$1;
    } else if (Symbol.iterator in Object(arr$$1)) {
      return sliceIterator(arr$$1, i);
    } else {
      throw new TypeError("Invalid attempt to destructure non-iterable instance");
    }
  };
}();













var toConsumableArray = function (arr$$1) {
  if (Array.isArray(arr$$1)) {
    for (var i = 0, arr2 = Array(arr$$1.length); i < arr$$1.length; i++) arr2[i] = arr$$1[i];

    return arr2;
  } else {
    return Array.from(arr$$1);
  }
};

/*global System,global,Global,self,Node,ImageData*/
function getGlobal() {
  if (typeof System !== "undefined") return System.global;
  if (typeof window !== "undefined") return window;
  if (typeof global !== "undefined") return global;
  if (typeof Global !== "undefined") return Global;
  if (typeof self !== "undefined") return self;
  return function () {
    return this;
  }();
}

function signatureOf(name, func) {
  var source = String(func),
      match = source.match(/function\s*[a-zA-Z0-9_$]*\s*\(([^\)]*)\)/),
      params = match && match[1] || '';
  return name + '(' + params + ')';
}



function pluck(list, prop) {
  return list.map(function (ea) {
    return ea[prop];
  });
}

var knownSymbols = function () {
  return Object.getOwnPropertyNames(Symbol).filter(function (ea) {
    return _typeof(Symbol[ea]) === "symbol";
  }).reduce(function (map, ea) {
    return map.set(Symbol[ea], "Symbol." + ea);
  }, new Map());
}();

var symMatcher = /^Symbol\((.*)\)$/;

function printSymbol(sym) {
  if (Symbol.keyFor(sym)) return "Symbol.for(\"" + Symbol.keyFor(sym) + "\")";
  if (knownSymbols.get(sym)) return knownSymbols.get(sym);
  var matched = String(sym).match(symMatcher);
  return String(sym);
}

function safeToString(value) {
  if (!value) return String(value);
  if (Array.isArray(value)) return "[" + value.map(safeToString).join(",") + "]";
  if ((typeof value === "undefined" ? "undefined" : _typeof(value)) === "symbol") return printSymbol(value);
  try {
    return String(value);
  } catch (e) {
    throw new Error("Cannot print object: " + e.stack);
  }
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function printEvalResult(evalResult) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var value = evalResult.value,
      isError = evalResult.isError,
      isPromise = evalResult.isPromise,
      promisedValue = evalResult.promisedValue,
      promiseStatus = evalResult.promiseStatus;


  if (isError || value instanceof Error) {
    var err = value,
        stringified = String(err),
        stack = err.stack || "";
    if (stack && err.message !== err.stack) {
      stack = String(stack);
      var errInStackIdx = stack.indexOf(stringified);
      if (errInStackIdx === 0) stack = stack.slice(stringified.length);
      stringified += "\n" + stack;
    }
    return stringified;
  }

  if (isPromise) {
    var status = lively_lang.string.print(promiseStatus),
        printed = promiseStatus === "pending" ? undefined : printEvalResult({ value: promisedValue }, options);
    return "Promise({status: " + status + ", " + (value === undefined ? "" : "value: " + printed) + "})";
  }

  if (value instanceof Promise) return 'Promise({status: "unknown"})';

  if (options.inspect) return printInspectEvalValue(value, options.inspectDepth || 2);

  // options.asString
  return String(value);
}

var printInspectEvalValue = function () {
  var itSym = typeof Symbol !== "undefined" && Symbol.iterator,
      maxIterLength = 10,
      maxStringLength = 100,
      maxNumberOfKeys = 100,
      maxNumberOfLines = 1000;

  return printInspect;

  function printInspect(object, maxDepth) {
    if ((typeof maxDepth === "undefined" ? "undefined" : _typeof(maxDepth)) === "object") maxDepth = maxDepth.maxDepth || 2;

    if (!object) return String(object);
    if (typeof object === "string") {
      var mark = object.includes("\n") ? "`" : '"';
      object = object.split('\n').slice(0, maxNumberOfLines).join('\n');
      return mark + object + mark;
    }
    if (object instanceof Error) return object.stack || safeToString(object);
    if (!lively_lang.obj.isObject(object)) return safeToString(object);
    try {
      var inspected = lively_lang.obj.inspect(object, {
        customPrinter: inspectPrinter, maxNumberOfKeys: maxNumberOfKeys,
        maxDepth: maxDepth, printFunctionSource: true
      });
    } catch (e) {}
    // return inspected;
    return inspected === "{}" ? safeToString(object) : inspected;
  }

  function printIterable(val, ignore) {
    var isIterable = typeof val !== "string" && !Array.isArray(val) && itSym && typeof val[itSym] === "function";
    if (!isIterable) return ignore;
    var hasEntries = typeof val.entries === "function",
        it = hasEntries ? val.entries() : val[itSym](),
        values = [],
        open = hasEntries ? "{" : "[",
        close = hasEntries ? "}" : "]",
        name = val.constructor && val.constructor.name || "Iterable";
    for (var i = 0, next; i < maxIterLength; i++) {
      next = it.next();
      if (next.done) break;
      values.push(next.value);
    }
    var printed = values.map(function (ea) {
      return hasEntries ? String(ea[0]) + ": " + String(ea[1]) : printInspect(ea, 2);
    }).join(", ");
    return name + "(" + open + printed + close + ")";
  }

  function inspectPrinter(val, ignore, continueInspectFn) {
    if (!val) return ignore;
    if ((typeof val === "undefined" ? "undefined" : _typeof(val)) === "symbol") return printSymbol(val);
    if (typeof val === "string") return lively_lang.string.print(lively_lang.string.truncate(val, maxStringLength));
    if (val.isMorph) return safeToString(val);
    if (val instanceof Promise) return "Promise()";
    if (typeof Node !== "undefined" && val instanceof Node) return safeToString(val);
    if (typeof ImageData !== "undefined" && val instanceof ImageData) return safeToString(val);
    var length = val.length || val.byteLength;
    if (length !== undefined && length > maxIterLength && val.slice) {
      var printed = typeof val === "string" || val.byteLength ? safeToString(val.slice(0, maxIterLength)) : val.slice(0, maxIterLength).map(continueInspectFn);
      return "[" + printed + ",...]";
    }
    var iterablePrinted = printIterable(val, ignore);
    if (iterablePrinted !== ignore) return iterablePrinted;
    return ignore;
  }
}();

/*global require, __dirname*/

// helper

function getObjectForCompletion(evalFunc, stringToEval) {
  var startLetters = '';
  return Promise.resolve().then(function () {
    // thenDo = function(err, obj, startLetters)
    var idx = stringToEval.lastIndexOf('.');
    if (idx >= 0) {
      startLetters = stringToEval.slice(idx + 1);
      stringToEval = stringToEval.slice(0, idx);
    } else {
      startLetters = stringToEval;
      stringToEval = '(typeof window === "undefined" ? global : window)';
    }
    return evalFunc(stringToEval);
  }).then(function (evalResult) {
    return {
      evalResult: evalResult,
      startLetters: startLetters,
      code: stringToEval
    };
  });
}

function propertyExtract(excludes, obj$$1, extractor) {
  return Object.getOwnPropertyNames(obj$$1).concat(Object.getOwnPropertySymbols(obj$$1).map(printSymbol)).filter(function (key) {
    return excludes.indexOf(key) === -1;
  }).map(extractor).filter(function (ea) {
    return !!ea;
  }).sort(function (a, b) {
    return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
  });
}

function getMethodsOf(excludes, obj$$1) {
  return propertyExtract(excludes, obj$$1, function (key) {
    if (obj$$1.__lookupGetter__ && obj$$1.__lookupGetter__(key) || typeof obj$$1[key] !== 'function') return null;
    return { name: key, completion: signatureOf(key, obj$$1[key]) };
  });
}

function getAttributesOf(excludes, obj$$1) {
  return propertyExtract(excludes, obj$$1, function (key) {
    if (obj$$1.__lookupGetter__ && !obj$$1.__lookupGetter__(key) && typeof obj$$1[key] === 'function') return null;
    return { name: key, completion: key };
  });
}

function getProtoChain(obj$$1) {
  var protos = [],
      proto = obj$$1;
  while (obj$$1) {
    protos.push(obj$$1);obj$$1 = obj$$1.__proto__;
  }
  return protos;
}

function getDescriptorOf(originalObj, proto) {
  function shorten(s, len) {
    if (s.length > len) s = s.slice(0, len) + '...';
    return s.replace(/\n/g, '').replace(/\s+/g, ' ');
  }

  if (originalObj === proto) {
    if (typeof originalObj !== 'function') return shorten(safeToString(originalObj), 50);
    var funcString = originalObj.toString(),
        body = shorten(funcString.slice(funcString.indexOf('{') + 1, funcString.lastIndexOf('}')), 50);
    return signatureOf(originalObj.displayName || originalObj.name || 'function', originalObj) + ' {' + body + '}';
  }

  var klass = proto.hasOwnProperty('constructor') && proto.constructor;
  if (!klass) return 'prototype';
  if (typeof klass.type === 'string' && klass.type.length) return shorten(klass.type, 50);
  if (typeof klass.name === 'string' && klass.name.length) return shorten(klass.name, 50);
  return "anonymous class";
}

function descriptorsOfObjAndProtoProperties(obj$$1) {
  var excludes = [],
      completions = getProtoChain(obj$$1).map(function (proto) {
    var descr = getDescriptorOf(obj$$1, proto),
        methodsAndAttributes = getMethodsOf(excludes, proto).concat(getAttributesOf(excludes, proto));
    excludes = excludes.concat(pluck(methodsAndAttributes, 'name'));
    return [descr, pluck(methodsAndAttributes, 'completion')];
  });
  return completions;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// the main deal
function getCompletions(evalFunc, string$$1, thenDo) {
  // thendo = function(err, completions/*ARRAY*/)
  // eval string and for the resulting object find attributes and methods,
  // grouped by its prototype / class chain
  // if string is something like "foo().bar.baz" then treat "baz" as start
  // letters = filter for properties of foo().bar
  // ("foo().bar.baz." for props of the result of the complete string)
  var promise$$1 = getObjectForCompletion(evalFunc, string$$1).then(function (evalResultAndStartLetters) {
    var evalResult = evalResultAndStartLetters.evalResult,
        value = evalResult && evalResult.isEvalResult ? evalResult.value : evalResult,
        result = {
      completions: descriptorsOfObjAndProtoProperties(value),
      startLetters: evalResultAndStartLetters.startLetters,
      code: evalResultAndStartLetters.code
    };

    if (evalResult && evalResult.isPromise) {
      if (evalResult.promiseStatus === "fulfilled") result.promiseResolvedCompletions = descriptorsOfObjAndProtoProperties(evalResult.promisedValue);else if (evalResult.promiseStatus === "rejected") result.promiseRejectedCompletions = descriptorsOfObjAndProtoProperties(evalResult.promisedValue);
    }
    return result;
  });
  if (typeof thenDo === "function") {
    promise$$1.then(function (result) {
      return thenDo(null, result);
    }).catch(function (err) {
      return thenDo(err);
    });
  }
  return promise$$1;
}



var completions = Object.freeze({
	getObjectForCompletion: getObjectForCompletion,
	getCompletions: getCompletions
});

var id = lively_ast.nodes.id;
var literal = lively_ast.nodes.literal;
var member = lively_ast.nodes.member;


var defaultDeclarationWrapperName = "lively.capturing-declaration-wrapper";
var defaultClassToFunctionConverterName = "initializeES6ClassForLively";

function processInlineCodeTransformOptions(parsed, options) {
  if (!parsed.comments) return options;
  var livelyComment = parsed.comments.find(function (ea) {
    return ea.text.startsWith("lively.vm ");
  });
  if (!livelyComment) return options;
  try {
    var inlineOptions = eval("inlineOptions = {" + livelyComment.text.slice("lively.vm ".length) + "};");
    return Object.assign(options, inlineOptions);
  } catch (err) {
    return options;
  }
}

function evalCodeTransform(code, options) {
  // variable declaration and references in the the source code get
  // transformed so that they are bound to `varRecorderName` aren't local
  // state. THis makes it possible to capture eval results, e.g. for
  // inspection, watching and recording changes, workspace vars, and
  // incrementally evaluating var declarations and having values bound later.

  // 1. Allow evaluation of function expressions and object literals
  code = lively_ast.transform.transformSingleExpression(code);
  var parsed = lively_ast.parse(code, { withComments: true });

  options = processInlineCodeTransformOptions(parsed, options);

  // 2. Annotate definitions with code location. This is being used by the
  // function-wrapper-source transform.

  var _query$topLevelDeclsA = lively_ast.query.topLevelDeclsAndRefs(parsed),
      classDecls = _query$topLevelDeclsA.classDecls,
      funcDecls = _query$topLevelDeclsA.funcDecls,
      varDecls = _query$topLevelDeclsA.varDecls,
      annotation = {};

  if (options.hasOwnProperty("evalId")) annotation.evalId = options.evalId;
  if (options.sourceAccessorName) annotation.sourceAccessorName = options.sourceAccessorName;
  [].concat(toConsumableArray(classDecls), toConsumableArray(funcDecls)).forEach(function (node) {
    return node["x-lively-object-meta"] = _extends({}, annotation, { start: node.start, end: node.end });
  });
  varDecls.forEach(function (node) {
    return node.declarations.forEach(function (decl) {
      return decl["x-lively-object-meta"] = _extends({}, annotation, { start: decl.start, end: decl.end });
    });
  });

  // transforming experimental ES features into accepted es6 form...
  parsed = lively_ast.transform.objectSpreadTransform(parsed);

  // 3. capture top level vars into topLevelVarRecorder "environment"

  if (!options.topLevelVarRecorder && options.topLevelVarRecorderName) {
    var G = getGlobal();
    if (options.topLevelVarRecorderName === "GLOBAL") {
      // "magic"
      options.topLevelVarRecorder = getGlobal();
    } else {
      options.topLevelVarRecorder = lively_lang.Path(options.topLevelVarRecorderName).get(G);
    }
  }

  if (options.topLevelVarRecorder) {

    // capture and wrap logic
    var blacklist = (options.dontTransform || []).concat(["arguments"]),
        undeclaredToTransform = !!options.recordGlobals ? null /*all*/ : lively_lang.arr.withoutAll(Object.keys(options.topLevelVarRecorder), blacklist),
        varRecorder = id(options.varRecorderName || '__lvVarRecorder'),
        es6ClassToFunctionOptions = undefined;

    if (options.declarationWrapperName || typeof options.declarationCallback === "function") {
      // 2.1 declare a function that wraps all definitions, i.e. all var
      // decls, functions, classes etc that get captured will be wrapped in this
      // function. This allows to define some behavior that is run whenever
      // variables get initialized or changed as well as transform values.
      // The parameters passed are:
      //   name, kind, value, recorder
      // Note that the return value of declarationCallback is used as the
      // actual value in the code being executed. This allows to transform the
      // value as necessary but also means that declarationCallback needs to
      // return sth meaningful!
      var declarationWrapperName = options.declarationWrapperName || defaultDeclarationWrapperName;

      options.declarationWrapper = member(id(options.varRecorderName || '__lvVarRecorder'), literal(declarationWrapperName), true);

      if (options.declarationCallback) options.topLevelVarRecorder[declarationWrapperName] = options.declarationCallback;
    }

    var transformES6Classes = options.hasOwnProperty("transformES6Classes") ? options.transformES6Classes : true;
    if (transformES6Classes) {
      // Class declarations and expressions are converted into a function call
      // to `createOrExtendClass`, a helper that will produce (or extend an
      // existing) constructor function in a way that allows us to redefine
      // methods and properties of the class while keeping the class object
      // identical
      if (!(defaultClassToFunctionConverterName in options.topLevelVarRecorder)) options.topLevelVarRecorder[defaultClassToFunctionConverterName] = lively_classes.runtime.initializeClass;
      es6ClassToFunctionOptions = {
        currentModuleAccessor: options.currentModuleAccessor,
        classHolder: varRecorder,
        functionNode: member(varRecorder, defaultClassToFunctionConverterName),
        declarationWrapper: options.declarationWrapper,
        evalId: options.evalId,
        sourceAccessorName: options.sourceAccessorName
      };
    }

    // 3.2 Here we call out to the actual code transformation that installs the captured top level vars
    parsed = lively_sourceTransform.capturing.rewriteToCaptureTopLevelVariables(parsed, varRecorder, {
      es6ImportFuncId: options.es6ImportFuncId,
      es6ExportFuncId: options.es6ExportFuncId,
      ignoreUndeclaredExcept: undeclaredToTransform,
      exclude: blacklist,
      declarationWrapper: options.declarationWrapper || undefined,
      classToFunction: es6ClassToFunctionOptions,
      evalId: options.evalId,
      sourceAccessorName: options.sourceAccessorName,
      keepTopLevelVarDecls: options.keepTopLevelVarDecls
    });
  }

  if (options.wrapInStartEndCall) {
    parsed = lively_ast.transform.wrapInStartEndCall(parsed, {
      startFuncNode: options.startFuncNode,
      endFuncNode: options.endFuncNode
    });
  }

  var result = lively_ast.stringify(parsed);

  if (options.sourceURL) result += "\n//# sourceURL=" + options.sourceURL.replace(/\s/g, "_");

  return result;
}

function evalCodeTransformOfSystemRegisterSetters(code) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  if (!options.topLevelVarRecorder) return code;

  if (typeof options.declarationCallback === "function" || options.declarationWrapperName) {
    var declarationWrapperName = options.declarationWrapperName || defaultDeclarationWrapperName;
    options.declarationWrapper = member(id(options.varRecorderName), literal(declarationWrapperName), true);
    if (options.declarationCallback) options.topLevelVarRecorder[declarationWrapperName] = options.declarationCallback;
  }

  var parsed = lively_ast.parse(code),
      blacklist = (options.dontTransform || []).concat(["arguments"]),
      undeclaredToTransform = !!options.recordGlobals ? null /*all*/ : lively_lang.arr.withoutAll(Object.keys(options.topLevelVarRecorder), blacklist),
      result = lively_sourceTransform.capturing.rewriteToRegisterModuleToCaptureSetters(parsed, id(options.varRecorderName || '__lvVarRecorder'), _extends({ exclude: blacklist }, options));
  return lively_ast.stringify(result);
}

/*global: global, System*/

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// options
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var defaultTopLevelVarRecorderName = '__lvVarRecorder';
var startEvalFunctionName = "lively.vm-on-eval-start";
var endEvalFunctionName = "lively.vm-on-eval-end";

function _normalizeEvalOptions(opts) {
  if (!opts) opts = {};

  opts = _extends({
    targetModule: null,
    sourceURL: opts.targetModule,
    runtime: null,
    context: getGlobal(),
    varRecorderName: defaultTopLevelVarRecorderName,
    dontTransform: [], // blacklist vars
    recordGlobals: null,
    returnPromise: true,
    promiseTimeout: 200,
    waitForPromise: true,
    wrapInStartEndCall: false,
    onStartEval: null,
    onEndEval: null
  }, opts);

  if (opts.targetModule) {
    var moduleEnv = opts.runtime && opts.runtime.modules && opts.runtime.modules[opts.targetModule];
    if (moduleEnv) opts = Object.assign(opts, moduleEnv);
  }

  if (opts.wrapInStartEndCall) {
    opts.startFuncNode = {
      type: "MemberExpression",
      object: { type: "Identifier", name: opts.varRecorderName },
      property: { type: "Literal", value: startEvalFunctionName },
      computed: true
    };
    opts.endFuncNode = {
      type: "MemberExpression",
      object: { type: "Identifier", name: opts.varRecorderName },
      property: { type: "Literal", value: endEvalFunctionName },
      computed: true
    };
  }

  return opts;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// eval
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function _eval(__lvEvalStatement, __lvVarRecorder /*needed as arg for capturing*/, __lvOriginalCode) {
  return eval(__lvEvalStatement);
}

function runEval$1(code, options, thenDo) {
  // The main function where all eval options are configured.
  // options can be: {
  //   runtime: {
  //     modules: {[MODULENAME: PerModuleOptions]}
  //   }
  // }
  // or directly, PerModuleOptions = {
  //   varRecorderName: STRING, // default is '__lvVarRecorder'
  //   topLevelVarRecorder: OBJECT,
  //   context: OBJECT,
  //   sourceURL: STRING,
  //   recordGlobals: BOOLEAN, // also transform free vars? default is false
  //   transpiler: FUNCTION(source, options) // for transforming the source after the lively xfm
  //   wrapInStartEndCall: BOOLEAN
  //   onStartEval: FUNCTION()?,
  //   onEndEval: FUNCTION(err, value)? // note: we pass in the value of last expr, not EvalResult!
  // }

  if (typeof options === 'function' && arguments.length === 2) {
    thenDo = options;options = null;
  }

  var result = new EvalResult(),
      returnedError,
      returnedValue,
      onEvalEndError,
      onEvalEndValue,
      onEvalStartCalled = false,
      onEvalEndCalled = false;
  options = _normalizeEvalOptions(options);

  // 1. In case we rewrite the code with on-start and on-end calls we prepare
  // the environment with actual function handlers that will get called once
  // the code is evaluated

  var evalDone = lively_lang.promise.deferred(),
      recorder = options.topLevelVarRecorder || getGlobal(),
      originalSource = code;

  if (options.wrapInStartEndCall) {
    if (recorder[startEvalFunctionName]) console.warn(result.addWarning("startEvalFunctionName " + startEvalFunctionName + " already exists in recorder!"));

    if (recorder[endEvalFunctionName]) console.warn(result.addWarning("endEvalFunctionName " + endEvalFunctionName + " already exists in recorder!"));

    recorder[startEvalFunctionName] = function () {
      if (onEvalStartCalled) {
        console.warn(result.addWarning("onEvalStartCalled multiple times!"));return;
      }
      onEvalStartCalled = true;
      if (typeof options.onStartEval === "function") options.onStartEval();
    };

    recorder[endEvalFunctionName] = function (err, value) {
      if (onEvalEndCalled) {
        console.warn(result.addWarning("onEvalEndCalled multiple times!"));return;
      }
      onEvalEndCalled = true;
      finishEval(err, value, result, options, recorder, evalDone, thenDo);
    };
  }

  // 2. Transform the code to capture top-level variables, inject function calls, ...
  try {
    code = evalCodeTransform(code, options);
    if (options.header) code = options.header + code;
    if (options.footer) code = code + options.footer;
    if (options.transpiler) code = options.transpiler(code, options.transpilerOptions);
    // console.log(code);
  } catch (e) {
    console.warn(result.addWarning("lively.vm evalCodeTransform not working: " + e));
  }

  // 3. Now really run eval!
  try {
    typeof $world !== "undefined" && $world.get('log') && ($world.get('log').textString = code);
    returnedValue = _eval.call(options.context, code, options.topLevelVarRecorder, options.originalSource || originalSource);
  } catch (e) {
    returnedError = e;
  }

  // 4. Wrapping up: if we inject a on-eval-end call we let it handle the
  // wrap-up, otherwise we firectly call finishEval()
  if (options.wrapInStartEndCall) {
    if (returnedError && !onEvalEndCalled) recorder[endEvalFunctionName](returnedError, undefined);
  } else {
    finishEval(returnedError, returnedError || returnedValue, result, options, recorder, evalDone, thenDo);
  }

  return options.sync ? result : evalDone.promise;
}

function finishEval(err, value, result, options, recorder, evalDone, thenDo) {
  // 5. Here we end the evaluation. Note that if we are in sync mode we cannot
  // use any Promise since promises always run on next tick. That's why we have
  // to slightly duplicate the finish logic...

  if (options.wrapInStartEndCall) {
    delete recorder[startEvalFunctionName];
    delete recorder[endEvalFunctionName];
  }

  if (err) {
    result.isError = true;result.value = err;
  } else result.value = value;
  if (result.value instanceof Promise) result.isPromise = true;

  if (options.sync) {
    result.processSync(options);
    if (typeof options.onEndEval === "function") options.onEndEval(err, value);
  } else {
    result.process(options).then(function () {
      typeof thenDo === "function" && thenDo(null, result);
      typeof options.onEndEval === "function" && options.onEndEval(err, value);
      return result;
    }, function (err) {
      typeof thenDo === "function" && thenDo(err, undefined);
      typeof options.onEndEval === "function" && options.onEndEval(err, undefined);
      return result;
    }).then(evalDone.resolve, evalDone.reject);
  }
}

function syncEval$1(string$$1, options) {
  // See #runEval for options.
  // Although the defaul eval is synchronous we assume that the general
  // evaluation might not return immediatelly. This makes is possible to
  // change the evaluation backend, e.g. to be a remotely attached runtime
  options = Object.assign(options || {}, { sync: true });
  return runEval$1(string$$1, options);
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// EvalResult
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

var EvalResult = function () {
  function EvalResult() {
    classCallCheck(this, EvalResult);

    this.isEvalResult = true;
    this.value = undefined;
    this.warnings = [];
    this.isError = false;
    this.isPromise = false;
    this.promisedValue = undefined;
    this.promiseStatus = "unknown";
  }

  createClass(EvalResult, [{
    key: "addWarning",
    value: function addWarning(warn) {
      this.warnings.push(warn);return warn;
    }
  }, {
    key: "printed",
    value: function printed() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

      this.value = printEvalResult(this, options);
    }
  }, {
    key: "processSync",
    value: function processSync(options) {
      if (options.inspect || options.asString) this.value = this.print(this.value, options);
      return this;
    }
  }, {
    key: "process",
    value: function process(options) {
      var result = this;
      if (result.isPromise && options.waitForPromise) {
        return tryToWaitForPromise(result, options.promiseTimeout).then(function () {
          if (options.inspect || options.asString) result.printed(options);
          return result;
        });
      }
      if (options.inspect || options.asString) result.printed(options);
      return Promise.resolve(result);
    }
  }]);
  return EvalResult;
}();

function tryToWaitForPromise(evalResult, timeoutMs) {
  console.assert(evalResult.isPromise, "no promise in tryToWaitForPromise???");
  var timeout = {},
      timeoutP = new Promise(function (resolve) {
    return setTimeout(resolve, timeoutMs, timeout);
  });
  return Promise.race([timeoutP, evalResult.value]).then(function (resolved) {
    return Object.assign(evalResult, resolved !== timeout ? { promiseStatus: "fulfilled", promisedValue: resolved } : { promiseStatus: "pending" });
  }).catch(function (rejected) {
    return Object.assign(evalResult, { promiseStatus: "rejected", promisedValue: rejected });
  });
}

var funcCall = lively_ast.nodes.funcCall;
var member$1 = lively_ast.nodes.member;
var literal$1 = lively_ast.nodes.literal;


// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// load support

function ensureImportsAreImported(System, code, parentModule) {
  // FIXME do we have to do a reparse? We should be able to get the ast from
  // the rewriter...
  var body = lively_ast.parse(code).body,
      imports = body.filter(function (node) {
    return node.type === "ImportDeclaration";
  });
  return Promise.all(imports.map(function (node) {
    return System.normalize(node.source.value, parentModule).then(function (fullName) {
      return System.get(fullName) || System.import(fullName);
    });
  })).catch(function (err) {
    console.error("Error ensuring imports: " + err.message);throw err;
  });
}

function hasUnimportedImports(System, code, parentModule) {
  var body = lively.ast.parse(code).body,
      imports = body.filter(function (node) {
    return node.type === "ImportDeclaration";
  }),
      importedModules = lively_lang.arr.uniq(imports.map(function (ea) {
    return ea.source.value;
  })).filter(Boolean),
      unloadedImports = importedModules.filter(function (ea) {
    return !System.get(System.decanonicalize(ea, parentModule));
  });
  return unloadedImports.length > 0;
}

// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// transpiler to make es next work

function babelTranspilerForAsyncAwaitCode(System, babel, filename, env) {
  // The function wrapper is needed b/c we need toplevel awaits and babel
  // converts "this" => "undefined" for modules
  return function (source, options) {
    options = Object.assign({
      sourceMap: undefined, // 'inline' || true || false
      inputSourceMap: undefined,
      filename: filename,
      code: true,
      ast: false
    }, options);
    var sourceForBabel = "(async function(__rec) {\n" + source + "\n}).call(this);",
        transpiled = babel.transform(sourceForBabel, options).code;
    transpiled = transpiled.replace(/\}\)\.call\(undefined\);$/, "}).call(this)");
    return transpiled;
  };
}

function babelPluginTranspilerForAsyncAwaitCode(System, babelWrapper, filename, env) {

  // The function wrapper is needed b/c we need toplevel awaits and babel
  // converts "this" => "undefined" for modules
  return function (source, options) {
    var babelOptions = System.babelOptions || {},
        presets = [];
    presets.push(babelWrapper.presetES2015);
    if (babelOptions.stage3) presets.push({ plugins: babelWrapper.pluginsStage3 });
    if (babelOptions.stage2) presets.push({ plugins: babelWrapper.pluginsStage2 });
    if (babelOptions.stage1) presets.push({ plugins: babelWrapper.pluginsStage1 });

    options = Object.assign({
      sourceMap: undefined, // 'inline' || true || false
      inputSourceMap: undefined,
      filename: filename,
      babelrc: false,
      // plugins: plugins,
      presets: presets,
      moduleIds: false,
      code: true,
      ast: false
    }, options);
    var sourceForBabel = "(async function(__rec) {\n" + source + "\n}).call(this);",
        transpiled = babelWrapper.babel.transform(sourceForBabel, options).code;
    transpiled = transpiled.replace(/\}\)\.call\(undefined\);$/, "}).call(this)");
    return transpiled;
  };
}

function getEs6Transpiler(System, options, env) {
  if (options.transpiler) return options.transpiler;
  if (!options.es6Transpile) return null;

  if (System.transpiler === "babel") {
    var babel = System.global[System.transpiler] || System.get(System.decanonicalize(System.transpiler));

    return babel ? babelTranspilerForAsyncAwaitCode(System, babel, options.targetModule, env) : System.import(System.transpiler).then(function (babel) {
      return babelTranspilerForAsyncAwaitCode(System, babel, options.targetModule, env);
    });
  }

  if (System.transpiler === "plugin-babel") {
    var babelPluginPath = System.decanonicalize("plugin-babel"),
        babelPath = babelPluginPath.split("/").slice(0, -1).concat("systemjs-babel-browser.js").join("/"),
        babelPlugin = System.get(babelPath);

    return babelPlugin ? babelPluginTranspilerForAsyncAwaitCode(System, babelPlugin, options.targetModule, env) : System.import(babelPath).then(function (babelPlugin) {
      return babelPluginTranspilerForAsyncAwaitCode(System, babelPlugin, options.targetModule, env);
    });
  }

  if (System.transpiler === "lively.transpiler") {
    var Transpiler = System.get(System.decanonicalize("lively.transpiler")).default,
        transpiler = new Transpiler(System, options.targetModule, env);
    return function (source, options) {
      return transpiler.transpileDoit(source, options);
    };
  }

  throw new Error("Sorry, currently only babel is supported as es6 transpiler for runEval!");
}

function runEval$2(System, code, options) {
  options = _extends({
    targetModule: null, parentModule: null,
    es6Transpile: true,
    transpiler: null, // function with params: source, options
    transpilerOptions: null,
    format: "esm"
  }, options);
  var defaultSourceAccessorName = "__lvOriginalCode";
  var originalSource = code;

  System.debug && console.log("[lively.module] runEval: " + code.slice(0, 100).replace(/\n/mg, " ") + "...");

  var _options = options,
      format = _options.format,
      targetModule = _options.targetModule,
      parentModule = _options.parentModule;

  targetModule = System.decanonicalize(targetModule || "*scratch*", parentModule);
  options.targetModule = targetModule;

  if (format) {
    var meta = System.getConfig().meta[targetModule];
    if (!meta) meta = {};
    if (!meta[targetModule]) meta[targetModule] = {};
    if (!meta[targetModule].format) {
      meta[targetModule].format = format;
      System.config(meta);
    }
  }

  var module = System.get("@lively-env").moduleEnv(targetModule),
      recorder = module.recorder,
      recorderName = module.recorderName,
      dontTransform = module.dontTransform,
      transpiler = getEs6Transpiler(System, options, module),
      header = "var _moduleExport = " + recorderName + "._moduleExport,\n" + ("    _moduleImport = " + recorderName + "._moduleImport;\n");


  options = _extends({
    waitForPromise: true,
    sync: false,
    evalId: options.evalId || module.nextEvalId(),
    sourceAccessorName: (options.hasOwnProperty("embedOriginalCode") ? options.embedOriginalCode : true) ? defaultSourceAccessorName : undefined,
    originalSource: originalSource
  }, options, {
    header: header,
    recordGlobals: true,
    dontTransform: dontTransform,
    varRecorderName: recorderName,
    topLevelVarRecorder: recorder,
    sourceURL: options.sourceURL || options.targetModule,
    context: options.context || recorder,
    wrapInStartEndCall: true, // for async / await eval support
    es6ExportFuncId: "_moduleExport",
    es6ImportFuncId: "_moduleImport",
    transpiler: transpiler,
    declarationWrapperName: module.varDefinitionCallbackName,
    currentModuleAccessor: funcCall(member$1(funcCall(member$1(member$1("__lvVarRecorder", "System"), "get"), literal$1("@lively-env")), "moduleEnv"), literal$1(options.targetModule))
  });

  // delay eval to ensure imports
  if (!options.sync && !options.importsEnsured && hasUnimportedImports(System, code, targetModule)) {
    return ensureImportsAreImported(System, code, targetModule).then(function () {
      return runEval$2(System, originalSource, _extends({}, options, { importsEnsured: true }));
    });
  }

  // delay eval to ensure SystemJS module record
  if (!module.record()) {
    if (!options.sync && !options._moduleImported) return System.import(targetModule).catch(function (err) {
      return null;
    }).then(function () {
      return runEval$2(System, originalSource, _extends({}, options, { _moduleImported: true }));
    });

    module.ensureRecord(); // so we can record dependent modules
  }

  // delay eval to ensure transpiler is loaded
  if (options.es6Transpile && options.transpiler instanceof Promise) {
    if (!options.sync && !options._transpilerLoaded) {
      return options.transpiler.catch(function (err) {
        return console.error(err);
      }).then(function (transpiler) {
        return runEval$2(System, originalSource, _extends({}, options, { transpiler: transpiler, _transpilerLoaded: true }));
      });
    } else {
      console.warn("[lively.vm] sync eval requested but transpiler is not yet loaded, will continue without transpilation!");
      options.transpiler = null;
    }
  }

  System.debug && console.log("[lively.module] runEval in module " + targetModule + " started");

  lively_notifications.emit("lively.vm/doitrequest", {
    code: originalSource,
    waitForPromise: options.waitForPromise,
    targetModule: options.targetModule
  }, Date.now(), System);

  System.get("@lively-env").evaluationStart(targetModule);

  var result = runEval$1(code, options);

  return options.sync ? evalEnd(System, originalSource, options, result) : Promise.resolve(result).then(function (result) {
    return evalEnd(System, originalSource, options, result);
  });
}

function evalEnd(System, code, options, result) {

  System.get("@lively-env").evaluationEnd(options.targetModule);
  System.debug && console.log("[lively.module] runEval in module " + options.targetModule + " done");

  lively_notifications.emit("lively.vm/doitresult", {
    code: code, result: result,
    waitForPromise: options.waitForPromise,
    targetModule: options.targetModule
  }, Date.now(), System);

  return result;
}

/*global System,location*/
var EvalStrategy = function () {
  function EvalStrategy() {
    classCallCheck(this, EvalStrategy);
  }

  createClass(EvalStrategy, [{
    key: "runEval",
    value: function () {
      var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(source, options) {
        return regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                return _context.abrupt("return", Promise.reject("runEval(source, options) not yet implemented for " + this.constructor.name));

              case 1:
              case "end":
                return _context.stop();
            }
          }
        }, _callee, this);
      }));

      function runEval(_x, _x2) {
        return _ref.apply(this, arguments);
      }

      return runEval;
    }()
  }, {
    key: "keysOfObject",
    value: function () {
      var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(prefix, options) {
        return regeneratorRuntime.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                return _context2.abrupt("return", Promise.reject("keysOfObject(prefix, options) not yet implemented for " + this.constructor.name));

              case 1:
              case "end":
                return _context2.stop();
            }
          }
        }, _callee2, this);
      }));

      function keysOfObject(_x3, _x4) {
        return _ref2.apply(this, arguments);
      }

      return keysOfObject;
    }()
  }]);
  return EvalStrategy;
}();

var SimpleEvalStrategy = function (_EvalStrategy) {
  inherits(SimpleEvalStrategy, _EvalStrategy);

  function SimpleEvalStrategy() {
    classCallCheck(this, SimpleEvalStrategy);
    return possibleConstructorReturn(this, (SimpleEvalStrategy.__proto__ || Object.getPrototypeOf(SimpleEvalStrategy)).apply(this, arguments));
  }

  createClass(SimpleEvalStrategy, [{
    key: "runEval",
    value: function () {
      var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(source, options) {
        return regeneratorRuntime.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                return _context3.abrupt("return", Promise.resolve().then(function () {
                  try {
                    return Promise.resolve({ value: eval(source) });
                  } catch (err) {
                    return { isError: true, value: err };
                  }
                }));

              case 1:
              case "end":
                return _context3.stop();
            }
          }
        }, _callee3, this);
      }));

      function runEval(_x5, _x6) {
        return _ref3.apply(this, arguments);
      }

      return runEval;
    }()
  }, {
    key: "keysOfObject",
    value: function () {
      var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(prefix, options) {
        var _this2 = this;

        var result;
        return regeneratorRuntime.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                _context4.next = 2;
                return lively.vm.completions.getCompletions(function (code) {
                  return _this2.runEval(code, options);
                }, prefix);

              case 2:
                result = _context4.sent;
                return _context4.abrupt("return", { completions: result.completions, prefix: result.startLetters });

              case 4:
              case "end":
                return _context4.stop();
            }
          }
        }, _callee4, this);
      }));

      function keysOfObject(_x7, _x8) {
        return _ref4.apply(this, arguments);
      }

      return keysOfObject;
    }()
  }]);
  return SimpleEvalStrategy;
}(EvalStrategy);

var LivelyVmEvalStrategy = function (_EvalStrategy2) {
  inherits(LivelyVmEvalStrategy, _EvalStrategy2);

  function LivelyVmEvalStrategy() {
    classCallCheck(this, LivelyVmEvalStrategy);
    return possibleConstructorReturn(this, (LivelyVmEvalStrategy.__proto__ || Object.getPrototypeOf(LivelyVmEvalStrategy)).apply(this, arguments));
  }

  createClass(LivelyVmEvalStrategy, [{
    key: "normalizeOptions",
    value: function normalizeOptions(options) {
      if (!options.targetModule) throw new Error("runEval called but options.targetModule not specified!");

      return Object.assign({
        sourceURL: options.targetModule + "_doit_" + Date.now()
      }, options);
    }
  }, {
    key: "runEval",
    value: function () {
      var _ref5 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(source, options) {
        var System;
        return regeneratorRuntime.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                options = this.normalizeOptions(options);
                System = options.System || lively.modules.System;

                System.config({ meta: defineProperty({}, options.targetModule, { format: "esm" }) });
                return _context5.abrupt("return", lively.vm.runEval(source, options));

              case 4:
              case "end":
                return _context5.stop();
            }
          }
        }, _callee5, this);
      }));

      function runEval(_x9, _x10) {
        return _ref5.apply(this, arguments);
      }

      return runEval;
    }()
  }, {
    key: "keysOfObject",
    value: function () {
      var _ref6 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(prefix, options) {
        var result;
        return regeneratorRuntime.wrap(function _callee6$(_context6) {
          while (1) {
            switch (_context6.prev = _context6.next) {
              case 0:
                _context6.next = 2;
                return lively.vm.completions.getCompletions(function (code) {
                  return lively.vm.runEval(code, options);
                }, prefix);

              case 2:
                result = _context6.sent;
                return _context6.abrupt("return", { completions: result.completions, prefix: result.startLetters });

              case 4:
              case "end":
                return _context6.stop();
            }
          }
        }, _callee6, this);
      }));

      function keysOfObject(_x11, _x12) {
        return _ref6.apply(this, arguments);
      }

      return keysOfObject;
    }()
  }]);
  return LivelyVmEvalStrategy;
}(EvalStrategy);

var RemoteEvalStrategy = function (_LivelyVmEvalStrategy) {
  inherits(RemoteEvalStrategy, _LivelyVmEvalStrategy);

  function RemoteEvalStrategy() {
    classCallCheck(this, RemoteEvalStrategy);
    return possibleConstructorReturn(this, (RemoteEvalStrategy.__proto__ || Object.getPrototypeOf(RemoteEvalStrategy)).apply(this, arguments));
  }

  createClass(RemoteEvalStrategy, [{
    key: "sourceForRemote",
    value: function sourceForRemote(action, arg, options) {
      var contextFetch = lively_lang.obj.isString(options.context) ? options.context : false;
      options = lively_lang.obj.dissoc(options, ["systemInterface", "System", "context"]);
      return "\n(function() {\n  var arg = " + JSON.stringify(arg) + ",\n      options = " + JSON.stringify(options) + ";\n  if (typeof lively === \"undefined\" || !lively.vm) {\n    return Promise.resolve({\n      isEvalResult: true,\n      isError: true,\n      value: 'lively.vm not available!'\n    });\n  }\n  var hasSystem = typeof System !== \"undefined\"\n  options.context = " + contextFetch + "\n  if (!options.context) {\n    options.context = hasSystem\n      ? System.global\n      : typeof window !== \"undefined\"\n          ? window\n          : typeof global !== \"undefined\"\n              ? global\n              : typeof self !== \"undefined\" ? self : this;\n  }\n  function evalFunction(source, options) {\n    if (hasSystem) {\n      var conf = {meta: {}}; conf.meta[options.targetModule] = {format: \"esm\"};\n      System.config(conf);\n    } else {\n      options = Object.assign({topLevelVarRecorderName: \"GLOBAL\"}, options);\n      delete options.targetModule;\n    }\n    return lively.vm.runEval(source, options);\n  }\n  function keysOfObjectFunction(prefix, options) {\n    return lively.vm.completions.getCompletions(code => evalFunction(code, options), prefix)\n      .then(result => ({isEvalResult: true, completions: result.completions, prefix: result.startLetters}));\n  }\n  return " + (action === "eval" ? "evalFunction" : "keysOfObjectFunction") + "(arg, options)\n    .catch(err => ({isEvalResult: true, isError: true, value: String(err.stack || err)}));\n})();\n";
    }
  }, {
    key: "runEval",
    value: function () {
      var _ref7 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(source, options) {
        return regeneratorRuntime.wrap(function _callee7$(_context7) {
          while (1) {
            switch (_context7.prev = _context7.next) {
              case 0:
                return _context7.abrupt("return", this.remoteEval(this.sourceForRemote("eval", source, options), options));

              case 1:
              case "end":
                return _context7.stop();
            }
          }
        }, _callee7, this);
      }));

      function runEval(_x13, _x14) {
        return _ref7.apply(this, arguments);
      }

      return runEval;
    }()
  }, {
    key: "keysOfObject",
    value: function () {
      var _ref8 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(prefix, options) {
        return regeneratorRuntime.wrap(function _callee8$(_context8) {
          while (1) {
            switch (_context8.prev = _context8.next) {
              case 0:
                return _context8.abrupt("return", this.remoteEval(this.sourceForRemote("keysOfObject", prefix, options), options));

              case 1:
              case "end":
                return _context8.stop();
            }
          }
        }, _callee8, this);
      }));

      function keysOfObject(_x15, _x16) {
        return _ref8.apply(this, arguments);
      }

      return keysOfObject;
    }()
  }, {
    key: "remoteEval",
    value: function () {
      var _ref9 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9(source, options) {
        var result;
        return regeneratorRuntime.wrap(function _callee9$(_context9) {
          while (1) {
            switch (_context9.prev = _context9.next) {
              case 0:
                _context9.prev = 0;
                _context9.next = 3;
                return this.basicRemoteEval(source, options);

              case 3:
                result = _context9.sent;
                return _context9.abrupt("return", typeof result === "string" ? JSON.parse(result) : result);

              case 7:
                _context9.prev = 7;
                _context9.t0 = _context9["catch"](0);
                return _context9.abrupt("return", { isError: true, value: "Remote eval failed: " + (result || _context9.t0) });

              case 10:
              case "end":
                return _context9.stop();
            }
          }
        }, _callee9, this, [[0, 7]]);
      }));

      function remoteEval(_x17, _x18) {
        return _ref9.apply(this, arguments);
      }

      return remoteEval;
    }()
  }, {
    key: "basicRemoteEval",
    value: function () {
      var _ref10 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee10(source, options) {
        return regeneratorRuntime.wrap(function _callee10$(_context10) {
          while (1) {
            switch (_context10.prev = _context10.next) {
              case 0:
                throw new Error("Not yet implemented");

              case 1:
              case "end":
                return _context10.stop();
            }
          }
        }, _callee10, this);
      }));

      function basicRemoteEval(_x19, _x20) {
        return _ref10.apply(this, arguments);
      }

      return basicRemoteEval;
    }()
  }]);
  return RemoteEvalStrategy;
}(LivelyVmEvalStrategy);

var HttpEvalStrategy = function (_RemoteEvalStrategy) {
  inherits(HttpEvalStrategy, _RemoteEvalStrategy);
  createClass(HttpEvalStrategy, null, [{
    key: "defaultURL",
    get: function get() {
      return "http://localhost:3000/lively";
    }
  }]);

  function HttpEvalStrategy(url) {
    classCallCheck(this, HttpEvalStrategy);

    var _this5 = possibleConstructorReturn(this, (HttpEvalStrategy.__proto__ || Object.getPrototypeOf(HttpEvalStrategy)).call(this));

    _this5.url = url || _this5.constructor.defaultURL;
    return _this5;
  }

  createClass(HttpEvalStrategy, [{
    key: "normalizeOptions",
    value: function normalizeOptions(options) {
      options = get$1(HttpEvalStrategy.prototype.__proto__ || Object.getPrototypeOf(HttpEvalStrategy.prototype), "normalizeOptions", this).call(this, options);
      return Object.assign({ serverEvalURL: this.url }, options, { context: null });
    }
  }, {
    key: "basicRemoteEval",
    value: function () {
      var _ref11 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee11(source, options) {
        var method;
        return regeneratorRuntime.wrap(function _callee11$(_context11) {
          while (1) {
            switch (_context11.prev = _context11.next) {
              case 0:
                options = this.normalizeOptions(options);
                method = "basicRemoteEval_" + (System.get("@system-env").node ? "node" : "web");
                _context11.next = 4;
                return this[method]({ method: "POST", body: source }, options.serverEvalURL);

              case 4:
                return _context11.abrupt("return", _context11.sent);

              case 5:
              case "end":
                return _context11.stop();
            }
          }
        }, _callee11, this);
      }));

      function basicRemoteEval(_x21, _x22) {
        return _ref11.apply(this, arguments);
      }

      return basicRemoteEval;
    }()
  }, {
    key: "basicRemoteEval_web",
    value: function () {
      var _ref12 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee12(payload, url) {
        var _ref13, _ref14, domain, loc, crossDomain, res;

        return regeneratorRuntime.wrap(function _callee12$(_context12) {
          while (1) {
            switch (_context12.prev = _context12.next) {
              case 0:
                _ref13 = url.match(/[^:]+:\/\/[^\/]+/) || [url], _ref14 = slicedToArray(_ref13, 1), domain = _ref14[0], loc = void 0, crossDomain = void 0;

                // fixme: this should be replaced by accessing the location
                //        in a canonical way

                if (System.get("@system-env").worker) loc = window.location;else {
                  loc = document.location;
                }

                crossDomain = loc.origin !== domain;

                if (crossDomain) {
                  // use lively.server proxy plugin
                  payload.headers = _extends({}, payload.headers, {
                    'pragma': 'no-cache',
                    'cache-control': 'no-cache',
                    "x-lively-proxy-request": url
                  });
                  url = loc.origin;
                }

                _context12.prev = 4;
                _context12.next = 7;
                return window.fetch(url, payload);

              case 7:
                res = _context12.sent;
                _context12.next = 13;
                break;

              case 10:
                _context12.prev = 10;
                _context12.t0 = _context12["catch"](4);
                throw new Error("Cannot reach server at " + url + ": " + _context12.t0.message);

              case 13:
                if (res.ok) {
                  _context12.next = 15;
                  break;
                }

                throw new Error("Server at " + url + ": " + res.statusText);

              case 15:
                return _context12.abrupt("return", res.text());

              case 16:
              case "end":
                return _context12.stop();
            }
          }
        }, _callee12, this, [[4, 10]]);
      }));

      function basicRemoteEval_web(_x23, _x24) {
        return _ref12.apply(this, arguments);
      }

      return basicRemoteEval_web;
    }()
  }, {
    key: "basicRemoteEval_node",
    value: function () {
      var _ref15 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee13(payload, url) {
        var urlParse, http, opts;
        return regeneratorRuntime.wrap(function _callee13$(_context13) {
          while (1) {
            switch (_context13.prev = _context13.next) {
              case 0:
                urlParse = System._nodeRequire("url").parse, http = System._nodeRequire(url.startsWith("https:") ? "https" : "http"), opts = Object.assign({ method: payload.method || "GET" }, urlParse(url));
                return _context13.abrupt("return", new Promise(function (resolve, reject) {
                  var request = http.request(opts, function (res) {
                    res.setEncoding('utf8');
                    var data = "";
                    res.on('data', function (chunk) {
                      return data += chunk;
                    });
                    res.on('end', function () {
                      return resolve(data);
                    });
                    res.on('error', function (err) {
                      return reject(err);
                    });
                  });
                  request.on('error', function (err) {
                    return reject(err);
                  });
                  request.end(payload.body);
                }));

              case 2:
              case "end":
                return _context13.stop();
            }
          }
        }, _callee13, this);
      }));

      function basicRemoteEval_node(_x25, _x26) {
        return _ref15.apply(this, arguments);
      }

      return basicRemoteEval_node;
    }()
  }]);
  return HttpEvalStrategy;
}(RemoteEvalStrategy);

var L2LEvalStrategy = function (_RemoteEvalStrategy2) {
  inherits(L2LEvalStrategy, _RemoteEvalStrategy2);

  function L2LEvalStrategy(l2lClient, targetId) {
    classCallCheck(this, L2LEvalStrategy);

    var _this6 = possibleConstructorReturn(this, (L2LEvalStrategy.__proto__ || Object.getPrototypeOf(L2LEvalStrategy)).call(this));

    _this6.l2lClient = l2lClient;
    _this6.targetId = targetId;
    return _this6;
  }

  createClass(L2LEvalStrategy, [{
    key: "basicRemoteEval",
    value: function () {
      var _ref16 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee14(source, options) {
        var l2lClient, targetId, _ref17, evalResult;

        return regeneratorRuntime.wrap(function _callee14$(_context14) {
          while (1) {
            switch (_context14.prev = _context14.next) {
              case 0:
                l2lClient = this.l2lClient;
                targetId = this.targetId;
                _context14.next = 4;
                return new Promise(function (resolve, reject) {
                  return l2lClient.sendTo(targetId, "remote-eval", { source: source }, resolve);
                });

              case 4:
                _ref17 = _context14.sent;
                evalResult = _ref17.data;

                if (evalResult && evalResult.value && evalResult.value.isEvalResult) evalResult = evalResult.value;
                return _context14.abrupt("return", evalResult);

              case 8:
              case "end":
                return _context14.stop();
            }
          }
        }, _callee14, this);
      }));

      function basicRemoteEval(_x27, _x28) {
        return _ref16.apply(this, arguments);
      }

      return basicRemoteEval;
    }()
  }]);
  return L2LEvalStrategy;
}(RemoteEvalStrategy);



var evalStrategies = Object.freeze({
	RemoteEvalStrategy: RemoteEvalStrategy,
	EvalStrategy: EvalStrategy,
	SimpleEvalStrategy: SimpleEvalStrategy,
	LivelyVmEvalStrategy: LivelyVmEvalStrategy,
	HttpEvalStrategy: HttpEvalStrategy,
	L2LEvalStrategy: L2LEvalStrategy
});

function runEval$$1(code, options) {
  var _options = options = _extends({
    format: "esm",
    System: null,
    targetModule: null
  }, options),
      format = _options.format,
      S = _options.System,
      targetModule = _options.targetModule;

  if (!S && typeof System !== "undefined") S = System;
  if (!S && targetModule) {
    return Promise.reject(new Error("options to runEval have targetModule but cannot find system loader!"));
  }

  return targetModule && ["esm", "es6", "register"].includes(format) ? runEval$2(S, code, options) : runEval$1(code, options);
}

function syncEval$$1(code, options) {
  return syncEval$1(code, options);
}

exports.completions = completions;
exports.runEval = runEval$$1;
exports.syncEval = syncEval$$1;
exports.evalStrategies = evalStrategies;
exports.defaultTopLevelVarRecorderName = defaultTopLevelVarRecorderName;
exports.defaultClassToFunctionConverterName = defaultClassToFunctionConverterName;
exports.evalCodeTransform = evalCodeTransform;
exports.evalCodeTransformOfSystemRegisterSetters = evalCodeTransformOfSystemRegisterSetters;

}((this.lively.vm = this.lively.vm || {}),lively.lang,lively.ast,lively.sourceTransform,lively.classes,lively.notifications));

  if (typeof module !== "undefined" && module.exports) module.exports = GLOBAL.lively.vm;
})();