text: /*
   * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
   * This devtool is neither made for production nor for readable output files.
   * It uses "eval()" calls to create a separate source file in the browser devtools.
   * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
   * or disable the default devtool with "devtool: false".
   * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
   */
  /******/ (() => { // webpackBootstrap
  /******/ 	var __webpack_modules__ = ({
  
  /***/ "../../browser.js":
  /*!************************!*\
    !*** ../../browser.js ***!
    \************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("\nconst olo = module.exports = {};\n\nolo.expression = __webpack_require__(/*! ./lib/expression */ \"../../lib/expression.js\");\n\nolo.document = __webpack_require__(/*! ./lib/document */ \"../../lib/document.js\");\n\nolo.Store = __webpack_require__(/*! ./lib/store */ \"../../lib/store.js\");\nolo.MemoryStore = __webpack_require__(/*! ./lib/memory-store */ \"../../lib/memory-store.js\");\nolo.BrowserStore = __webpack_require__(/*! ./src/browser-store */ \"../../src/browser-store.js\");\nolo.HTTPStore = __webpack_require__(/*! ./lib/http-store */ \"../../lib/http-store.js\");\nolo.Router = __webpack_require__(/*! ./lib/router */ \"../../lib/router.js\");\n\n\n//# sourceURL=webpack:///../../browser.js?");
  
  /***/ }),
  
  /***/ "../../lib/document.js":
  /*!*****************************!*\
    !*** ../../lib/document.js ***!
    \*****************************/
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
  
  eval("/**\n *  <!--<% __render__ = require 'markdown' %>-->\n *  olojs.document\n *  ============================================================================\n *  This module contains functions to parse, evaluate and render olojs\n *  documents.\n *\n *  ```js\n *  source = \"Twice x is <% 2*x %>!\";\n *  evaluate = olojs.document.parse(source);\n *  context = olojs.document.createContext({x:10});\n *  {data, text} = await evaluate(context);    \n *      // data: {x:10}\n *      // text: \"Twice x is 20\"\n *  ```\n */\n\nconst swan = __webpack_require__(/*! ./expression */ \"../../lib/expression.js\");\n\n\n\n\n\n/**\n *  olojs.document.parse - function\n *  ----------------------------------------------------------------------------\n *  Compiles a document source into an `evaluate` function that takes as input\n *  a document context object and returns the document namespace object and its\n *  rendered text.\n *\n *  ```js\n *  evaluate = olojs.document.parse(source);\n *  {data, text} = await evaluate(context);\n *  ```\n *\n *  - `source` is a string containing the source of the olojs document to be\n *    evaluated\n *  - `evaluate` is an asynchronous function that evaluates the document and\n *    returns its namespace and its rendered text\n *  - `data` is an object containing all the names defined by the inline\n *    expressions of the document (the document namespace).\n *  - `text` is a string obtained by replacing every inline expression with its \n *    strigified value. \n *  \n *  > Notice that in a swan expression context, `str(data)` will return `text`,\n *  > therefore `await context.str(data)` is a way to obtain `text` given `data`\n *  > in JavaScript.\n */\nexports.parse = function (source) {\n    var source = String(source);\n\n    // // Parse fragments\n    // source = source.replace(/<\\s*def:([a-z_A-Z]+[a-z_A-Z0-9]*)\\s+(.*)>(.*)<\\s*\\/def:\\1\\s*>/g, (match, identifier, attributes, content) => {\n    //     return \"\";\n    // });    \n\n    // Find all the swan expressions in the source, store them in an array and\n    // replace them with a placeholder.\n    const parsedExpressions = [];\n    source = source.replace(/<%([\\s\\S]+?)%>/g, (match, expressionSource) => {\n        let i = parsedExpressions.length;\n        let parsedExpression = swan.parse(expressionSource);\n        parsedExpression.source = expressionSource;\n        parsedExpressions.push( parsedExpression );\n        return `<%%>`;\n    });\n    const textChunks = source.split('<%%>');\n\n    // The returned `evaluate` function\n    return async (context) => {\n        const doc = {};\n        \n        // Create a copy ot the context\n        context = Object.assign(Object.create(Object.getPrototypeOf(context)), context);\n        \n        // Evaluate each expression in the given context and replace the\n        // expression source with the stringified expression value\n        doc.text = textChunks[0] || \"\";\n        for (let i=0; i<parsedExpressions.length; i++) {\n            let evaluateExpression = parsedExpressions[i];\n            try {\n                var value = await evaluateExpression(context);\n            } catch (error) {\n                // in case of error returns an Undefined failure value\n                var value = await context.undefined('failure', error);\n            }\n            doc.text += await context.str(value) + textChunks[i+1];\n        }\n        \n        // Decorate the rendered text with the `__render__` function, if present\n        if (typeof context.__render__ === 'function') {\n            const decoratedText = await context.__render__(doc.text);\n            doc.text = await context.str(decoratedText);\n        }\n        \n        // Extract the document namespace,\n        // discarding the global context variables.\n        doc.data = Object.assign({}, context);\n        \n        // Return both rendered text and data\n        return doc\n    };\n}\n\n\n\n\n/**\n *  olojs.document.createContext - function\n *  ----------------------------------------------------------------------------\n *  Creates a custom document evaluation context, by adding to the basic\n *  context all the names defined in the passed namespaces.\n *\n *  ```js\n *  context = olojs.document.createContext(...namespaces)\n *  ```\n *  - `namespaces`: list of objects; each of them, from left to right, will be\n *    mixed-in to the basic document context\n *  - `context`: an object containing all the named values and functions that\n *    will be visible to the document inline expressions.\n */\nexports.createContext = function (...namespaces) {\n    return swan.createContext(documentGlobals, ...namespaces);\n}\n\nconst documentGlobals = {};\n\n\n\n//# sourceURL=webpack:///../../lib/document.js?");
  
  /***/ }),
  
  /***/ "../../lib/expression.js":
  /*!*******************************!*\
    !*** ../../lib/expression.js ***!
    \*******************************/
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
  
  eval("const swan = __webpack_require__(/*! @onlabsorg/swan-js */ \"../../node_modules/@onlabsorg/swan-js/index.js\");\n\nconst Lexer = __webpack_require__(/*! @onlabsorg/swan-js/lib/lexer */ \"../../node_modules/@onlabsorg/swan-js/lib/lexer.js\");\nLexer.matchIdentifier = identifier => /^[a-z_A-Z]+[a-z_A-Z0-9]*$/.test(identifier);\n\nconst swan_modules = __webpack_require__(/*! @onlabsorg/swan-js/lib/modules */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/index.js\");\nswan_modules.markdown = () => Promise.all(/*! import() | swan_modules/markdown */[__webpack_require__.e(\"vendors-node_modules_marked_lib_marked_cjs\"), __webpack_require__.e(\"swan_modules/markdown\")]).then(__webpack_require__.t.bind(__webpack_require__, /*! ./swan_modules/markdown.js */ \"../../lib/swan_modules/markdown.js\", 23));\n\nexports.parse = function (source) {\n    try {\n        return swan.parse(source);\n    } catch (error) {\n        return () => new swan.types.Undefined(\"Syntax\", error);\n    }\n}\n\nexports.createContext = swan.createContext;\n\nexports.types = swan.types;\n\nexports.modules = swan_modules;\n\n\n//# sourceURL=webpack:///../../lib/expression.js?");
  
  /***/ }),
  
  /***/ "../../lib/http-store.js":
  /*!*******************************!*\
    !*** ../../lib/http-store.js ***!
    \*******************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("__webpack_require__(/*! isomorphic-fetch */ \"../../node_modules/isomorphic-fetch/fetch-npm-browserify.js\");\nconst pathlib = __webpack_require__(/*! path */ \"../../node_modules/path-browserify/index.js\");\nconst Store = __webpack_require__(/*! ./store */ \"../../lib/store.js\");\n\n\nconst isObject = obj => obj && typeof obj === 'object' && !Array.isArray(obj);\nconst isURI = s => /^([a-zA-Z][a-zA-Z0-9+.-]*):\\/(.*)$/.test(s);\n\n\n/**\n *  <!--<% __render__ = require 'markdown' %>-->\n *\n *  HTTPStore\n *  ============================================================================\n *  This store handles read/write operations on remote olo-documents\n *  via HTTP(S).\n *\n *  ```js\n *  httpStore = new HTTPStore(rootURL, options)\n *  ```\n *\n *  - `rootURL` is the base URL that will be prepended to the paths passed to\n *    the `read`, `write` and `delete` methods.\n *  - `options.headers` are custom headers that will be added to every HTTP\n *    request.\n *  - `options.extension` is a custom file extension to be appended to the path\n *    of each `read`, `write` and `delete` request.\n *  - `httpStore` is a [olojs.Store](./store.md) object\n *  \n *  > HTTPStore inherits from the [Store](./store.md) class and overrides the\n *  > methods described below.\n */\nclass HTTPStore extends Store {\n\n    constructor (rootURL, options={}) {\n        super();\n        if (rootURL.slice(0,6).toLowerCase() === 'http:/') {\n            this.rootURL = 'http:/' + pathlib.normalize(`/${rootURL.slice(6)}/`);\n        } else if (rootURL.slice(0,7).toLowerCase() === 'https:/') {\n            this.rootURL = 'https:/' + pathlib.normalize(`/${rootURL.slice(7)}/`);\n        } else {\n            throw new Error(`Invalid http URL: ${rootURL}`)\n        }\n        this.headers = Object.assign({}, options.headers);\n        this.extension = normalizeExtension(options.extension);\n    }\n\n    resolveURL (path) {\n        return this.rootURL + pathlib.normalize(`/${path}`).slice(1);\n    }\n\n\n    /**\n     *  async httpStore.read: String path -> String source\n     *  ------------------------------------------------------------------------\n     *  Retrieves a remote olo-document via HTTP GET (HTTPS GET).\n     *\n     *  ```js\n     *  source = await httpStore.read(\"/path/to/doc\")\n     *  ```\n     *\n     *  - On 200 status code, returns the response body as string\n     *  - On 403 status code, throws a `HTTPStore.ReadPermissionDeniedError`\n     *  - On 404 status code, return an empty string\n     *  - On 405 or 501 status code, throws a `HTTPStore.ReadOperationNotAllowedError`\n     *  - On any other status code, throws a generic error\n     */\n    async read (path) {\n        if (isURI(path)) throw new this.constructor.ReadOperationNotAllowedError(path);\n        const url = this.resolveURL(path + this.extension);\n\n        const response = await fetch(url, {\n            method: 'get',\n            headers: Object.assign({}, this.headers, {\n                'Accept': 'text/*',\n            }),\n        });\n\n        switch (response.status) {\n            case 200:\n                return await response.text();\n            case 403:\n                throw new this.constructor.ReadPermissionDeniedError(path);\n            case 404:\n                return \"\";\n            case 405:\n            case 501:\n                throw new this.constructor.ReadOperationNotAllowedError(path);\n            default:\n                let message = await response.text();\n                throw new Error(message);\n        }\n    }\n\n\n    /**\n     *  async httpStore.write: (String path, String source) -> undefined\n     *  ------------------------------------------------------------------------\n     *  Modifies a remote olo-document via HTTP PUT (HTTPS PUT).\n     *\n     *  ```js\n     *  await httpStore.write(\"/path/to/doc\", source)\n     *  ```\n     *\n     *  - On 200 and 201 status code, returns\n     *  - On 403 status code, throws a `HTTPStore.WritePermissionDeniedError`\n     *  - On 405 or 501 status code, throws a `HTTPStore.WriteOperationNotAllowedError`\n     *  - On any other status code, throws a generic error\n     */\n    async write (path, source) {\n        if (isURI(path)) throw new this.constructor.WriteOperationNotAllowedError(path);\n        const url = this.resolveURL(path + this.extension);\n\n        const response = await fetch(url, {\n            method: 'put',\n            headers: Object.assign({}, this.headers, {\n                'Accept': 'text/*',\n                'Content-Type': 'text/plain',\n            }),\n            body: String(source)\n        });\n\n        switch (response.status) {\n            case 200:\n            case 201:\n                break;\n            case 403:\n                throw new this.constructor.WritePermissionDeniedError(path);\n            case 405:\n            case 501:\n                throw new this.constructor.WriteOperationNotAllowedError(path);\n            default:\n                let message = await response.text();\n                throw new Error(message);\n        }\n    }\n\n\n    /**\n     *  async httpStore.delete: String path -> undefined\n     *  ------------------------------------------------------------------------\n     *  Removes a remote olo-document via HTTP DELETE (HTTPS DELETE).\n     *\n     *  ```js\n     *  await httpStore.delete(\"/path/to/doc\")\n     *  ```\n     *\n     *  - On 200 status code, returns\n     *  - On 403 status code, throws a `HTTPStore.WritePermissionDeniedError`\n     *  - On 405 or 501 status code, throws a `HTTPStore.WriteOperationNotAllowedError`\n     *  - On any other status code, throws a generic error\n     */\n    async delete (path) {\n        if (isURI(path)) throw new this.constructor.WriteOperationNotAllowedError(path);\n        const url = this.resolveURL(path + this.extension);\n\n        const response = await fetch(url, {\n            method: 'delete',\n            headers: Object.assign({}, this.headers, {\n                'Accept': 'text/*',\n                'Content-Type': 'text/plain',\n            })\n        });\n\n        switch (response.status) {\n            case 200:\n                break;\n            case 403:\n                throw new this.constructor.WritePermissionDeniedError(path);\n            case 405:\n            case 501:\n                throw new this.constructor.WriteOperationNotAllowedError(path);\n            default:\n                let message = await response.text();\n                throw new Error(message);\n        }\n    }\n}\n\n\nmodule.exports = HTTPStore;\n\n\n\n// -----------------------------------------------------------------------------\n//  Helper Functions\n// -----------------------------------------------------------------------------\n\nfunction normalizeExtension (ext=\"\") {\n    while (ext[0] === \".\") ext = ext.slice(1);\n    return ext === \"\" ? ext : `.${ext}`;\n}\n\n\n//# sourceURL=webpack:///../../lib/http-store.js?");
  
  /***/ }),
  
  /***/ "../../lib/memory-store.js":
  /*!*********************************!*\
    !*** ../../lib/memory-store.js ***!
    \*********************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const pathlib = __webpack_require__(/*! path */ \"../../node_modules/path-browserify/index.js\");\nconst Store = __webpack_require__(/*! ./store */ \"../../lib/store.js\");\n\n\n\n/**\n *  <!--<% __render__ = require 'markdown' %>-->\n *\n *  MemoryStore\n *  ============================================================================\n *  This store handles read/write operations on an in-memory map object.\n *\n *  ```js\n *  memStore = new MemoryStore({\n *      \"/path/to/doc1\": \"source of doc1\",\n *      \"/path/to/doc2\": \"source of doc2\",\n *      ...\n *  })\n *  ```\n *\n *  > MemoryStore inherits from the [Store](./store.md) class and overrides the\n *  > methods described below.\n */\nclass MemoryStore extends Store {\n\n    constructor (documents={}) {\n        super();\n        this._content = new Map();\n        for (let path in documents) {\n            this._content.set(this.normalizePath(path), String(documents[path]));\n        }\n    }\n\n    /**\n     *  async memStore.read: String path -> String source\n     *  ------------------------------------------------------------------------\n     *  Retrieves the in-memory document source mapped to the given path.\n     *\n     *  ```js\n     *  const source = await memStore.read(\"/path/to/doc\");\n     *  ```\n     *\n     *  - When requesting `path/to/x/../doc`, the content of `/path/to/doc` will\n     *    be returned\n     *  - When requesting an entry that doesn't exist, and empty string will be\n     *    returned\n     */\n    read (path) {\n        const normPath = this.normalizePath(path);\n        return this._content.get(normPath) || \"\";\n    }\n\n\n    /**\n     *  async memStore.write: (String path, String source) -> undefined\n     *  ------------------------------------------------------------------------\n     *  Maps a document path to a source, in memory.\n     *\n     *  ```js\n     *  await memStore.write(\"/path/to/doc\", source);\n     *  ```\n     *\n     *  - If path is `path/to/x/../doc`, the content of `/path/to/doc` will\n     *    be modified with the passed source\n     *  - `source` will be always converted to string\n     */\n    write (path, source) {\n        const normPath = this.normalizePath(path);\n        return this._content.set(normPath, String(source));\n    }\n\n\n    /**\n     *  async memStore.delete: String path -> undefined\n     *  ------------------------------------------------------------------------\n     *  Erases the doc source mapped in memory to the given path.\n     *\n     *  ```js\n     *  await memStore.delete(\"/path/to/doc\");\n     *  ```\n     *\n     *  - If path is `path/to/x/../doc`, the entry `/path/to/doc` will be deleted\n     */\n    delete (path) {\n        const normPath = this.normalizePath(path);\n        return this._content.delete(normPath);\n    }\n}\n\nmodule.exports = MemoryStore;\n\n\n//# sourceURL=webpack:///../../lib/memory-store.js?");
  
  /***/ }),
  
  /***/ "../../lib/router.js":
  /*!***************************!*\
    !*** ../../lib/router.js ***!
    \***************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const pathlib = __webpack_require__(/*! path */ \"../../node_modules/path-browserify/index.js\");\nconst Store = __webpack_require__(/*! ./store */ \"../../lib/store.js\");\n\nconst URI_SCHEME_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*$/\nconst URI_RE        = /^([a-zA-Z][a-zA-Z0-9+.-]*):\\/(.*)$/;\n\n\n\n\n/**\n *  <!--<% __render__ = require 'markdown' %>-->\n *\n *  Router\n *  ============================================================================\n *  This store is a container for other stores and routes the `read`, `write`\n *  and `delete` requests to the store best matching the path.\n *\n *  ```js\n *  routes = {\n *      \"/path/to/store_1/\": store_1,\n *      \"/path/to/store_2/\": store_2,\n *      ...\n *  };\n *\n *  router = new Router(routes);\n *  ```\n *\n *  Every time a `read`, `write` or `delete` method is called on a `path`, the \n *  router delegates to the corresponding method of the store matching the path. \n *  For example, with reference to the router declaration above:\n *\n *  - `router.read('/path/to/store_1/path/to/doc')` will result in a call to\n *    `store_1.read('/path/to/doc')`\n *  - `router.read('/path/to/store_2/path/to/doc')` will result in a call to\n *    `store_2.read('/path/to/doc')`\n *  \n *  If no match is found, it will behave as empty store, which is: `read` will\n *  return an empty string, `write` and `delete` will throw a \n *  `WriteOperationNotAllowed` error.\n *  \n *  The constructor will ignore the properties of the `routes` object which are\n *  not valid stores (i.e. objects that do not have any of the methods\n *  `read`, `write` or `delete`).\n *  The easiest way to create a valid store is by extending the\n *  [Store](./store.md) class.\n *  \n *  URI-like paths `xxx:/path/to/doc` are treated as shortcuts to the\n *  path `/.schemes/xxx/path/to/doc`.\n *  \n *  > Router inherits from the [Store](./store.md) class and overrides the\n *  > methods described below.\n */\nclass Router extends Store {\n\n    constructor (routes) {\n        super();\n        this._routes = {};\n        for (let path in routes) {\n            this.mount(path, routes[path]);\n        }\n    }\n\n\n    /**\n     *  async router.read: String path -> String source\n     *  ------------------------------------------------------------------------\n     *  Retrieves an olo-document from the matching sub-store.\n     *\n     *  ```js\n     *  router = new Router({\n     *      \"/path/to/store_1/\": store_1,\n     *      \"/path/to/store_2/\": store_2,\n     *      ...\n     *  })\n     *\n     *  source = await router.read(\"/path/to/store_i/sub/path/to/doc\");\n     *  ```\n     *\n     *  - When requesting `/path/to/store_i/sub/path/to/doc`, it returns\n     *    `await store_i.read('/sub/path/to/doc')`.\n     *  - When no store is mounted on `/path/to/store_i/`, it returns an empty\n     *    string\n     */\n    async read (path) {\n        const [store, subPath] = this._match(path);\n        return store ? await store.read(subPath) : await super.read(path);\n    }\n\n\n    /**\n     *  async router.write: (String path, String source) -> undefined\n     *  ------------------------------------------------------------------------\n     *  Modifies an olo-document contained in the matching sub-store.\n     *\n     *  ```js\n     *  router = new Router({\n     *      \"/path/to/store_1/\": store_1,\n     *      \"/path/to/store_2/\": store_2,\n     *      ...\n     *  })\n     *\n     *  await router.write(\"/path/to/store_i/sub/path/to/doc\", source);\n     *  ```\n     *\n     *  - When `/path/to/store_i/sub/path/to/doc` is passed, it calls\n     *    `await store_i.write('/sub/path/to/doc', source)`.\n     *  - When no store is mounted on `/path/to/store_i`, it throws a\n     *    `Router.WriteOperationNotAllowedError`.\n     */\n    async write (path, source) {\n        const [store, subPath] = this._match(path);\n        return store ? await store.write(subPath, source) : await super.write(path, source);\n    }\n\n\n    /**\n     *  async router.delete: String path -> undefined\n     *  ------------------------------------------------------------------------\n     *  Deletes an olo-document contained in the matching sub-store.\n     *\n     *  ```js\n     *  router = new Router({\n     *      \"/path/to/store_1/\": store_1,\n     *      \"/path/to/store_2/\": store_2,\n     *      ...\n     *  })\n     *\n     *  await router.delete(\"/path/to/store_i/sub/path/to/doc\");\n     *  ```\n     *\n     *  - When `/path/to/store_i/sub/path/to/doc` is passed, it calls\n     *    `await store_i.delete('/sub/path/to/doc')`.\n     *  - When no store is mounted on `/path/to/store_i/`, it throws a\n     *    `Router.WriteOperationNotAllowedError`.\n     */\n    async delete (path) {\n        const [store, subPath] = this._match(path);\n        return store ? await store.delete(subPath) : await super.delete(path);\n    }\n\n\n    // INTERNALS\n\n    normalizePath (path) {\n        const uri = path.match(URI_RE);\n        if (uri) {\n            const uriScheme = uri[1];\n            const uriPath = uri[2];\n            return super.normalizePath(`/.schemes/${uriScheme}/${uriPath}`);\n        } else {\n            return super.normalizePath(path);\n        }\n    }\n\n    resolvePath (basePath, subPath) {\n        return subPath.match(URI_RE) ? subPath : super.resolvePath(basePath, subPath);\n    }\n\n    // Finds the route that best matches the given document path and returns\n    // the corresponding store and the path relative to the matching route\n    _match (path) {\n        const normPath = this.normalizePath(path);\n        const matches = this._iterMatches(normPath);\n        return matches.next().value || [null, normPath];\n    }\n\n    *_iterMatches (normPath) {\n        for (let [routeId, store] of this._iterRoutes()) {\n            if (normPath.indexOf(routeId) === 0) {\n                const subPath = normPath.slice(routeId.length-1);\n                yield [store, subPath];\n            }\n        }\n    }\n\n    *_iterRoutes () {\n        const routeIds = Object.keys(this._routes).sort().reverse();\n        for (let routeId of routeIds) {\n            yield [routeId, this._routes[routeId]];\n        }\n    }\n\n    mount (path, store) {\n        path = this.normalizePath(path);\n        if (isStore(store)) {\n            this._routes[ this.normalizePath(`${path}/`) ] = store;\n        }\n    }\n\n    unmount (path) {\n        path = this.normalizePath(path);\n        delete this._routes[ this.normalizePath(`${path}/`) ];\n    }\n}\n\nmodule.exports = Router;\n\n\n\n// -----------------------------------------------------------------------------\n//  SERVICE FUNCTIONS\n// -----------------------------------------------------------------------------\n\nconst isStore = obj => {\n    if (typeof obj.read !== \"function\") return false;\n    if (typeof obj.write !== \"function\") return false;\n    if (typeof obj.delete !== \"function\") return false;\n    return true;\n};\n\nconst renameKeys = (ren, obj) => {\n    const newObj = {};\n    for (let key in obj) newObj[ren(key)] = obj[key];\n    return newObj;\n}\n\nconst sortObject = obj => {\n    const keys = Object.keys(obj).sort().reverse();\n    const map = new Map();\n    for (let key of keys) map.set(key, obj[key]);\n    return map;\n}\n\nconst filterObject = (test, obj) => {\n    const newObj = {};\n    for (let key in obj) if (test(obj[key])) newObj[key] = obj[key];\n    return newObj;\n}\n\nconst pushIfMissing = (list, item) => {\n    if (list.indexOf(item) === -1) list.push(item);\n}\n\nconst mergeLists = (list1, list2) => {\n    for (let item of list2) pushIfMissing(list1, item);\n}\n\n\n//# sourceURL=webpack:///../../lib/router.js?");
  
  /***/ }),
  
  /***/ "../../lib/store.js":
  /*!**************************!*\
    !*** ../../lib/store.js ***!
    \**************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const pathlib = __webpack_require__(/*! path */ \"../../node_modules/path-browserify/index.js\");\nconst document = __webpack_require__(/*! ./document */ \"../../lib/document.js\");\n\n\n/**\n *  <!--<% __render__ = require 'markdown' %>-->\n *\n *  Store\n *  ============================================================================\n *  This is the base class to be used to create olojs document stores.\n *  When instantiatete directly it behaves like a read-only empty store.\n *\n *  ```js\n *  // A read-only empty store\n *  store = new Store();\n *  \n *  // A store implementation\n *  class ChildStore extends Store {\n *      async read (path) { ... }\n *      async write (path, source) { ... }\n *      async delete (path) { ... }\n *  }\n *  ```\n */\nclass Store {\n\n    /**\n     *  async store.read: String path -> String source\n     *  ------------------------------------------------------------------------\n     *  Returns the source of the document mapped in this store to the given\n     *  path.\n     *\n     *  ```js\n     *  source = await store.read(\"/path/to/doc\");\n     *  ```\n     *\n     *  Every implmenentation of this method should behave according to the\n     *  following standard:\n     *\n     *  - It should return a string\n     *  - It should throw `Store.ReadPermissionDeniedError` if the store\n     *    instance has no read permission on the given path.\n     *   \n     *  When instantiated directly, the base store `read` method returns always\n     *  an empty string.\n     */\n    async read (path) {\n        return \"\";\n    }\n\n\n    /**\n     *  async store.write: (String path, String source) -> undefined\n     *  ------------------------------------------------------------------------\n     *  Changes the source of the document at the given path.\n     *\n     *  ```js\n     *  await store.write(\"/path/to/doc\", \"This is the doc content.\");\n     *  ```\n     *\n     *  Every implmenentation of this method should behave according to the\n     *  following standard:\n     *\n     *  - After calling this method on `path`, `store.read(path)` should\n     *    return the new source.\n     *  - It should throw `Store.WritePermissionDeniedError` if the store\n     *    instance has no write permission on the given path.\n     *  - It should throw `Store.WriteOperationNotAllowedError` if the store\n     *    is read-only.\n     *     \n     *  When instantiated directly, the base store `write` method always throws\n     *  `Store.WriteOperationNotAllowedError`.\n     */\n    async write (path, source) {\n        throw new this.constructor.WriteOperationNotAllowedError(this.normalizePath(path));\n    }\n\n\n    /**\n     *  async store.delete: String path -> undefined\n     *  ------------------------------------------------------------------------\n     *  Removes a document from the store.\n     *\n     *  ```js\n     *  await store.delete(\"/path/to/doc\");\n     *  ```\n     *\n     *  Every implmenentation of this method should behave according to the\n     *  following standard:\n     *\n     *  - After calling this method on `path`, `store.read(path)` should\n     *    return an empty string.\n     *  - It should throw `Store.WritePermissionDeniedError` if the store\n     *    instance has no write permission on the given path.\n     *  - It should throw `Store.WriteOperationNotAllowedError` if the store\n     *    is read-only.\n     *   \n     *  When instantiated directly, the base store `delete` method always throws\n     *  `Store.WriteOperationNotAllowedError`.\n     */\n    async delete (path) {\n        throw new this.constructor.WriteOperationNotAllowedError(this.normalizePath(path));\n    }\n\n\n    /**\n     *  store.parse: String source -> Function evalutate\n     *  ------------------------------------------------------------------------\n     *  Compiles a document source into an `evaluate` function that takes as input\n     *  a document context object and returns the document namespace object and its\n     *  rendered text.\n     *\n     *  ```js\n     *  evaluate = store.parse(source);\n     *  {data, text} = await evaluate(context);\n     *  ```\n     *\n     *  - `evaluate` is an asynchronous function that evaluates the document and\n     *    returns its namespace and its rendered text\n     *  - `context` is a valid document context created either with\n     *    `store.createContext` or with `document.createContext`.\n     *  - `data` is an object containing all the names defined by the inline\n     *    expressions of the document (the document namespace).\n     *  - `text` is a string obtained by replacing every inline expression with its\n     *    strigified value.\n     */\n    parse (source) {\n        return document.parse(source);\n    }\n\n    /**\n     *  store.createContext: (String path, ...Object namespace) -> Object context\n     *  ------------------------------------------------------------------------\n     *  Create a document context bound to this store.\n     *  \n     *  ```\n     *  context = store.createContext(docPath, ns1, ns2, ...)\n     *  ```\n     *  \n     *  The `context` object is a document context that contains the following\n     *  properties:\n     *  \n     *  - A `__path__` string equal to `docPath`\n     *  - A `__dirpath__` string equal to the directory path of `docPath`\n     *  - All the names contained in the passed namespaces\n     *  - An `import` function that given a document path, loads it from the\n     *    current store, evaluates it and returns its namespace. The import\n     *    document path is parsed as relative to `docPath`.\n     */\n    createContext (path, ...namespaces) {\n        const cache = new Cache(this);\n        return createContext(this, cache, path, ...namespaces);\n    }\n    \n    /**\n     *  store.load: (String path, ...Object namespace) -> {String source, Object context, Function evaluate, Object data, String text}\n     *  ------------------------------------------------------------------------\n     *  Read, parse and evaluate a document.\n     *  \n     *  ```\n     *  {source, context, evaluate, data, text} = store.load(docPath, ns1, ns2, ...)\n     *  ```\n     *  \n     *  where:\n     *  \n     *  - `source` is the document source mapped to docPath\n     *  - `context` is the document context including the preset namespaces ns1, ns2, ...\n     *  - `evaluate` is the source compiled into a function\n     *  - `data` is the document namespace as returned by `evaluate`\n     *  - `text` is the document rendered text as returned by `evaluate`\n     */\n    async load (path, ...namespaces) {\n        const source = await this.read(path);\n        const context = this.createContext(path, ...namespaces);\n        const evaluate = this.parse(source);\n        const {data, text} = await evaluate(context);\n        return {source, context, evaluate, data, text};\n    }\n\n\n    // -------------------------------------------------------------------------\n    //  Internal methods\n    // -------------------------------------------------------------------------\n\n    // Normalize a path, resolvin `.`, `..` and adding `/` at the beginning\n    normalizePath (path) {\n        return pathlib.normalize(`/${path}`);\n    }\n\n    // Resolve a subPath relative to a basePath, ignoring the file name\n    resolvePath (basePath, subPath) {\n        if (subPath[0] === '/') {\n            return pathlib.normalize(subPath);\n        } else {\n            const baseDirPath = basePath.slice(-1) === '/' ?\n                    basePath : pathlib.resolve(basePath, '..');\n            return pathlib.join(baseDirPath, subPath);\n        }\n    }\n}\n\n\n\n// Base class for Store Errors\nStore.Error = class extends Error {};\n\n\n// Base class for Store.ReadPermissionDeniedError and\n// Store.WritePermissionDeniedError.\nStore.PermissionDeniedError = class extends Store.Error {\n\n    constructor (operation, path) {\n        super(`Permission denied: ${operation} ${path}`);\n    }\n}\n\n/**\n *  Store.ReadPermissionDeniedError - class\n *  ----------------------------------------------------------------------------\n *  Error thrown when attempting a read operation for which the store instance\n *  has no read access.\n *\n *  ```js\n *  throw new Store.ReadPermissionDeniedError('/path/to/doc');\n *  ```\n */\nStore.ReadPermissionDeniedError = class extends Store.PermissionDeniedError {\n\n    constructor (path) {\n        super(\"READ\", path);\n    }\n}\n\n/**\n *  Store.WritePermissionDeniedError - class\n *  ----------------------------------------------------------------------------\n *  Error thrown when attempting a write operation for which the store instance\n *  has no write access.\n *\n *  ```js\n *  throw new Store.WritePermissionDeniedError('/path/to/doc');\n *  ```\n */\nStore.WritePermissionDeniedError = class extends Store.PermissionDeniedError {\n\n    constructor (path) {\n        super(\"WRITE\", path);\n    }\n}\n\n\n// Base class for Store.ReadOperationNotAllowedError and\n// Store.WriteOperationNotAllowedError.\nStore.OperationNotAllowedError = class extends Store.Error {\n\n    constructor (operation, path) {\n        super(`Operation not allowed: ${operation} ${path}`);\n    }\n}\n\n/**\n *  Store.ReadOperationNotAllowedError - class\n *  ----------------------------------------------------------------------------\n *  Error thrown when the read operation is not defined on the store.\n *\n *  ```js\n *  throw new Store.ReadOperationNotAllowedError('/path/to/doc');\n *  ```\n */\nStore.ReadOperationNotAllowedError = class extends Store.OperationNotAllowedError {\n\n    constructor (path) {\n        super(\"READ\", path);\n    }\n}\n\n/**\n *  Store.WriteOperationNotAllowedError - class\n *  ----------------------------------------------------------------------------\n *  Error thrown when the write operation is not defined on the store.\n *\n *  ```js\n *  throw new Store.WriteOperationNotAllowedError('/path/to/doc');\n *  ```\n */\nStore.WriteOperationNotAllowedError = class extends Store.OperationNotAllowedError {\n\n    constructor (path) {\n        super(\"WRITE\", path);\n    }\n}\n\n\n\nfunction createContext (store, cache, docPath, ...namespaces) {\n    const context = document.createContext(...namespaces);\n\n    context.__path__ = store.normalizePath(docPath);\n    context.__dirpath__ = pathlib.dirname(context.__path__);\n\n    context.import = async subPath => {\n        const targetPath = store.resolvePath(context.__path__, subPath);\n        const {source, evaluate} = await cache.get(targetPath);\n        const targetContext = createContext(store, cache, targetPath);\n        const {text, data} = await evaluate(targetContext);\n        data.__str__ = () => text;\n        return data;\n    }\n\n    return context;\n}\n\nclass Cache extends Map {\n\n    constructor (store) {\n        super();\n        this.store = store;\n    }\n\n    async get (path) {\n        const normPath = this.store.normalizePath(path);\n        if (!this.has(normPath)) {\n            const source = await this.store.read(normPath);\n            const evaluate = this.store.parse(source);\n            this.set(normPath, {source, evaluate});\n        }\n        return super.get(normPath);\n    }\n}\n\n\n\n// Exports\nmodule.exports = Store;\n\n\n//# sourceURL=webpack:///../../lib/store.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/index.js":
  /*!******************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/index.js ***!
    \******************************************************/
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
  
  eval("/**\n *  swan\n *  ============================================================================\n *  The swan JavaScript API include a `parse` function and a `createContext`\n *  function to parse and evaluate expressions. \n */\n\nconst types = exports.types = __webpack_require__(/*! ./lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst parse = __webpack_require__(/*! ./lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst builtins = __webpack_require__(/*! ./lib/builtins */ \"../../node_modules/@onlabsorg/swan-js/lib/builtins.js\");\n\n\n/**\n *  swan.parse - function\n *  ----------------------------------------------------------------------------\n *  Parses a swan expression and returns a function that maps a context to an\n *  expression value.\n *  \n *  ```js\n *  evaluate = swan.parse(expression);\n *  value = await evaluate(context);\n *  ```\n *  \n *  Where:\n *  - `espression` is a string containing any valid swan expression\n *  - `context` is a valid swan expression context\n *  - `value` is the value that expression result has in the given context\n */\n\nexports.parse = function (expression) {\n    const evaluate = parse(expression);\n    return async (context={}) => {\n        const term = await evaluate(context);\n        return term.unwrap();\n    }\n}\n\n\n\n/**\n *  swan.createContext - function\n *  ----------------------------------------------------------------------------\n *  Creates a valid expression context.\n *  \n *  ```js\n *  context = swan.createContext(...namespaces)\n *  ```\n *  \n *  Where:\n *  - `namespaces` is a list of objects `ns1, ns2, ns3, ...` that will be merged\n *    to the swan builtin namespace\n *  - `context` is an object containing all the swan builtins, plus\n *    all the properties of the passed namespaces, added in order.\n */\nexports.createContext = function (...namespaces) {\n    let context = Object.create(builtins);\n    for (let namespace of namespaces) {\n        context = Object.assign(Object.create(context), namespace);\n    }\n    return context;\n}\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/builtins.js":
  /*!*************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/builtins.js ***!
    \*************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/**\n *  Swan Builtins\n *  ============================================================================\n *  \n *  The swan builtins is a collection of functions and constants that are\n *  always present in a swan context.\n */\n\nconst types = __webpack_require__(/*! ./types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\n\n\nconst builtins = module.exports = {\n    \n    /**\n     *  TRUE: Bool\n     *  ----------------------------------------------------------------------------\n     *  This constant represent the boolean true value in swan.\n     */\n    TRUE: true,\n    \n    \n    /**\n    *  FALSE: Bool\n    *  ----------------------------------------------------------------------------\n     *  This constant represent the boolean false value in swan.\n     */\n    FALSE: false,\n\n\n    /**\n     *  bool: Term t -> Bool b\n     *  ----------------------------------------------------------------------------\n     *  \n     *  Given a swan term X, the `bool.from` function returns TRUE if the\n     *  term is truty, otherwise it returns FALSE.\n     *  \n     *  Falsy elements are: `FALSE`, `0`, `\"\"`, `[]`, `{}`, `()`, an any \n     *  Undefined item and any tuple containing only falsy elements.\n     *  \n     *  Any other term is truty.\n     */\n    bool (...values) {\n        return new types.Tuple(...values).toBoolean();\n    },\n    \n    \n    /**\n     *  dom: Mapping m -> Tuple t\n     *  ------------------------------------------------------------------------\n     *  Returns the domain of the passed mappings m, which is:\n     *  \n     *  - The tuple (0,1,2,...,size(m)-1) if m is a Text item\n     *  - The tuple (0,1,2,...,size(m)-1) if m is a List item\n     *  - The tuple of the name mapped by m if m is a Namespace item\n     *  \n     *  If m is not a Mapping item, it returns Undefined Term.\n     *  If the argument is a tuple, it applies only to its first item.\n     */\n    dom (x) {\n        const X = types.wrap(x);\n        return X instanceof types.Mapping ? new types.Tuple(...X.domain) : new Undefined(\"Term\");\n    },\n\n\n    /**\n     *  not: Term t -> Bool b\n     *  ----------------------------------------------------------------------------\n     *  \n     *  Given a swan term X, the `bool.not` function returns FALSE if the\n     *  term is truty, otherwise it returns TRUE.\n     *  \n     *  For the definition of truty and falsy terms, see `bool.from`.\n     */\n    not (...values) {\n        return !builtins.bool(...values);\n    },\n\n\n    /**\n     *  range: Numb n -> Numb Typle r\n     *  ----------------------------------------------------------------------------\n     *  Given a number `n`, this function returns the tuple of integers\n     *  (0, 1, 2, ..., m), where m is the highest integer lower than m.\n     *  \n     *  For example:\n     *  - `range 4` returns `(0,1,2,3)`\n     *  - `range 5.1` return `(0,1,2,3,4,5)`\n     *  \n     *  If `n` is not a number, this function returns Undefined Tuple.\n     *  If `n` is a tuple, only its first item will be considered.\n     */\n    range (n) {\n        if (types.wrap(n) instanceof types.Numb) {\n            let range = new types.Tuple();\n            for (let i=0; i<n; i++) {\n                range = new types.Tuple(range, i);\n            }\n            return range;\n        } else {\n            return new types.Undefined(\"Tuple\");\n        }\n    },\n    \n    \n    /**\n     *  require: Text id -> Namespace m\n     *  ----------------------------------------------------------------------------\n     *  This function loads the swan standard module identified by `id` and returns\n     *  it as a Namespace item.\n     *  \n     *  If `id` is a tuple, it applies only to its first item.\n     */\n    async require (module_id) {\n        \n        const modules = __webpack_require__(/*! ./modules */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/index.js\");\n        const payload = await modules[module_id]();\n        const module = payload.default || payload;\n        \n        if (typeof module === \"function\") {\n            return module(types);\n        } else {\n            return module\n        }    \n    },\n    \n    \n    /**\n     *  size: Mapping m -> Numb n\n     *  ------------------------------------------------------------------------\n     *  Returns the number of mappings in m, which is:\n     *  \n     *  - The number of characters if m is a Text item\n     *  - The number of items if m is a List item\n     *  - The number of names:value pairs if m is a Namespace item\n     *  \n     *  If m is not a Mapping item, it returns Undefined Number.\n     *  If the argument is a tuple, it applies only to its first item.\n     */\n    size (x) {\n        const X = types.wrap(x);\n        return X instanceof types.Mapping ? X.size : NaN;\n    },\n\n\n    // str: Term x -> Text s\n    // Converts the term x to string.\n    async str (...values) {\n        const term = new types.Tuple(...values);\n        const textTuple = await term.imapAsync(async (item) => {\n            if (item instanceof types.Namespace) {\n                const __str__ = item.apply(\"__str__\");\n                if (__str__ instanceof types.Func) {\n                    return await __str__.apply(item);\n                }\n            }\n            return item;\n        });\n        return textTuple.toString();\n    },\n    \n\n    /**\n     *  type: Item x -> Text t\n     *  ----------------------------------------------------------------------------\n     *  Given any item it returns the name of its type: `\"Bool\"` for Bool items,\n     *  `\"Numb\"` for Numb items, etc.\n     *  \n     *  If `x` is a tuple, it returns a tuple of type names.\n     */\n    type (...values) {\n        return new types.Tuple(...values).imapSync(X => X.typeName).unwrap();\n    },\n    \n    \n    /**\n     *  undefined: (Text t, Tuple a) -> Undefined u\n     *  ----------------------------------------------------------------------------\n     *  This function returns an `Undefined` item with type `t` and arguments `a`.\n     */\n    undefined (type, ...args) {\n        return new types.Undefined(type, ...args);\n    }\n}\n\n\n\n\n\n\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/builtins.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/interpreter.js":
  /*!****************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/interpreter.js ***!
    \****************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("// =============================================================================\n//  INTERPRETER\n//\n//  This module exports a `parser` function that takes an expression string as\n//  input and returns an asynchronous `evaluate` function. The `evaluate`\n//  function takes a context object, evaluate the expression AST and returns\n//  the expression value.\n//  \n//  The parser function is a `Parser` instance (see parser module). The parser\n//  is configured to wrap the AST nodes in custom nodes. Each custom node\n//  has an `evaluate` function that takes a `context` as input and returns\n//  the node value.\n//\n//  The node values returned by the `parse` function are wrapped in a type\n//  object (see types module).\n//  \n// =============================================================================\n\nconst {matchIdentifier} = __webpack_require__(/*! ./lexer */ \"../../node_modules/@onlabsorg/swan-js/lib/lexer.js\");\nconst {Parser, ASTNode} = __webpack_require__(/*! ./parser */ \"../../node_modules/@onlabsorg/swan-js/lib/parser.js\");\n\nconst types = __webpack_require__(/*! ./types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst Undefined = (position, type, ...args) => {\n    const undef = new types.Undefined(type, ...args);\n    undef.position = position;\n    return undef;\n}\n\n\n \n// -----------------------------------------------------------------------------\n//  AST Node Wrappers\n//\n//  These are the basic type of AST nodes: each node is either a binary\n//  operation, a unary operatio or a leaf.\n// -----------------------------------------------------------------------------\n\n// Generic binary operation used as a base class for actual AST nodes.\nclass BinaryOperation extends ASTNode {\n    \n    // Operation name\n    get name () {\n        return \"BinaryOperation\";\n    }\n    \n    // left-hand node of this binary operation\n    get leftHandOperand () {\n        return this.children[0];\n    }\n    \n    // right-hand node of this binary operation\n    get rightHandOperand () {\n        return this.children[1];\n    }\n    \n    // shortcut function to create a `types.Undefined` value when the binary\n    // operation is not defined\n    undefined (leftHandOperand, rightHandOperand) {\n        return Undefined(this.position,  this.name, \n                leftHandOperand, rightHandOperand);\n    }\n    \n    // this is inernally used to evaluate name definitions, when identifiers\n    // should not be resolved to their mapped values.\n    async evaluateInNameDomain (context) {\n        const id1 = await this.leftHandOperand.evaluateInNameDomain(context);\n        const id2 = await this.rightHandOperand.evaluateInNameDomain(context);\n        return this.undefined(id1, id2);\n    }\n}\n\n// Generic unary operation used as a base class for actual AST nodes.\nclass UnaryOperation extends ASTNode {\n\n    // Operation name\n    get name () {\n        return \"UnaryOperation\";\n    }\n    \n    // the operand node of this unary operation\n    get operand () {\n        return this.children[0];\n    }\n    \n    // shortcut function to create a `types.Undefined` value when the unary\n    // operation is not defined\n    undefined (operand) {\n        return Undefined(this.position, this.name, operand);\n    }\n    \n    // this is inernally used to evaluate name definitions, when identifiers\n    // should not be resolved to their mapped values.\n    async evaluateInNameDomain (context) {\n        const id = await this.operand.evaluateInNameDomain(context);        \n        return this.undefined(id);\n    }\n}\n\n// Generic leaf used as a base class for actual AST terminal nodes.\nclass Leaf extends ASTNode {\n    \n    // Operation name\n    get name () {\n        return \"Leaf\";\n    }\n    \n    // shortcut function to create a `types.Undefined` value when the leaf\n    // value is not defined\n    undefined (value) {\n        return Undefined(this.position, this.name, value);\n    }\n    \n    // this is inernally used to evaluate name definitions, when identifiers\n    // should not be resolved to their mapped values.\n    async evaluateInNameDomain (context) {\n        const value = await this.evaluate(context);\n        return this.undefined(value);\n    }\n    \n    // by default, a leaf node evaluates to the node value\n    async evaluate (context={}) {\n        return types.wrap(this.value);\n    }\n}\n\n\n\n// -----------------------------------------------------------------------------\n//  Core Operations\n// \n//  These are the foundamental operations of the swan language.\n// -----------------------------------------------------------------------------\n\n// Node representing a `()` literal, which is an empty tuple (aka Nothing).\nclass VoidLiteral extends Leaf {\n    \n    // Operation name\n    get name () {\n        return \"VoidLiteral\";\n    }\n    \n    async evaluate (context) {\n        return new types.Tuple();\n    }\n}\n\n// Node representing a numeric literal, such as `123.45`.\nclass NumberLiteral extends Leaf {\n    \n    // Operation name\n    get name () {\n        return \"NumberLiteral\";\n    }\n    \n    async evaluate (context={}) {\n        return new types.Numb(this.value);\n    }\n}\n\n// Node representing a string literal, such as `\"abc\"` or `'abc'`.\nclass StringLiteral extends Leaf {\n    \n    // Operation name\n    get name () {\n        return \"StringLiteral\";\n    }\n    \n    async evaluate (context={}) {\n        return new types.Text(this.value);\n    }\n}\n\n// Node representing a string template, which is a text enclosed between\n// accent quotes \"`\" and containing inline swan expression enclosed between\n// `${` and `}`.\nclass StringTemplate extends UnaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"StringTemplate\";\n    }\n    \n    async evaluate (context) {\n        \n        // retrieve the raw template text\n        let text = this.value;\n        \n        // replace all the inline expressions with a placeholder\n        const expressions = [];\n        text = text.replace(/\\${([\\s\\S]+?)}/g, (match, expressionSource) => {\n            const i = expressions.length;\n            expressions.push( parser.parse(expressionSource) );\n            return \"${\" + i + \"}\";\n        });\n        \n        // evaluate the inline expression and push their serialized value back\n        // to the template text\n        for (let i=0; i<expressions.length; i++) {\n            const xpTerm = await expressions[i].evaluate(context);\n            text = text.replace(\"${\" + i + \"}\", xpTerm.toString());\n        }\n        \n        // wrap and return the resolved template text\n        return new types.Text(text);\n    }\n}\n\n// Node representing a pairing operation `X , Y` which defines a tuple.\nclass PairingOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"PairingOperation\";\n    }\n    \n    // Pairs the names on the left-hand side of an assignment operation such\n    // as `a,b = 1,2` or of a function definition such as `(a,b) -> a+b`.\n    async evaluateInNameDomain (context) {\n        const id1 = await this.leftHandOperand.evaluateInNameDomain(context);\n        const id2 = await this.rightHandOperand.evaluateInNameDomain(context);\n        if ((id1 instanceof types.Text || id1 instanceof types.Tuple) && \n            (id2 instanceof types.Text || id2 instanceof types.Tuple)) {\n            return new types.Tuple(id1, id2);\n        } else {\n            return this.undefined(id1, id2);\n        }\n    }\n    \n    // Create a tuple given two terms.\n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        const term2 = await this.rightHandOperand.evaluate(context);\n        return new types.Tuple(term1, term2);\n    }\n}\n\n// Node representing a list literal `[T]`, where `T` is a tuple.\nclass ListDefinition extends UnaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"ListDefinition\";\n    }\n    \n    // Turns the child node into a list object\n    async evaluate (context) {\n        const term = await this.operand.evaluate(context);\n        return new types.List( Array.from(term) );\n    }    \n}\n\n// Node representing an identifier, which will be evaluated to its mapped value.\nclass NameReference extends Leaf {\n    \n    // Operation name\n    get name () {\n        return \"NameReference\";\n    }\n    \n    // Returns the identifier value as a Text object\n    async evaluateInNameDomain (context) {\n        return new types.Text(this.value);\n    }\n    \n    // Returns the name mapped to the identifier value in the given context\n    async evaluate (context) {\n        const name = this.value;\n        if (!matchIdentifier(name)) return this.undefined(name);\n        const value = context[name];\n        if (value === Object.prototype[name]) return this.undefined(name);\n        return types.wrap(value);\n    }\n}\n\n// Node representing a labelling operation `name : value`.\nclass LabellingOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"LabellingOperation\";\n    }\n    \n    // Maps the left-hand names to the right-hand values and returns the values\n    async evaluate (context) {\n        \n        const term1 = await this.leftHandOperand.evaluateInNameDomain(context);\n        const term2 = await this.rightHandOperand.evaluate(context);\n        \n        if (term1 instanceof types.Undefined) {\n            return this.undefined(term1, term2);\n        }\n\n        this.constructor.defineNames(context, term1, term2);\n        //new types.Namespace(context).assign(term1, term2);\n        \n        return term2;\n    }\n    \n    static defineNames (context, term1, term2) {\n        const names = Array.from(term1).map(types.unwrap);\n        const values = Array.from(term2).map(types.unwrap);\n        \n        if (values.length > names.length) {\n            values[names.length-1] = new types.Tuple(...values.slice(names.length-1));\n        }\n        \n        for (let i=0; i<names.length; i++) {\n            context[ names[i] ] = i < values.length ? types.unwrap(values[i]) : null;\n        }        \n    }\n}\n\n// Node representing an assignment operation `name = value`.\nclass AssignmentOperation extends LabellingOperation {\n    \n    // Operation name\n    get name () {\n        return \"AssignmentOperation\";\n    }\n    \n    // Maps the left-hand names to the right-hand values and returns Nothing\n    async evaluate (context) {\n        const term2 = await super.evaluate(context);\n        if (term2 instanceof types.Undefined && term2.position === this.position) {\n            return term2;\n        } else {\n            return new types.Tuple();\n        }\n    }\n}\n\n// Node representing a namespace literal `{T}`, where `T` is a tuple.\nclass NamespaceDefinition extends UnaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"NamespaceDefinition\";\n    }\n    \n    // Evaluates the operand in a child context and returns the resulting namespace\n    async evaluate (context) {\n        const subContext = Object.assign(Object.create(context), {});\n        await this.operand.evaluate(subContext);\n        return new types.Namespace( Object.assign({}, subContext) );\n    }\n}\n\n// Node representing a function definition `names -> expression`.\nclass FunctionDefinition extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"FunctionDefinition\";\n    }\n    \n    // Creates a new Func object\n    async evaluate (context) {\n        const params = await this.leftHandOperand.evaluateInNameDomain(context);\n        if (params instanceof types.Undefined) {\n            return this.undefined(params, this.rightHandOperand);\n        }\n        const func = async (...args) => {\n            const functionContext = Object.create(context);\n            functionContext.self = func;\n            LabellingOperation.defineNames(functionContext, params, args);\n            return await this.rightHandOperand.evaluate(functionContext);\n        }\n        return new types.Func(func);\n    }\n}\n\n// Node representing an application operation `Y X`.\nclass ApplyOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"ApplyOperation\";\n    }\n    \n    // Returns LHO(RHO), where LHO can be a Func or a Mapping\n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        const term2 = await this.rightHandOperand.evaluate(context);\n        return await this.apply(term1, term2);\n    }\n    \n    apply (term1, term2) {\n        return term1.imapAsync(async item1 => {\n            \n            if (item1 instanceof types.Applicable) {\n                try {\n                    return types.wrap( await item1.apply(...term2) );\n                } catch (error) {\n                    return Undefined(this.position, \"Term\", error);\n                }                \n            } \n            \n            else {\n                return this.undefined(term1, term2);\n            }\n        });        \n    }\n}\n\n// Node representing a map operation `X => Y`.\nclass MapOperation extends ApplyOperation {\n    \n    // Operation name\n    get name () {\n        return \"MapOperation\";\n    }\n    \n    // (a,b,c) => F returns (F a, F b, F c)\n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        const term2 = await this.rightHandOperand.evaluate(context);        \n        return term1.imapAsync(item1 => this.apply(term2, item1));\n    }\n}\n\n// Node representing a function piping operation `X >> Y`.\nclass PipeOperation extends ApplyOperation {\n    \n    // Operation name\n    get name () {\n        return \"PipeOperation\";\n    }\n    \n    // (f >> g) x returns g(f x) \n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        const term2 = await this.rightHandOperand.evaluate(context);\n        return new types.Func(async (...args) => {\n            const args1 = new types.Tuple(...args);\n            const args2 = await this.apply(term1, args1);\n            return await this.apply(term2, args2);\n        });\n    }\n}\n\n// Node representing a function composition operation `X << Y`.\nclass ComposeOperation extends ApplyOperation {\n    \n    // Operation name\n    get name () {\n        return \"ComposeOperation\";\n    }\n    \n    // (f << g) x returns f(g x) \n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        const term2 = await this.rightHandOperand.evaluate(context);\n        return new types.Func(async (...args) => {\n            const args2 = new types.Tuple(...args);\n            const args1 = await this.apply(term2, args2);\n            return await this.apply(term1, args1);\n        });\n    }\n}\n\n// Node representing a sub-contexting operation `X . Y`.\nclass SubcontextingOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"SubcontextingOperation\";\n    }\n    \n    // Evaluates the RHO in a new child-context augumented with the LHO\n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        return await term1.imapAsync(async item1 => {\n            if (item1 instanceof types.Namespace) {\n                return await item1.vmapAsync(async namespace => {\n                    const subContext = Object.assign(Object.create(context), namespace);\n                    return await this.rightHandOperand.evaluate(subContext);\n                })\n            } else {\n                return this.undefined(item1, this.rightHandOperand);\n            }            \n        });\n    }\n}\n\n\n\n// -----------------------------------------------------------------------------\n//  Unary Operators +x and -x\n//  \n//  There are only two unary operations is swan: `+X` and `-X`.\n// -----------------------------------------------------------------------------\n\n// Node representing a `+X` unary operation.\nclass IdentityOperation extends UnaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"IdentityOperation\";\n    }\n    \n    async evaluate (context) {\n        return this.operand.evaluate(context);\n    }\n}\n\n// Node representing a `-X` unary operation.\nclass NegationOperation extends UnaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"NegationOperation\";\n    }\n    \n    async evaluate (context) {\n        const term = await this.operand.evaluate(context);\n        return term.imapSync(item => {\n            if (typeof item.negate === \"function\") {\n                return item.negate();\n            } else {\n                return this.undefined(item);\n            }\n        });\n    }\n}\n\n\n\n// -----------------------------------------------------------------------------\n//  Logic operations\n//  \n//  Nodes representing the swan logic operations `AND`, `OR`, `IF` and `ELSE`.\n// -----------------------------------------------------------------------------\n\n// Node representing the OR operation `X | Y`.\nclass OrOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"OrOperation\";\n    }\n    \n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        if (term1.toBoolean()) {\n            return term1;\n        } else {\n            return await this.rightHandOperand.evaluate(context);\n        }\n    }\n}\n\n// Node representing the AND operation `X & Y`.\nclass AndOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"AndOperation\";\n    }\n    \n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        if (term1.toBoolean()) {\n            return await this.rightHandOperand.evaluate(context);\n        } else {\n            return term1;\n        }\n    }\n}\n\n// Node representing the IF operation `X ? Y`.\nclass ConditionalOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"ConditionalOperation\";\n    }\n    \n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        if (term1.toBoolean()) {\n            return await this.rightHandOperand.evaluate(context);\n        } else {\n            return Undefined(this.position, 'Term');\n        }\n    }\n}\n\n// Node representing the ELSE operation `X ; Y`.\nclass AlternativeOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"AlternativeOperation\";\n    }\n    \n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        if (term1 instanceof types.Undefined) {\n            return await this.rightHandOperand.evaluate(context);\n        } else {\n            return term1;\n        }\n    }    \n}\n\n\n\n// -----------------------------------------------------------------------------\n//  Arithmetic Binary Operations\n//  \n//  These nodes represnt the swan binary operations `+`, `-`, `*`, `/` and `**`.\n// -----------------------------------------------------------------------------\n\n// Generic arithmetic operation used as base for the actual operations.\nclass ArithmeticOperation extends BinaryOperation {\n    \n    // Operation name\n    get name () {\n        return \"ArithmeticOperation\";\n    }\n    \n    async evaluate (context, op) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        const term2 = await this.rightHandOperand.evaluate(context);\n        const pairs = Array.from(term1.iterPairs(term2));\n        const items = pairs.map(([item1, item2]) => op(item1, item2));\n        return items.length === 1 ? items[0] : new types.Tuple(...items);\n    }\n}\n\n// Node representing a sum operation `X + Y`.\nclass SumOperation extends ArithmeticOperation {\n    \n    // Operation name\n    get name () {\n        return \"SumOperation\";\n    }\n    \n    async evaluate (context) {\n        return await super.evaluate(context, (item1, item2) => {\n            \n            if (item1.typeName === item2.typeName && \n                    typeof item1.sum === \"function\") {\n                        \n                return item1.sum(item2);\n                \n            } else {\n                return this.undefined(item1, item2);\n            }\n        });\n    }\n}\n\n// Node representing a subtraction operation `X - Y`.\nclass SubOperation extends ArithmeticOperation {\n\n    // Operation name\n    get name () {\n        return \"SubOperation\";\n    }\n    \n    async evaluate (context) {\n        return await super.evaluate(context, (item1, item2) => {\n            if (item1.typeName === item2.typeName && \n                    typeof item1.sum === \"function\" &&\n                    typeof item2.negate === \"function\") {\n                        \n                return item1.sum( item2.negate() );\n                \n            } else {\n                return this.undefined(item1, item2);\n            }\n        });\n    }    \n}\n\n// Node representing a product operation `X * Y`.\nclass MulOperation extends ArithmeticOperation {\n    \n    // Operation name\n    get name () {\n        return \"MulOperation\";\n    }\n    \n    async evaluate (context) {\n        return await super.evaluate(context, (item1, item2) => {\n            if (item1.typeName === item2.typeName && \n                    typeof item1.mul === \"function\") {\n                        \n                return item1.mul(item2);\n                \n            } else {\n                return this.undefined(item1, item2);\n            }\n        });\n    }        \n}\n\n// Node representing a division operation `X / Y`.\nclass DivOperation extends ArithmeticOperation {\n\n    // Operation name\n    get name () {\n        return \"DivOperation\";\n    }\n    \n    async evaluate (context) {\n        return await super.evaluate(context, (item1, item2) => {\n            if (item1.typeName === item2.typeName && \n                    typeof item1.mul === \"function\" &&\n                    typeof item2.invert === \"function\") {\n                        \n                return item1.mul( item2.invert() );\n                \n            } else {\n                return this.undefined(item1, item2);\n            }\n        });\n    }        \n}\n\n// Node representing a modulo operation `X % Y`.\nclass ModOperation extends ArithmeticOperation {\n\n    // Operation name\n    get name () {\n        return \"ModOperation\";\n    }\n    \n    async evaluate (context) {\n        return await super.evaluate(context, (item1, item2) => {\n            if (item1 instanceof types.Numb && item2 instanceof types.Numb) {\n                return types.wrap( types.unwrap(item1) % types.unwrap(item2) );\n                \n            } else {\n                return this.undefined(item1, item2);\n            }\n        });\n    }        \n}\n\n// Node representing a power operation `X ** Y`.\nclass PowOperation extends ArithmeticOperation {\n\n    // Operation name\n    get name () {\n        return \"PowOperation\";\n    }\n    \n    async evaluate (context) {\n        return await super.evaluate(context, (item1, item2) => {\n            if (item1.typeName === item2.typeName && \n                    typeof item1.pow === \"function\") {\n                        \n                return item1.pow(item2);\n                \n            } else {\n                return this.undefined(item1, item2);\n            }\n        });\n    }        \n}\n\n\n\n// -----------------------------------------------------------------------------\n//  Comparison Binary Operations\n//  \n//  Nodes representing the comparison operations `==`, `!=`, `>`, `>=`, `<` and\n//  `<=`.\n// -----------------------------------------------------------------------------\n\n// Generic comparison operation used as base for the actual operations.\nclass ComparisonOperation extends BinaryOperation {\n        \n    // Operation name\n    get name () {\n        return \"ComparisonOperation\";\n    }\n    \n    async evaluate (context) {\n        const term1 = await this.leftHandOperand.evaluate(context);\n        const term2 = await this.rightHandOperand.evaluate(context);\n        return term1.compare(term2);\n    }\n}\n\n// Node representing an equality check operation `X == Y`.\nclass EqOperation extends ComparisonOperation {\n    \n    // Operation name\n    get name () {\n        return \"EqOperation\";\n    }\n    \n    async evaluate (context) {\n        const cmp = await super.evaluate(context);\n        return new types.Bool(cmp === '=');\n    }\n}\n\n// Node representing an non-equality check operation `X != Y`.\nclass NeOperation extends ComparisonOperation {\n    \n    // Operation name\n    get name () {\n        return \"NeOperation\";\n    }\n    \n    async evaluate (context) {\n        const cmp = await super.evaluate(context);\n        return new types.Bool(cmp !== '=');\n    }    \n}\n\n// Node representing a less-than check operation `X < Y`.\nclass LtOperation extends ComparisonOperation {\n    \n    // Operation name\n    get name () {\n        return \"LtOperation\";\n    }\n    \n    async evaluate (context) {\n        const cmp = await super.evaluate(context);\n        return new types.Bool(cmp === '<');\n    }        \n}\n\n// Node representing a less-than-or-equal-to check operation `X <= Y`.\nclass LeOperation extends ComparisonOperation {\n    \n    // Operation name\n    get name () {\n        return \"LeOperation\";\n    }\n    \n    async evaluate (context) {\n        const cmp = await super.evaluate(context);\n        return new types.Bool(cmp === '<' || cmp === '=');\n    }        \n}\n\n// Node representing a greater-than check operation `X > Y`.\nclass GtOperation extends ComparisonOperation {\n    \n    // Operation name\n    get name () {\n        return \"GtOperation\";\n    }\n    \n    async evaluate (context) {\n        const cmp = await super.evaluate(context);\n        return new types.Bool(cmp === '>');\n    }        \n}\n\n// Node representing a greater-than-or-equal-to check operation `X >= Y`.\nclass GeOperation extends ComparisonOperation {\n    \n    // Operation name\n    get name () {\n        return \"GeOperation\";\n    }\n    \n    async evaluate (context) {\n        const cmp = await super.evaluate(context);\n        return new types.Bool(cmp === '>' || cmp === '=');\n    }\n}\n\n\n\n// -----------------------------------------------------------------------------\n//  Parser  \n// -----------------------------------------------------------------------------\n\nconst parser = new Parser({\n\n     binaryOperations: {\n         \",\"  : {precedence:10, Node: PairingOperation    },\n         \":\"  : {precedence:12, Node: LabellingOperation  },\n         \"=\"  : {precedence:12, Node: AssignmentOperation },\n         \"=>\" : {precedence:13, Node: MapOperation        },\n         \">>\" : {precedence:14, Node: PipeOperation       },\n         \"<<\" : {precedence:14, Node: ComposeOperation  , right:true},\n         \"->\" : {precedence:15, Node: FunctionDefinition, right:true},\n\n         \";\"  : {precedence:21, Node: AlternativeOperation },\n         \"?\"  : {precedence:22, Node: ConditionalOperation },\n         \"|\"  : {precedence:23, Node: OrOperation          },\n         \"&\"  : {precedence:23, Node: AndOperation         },\n         \n         \"==\" : {precedence:24, Node: EqOperation },\n         \"!=\" : {precedence:24, Node: NeOperation },\n         \"<\"  : {precedence:24, Node: LtOperation },\n         \"<=\" : {precedence:24, Node: LeOperation },\n         \">\"  : {precedence:24, Node: GtOperation },\n         \">=\" : {precedence:24, Node: GeOperation },\n         \n         \"+\"  : {precedence:25, Node: SumOperation },\n         \"-\"  : {precedence:25, Node: SubOperation },\n         \"*\"  : {precedence:26, Node: MulOperation },\n         \"/\"  : {precedence:26, Node: DivOperation },\n         \"%\"  : {precedence:26, Node: ModOperation },\n         \"**\" : {precedence:27, Node: PowOperation },\n         \n         \".\"  : {precedence:30, Node: SubcontextingOperation },\n         \"\"   : {precedence:30, Node: ApplyOperation         },\n     },\n     \n     unaryOperations: {\n        \"+\": { Node: IdentityOperation },\n        \"-\": { Node: NegationOperation },\n     },\n     \n     groupingOperations: {\n         \"[]\" : { Node: ListDefinition      },\n         \"{}\" : { Node: NamespaceDefinition },\n     },\n\n     literals: {\n         void       : { Node: VoidLiteral    },\n         identifier : { Node: NameReference  },\n         string1    : { Node: StringLiteral  },\n         string2    : { Node: StringLiteral  },\n         string3    : { Node: StringTemplate },\n         number     : { Node: NumberLiteral  },\n     }\n});\n\nmodule.exports = source => {\n    const ast = parser.parse(source);        \n    return (context={}) => ast.evaluate(context);\n}\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/interpreter.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/lexer.js":
  /*!**********************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/lexer.js ***!
    \**********************************************************/
  /***/ ((module) => {
  
  eval("\nclass Lexer {\n    \n    constructor (options) {\n        this.binaryOperators = new Set(options.binaryOperators);\n        this.unaryOperators = new Set(options.unaryOperators);\n        \n        const isSymbol = operator => !this.matchIdentifierStart(operator);\n        this.SYMBOLS = new Set( ['{', '[', '(', ')', ']', '}']\n                .concat(options.binaryOperators.filter(isSymbol)) \n                .concat(options.unaryOperators.filter(isSymbol)));\n    }\n\n    matchSpace           (char) { return char && char.match(/^\\s$/)           }\n    matchQuote           (char) { return char && char.match(/^[\"'`]$/)        }\n    matchIdentifierStart (char) { return char && char.match(/^[a-z_A-Z]$/)    }\n    matchIdentifierPart  (char) { return char && char.match(/^[a-z_A-Z0-9]$/) }\n    matchDecimalDigit    (char) { return char && char.match(/^[0-9]$/)        }\n    matchSign            (char) { return char === \"+\" || char === \"-\"         }\n    matchCommentStart    (sym)  { return sym === \"#\"                          }\n    matchSymbol          (sym)  { return this.SYMBOLS.has(sym)                }\n    \n    * tokenize (source) {\n        \n        const createToken = (type, value, index) => \n                new this.constructor.Token(this, type, value, new this.constructor.Position(source, index));\n                \n        const createSyntaxError = (message, index) => \n                new this.constructor.SyntaxError(message, source, index);\n        \n        var i = 0, len = source.length;\n        while (true) {\n            while (this.matchSpace(source[i])) i++;\n            if (i >= len) break;\n\n            // if string literal\n            if (this.matchQuote(source[i])) {\n                let value = \"\";            \n                let quoteSymbol = source[i]; i++;\n                while (source[i] !== quoteSymbol) {\n                    if (i >= len) throw createSyntaxError(\"Closing quote expected\", i);\n                    value += source[i]; i++;\n                }\n                let token = createToken(Token.STRING, value, i);\n                token.quoteSymbol = quoteSymbol;\n                yield token; i++;\n            }\n            \n            // if identifier\n            else if (this.matchIdentifierStart(source[i])) {\n                let value = source[i]; i++;\n                while (this.matchIdentifierPart(source[i])) {\n                    value += source[i]; i++;\n                }\n                yield createToken(Token.IDENTIFIER, value, i);\n            }\n\n            // if number literal\n            else if (this.matchDecimalDigit(source[i])) {\n                let numStr = source[i]; i++;\n                \n                while (this.matchDecimalDigit(source[i])) {\n                    numStr += source[i]; i++;\n                }\n\n                if (source[i] === \".\") {\n                    numStr += source[i]; i++;\n                    while (this.matchDecimalDigit(source[i])) {\n                        numStr += source[i]; i++;\n                    }        \n                }\n                \n                if (source[i] === 'e' || source[i] === 'E') {\n                    numStr += 'E'; i++;\n                    if (source[i] === '+' || source[i] === '-') { // exponent sign\n                        numStr += source[i]; i++;\n                    }\n                    if (!this.matchDecimalDigit(source[i])) {\n                        throw createSyntaxError(`Expected exponent value`, i);                    \n                    }\n                    numStr += source[i]; i++;\n                    while (this.matchDecimalDigit(source[i])) {\n                        numStr += source[i]; i++;\n                    }        \n                }\n                \n                if (this.matchIdentifierStart(source[i])) {\n                    throw createSyntaxError(`Invalid number`, i-1);\n                } else if (source[i] === \".\") {\n                    throw createSyntaxError('Unexpected period', i);\n                }\n\n                yield createToken(Token.NUMBER, Number(numStr), i);\n            }\n            \n            else if (this.matchCommentStart(source[i])) {\n                i++; while (source[i] !== \"\\n\" && i < len) i++;\n            }\n            \n            else if (this.matchSymbol( source[i]+source[i+1] )) {\n                yield createToken(Token.SYMBOL, source[i]+source[i+1], i); i+=2;\n            } \n            \n            else if (this.matchSymbol( source[i] )) {\n                yield createToken(Token.SYMBOL, source[i], i); i++;\n            } \n\n            else {\n                throw createSyntaxError(`Unexpected character '${source[i]}'`, i);\n            }\n        }        \n    }\n    \n    static get Position    () { return Position    }\n    static get SyntaxError () { return SyntaxError }\n    static get Token       () { return Token       }\n    \n    static matchIdentifier (identifier) {\n        return /^[a-z_A-Z]+[a-z_A-Z0-9]*$/.test(identifier);\n    }\n}\n\n\n\nclass Token {\n    \n    constructor (lexer, type, value, pos) {\n        this.lexer = lexer;\n        this.type = type;\n        this.value = value;\n        this.position = pos;\n    }    \n    \n    matchSymbol (sym) {\n        return this.type === Token.SYMBOL && this.value === sym;\n    }\n    \n    matchSign () {\n        return this.matchSymbol(\"+\") || this.matchSymbol(\"-\");\n    }\n    \n    matchIdentifier () {\n        return this.type === Token.IDENTIFIER && !this.lexer.binaryOperators.has(this.value);\n    }\n    \n    matchBinaryOperator () {\n        return (this.type === Token.SYMBOL || this.type === Token.IDENTIFIER) && \n                this.lexer.binaryOperators.has(this.value);\n    }\n    \n    matchUnaryOperator () {\n        return (this.type === Token.SYMBOL || this.type === Token.IDENTIFIER) && \n                this.lexer.unaryOperators.has(this.value);\n    }\n\n    matchOpenBracket () {\n        return this.matchSymbol('(') || this.matchSymbol('[');\n    }\n    \n    matchNumberLiteral () {\n        return this.type === Token.NUMBER;\n    }\n    \n    matchStringLiteral () {\n        return this.type === Token.STRING;\n    }\n\n    matchLiteral () {\n        return this.type === Token.NUMBER || this.type === Token.STRING;\n    }\n}\n\n// Token types\nToken.SYMBOL = 0;\nToken.NUMBER = 1;\nToken.STRING = 2;\nToken.IDENTIFIER = 3;\n\n\n\nclass Position {\n\n    constructor (source, index) {\n        this.source = source;\n        this.index = index;\n    }\n    \n    getLocation () {\n        const lines = this.source.slice(0, this.index).split('\\n');\n        const row = lines.length;\n        const col = lines.pop().length;\n        return [row, col];\n    }\n    \n    toString () {\n        const [row, col] = this.getLocation();\n        return `@${row}:${col}`;\n    }    \n}\n\n\n\nclass SyntaxError extends Error {\n    \n    constructor (message, source, index) {\n        const position = new Position(source, index);\n        super(`${message} ${position}`);\n        this.position = position;\n    }\n}\n\n\n\nmodule.exports = Lexer;\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/lexer.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/modules/debug.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/modules/debug.js ***!
    \******************************************************************/
  /***/ ((module) => {
  
  eval("/**\n *  debug module\n *  ============================================================================\n *  The debug module provides functions for debugging swan code.\n */\n\n\n\nmodule.exports = types => {\n    const debug = {};\n    \n    \n    /**\n     *  debug.log: Term t -> Text id\n     *  ------------------------------------------------------------------------\n     *  The log function writes the passed item to the javascript console.\n     */\n    let logCount = 0;\n    debug.log = (...values) => {\n        const term = new types.Tuple(...values).normalize();\n        \n        logCount++;\n        console.log(`Log ${logCount}:`, term);\n        return `[[Log ${logCount}]]`;\n    }\n    \n    \n    /**\n     *  debug.inspect: Term t -> Namespace info\n     *  ------------------------------------------------------------------------\n     *  Returns an object containing detailed information about the passed term.\n     */\n    debug.inspect = (...values) => {\n        const term = new types.Tuple(...values).normalize();\n        \n        const info = {\n            type: term.typeName\n        }\n        \n        // return;\n\n        switch (info.type) {\n            \n            case \"Bool\":\n            case \"Numb\":\n            case \"Text\":\n                info.value = types.unwrap(term);\n                break;\n                \n            case \"List\":\n                info.value = term.domain.map(index => debug.inspect(term.vget(index)));\n                break;\n                \n            case \"Namespace\":\n                info.value = {};\n                for (let key of term.domain) {\n                    info.value[key] = debug.inspect(term.vget(key))\n                }\n                break;\n                \n            case \"Func\":\n                break;\n                \n            case \"Tuple\":\n                info.value = Array.from(term.items()).map(item => debug.inspect(item));\n                break;\n                \n            case \"Undefined\":\n                info.operation = term.type;\n                info.arguments = term.args.map(arg => debug.inspect(arg));\n                if (term.position) {\n                    const [row, col] = term.position.getLocation();\n                    info.source = term.position.source.split('\\n')[row-1];\n                    info.position = col;\n                }\n                break;\n        }\n        \n        return info;\n    }\n    \n    return debug;\n}\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/modules/debug.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/modules/index.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/modules/index.js ***!
    \******************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("module.exports = {\n\n    \"numb\"      : () => Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! ./numb.js */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/numb.js\", 23)),\n    \"text\"      : () => Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! ./text.js */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/text.js\", 23)),\n    \"list\"      : () => Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! ./list.js */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/list.js\", 23)),\n    \n    \"time\"      : () => Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! ./time.js */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/time.js\", 23)),\n    \"json\"      : () => Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! ./json.js */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/json.js\", 23)),\n    \"debug\"     : () => Promise.resolve(/*! import() */).then(__webpack_require__.t.bind(__webpack_require__, /*! ./debug.js */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/debug.js\", 23))\n}\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/modules/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/modules/json.js":
  /*!*****************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/modules/json.js ***!
    \*****************************************************************/
  /***/ ((module) => {
  
  eval("/**\n *  json module\n *  ============================================================================\n *  \n *  This module contains functions for parsing and serializing JSON data.\n */\n \nmodule.exports = types => {\n    const json = {};\n    \n    const undefined_text = new types.Undefined(\"Text\");\n    const undefined_namespace = new types.Undefined(\"Namespace\");\n\n    const isString = x => types.wrap(x) instanceof types.Text;\n    const isNamespace = x => types.wrap(x) instanceof types.Namespace;\n\n    \n    /**\n     *  json.parse: Text t -> Namespace ns\n     *  ------------------------------------------------------------------------\n     *  Converts a JSON string to a namespace. \n     */\n    json.parse = str => isString(str) ? JSON.parse(types.unwrap(str)) : undefined_namespace;\n\n\n    /**\n     *  json.parse: Term t -> Text s\n     *  ------------------------------------------------------------------------\n     *  Converts a term to a JSON string. It returns `Undefined(Text)` if `t` is\n     *  a `Func` or an `Undefined` item.\n     */\n    json.serialize = (...items) => {\n        const term = new types.Tuple(...items);\n        \n        return term.imapSync(item => {            \n            switch (item.typeName) {\n                \n                case 'Bool':\n                case 'Numb':\n                case 'Text':\n                case 'List':\n                case 'Namespace':\n                    return JSON.stringify(types.unwrap(item), null, 2);\n                    \n                default:\n                    return undefined_text;\n            }\n        });\n    }\n\n    return json;\n}\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/modules/json.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/modules/list.js":
  /*!*****************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/modules/list.js ***!
    \*****************************************************************/
  /***/ ((module) => {
  
  eval("/**\n *  list module\n *  ============================================================================\n *  \n *  This module contains functions that operate on the swan List data type.\n */\n \nmodule.exports = types => {\n    const list = {};\n    \n    const undefined_text = new types.Undefined(\"Text\");\n    const undefined_list = new types.Undefined(\"List\");\n\n    const isNumb = x => types.wrap(x) instanceof types.Numb;\n    const isText = x => types.wrap(x) instanceof types.Text;\n    const isList = x => types.wrap(x) instanceof types.List;\n    const isFunc = x => types.wrap(x) instanceof types.Func;\n\n\n    /**\n     *  list.reverse: List l1 -> List l2\n     *  ------------------------------------------------------------------------\n     *  Given a list l1, returns a new list l2, containing the items of l1 in\n     *  reversed order.\n     *  If the argument is not a List item, this function returns Undefined List.\n     *  If the parameter is a tuple, this function applies only to the first\n     *  item and ignore the others.\n     */\n    list.reverse = L => {\n        if (isList(L)) {\n            const rlist = [];\n            for (let i=L.length-1; i>=0; i--) rlist.push(L[i]);\n            return rlist;\n        } else {\n            return undefined_list;\n        }\n    };\n\n    \n    /**\n     *  list.find: Item x -> List L -> Numb k\n     *  ------------------------------------------------------------------------\n     *  Takes an item `x` as argument and returns a function `f`. If the \n     *  argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a list `L` as argument and returns the first position of `x` in \n     *    `L` or `-1` if `x` is not contained in `L`.\n     *  - returns Undefined List if the argument of `f` is not a List item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    list.find = x => L => isList(L) ? L.indexOf(x) : NaN;\n    \n\n    /**\n    *  list.rfind: Item x -> List L -> Numb k\n    *  ------------------------------------------------------------------------\n    *  Takes an item `x` as argument and returns a function `f`. \n    *  If the argument is a tuple, it applies only to its first item.\n    *  \n    *  The returned function `f`: \n    *  - takes a list `L` as argument and returns the last position of `x` in \n    *    `L` or `-1` if `x` is not contained in `L`.\n    *  - returns Undefined List if the argument of `f` is not a List item\n    *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    list.rfind = x => L => isList(L) ? L.lastIndexOf(x) : NaN;\n    \n\n    /**\n     *  list.head: Numb n -> List L -> List l\n     *  ------------------------------------------------------------------------\n     *  Takes a number `n` as argument and returns a function `f`. \n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a list `L` as argument and returns the sub-list at the left-side \n     *    of the n-th item. If n is negative, the item position is computed as \n     *    relative to the end of `L`.     \n     *  - returns Undefined List if the argument of `f` is not a List item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    list.head = n => L => isNumb(n) && isList(L) ? L.slice(0,n) : undefined_list;\n\n    /**\n     *  list.tail: Numb n -> List L -> List l\n     *  ------------------------------------------------------------------------\n     *  Takes a number `n` as argument and returns a function `f`. \n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a list `L` as argument and returns the sub-list at the \n     *    right-side of the n-th item (including the latter). If n is negative, \n     *    the item position is computed as relative to the end of `L`.     \n     *  - returns Undefined List if the argument of `f` is not a List item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    list.tail = n => L => isNumb(n) && isList(L) ? L.slice(n) : undefined_list;\n\n\n    /**\n     *  list.join: Text s -> List L -> Text S\n     *  ------------------------------------------------------------------------\n     *  Takes a separator `s` as argument and returns a function `f`.\n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a List `L` of Text items as argument and returns the string\n     *    obtained by joining all the items with interposed  sparator.\n     *  - returns Undefined List if the argument of `f` is not a List item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    list.join = separator => L => {\n        if (!isText(separator)) return undefined_text;\n        for (let value of L) if (!isText(value)) return undefined_text;\n        return L.join(separator);\n    };\n\n\n    return list;   \n}\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/modules/list.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/modules/numb.js":
  /*!*****************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/modules/numb.js ***!
    \*****************************************************************/
  /***/ ((module) => {
  
  eval("/**\n *  numb module\n *  ============================================================================\n *  \n *  This module contains functions and constants that operate on the swan Numb\n *  data type.\n *  \n *  Unless specified otherwise, all the functions of this library assume that\n *  their parameter is an item (1-d tuple). If more that one item is passed\n *  to a function, only the first item will be used and the others will be\n *  ignored.\n */\n\nmodule.exports = types => {\n    const numb = {};\n    \n    const isNumb = x => types.wrap(x) instanceof types.Numb;\n    const isText = x => types.wrap(x) instanceof types.Text;\n\n\n    /**\n     *  Math constants\n     *  ------------------------------------------------------------------------\n     *  The following constants are defined:\n     *  \n     *  - `numb.INFINITY`: Infinity.\n     *  - `numb.PI`: Ratio of the a circle's circumference to its diameter, approximately 3.14159.\n     *  - `numb.E`: Euler's constant and the base of natural logarithms, approximately 2.718.\n     */\n    numb.INFINITY = Infinity;\n    numb.PI = Math.PI;\n    numb.E = Math.E;\n\n\n    /**\n     *  numb.parse: Text s -> Numb n\n     *  ------------------------------------------------------------------------\n     *  Converts a string to a number. It accepts also binary (0b...), octal\n     *  (0o...) and exadecimal (0x...) string representations of numbers.\n     *  If the argument is not a valid string, this function returns Undefined Number.\n     */\n    numb.parse = s => isText(s) ? Number(s) : NaN;\n    \n    \n    /**\n     *  Trigonometric functions\n     *  ------------------------------------------------------------------------\n     *  The Numb namespace contains the following trigonometric functions: \n     *  \n     *  - `numb.cos`:  Returns the cosine of a number.\n     *  - `numb.sin`:  Returns the sine of a number.\n     *  - `numb.tan`:  Returns the tangent of a number.\n     *  - `numb.acos`: Returns the arccosine of a number.\n     *  - `numb.asin`: Returns the arcsine of a number.\n     *  - `numb.atan`: Returns the arctangent of a number.\n     *  \n     *  If the argument is not a number, these functions return Undefined Number.\n     */\n    numb.cos  = x => isNumb(x) ? Math.cos(x)  : NaN;\n    numb.sin  = x => isNumb(x) ? Math.sin(x)  : NaN;\n    numb.tan  = x => isNumb(x) ? Math.tan(x)  : NaN;\n    numb.acos = x => isNumb(x) ? Math.acos(x) : NaN;\n    numb.asin = x => isNumb(x) ? Math.asin(x) : NaN;\n    numb.atan = x => isNumb(x) ? Math.atan(x) : NaN;\n\n    \n    /**\n     *  Hyperbolic functions\n     *  ------------------------------------------------------------------------\n     *  The Numb namespace contains the following hyperbolic functions: \n     *  \n     *  - `numb.cosh`:  Returns the hyperbolic cosine of a number.\n     *  - `numb.sinh`:  Returns the hyperbolic sine of a number.\n     *  - `numb.tanh`:  Returns the hyperbolic tangent of a number.\n     *  - `numb.acosh`: Returns the hyperbolic arccosine of a number.\n     *  - `numb.asinh`: Returns the hyperbolic arcsine of a number.\n     *  - `numb.atanh`: Returns the hyperbolic arctangent of a number.\n     *  \n     *  If the argument is not a number, these functions return Undefined Number.\n     */\n    numb.cosh  = x => isNumb(x) ? Math.cosh(x)  : NaN;\n    numb.sinh  = x => isNumb(x) ? Math.sinh(x)  : NaN;\n    numb.tanh  = x => isNumb(x) ? Math.tanh(x)  : NaN;\n    numb.acosh = x => isNumb(x) ? Math.acosh(x) : NaN;\n    numb.asinh = x => isNumb(x) ? Math.asinh(x) : NaN;\n    numb.atanh = x => isNumb(x) ? Math.atanh(x) : NaN;\n    \n    \n    /**\n     *  Rounding\n     *  ------------------------------------------------------------------------\n     *  The following functions perform number rounding. \n     *  \n     *  - `Math.ceil`: Returns the smallest integer greater than or equal to a number.\n     *  - `Math.floor`: Returns the largest integer less than or equal to a number.\n     *  - `Math.trunc`: Returns the integer part of the number x, removing any fractional digits.\n     *  - `Math.round`: Returns the value of a number rounded to the nearest integer.\n     *  \n     *  If the argument is not a number, these functions return Undefined Number.\n     */\n    numb.ceil  = x => isNumb(x) ? Math.ceil(x)  : NaN;\n    numb.floor = x => isNumb(x) ? Math.floor(x) : NaN;\n    numb.trunc = x => isNumb(x) ? Math.trunc(x) : NaN;\n    numb.round = x => isNumb(x) ? Math.round(x) : NaN;\n    \n\n    /**\n     *  numb.abs - function\n     *  ------------------------------------------------------------------------\n     *  Returns the absolute value of a number. \n     *  If the argument is not a number, this functions return Undefined Number.\n     */\n    numb.abs = x => isNumb(x) ? Math.abs(x) : NaN;\n\n\n    /**\n     *  numb.exp - function\n     *  ------------------------------------------------------------------------\n     *  Returns E^x, where x is the argument, and E is Euler's constant. \n     *  If the argument is not a number, this functions return Undefined Number.\n     */\n    numb.exp = x => isNumb(x) ? Math.exp(x) : NaN;\n    \n    \n    /**\n     *  numb.log - function\n     *  ------------------------------------------------------------------------\n     *  Returns the natural logarithm of a number. \n     *  If the argument is not a number, this functions return Undefined Number.\n     */\n    numb.log = x => isNumb(x) ? Math.log(x) : NaN;\n    \n    \n    /**\n     *  numb.log10 - function\n     *  ------------------------------------------------------------------------\n     *  Returns the base 10 logarithm of a number. \n     *  If the argument is not a number, this functions return Undefined Number.\n     */\n    numb.log10 = x => isNumb(x) ? Math.log10(x) : NaN;\n    \n    \n    /**\n     *  numb.max - function\n     *  ------------------------------------------------------------------------\n     *  Returns the largest of zero or more numbers.\n     *  If any argument is not a number, this functions return Undefined Number.\n     */\n    numb.max = Math.max;\n\n\n    /**\n     *  numb.min - function\n     *  ------------------------------------------------------------------------\n     *  Returns the smallest of zero or more numbers.\n     *  If any argument is not a number, this functions return Undefined Number.\n     */\n    numb.min = Math.min;\n    \n\n    /**\n     *  numb.random - function\n     *  ------------------------------------------------------------------------\n     *  Returns a pseudo-random number between 0 and the given argument.\n     *  If the argument is not a number, this functions return Undefined Number.\n     */\n    numb.random = x => isNumb(x) ? Math.random()*x : NaN;\n\n\n    /**\n     *  numb.sqrt - function\n     *  ------------------------------------------------------------------------\n     *  Returns the positive square root of a number.\n     *  If any argument is not a number, this functions return Undefined Number.\n     */\n    numb.sqrt = x => isNumb(x) ? Math.sqrt(x) : NaN;\n    \n    \n    return numb;  \n}\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/modules/numb.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/modules/text.js":
  /*!*****************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/modules/text.js ***!
    \*****************************************************************/
  /***/ ((module) => {
  
  eval("/**\n *  text module\n *  ============================================================================\n *  \n *  This module contains functions that operate on the swan Text data type.\n */\n \nmodule.exports = types => {\n    const text = {};\n    \n    const undefined_text = new types.Undefined(\"Text\");\n\n    const isNumber = x => types.wrap(x) instanceof types.Numb;\n    const isString = x => types.wrap(x) instanceof types.Text;\n\n    \n    /**\n     *  text.find: Text s -> Text S -> Numb k\n     *  ------------------------------------------------------------------------\n     *  Takes a string `s` as argument and returns a function `f`. \n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a string `S` as argument and returns the first position of `s` \n     *    in `S` or `-1` if `s` is not contained in `S`.\n     *  - returns Undefined Number if the argument of `f` is not a Text item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    text.find = s1 => s2 => isString(s1) && isString(s2) ? s2.indexOf(s1) : NaN;\n\n\n    /**\n     *  text.rfind: Text s -> Text S -> Numb k\n     *  ------------------------------------------------------------------------\n     *  Takes a string `s` as argument and returns a function `f`.\n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a string `S` as argument and returns the last position of `s` \n     *    in `S` or `-1` if `s` is not contained in `S`.\n     *  - returns Undefined Number if the argument of `f` is not a Text item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    text.rfind = s1 => s2 => isString(s1) && isString(s2) ? s2.lastIndexOf(s1) : NaN;\n    \n\n    /**\n     *  text.lower: Text S -> Text s\n     *  ------------------------------------------------------------------------\n     *  Returns the passed string in lower-case. \n     *  If the argument is not a Text item, this functions return Undefined text.\n     *  If the parameter is a tuple, this function applies to its first item only.\n     */\n    text.lower = str => isString(str) ? str.toLowerCase() : undefined_text;\n    \n\n    /**\n     *  text.upper: Text s -> Text S\n     *  ------------------------------------------------------------------------\n     *  Returns the passed string in upper-case. \n     *  If the argument is not a Text item, this functions return Undefined text.\n     *  If the parameter is a tuple, this function applies to its first item only.\n     */\n    text.upper = str => isString(str) ? str.toUpperCase() : undefined_text;\n    \n    \n    /**\n     *  text.trim: Text S -> Text s\n     *  ------------------------------------------------------------------------\n     *  Removed the leading and trailing spaces from the given string.\n     *  If the argument is not a Text item, this functions return Undefined text.\n     *  If the parameter is a tuple, this function applies to its first item only.\n     */\n    text.trim = s => isString(s) ? s.trim() : undefined_text;\n\n\n    /**\n     *  text.trim_head: Text S -> Text s\n     *  ------------------------------------------------------------------------\n     *  Removed the leading spaces from the given string.\n     *  If the argument is not a Text item, this functions return Undefined text.\n     *  If the parameter is a tuple, this function applies to its first item only.\n     */\n    text.trim_head = s => isString(s) ? s.trimStart() : undefined_text;\n\n\n    /**\n     *  text.trim_tail: Text S -> Text s\n     *  ------------------------------------------------------------------------\n     *  Removed the trailing spaces from the given string.\n     *  If the argument is not a Text item, this functions return Undefined text.\n     *  If the parameter is a tuple, this function applies to its first item only.\n     */\n    text.trim_tail = s => isString(s) ? s.trimEnd() : undefined_text;\n    \n\n    /**\n     *  text.head: Numb n -> Text S -> Text s\n     *  ------------------------------------------------------------------------\n     *  Takes a number `n` as argument and returns a function `f`.\n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a string `s` as argument and returns the substring at the \n     *    left-side of the n-th character. If n is negative, the character \n     *    position is computed as relative to the end of `L`.\n     *  - returns Undefined Text if the argument of `f` is not a Text item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    text.head = n => s => isNumber(n) && isString(s) ? s.slice(0,n) : undefined_text;\n    \n\n    /**\n     *  text.tail: Numb n -> Text S -> Text s\n     *  ------------------------------------------------------------------------\n     *  Takes a number `n` as argument and returns a function `f`.\n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a string `s` as argument and returns the substring at the \n     *    right-side of the n-th character (including the latter). If n is \n     *    negative, the character position is computed as relative to the \n     *    end of `S`.\n     *  - returns Undefined Text if the argument of `f` is not a Text item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    text.tail = n => s => isNumber(n) && isString(s) ? s.slice(n) : undefined_text;\n\n\n    /**\n     *  text.split: Text s -> Text S -> List l\n     *  ------------------------------------------------------------------------\n     *  Takes a string `s` as argument and returns a function `f`.\n     *  If the argument is a tuple, it applies only to its first item.\n     *  \n     *  The returned function `f`: \n     *  - takes a string `S` as argument and returns the list of substring \n     *    separated by s. For example, if the divider is `s=\":\"` and the string \n     *    is `S=\"a:b:c\"`, the function `f` returns `[\"a\",\"b\",\"c\"]`.\n     *  - returns Undefined Text if the argument of `f` is not a Text item\n     *  - applies only on the first item if the parameter of `f` is a tuple\n     */\n    text.split = s1 => s2 => isString(s1) && isString(s2) ? s2.split(s1) : undefined_text; \n    \n    \n    return text;   \n}\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/modules/text.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/modules/time.js":
  /*!*****************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/modules/time.js ***!
    \*****************************************************************/
  /***/ ((module) => {
  
  eval("/**\n *  time module\n *  ============================================================================\n *  \n *  This module contains functions and constants that operate on time and\n *  dates.\n *  \n *  Unless specified otherwise, all the functions of this library assume that\n *  their parameter is an item (1-d tuple). If more that one item is passed\n *  to a function, only the first item will be used and the others will be\n *  ignored.\n */\n\nmodule.exports = types => {\n    const time = {};\n    \n    const isNumb = x => types.wrap(x) instanceof types.Numb;\n    const isText = x => types.wrap(x) instanceof types.Text;\n    const isNamespace = x => types.wrap(x) instanceof types.Namespace;\n    \n    const undefined_text = new types.Undefined(\"Text\");\n    const undefined_date = new types.Undefined(\"Date\");\n\n\n    /**\n     *  time.now: () => Numb t\n     *  ------------------------------------------------------------------------\n     *  It returns the current epoch time in seconds.\n     */\n    time.now = () => Date.now() / 1000;\n\n\n    /**\n     *  time.timezone: () -> Numb n\n     *  ------------------------------------------------------------------------\n     *  It returns the current UTC time-zone offset in hours. For example in \n     *  UTC+1 it will return +1.\n     */\n    time.timezone = () => -(new Date()).getTimezoneOffset() / 60;\n    \n    \n    /**\n     *  time.to_date: Numb t -> Namespace d\n     *  ------------------------------------------------------------------------\n     *  Given an epoch time expressed in seconds, it returns a `date` Namespace \n     *  containg the following local date information:\n     *  \n     *  - `date.year` : Numb\n     *  - `date.month` : Numb between 1 (January) and 12 (December)\n     *  - `date.day` : Numb between 1 and 31\n     *  - `date.hours` : Numb between 0 and 23\n     *  - `date.minutes` : Numb between 0 and 59\n     *  - `date.seconds` : Numb between 0.000 and 59.999\n     */\n    time.to_date = t => {\n        if (!isNumb(t)) return undefined_date;\n        const date = new Date(t*1000);\n        return {\n            year: date.getFullYear(),\n            month: date.getMonth() + 1,\n            day: date.getDate(),\n            hours: date.getHours(),\n            minutes: date.getMinutes(),\n            seconds: date.getSeconds() + date.getMilliseconds() / 1000,\n        }\n    }\n\n    \n    /**\n     *  time.to_UTC_date: Numb t -> Namespace d\n     *  ------------------------------------------------------------------------\n     *  Given an epoch time expressed in seconds, it returns a `date` Namespace \n     *  containg the following UTC date information:\n     *  \n     *  - `date.year` : Numb\n     *  - `date.month` : Numb between 1 (January) and 12 (December)\n     *  - `date.day` : Numb between 1 and 31\n     *  - `date.hours` : Numb between 0 and 23\n     *  - `date.minutes` : Numb between 0 and 59\n     *  - `date.seconds` : Numb between 0.000 and 59.999\n     */\n    time.to_UTC_date = t => {\n        if (!isNumb(t)) return undefined_date;\n        const date = new Date(t*1000);\n        return {\n            year: date.getUTCFullYear(),\n            month: date.getUTCMonth() + 1,\n            day: date.getUTCDate(),\n            hours: date.getUTCHours(),\n            minutes: date.getUTCMinutes(),\n            seconds: date.getUTCSeconds() + date.getUTCMilliseconds() / 1000,\n        }\n    },\n    \n\n    /**\n     *  time.from_date: Namespace d -> Numb t\n     *  ------------------------------------------------------------------------\n     *  Given a local date namespace, it returns the correspondign epoch time \n     *  expressed in seconds.\n     */\n    time.from_date = date => {\n        if (!isNamespace(date)) return NaN;\n        const seconds = date.seconds ? Math.trunc(date.seconds) : 0;\n        const milliseconds = Math.round((date.seconds - seconds) * 1000);\n        return Number(new Date(\n            date.year || 0,\n            (date.month || 1) - 1,\n            date.day || 1,\n            date.hours || 0,\n            date.minutes || 0,\n            seconds,\n            milliseconds\n        )) / 1000;\n    },\n\n    \n    /**\n     *  time.from_UTC_date: Namespace d -> Numb t\n     *  ------------------------------------------------------------------------\n     *  Given an UTC date namespace, it returns the correspondign epoch time \n     *  expressed in seconds.\n     */\n    time.from_UTC_date = date => {\n        if (!isNamespace(date)) return NaN;\n        const seconds = date.seconds ? Math.trunc(date.seconds) : 0;\n        const milliseconds = Math.round((date.seconds - seconds) * 1000);\n        return Number(Date.UTC(\n            date.year || 0,\n            (date.month || 1) - 1,\n            date.day || 1,\n            date.hours || 0,\n            date.minutes || 0,\n            seconds,\n            milliseconds\n        )) / 1000;\n    },\n\n\n    /**\n     *  time.to_ISO_string: Numb t -> Text d\n     *  ------------------------------------------------------------------------\n     *  Given an epoch time in seconds, it returns its ISO string representation.\n     *  For example:\n     *  \n     *  ```\n     *  time = time.to_ISO_string(1639513675.900)\n     *  // returns \"2021-12-14T20:27:55.900Z\"\n     *  ```\n     */\n    time.to_ISO_string = t => isNumb(t) ? new Date(t*1000).toISOString() : undefined_text;\n    \n\n    /**\n     *  time.from_string: Text d -> Numb t\n     *  ------------------------------------------------------------------------\n     *  Returns an epoch time in seconds given a date string representation.\n     *  For example:\n     *  \n     *  ```\n     *  time = time.from_string(\"2021-12-14T20:27:55.900Z\")   \n     *  // returns 1639513675.900 s\n     *  ```\n     */\n    time.from_string = s => isText(s) ? Number( Date.parse(s) ) / 1000 : NaN;\n    \n\n    /**\n     *  time.week_day: Numb t -> Numb wd\n     *  ------------------------------------------------------------------------\n     *  Given an epoch time, it returns the day of the week of the corresponding, \n     *  date in the loacal timezone. Sunday is 0, monday is 1, tuesday is 2, etc.\n     *  For example:\n     *  \n     *  ```\n     *  time.week_day(1639513675.900)   // returns 2 for Tuesday\n     *  ```\n     */\n    time.week_day = t => isNumb(t) ? new Date(t*1000).getDay() : NaN;\n    \n\n    /**\n     *  time.week_number: Numb t -> Numb w\n     *  ------------------------------------------------------------------------\n     *  Given an epoch time, it returns the week number of the corresponding, \n     *  date in the loacal timezone. For example:\n     *  \n     *  ```\n     *  time.week_number(1639513675.900)   // returns 50\n     *  ```\n     */\n    time.week_number = t => {\n        if (!isNumb(t)) return NaN;\n        const date = new Date(t*1000);\n        date.setHours(0, 0, 0, 0);\n        // Thursday in current week decides the year.\n        date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);\n        // January 4 is always in week 1.\n        var week1 = new Date(date.getFullYear(), 0, 4);\n        // Adjust to Thursday in week 1 and count number of weeks from date to week1.\n        return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);        \n    };\n    \n    \n    return time;  \n}\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/modules/time.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/parser.js":
  /*!***********************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/parser.js ***!
    \***********************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("// This is the parser used by the Swan interpreter. In general the module\n// provides a parser able to generate an abstract syntax tree from any\n// sequence of binary or unary operations evantually grouped with parenthesis,\n// square braces or curly braces.\n\n\n\n// The Lexer converts a plain expression string in a sequence of tokens.\n// This is the first step of the parsing procedure.\nconst Lexer = __webpack_require__(/*! ./lexer */ \"../../node_modules/@onlabsorg/swan-js/lib/lexer.js\");\n\n\n\n//  The `Parser` class that takes as parametse an `options` object that defines \n//  the expression operations.\n//  \n//  A `Parser` instance has a `parse` method that takes an expression string as\n//  argument and return an Abstract Syntax Tree. Each node of the AST is an\n//  instance of the ASTNode class, which is also exported by this module.\nclass Parser {\n    \n    constructor (options) {\n        this.options = options;\n        \n        // create the lexer, given the list of the valid operators\n        this.lexer = new Lexer({\n            binaryOperators: Object.keys(options.binaryOperations),\n            unaryOperators: Object.keys(options.unaryOperations)\n        });\n    }\n    \n    // Converts an expression string to a list of tokens and return a `Tokens`\n    // instance (See Token class below).\n    tokenize (source) {\n        return new Tokens(...this.lexer.tokenize(source));\n    }\n\n    // Creates a Syntax error\n    createSyntaxError (message, token) {\n        return new Lexer.SyntaxError(message, token.position.source, token.position.index);\n    }\n    \n    // Creates a binary operation ASTNode. It eventually uses a custom ASTNode \n    // class if provided with the options object.\n    createBinaryOperation (operator, leftHandOperand, rightHandOperand, position) {\n        const Node = this.options.binaryOperations[operator].Node || ASTNode;\n        return new Node(position, 'binary-operation', operator, leftHandOperand, rightHandOperand);\n    }\n    \n    // Creates a unary operation ASTNode. It eventually uses a custom ASTNode \n    // class if provided with the options object.\n    createUnaryOperation (operator, operand, position) {\n        const Node = this.options.unaryOperations[operator].Node || ASTNode;\n        return new Node(position, 'unary-operation', operator, operand);\n    }\n\n    // Creates a grouping operation ASTNode. It eventually uses a custom ASTNode \n    // class if provided with the options object.\n    createGroupingOperation (braces, operand, position) {\n        const Node = this.options.groupingOperations[braces].Node || ASTNode;\n        return new Node(position, 'grouping-operation', braces, operand);\n    }\n\n    // Creates a literal ASTNode. It eventually uses a custom ASTNode class\n    // if provided with the options object.\n    createLiteral (type, value, position) {\n        const Node = this.options.literals[type].Node || ASTNode;\n        return new Node(position, type, value);\n    }\n    \n    // The following tuns turns the next tokens into a single Operation tree.\n    // It stops when the passed `done` condition is true\n    parseExpression (tokens, done) {\n        \n        // If the `done` condition is immediately true, than the expression\n        // is empty and the `void` operation is returned.\n        if (done()) {\n            const lastToken = tokens.get() || tokens.last || tokens.tail;\n            tokens.inc(); return this.createLiteral('void', null, lastToken.position);\n        }\n        \n        // First generates an `expression` list [operand, operator, operand, operator, ...].\n        // Then sorts the operators by precedence and returns a function.\n        \n        // Initialize the shunting-yard object\n        const shuntingYard = new ShuntingYard(this.options.binaryOperations);\n        shuntingYard.pushOperand( this.parseOperand(tokens) );\n        \n        // Iterate over all the other operators and operands and add them\n        // to the `expression` list until the `done` condition is matched.\n        while (!done()) {\n            \n            // parse nexe operand\n            if (tokens.get() && tokens.get().matchBinaryOperator()) {\n                shuntingYard.pushOperator(tokens.get().value, tokens.get().position);\n                tokens.inc(); \n                if (done()) {\n                    throw this.createSyntaxError('Operand expected', tokens.get() || tokens.tail);\n                }\n            }\n            else {\n                // if the next token is not an operator, then an empty operator\n                // is assumed. This means that the expression consists of \n                // two operands next to each other, without any interposed\n                // operator.\n                shuntingYard.pushOperator(\"\", tokens.get(-1).position);\n            }\n            \n            // parse nexe operator\n            shuntingYard.pushOperand( this.parseOperand(tokens) );\n        }\n        \n        tokens.inc();\n        shuntingYard.done();\n        \n        // Returns the root operation\n        return this.popNode(shuntingYard);\n    }\n    \n    // Extracts an abstract syntax tree from the ShuntingYard object.\n    popNode (shuntingYard) {\n        if (shuntingYard.top instanceof Operator) {\n            const operator = shuntingYard.pop();\n            const rightHandOperand = this.popNode(shuntingYard);\n            const leftHandOperand = this.popNode(shuntingYard);\n            return this.createBinaryOperation(operator.symbol, leftHandOperand, rightHandOperand, operator.position);\n        } else {\n            return shuntingYard.pop();\n        }\n    }\n    \n    // Returns the next operand in line.\n    // An operand can be a value (leaf) or an branch of the operation tree.\n    parseOperand (tokens) {\n        var unaryOperator, operand, token = tokens.get();\n        \n        // If the end of the expression has been reached, throws an error\n        if (!token) {\n            throw this.createSyntaxError('Operand expected', tokens.tail);\n        }\n        \n        // If the operand is preceded by a unary operator\n        if (token.matchUnaryOperator()) {\n            unaryOperator = token; \n            token = tokens.inc().get();\n        }\n        \n        // If just a number literal\n        if (token.matchNumberLiteral()) {\n            operand = this.createLiteral('number', token.value, token.position); \n            tokens.inc();\n        }\n        \n        // If a string literal\n        else if (token.matchStringLiteral()) {\n            if (token.quoteSymbol === `'`) operand = this.createLiteral('string1', token.value, token.position);\n            else if (token.quoteSymbol === `\"`) operand = this.createLiteral('string2', token.value, token.position);\n            else if (token.quoteSymbol === '`') operand = this.createLiteral('string3', token.value, token.position);\n            tokens.inc();\n        }\n        \n        // If an identifier\n        else if (token.matchIdentifier()) {\n            operand = this.createLiteral('identifier', token.value, token.position);\n            tokens.inc();\n        }\n        \n        // If a subexpression between `(` and `)`\n        else if (token.matchSymbol('(')) {\n            tokens.inc(); \n            operand = this.parseExpression(tokens,  () => tokens.get() && tokens.get().matchSymbol(\")\") );\n        }\n        \n        // If a subexpression between `[` and `]`\n        else if (token.matchSymbol('[')) {\n            const position = token.position; \n            tokens.inc();\n            let expression = this.parseExpression(tokens,  () => tokens.get() && tokens.get().matchSymbol(\"]\") );\n            operand = this.createGroupingOperation('[]', expression, position);\n        }\n        \n        // If a subexpression between `{` and `}`\n        else if (token.matchSymbol('{')) {\n            const position = token.position; \n            tokens.inc();\n            let expression = this.parseExpression(tokens,  () => tokens.get() && tokens.get().matchSymbol(\"}\") );\n            operand = this.createGroupingOperation('{}', expression, position);\n        }\n        \n        // No valid operand found\n        else {\n            throw this.createSyntaxError('Operand expected', token);\n        }\n        \n        if (unaryOperator) {\n            return this.createUnaryOperation(unaryOperator.value, operand, unaryOperator.position);\n        } else {\n            return operand;\n        }\n    }    \n    \n    // This is the main API of this class. The user calls it to obtain an\n    // abstract syntax tree from the passed expression source.\n    parse (source) {\n        var tokens = this.tokenize(source);    // array of tokens\n        tokens.tail = {position: new Lexer.Position(source, source.length)};\n        \n        // Parse the entier expression and return the `evaluate` function\n        return this.parseExpression(tokens, () => tokens.done() );\n    }\n    \n    // Expose the Position object to the final user of this class.\n    static get Position () {\n        return Lexer.Position;\n    }\n}\n\n\n\n// A Tokens object contains the string of tokens returned by the lexer, together\n// with a bunch of handy methods designed to help the parsing process.\nclass Tokens {\n    \n    constructor (...tokens) {\n        this.tokens = tokens;\n        this.index = 0;\n    }\n    \n    inc (step=1) {\n        this.index += step;\n        return this;\n    }\n    \n    get (step=0) {\n        return this.tokens[this.index+step];\n    }\n    \n    get last () {\n        return this.tokens[this.tokens.length-1];\n    }\n    \n    done () {\n        return this.index >= this.tokens.length;\n    }\n}\n\n\n\n// The ShuntingYard instances implement the shunting yard algorithm to sort the\n// binary AST nodes based on the operator precedences. The precedences are\n// defined in the `binaryOperations` object passed to the constructor.\n// The `binaryOperations` object is defined by the user and passed to the\n// `Parser` constructor under `options.binaryOperations`.\nclass ShuntingYard {\n    \n    constructor (binaryOperations) {\n        this.binaryOperations = binaryOperations;\n        this.output = [];       // output queue\n        this.operators = [];    // operators stack\n    }\n    \n    pushOperand (operand) {\n        this.output.push(operand);\n    }\n    \n    pushOperator (symbol, position) {\n        const operator = new Operator(symbol, this.binaryOperations[symbol], position);\n        while (this.operators.length > 0 && this.lastOperator.preceeds(operator)) {\n            this.output.push(this.operators.pop());\n        }\n        this.operators.push(operator);\n    }\n    \n    done () {\n        while (this.operators.length > 0) {\n            this.output.push(this.operators.pop());            \n        }\n    }\n    \n    get lastOperator () {\n        return this.operators[this.operators.length-1] || null;\n    }\n    \n    get top () {\n        return this.output[this.output.length-1];\n    }\n    \n    pop () {\n        return this.output.pop();\n    }\n}\n\n\n\n// This class represents an operator being processed by the shunting yard\n// algorithm. This object is used by the `ShuntngYard` objects and by the\n// `popNode` method of the `Parser` objects.\nclass Operator {\n    \n    constructor (symbol, options, position) {\n        this.symbol = symbol;\n        this.options = options;\n        this.position = position;\n    }\n    \n    get precedence () { return this.options.precedence }\n    \n    get isRightAssociative () { return Boolean(this.options.right) }\n    \n    get isLeftAssociative () { return !this.isRightAssociative }\n    \n    preceeds (other) {\n        return this.precedence > other.precedence ||\n                (this.precedence === other.precedence && other.isLeftAssociative);\n    }\n}\n\n\n\n// This is a node of the Abstrac Syntax Tree returned by `parser.parse(expression)`.\nclass ASTNode {\n    \n    constructor (pos, type, value, ...children) {\n        \n        // Position object containing informations about the location of this\n        // nome in the expression source. See `Position` class definition in\n        // lexer module.\n        this.position = pos;\n        \n        // node.type contains one of the following strings:\n        //\n        //  - `\"binary-operation\"` if the node represents a binary operation. \n        //      In that case `node.value` contains the operator symbol and \n        //      `node.children` contains the left-hand and right-hand operands\n        //      (which are in turns ASTNode instances).\n        //      \n        //  - `\"unary-operation\"` if the node represents a unary operation. \n        //      In that case `node.value` contains the operator symbol and \n        //      `node.children` contains the operand (which is in turns an \n        //      ASTNode instance).\n        //      \n        //  - `\"grouping-operation\"` if the node represents a grouping between\n        //      squanre or curly braces. In that case `node.value` contains \n        //      either `\"[]\"` or `\"{}\"` and `node.children` contains the node\n        //      representing the expression between braces.\n        //      \n        //  - `\"void\"` if the node represents a void literal `()`. In that case\n        //      `node.value` is null and `node.children` is an empty array.\n        //\n        //  - `\"number\"` if the node represents a number literal. In that case\n        //      `node.value` contains the numeric value and `node.children` is \n        //      an empty array.\n        //\n        //  - `\"string1\"` if the node represents a string literal enclosed \n        //      between single quotes `''`. In that case `node.value` contains \n        //      the text value and `node.children` is an empty array.\n        //\n        //  - `\"string2\"` if the node represents a string literal enclosed \n        //      between double quotes `\"\"`. In that case `node.value` contains \n        //      the text value and `node.children` is an empty array.\n        //\n        //  - `\"string3\"` if the node represents a string literal enclosed \n        //      between accent quotes ````. In that case `node.value` contains \n        //      the text value and `node.children` is an empty array.\n        //\n        //  - `\"identifier\"` if the node represents an identifier. In that case \n        //      `node.value` contains the identifier as string and  \n        //      `node.children` is an empty array.\n        this.type = type;\n        this.value = value;\n        this.children = children;\n    }\n}\n\n\n\n// Exports\nmodule.exports = {Parser, ASTNode};\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/parser.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/lib/types.js":
  /*!**********************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/lib/types.js ***!
    \**********************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("// =============================================================================\n//  This module contains the Swan data types.\n//  \n//  The most generic data type is a `Term`: everything is a Term in swan. There\n//  are two type of Terms:\n//\n//  - `Item` is either Bool, Numb, Text, List, Namespace, Func or Undefined.\n//  - `Tuple` is the swan product type (a sequence of items)\n//  \n//  Each Item behaves also as a Tuple of one element and every tuple made of \n//  only one element behaves like an Item.\n//  \n//  An empty Tuple represents nothingness.\n//\n//  Each Term wraps a javascript object (the term `value`) and exposes a standard\n//  interface to interact with it. The term interface is documented below\n//  inside the Term class definition.\n// =============================================================================\n\nconst {matchIdentifier} = __webpack_require__(/*! ./lexer */ \"../../node_modules/@onlabsorg/swan-js/lib/lexer.js\");\n\n\nclass Term {\n    \n    // ###  TUPLE ITERATORS  ###################################################\n    \n    // This methods iterates over the tuple items. If the term is an Item, it\n    // will yield the item itself.\n    *items () {}\n    \n    // This method iterates over the tuple item values (the javascript wrapped\n    // objects). If the term is an Iterm, it will yield a single value.\n    *values () {\n        for (let item of this.items()) yield unwrap(item);\n    }\n    \n    // When iterating over a term, it yields the tuple item values.\n    *[Symbol.iterator] () {\n        for (let value of this.values()) yield value;\n    }\n\n    // Given two terms, it pairs their corresponding iterm and yields them as\n    // a pair. For example (item11, item12, item13) paired with (item21, item22,\n    // item23) yields [item11, item21], [item12, item22], [item13, item23].\n    *iterPairs (other) {\n        const iterator1 = this.items();\n        const iterator2 = other.items();\n        while (true) {\n            let iterItem1 = iterator1.next();\n            let iterItem2 = iterator2.next();\n            if (iterItem1.done && iterItem2.done) break;\n            yield [wrap(iterItem1.value), wrap(iterItem2.value)];\n        }        \n    }\n\n\n    // ###  TUPLE MAPPING  #####################################################\n    \n    // Maps each item via the synchronous function fn\n    imapSync (fn) {}\n    \n    // Maps each value via the synchronous function fn\n    vmapSync (fn) {}\n    \n    // Maps each item via the asynchronous function fn\n    async imapAsync (fn) {}\n    \n    // Maps each value via the asynchronous function fn\n    async vmapAsync (fn) {}    \n\n\n    // ###  TYPE CASTING  ######################################################\n\n    // Converts this term to a JavaScript Boolean\n    toBoolean () {}    \n\n    // Converts this term to a JavaScript String\n    toString () {}    \n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Term';\n    }\n    \n    // Returns true if this term is an empty tuple\n    isNothing () {}\n    \n    // Coverts a tuple containing only one item to an item. In any other case,\n    // returns this term as it is.\n    normalize () {}\n    \n    // Returns the JavaScript value wrapped in this term\n    unwrap () {}\n    \n\n    // ###  ALGEBRA  ###########################################################\n    // The following methods define the agebraic behavior of this term. Not all \n    // terms define all the algebraic methods. The method not being defined\n    // means that the corresponding operation is not defined.\n    \n    // Internal sum operation\n    // sum (other) {}   \n\n    // Additive inverse\n    // negate () {}\n    \n    // Additive neutral element check\n    // isNull () {}    \n    \n    // Additive neutral element\n    // static get null () {}\n    \n    // Internal product operation\n    // mul (other) {}\n    \n    // Multiplicative inverse\n    // invert () {}\n    \n    // Multiplicative neutral element check\n    // isUnit () {}\n    \n    // Multiplicative neutral element\n    // static get unit () {}\n    \n    // Power operation\n    // pow (other) {}\n    \n    // Compare this term with another term and it returns\n    // \"=\" if the two terms are equal\n    // \">\" if this term is greather than the other term\n    // \"<\" if this term is less than the other term\n    // \"#\" if no order is defined for this term but the two terms are not equal\n    // compare (other) {}\n}\n\n\nclass Item extends Term {\n    \n    constructor (value) {\n        super();\n        this.$value = value;\n    }\n\n    \n    // ###  TUPLE ITERATORS  ###################################################\n\n    // Yields this item as if it was a tuple made of one item only.\n    *items () {\n        yield this;\n    }\n\n    \n    // ###  TUPLE MAPPING  #####################################################\n\n    // Maps this item as if it was a tuple made of one item only.\n    imapSync (f) {\n        return wrap( f(this) );\n    }\n    \n    // Maps this item value as if it was a tuple made of one item only.\n    vmapSync (f) {\n        return wrap( f( unwrap(this) ) );\n    }\n    \n    // Maps this item as if it was a tuple made of one item only.\n    async imapAsync (f) {\n        return wrap( await f(this) );\n    }\n    \n    // Maps this item value as if it was a tuple made of one item only.\n    async vmapAsync (f) {\n        return wrap( await f( unwrap(this) ) );\n    }\n\n    \n    // ###  TYPE CASTING  ######################################################\n\n    // By default, an item is always true.\n    toBoolean () {\n        return true;\n    }    \n    \n    // By default, an item stringifies to the type name between `[[` and `]]`.\n    toString () {\n        return `[[${this.typeName}]]`;\n    }\n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n    \n    // Class name\n    get typeName () {\n        return 'Item';\n    }    \n\n    // An item is never an empty tuple\n    isNothing () {\n        return false;\n    }\n    \n    // An item is already in its normalized form\n    normalize () {\n        return this;\n    }\n    \n    // By default, it returns the argument passed to the constructor\n    unwrap () {\n        return this.$value;\n    }\n\n    \n    // ###  ALGEBRA  ###########################################################\n    \n    // This compare method is generally used by specific Items. It takes care \n    // of some common boilerplate and delegates the actual comparison to the\n    // function passed as second parameters.\n    // If called directly without the second parameter, it performs a\n    // JavaScript `===` comparison and returns either `=` or `#`.\n    // It also makes sure that Nothing is lower than anything elese.\n    compare (other, _compareSameTypeValues) {\n        if (other instanceof this.constructor) {\n            if (typeof _compareSameTypeValues === 'function') {\n                return _compareSameTypeValues(this.unwrap(), other.unwrap());\n            } else {\n                return this.unwrap() === other.unwrap() ? '=' : '#';                \n            }\n        } else {\n            return other.isNothing() ? '>' : '#';\n        }\n    }\n}\n\n\nclass Tuple extends Term {\n    \n    // Creates an Tuple instance given a sequence of values. The passed values\n    // can be items and/or tuples. The iterator function will take care of flattening\n    // the tuple, so that `new Tuple(a, new TupleObject(b, c))` is\n    // equivalent to `new TupleObject(a, b, c)`.\n    constructor (...items) {\n        super();\n        this._items = items.map(wrap);\n    }\n    \n\n    // ###  TUPLE ITERATORS  ###################################################\n\n    // Yields all the items of this tuple, flattening nested tuples.\n    *items () {\n        for (let item of this._items) {\n            for (let subItem of item.items()) yield subItem;\n        }        \n    }\n    \n        \n    // ###  TUPLE MAPPING  #####################################################\n\n    // Maps each item of this tuple through the passed synchronous function \n    // and returns a new tuple.\n    imapSync (f) {\n        const values = Array.from( this.items() ).map(f);\n        return new this.constructor(...values.map(wrap));\n    }\n    \n    // Maps each item value of this tuple through the passed synchronous \n    // function and returns a new tuple.\n    vmapSync (f) {\n        const values = Array.from( this.values() ).map(f);\n        return new this.constructor(...values.map(wrap));\n    }\n    \n    // Maps each item of this tuple through the passed asynchronous function \n    // and returns a new tuple.\n    async imapAsync (f) {\n        const values = await Promise.all(Array.from( this.items() ).map(f));\n        return new this.constructor(...values.map(wrap));\n    }\n    \n    // Maps each item value of this tuple through the passed asynchronous \n    // function and returns a new tuple.\n    async vmapAsync (f) {\n        const values = await Promise.all(Array.from( this.values() ).map(f));\n        return new this.constructor(...values.map(wrap));\n    }\n\n\n    // ###  TYPE CASTING  ######################################################\n\n    // A tuple booleanizes to false only if all its items booleanize to false.\n    toBoolean () {\n        for (let item of this.items()) {\n            if (item.toBoolean()) return true;\n        }\n        return false;\n    }\n    \n    // A tuple serializes to the concatenation of all the serialized items\n    toString () {\n        let text = \"\";\n        for (let item of this.items()) {\n            text += item.toString();\n        }\n        return text;\n    }\n\n\n    // ###  MISCELLANEOUS METHODS  #############################################\n    \n    // Class name\n    get typeName () {\n        const iterator = this.items();\n        const first = iterator.next();\n        \n        // If the tuple is empty return null\n        if (first.done) return 'Nothing';\n        \n        // If the tuple contains only one iterm, return that item\n        if (iterator.next().done) return first.value.typeName;\n        \n        // If the tuple contains more than one iterm, return the tuple itself\n        return 'Tuple';\n    }    \n    \n    // A tuple is nothing if it contains no items.\n    isNothing () {\n        let iterator = this.items();\n        return iterator.next().done;\n    } \n    \n    // A tuple normalizes to itself if it contains none or more than one item.\n    // If it contains only one item, it normalizes to that item.\n    normalize () {\n        const iterator = this.items();\n        const first = iterator.next();\n        \n        // If the tuple is empty return null\n        if (first.done) return this;\n        \n        // If the tuple contains only one iterm, return that item\n        if (iterator.next().done) return first.value;\n        \n        // If the tuple contains more than one iterm, return the tuple itself\n        return this;\n    } \n    \n    // A tuple unwraps to itself: there is no equivalent javascript object for\n    // a tuple. \n    unwrap () {\n        const iterator = this.values();\n        const first = iterator.next();\n        \n        // If the tuple is empty return null\n        if (first.done) return null;\n        \n        // If the tuple contains only one iterm, return that item\n        if (iterator.next().done) return first.value;\n        \n        // If the tuple contains more than one iterm, return the tuple itself\n        return this;\n    }    \n    \n    \n    // ###  ALGEBRA  ###########################################################\n    \n    // Tuples are compared lexicographically.\n    compare (other) {\n        for (let [item1, item2] of this.iterPairs(other)) {\n            if (item1.isNothing()) return item2.isNothing() ? '=' : '<';\n            if (item2.isNothing()) return '>';\n            let cmp = item1.compare(item2);\n            if (cmp !== '=') return cmp;\n        }\n        return '=';\n    }\n}\n\n\nclass Bool extends Item {\n    \n\n    // ###  TYPE CASTING  ######################################################\n\n    // Returns true if this is TRUE\n    toBoolean () {\n        return this.unwrap();\n    }\n    \n    // Serializes either to \"FALSE\" or to \"TRUE\"\n    toString () {\n        return this.unwrap() ? \"TRUE\" : \"FALSE\";\n    }\n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Bool';\n    }\n    \n    // ###  ALGEBRA  ###########################################################\n        \n    // The sum of two Bool items corresponds to the logic OR\n    sum (other) {\n        return new this.constructor(this.unwrap() || other.unwrap());\n    }\n    \n    // Additive inverse not defined\n    // negate () {}\n    \n    // Returns true if this is FALSE\n    isNull () {\n        return !this.unwrap();\n    }\n    \n    // The Additive neutral element is FALSE\n    static get null () {\n        return new this(false);\n    }\n    \n    // The product of two Bool items corresponds to the logic AND\n    mul (other) {\n        return new this.constructor(this.unwrap() && other.unwrap());\n    }\n    \n    // Multiplicative inverse not defined\n    // invert () {}\n\n    // Returns true if this is TRUE\n    isUnit () {\n        return this.unwrap();\n    }\n    \n    // The Multiplicative neutral element is TRUE\n    static get unit () {\n        return new this(true);\n    }\n\n    // Exponentiation operation not defined\n    // pow (other) {}\n\n    // FALSE is less than TRUE\n    compare (other) {\n        return super.compare(other, (thisIsTrue, otherIsTrue) => {\n            const thisIsFalse  = !thisIsTrue;\n            const otherIsFalse = !otherIsTrue;            \n            if (thisIsFalse && otherIsTrue) return '<';\n            if (thisIsTrue && otherIsFalse) return '>';\n            return '=';\n        })\n    }\n}\n\n\nclass Numb extends Item {\n    \n    // ###  TYPE CASTING  ######################################################\n\n    // Returns false if 0, or else true\n    toBoolean () {\n        return this.unwrap() !== 0;\n    }\n    \n    // Returns the number as a string\n    toString () {\n        return String( this.unwrap() );\n    }\n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Numb';\n    }\n    \n    // ###  ALGEBRA  ###########################################################\n\n    // Real numbers sum\n    sum (other) {\n        return new this.constructor(this.unwrap() + other.unwrap());\n    }\n    \n    // Real numbers negation\n    negate () {\n        return new this.constructor(-this.unwrap());\n    }\n    \n    // True if the number is 0\n    isNull () {\n        return this.unwrap() === 0;\n    }\n    \n    // 0\n    static get null () {\n        return new this(0);\n    }\n    \n    // Real numbers product\n    mul (other) {\n        return new this.constructor(this.unwrap() * other.unwrap());\n    }\n    \n    // Real numbers inverse (1/x)\n    invert () {\n        return new this.constructor(1 / this.unwrap());\n    }\n    \n    // True if the number is 1\n    isUnit () {\n        return this.unwrap() === 1;\n    }\n    \n    // 1\n    static get unit () {\n        return new this(1);\n    }\n    \n    // Real numbers power\n    pow (other) {\n        return new this.constructor(this.unwrap() ** other.unwrap());\n    }\n    \n    // Real numbers comparison\n    compare (other) {\n        return super.compare(other, (thisValue, otherValue) => {\n            return thisValue === otherValue ? '=' : (thisValue < otherValue ? '<' : '>');\n        });\n    }\n}\n\n\nclass Applicable extends Item {    \n    // An applicable is any type with an `apply` method.\n    // Applicables accept the swan apply operation `X Y`.\n    \n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Applicable';\n    }    \n}\n\n\nclass Mapping extends Applicable {\n    \n    // A mapping is an item that maps a set of items (domain of the mapping) to\n    // another set of items. For example, a string is a mapping between integer\n    // numbers and characters.\n    \n\n    // ###  MAPPING-SPECIFIC METHODS  ##########################################\n\n    // This should return an array of all the possible x values that this\n    // mapping maps\n    get domain () {}\n    \n    // This should return the value that this mapping maps to x\n    // It should always return a defined value if x is part of the domain\n    // It should always return `undefined` if x is not part of the domain \n    vget (x) {}\n\n    // This should return the item that this mapping maps to x\n    // It should Undefined Mapping if x is not part of the domain \n    iget (x) {\n        const value = this.vget(x);\n        return value === undefined ? new Undefined(\"Mapping\", x) : wrap(value);\n    }\n\n    // The size of a mapping is the number of items in its domain\n    get size () {\n        return this.domain.length;\n    }\n\n    // The image of a mapping is the array of all the mapped values\n    get image () {\n        return new List(this.domain.map(x => this.vget(x)));\n    }\n    \n    // The apply operation takes a tuple of items and returns the corresponding\n    // tuple of mapped items. If an item of the tuple is not part of the domain,\n    // the apply operation results in an Undefined item.\n    apply (...X) {\n        const Y = X.map(x => this.iget(x));\n        return Y.length === 1 ? Y[0] : new Tuple(...Y);\n    }\n\n    \n    // ###  TYPE CASTING  ######################################################\n\n    // A mapping with no pairs (empty mapping) booleanizes to false\n    toBoolean () {\n        return this.size > 0;\n    }    \n\n    // Returns \"[[<typename> of n terms]]\" where n is the mapping size\n    toString () {\n        const n = this.size;\n        return n === 1 ? `[[${this.typeName} of 1 item]]` : `[[${this.typeName} of ${n} items]]`;\n    }\n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Mapping';\n    }    \n}\n\n\nclass Sequence extends Mapping {\n    \n    // A sequence is a special mapping that maps integer numbers to generic\n    // items.\n    \n\n    // ###  MAPPING-SPECIFIC METHODS  ##########################################\n\n    // Returns the array of integers between 0 and size - 1\n    get domain () {\n        return Object.keys(this.unwrap()).map(Number);\n    }\n    \n    // Returns the i-th item of the sequence\n    vget (i) {\n        return typeof i === 'number' ? this.unwrap()[i] : undefined;\n    }    \n\n    // More efficient implementation of the size method\n    get size () {\n        return this.unwrap().length;\n    }    \n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Sequence';\n    }    \n}\n\n\nclass Text extends Sequence {\n    \n    // ###  TYPE CASTING  ######################################################\n\n    // Returns the Text value\n    toString () {\n        return this.unwrap();\n    }\n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Text';\n    }\n    \n    \n    // ###  ALGEBRA  ###########################################################\n\n    // The sum of two Text items is their concatenation\n    sum (other) {\n        return new this.constructor(this.unwrap() + other.unwrap());\n    }\n    \n    // Additive inverse not defined \n    // negate () {}\n    \n    // It returns true if the string is empty\n    isNull () { \n        return this.size === 0;\n    }\n    \n    // It returns the empty string\n    static get null () {\n        return new this(\"\");\n    }\n    \n    // Product operation not defined\n    // mul (other) {}\n    \n    // Multiplicative inverse not defined\n    // invert () {}\n    \n    // Multiplicative neutral element not defined\n    // isUnit () {}\n    \n    // Multiplicative neutral element not defined\n    // static get unit () {}\n    \n    // Exponentiation operation not defined\n    // pow (other) {}\n\n    // Compare two Text items in alphabetical order\n    compare (other) {\n        return super.compare(other, (thisString, otherString) => {\n            const cmp = thisString.localeCompare(otherString);\n            return cmp === 0 ? '=' : (cmp === -1 ? '<' : '>');\n        });\n    }\n}\n\n\nclass List extends Sequence {\n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'List';\n    }\n    \n\n    // ###  ALGEBRA  ###########################################################\n\n    // Concatenates the two arrays\n    sum (other) {\n        return new this.constructor( this.unwrap().concat(other.unwrap()) );\n    }\n    \n    // Additive inverse not defined\n    // negate () {}\n    \n    // Returns true if the list is empty\n    isNull () {\n        return this.size === 0;\n    }\n    \n    // Returns an empty list\n    static get null () {\n        return new this([]);\n    }\n    \n    // Product operation not defined\n    // mul (other) {}\n    \n    // Multiplicative inverse not defined\n    // invert () {}\n    \n    // Multiplicative neutral element not defined\n    // isUnit () {}\n    \n    // Multiplicative neutral element not defined\n    // static get unit () {}   \n    \n    // Exponentiation operation not defined\n    // pow (other) {}\n\n    // Lexicographical order\n    compare (other) {\n        return super.compare(other, (thisArray, otherArray) => {\n            const thisTuple  = new Tuple(...thisArray);\n            const otherTuple = new Tuple(...otherArray);\n            return thisTuple.compare(otherTuple);\n        });\n    } \n}\n\n\nclass Namespace extends Mapping {\n    \n    // ###  MAPPING-SPECIFIC METHODS  ##########################################\n\n    // Array of object keys which are valid identifiers\n    get domain () {\n        return Object.keys(this.unwrap()).filter(matchIdentifier);\n    }\n    \n    // Returns the value mapped to the give key\n    vget (key) {\n        const object = this.unwrap();\n        if (matchIdentifier(key) && object.hasOwnProperty(key)) {\n            return object[key];\n        }\n    }\n\n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Namespace';\n    }\n    \n\n    // ###  ALGEBRA  ###########################################################\n\n    // Merges two namespaces\n    sum (other) {\n        const sumObject = Object.assign({}, unwrap(this), unwrap(other));\n        return new this.constructor(sumObject);\n    }\n    \n    // Additive inverse not defined\n    // negate () {}\n    \n    // True if the namespace domain is empty\n    isNull () { \n        return this.size === 0;\n    }\n    \n    // Returns an empty namespace\n    static get null () {\n        return new this({});\n    }\n    \n    // Product operation not defined\n    // mul (other) {}\n    \n    // Multiplicative inverse not defined\n    // invert () {}\n    \n    // Multiplicative neutral element not defined\n    // isUnit () {}\n    \n    // Multiplicative neutral element not defined\n    // static get unit () {}\n    \n    // Exponentiation operation not defined\n    // pow (other) {}\n\n    // Two namespace are equal if they have same keys and equal values.\n    // No order is defined for namespaces: compare returns either '=' or '#'.\n    compare (other) {\n        return super.compare(other, (thisObject, otherObject) => {\n            const thisNames = this.domain;\n            const otherNames = other.domain;\n            if (thisNames.length !== otherNames.length) return '#';\n            for (let name of thisNames) {\n                const term1 = this.apply(name);\n                const term2 = other.apply(name);\n                const cmp = term1.compare(term2);\n                if (cmp !== '=') return cmp;\n            }\n            return '=';\n        });        \n    }\n}\n\n\nclass Func extends Applicable {\n    \n    // ###  FUNC-SPECIFIC METHODS  #############################################\n\n    // Calls the wrapped function and returns its output wrapped\n    async apply (...items) {\n        const func = this.unwrap();\n        const args = items.map(unwrap);\n        return wrap( await func(...args) );\n    }\n    \n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Func';\n    }\n    \n\n    // ###  ALGEBRA  ###########################################################\n\n    // Sum operation not defined\n    // sum (other) {}\n    \n    // Additive inverse not defined\n    // negate () {}\n    \n    // Additive neutral element not defined\n    // isNull () {}\n    \n    // Additive neutral element not defined\n    // static get null () {}\n    \n    // Product operation not defined\n    // mul (other) {}\n    \n    // Multiplicative inverse not defined\n    // invert () {}\n    \n    // Multiplicative neutral element not defined\n    // isUnit () {}\n    \n    // Multiplicative neutral element not defined\n    // static get unit () {}\n    \n    // Exponentiation operation not defined\n    // pow (other) {}\n\n    // Default comparison: equal if identical and no order defined\n    // compare (other) {}\n}\n\n\nclass Undefined extends Item {\n    \n    // Swan operations do not throw exceptions: they return Undefined instead.\n    // For debugging purposes, an Undefined item contains information about the \n    // undefined operation and the operands.\n    \n    constructor (type, ...args) {\n        super({\n            type: type, \n            args: args.map(unwrap)\n        });\n    }\n    \n\n    // ###  UNDEFINED-SPECIFIC PROPERTIES  #####################################\n\n    // A string containing the name of the undefined operation\n    get type () {\n        return super.unwrap().type;\n    }\n    \n    // Array of operands\n    get args () {\n        return super.unwrap().args;\n    }\n\n    \n    // ###  TYPE CASTING  ######################################################\n\n    toBoolean () {\n        return false;\n    }\n    \n    toString () {\n        return `[[Undefined ${this.type}]]`;\n    }\n\n    \n    // ###  MISCELLANEOUS METHODS  #############################################\n\n    // Class name\n    get typeName () {\n        return 'Undefined';\n    }    \n\n    // Unwraps to itself (no equivalent JavaScript type available)\n    unwrap () {\n        return this;\n    }\n    \n    \n    // ###  ALGEBRA  ###########################################################\n    \n    // Sum operation not defined\n    // sum (other) {}\n    \n    // Additive inverse not defined\n    // negate () {}\n    \n    // Additive neutral element not defined\n    // isNull () {}    \n    \n    // Additive neutral element not defined\n    // static get null () {}\n    \n    // Product operation not defined\n    // mul (other) {}\n    \n    // Multiplicative inverse not defined\n    // invert () {}\n    \n    // Multiplicative neutral element not defined\n    // isUnit () {}\n    \n    // Multiplicative neutral element not defined\n    // static get unit () {}\n    \n    // Exponentiation operation not defined\n    // pow (other) {}\n\n    // Default comparison: equal if identical and no order defined\n    // compare (other) {}\n}\n\n\n// Takes a javascript value and turns it into the corresponding swan term.\n// If the passed value is already wrapped, it returns it as it is.\nfunction wrap (value) {\n    \n    // if already wrpped\n    if (value instanceof Term) return value;\n    \n    // if not wrapped\n    switch (typeof(value)) {\n        \n        case \"undefined\":\n            return new Tuple();\n        \n        case \"boolean\":\n            return new Bool(value);\n            \n        case \"number\":\n            return Number.isNaN(value) ? new Undefined(\"Number\") : new Numb(value);\n            \n        case \"string\":\n            return new Text(value);\n            \n        case \"function\":\n            return new Func(value);\n            \n        // it must be an object\n        default:   \n        \n            // if null\n            if (value === null) return new Tuple();\n            \n            // if an array\n            if (Array.isArray(value)) return new List(value);\n            \n            // if a primitive object\n            switch (Object.prototype.toString.call(value)) {\n                case '[object Boolean]'  : return new Bool(Boolean(value));\n                case '[object Number]'   : return new Numb(Number(value));\n                case '[object String]'   : return new Text(String(value));\n                case '[object Function]' : return new Func(value);\n            }\n            \n            return new Namespace(value);\n    }\n}\n\n// Takes a swan term and returns the origina javascript value.\n// If the parameter is already unwrapped, it returns it as it is.\nfunction unwrap (term) {\n    return (term instanceof Term) ? term.unwrap() : term;\n}\n\n\nmodule.exports = {\n    Term,\n        Tuple,\n        Item,\n            Bool, \n            Numb, \n            Applicable,\n                Mapping, \n                    Sequence, \n                        Text, \n                        List, \n                    Namespace,\n                Func, \n            Undefined, \n                \n    wrap, unwrap\n};\n\n\n\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/lib/types.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/builtins.js":
  /*!**************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/builtins.js ***!
    \**************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ./expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst types = __webpack_require__(/*! ../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst builtins = __webpack_require__(/*! ../lib/builtins */ \"../../node_modules/@onlabsorg/swan-js/lib/builtins.js\");\n\nconst parse = __webpack_require__(/*! ../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst evaluate = (expression, presets={}) => parse(expression)(Object.assign(Object.create(builtins), presets));\n\n\ndescribe(\"builtins\", () => {\n    \n    describe(\"TRUE\", () => {\n        \n        it(\"should be true\", async () => {\n            expect(await evaluate(\"TRUE\")).to.be.Bool(true);\n        });\n    });\n    \n    describe(\"FALSE\", () => {\n        \n        it(\"should be true\", async () => {\n            expect(await evaluate(\"FALSE\")).to.be.Bool(false);\n        });\n    });\n\n    describe(\"bool: Term t -> Bool b\", () => {\n        \n        it(\"should return FALSE if the argument is a falsy term\", async () => {\n            expect(await evaluate(\"bool ()       \")).to.be.Bool(false);\n            expect(await evaluate(\"bool (1 == 2) \")).to.be.Bool(false);\n            expect(await evaluate(\"bool 0        \")).to.be.Bool(false);\n            expect(await evaluate(\"bool ''       \")).to.be.Bool(false);\n            expect(await evaluate(\"bool []       \")).to.be.Bool(false);\n            expect(await evaluate(\"bool {}       \")).to.be.Bool(false);\n            expect(await evaluate(\"bool ('a'/'b')\")).to.be.Bool(false);\n            expect(await evaluate(\"bool (0,'',[])\")).to.be.Bool(false);\n        });\n\n        it(\"should return TRUE if the argument is a truty term\", async () => {\n            expect(await evaluate(\"bool (x->x)   \")).to.be.Bool(true);\n            expect(await evaluate(\"bool (1 == 1) \")).to.be.Bool(true);\n            expect(await evaluate(\"bool 10       \")).to.be.Bool(true);\n            expect(await evaluate(\"bool 'abc'    \")).to.be.Bool(true);\n            expect(await evaluate(\"bool [1,2,3]  \")).to.be.Bool(true);\n            expect(await evaluate(\"bool {a:1}    \")).to.be.Bool(true);\n            expect(await evaluate(\"bool (1,'',[])\")).to.be.Bool(true);\n        });\n    });\n    \n    describe(\"not: Term t -> Bool b\", () => {\n        \n        it(\"should return TRUE if the argument is a falsy term\", async () => {\n            expect(await evaluate(\"not ()       \")).to.be.Bool(true);\n            expect(await evaluate(\"not (1 == 2) \")).to.be.Bool(true);\n            expect(await evaluate(\"not 0        \")).to.be.Bool(true);\n            expect(await evaluate(\"not ''       \")).to.be.Bool(true);\n            expect(await evaluate(\"not []       \")).to.be.Bool(true);\n            expect(await evaluate(\"not {}       \")).to.be.Bool(true);\n            expect(await evaluate(\"not ('a'/'b')\")).to.be.Bool(true);\n            expect(await evaluate(\"not (0,'',[])\")).to.be.Bool(true);\n        });\n\n        it(\"should return FALSE if the argument is a truty term\", async () => {\n            expect(await evaluate(\"not (x->x)   \")).to.be.Bool(false);\n            expect(await evaluate(\"not (1 == 1) \")).to.be.Bool(false);\n            expect(await evaluate(\"not 10       \")).to.be.Bool(false);\n            expect(await evaluate(\"not 'abc'    \")).to.be.Bool(false);\n            expect(await evaluate(\"not [1,2,3]  \")).to.be.Bool(false);\n            expect(await evaluate(\"not {a:1}    \")).to.be.Bool(false);\n            expect(await evaluate(\"not (1,'',[])\")).to.be.Bool(false);\n        });\n    });            \n    \n    describe(\"str: Term t -> Text s\", () => {\n        \n        it(\"should return either 'TRUE' or 'FALSE' if the argument is a Bool item\", async () => {\n            expect(await evaluate(\"str(1==1)\")).to.be.Text(\"TRUE\");\n            expect(await evaluate(\"str(1!=1)\")).to.be.Text(\"FALSE\");\n        });\n        \n        it(\"should return the stringified decimal if the argument is a Numb item\", async () => {\n            expect(await evaluate(\"str 123.45\")).to.be.Text(\"123.45\");\n        });\n\n        it(\"should return the argument itself if is a Text item\", async () => {\n            expect(await evaluate(\"str 'abc'\")).to.be.Text(\"abc\");\n        });\n\n        it(\"should return '[[List of <n> items]]' if the argument is a List item\", async () => {\n            expect(await evaluate(\"str [10,20,30]\")).to.be.Text(\"[[List of 3 items]]\");\n            expect(await evaluate(\"str [10]      \")).to.be.Text(\"[[List of 1 item]]\");\n            expect(await evaluate(\"str []        \")).to.be.Text(\"[[List of 0 items]]\");\n        });\n        \n        it(\"should return '[[Func]]' if the argument is a Func item\", async () => {\n            expect(await evaluate(\"str(x->x)\")).to.be.Text(\"[[Func]]\");\n        });\n        \n        it(\"should return '[[Undefined <type>]]' if the argument is an Undefined item\", async () => {\n            const u = new types.Undefined(\"TestOp\")\n            expect(await evaluate(\"str(u)\", {u})).to.be.Text(\"[[Undefined TestOp]]\");\n        });\n        \n        it(\"should concatenate the stringified items if the argument is a tuple\", async () => {\n            expect(await evaluate(\"str(12,'+',10)\")).to.be.Text(\"12+10\");\n            expect(await evaluate(\"str()         \")).to.be.Text(\"\");\n        });\n        \n        describe(\"when the argument is a Namespace item NS\", () => {\n            \n            it(\"should return '[[Namespace of n items]]' if no __str__ name is defined\", async () => {\n                expect(await evaluate(\"str{k1:1,k2:2,k3:3}\")).to.be.Text(\"[[Namespace of 3 items]]\");\n                expect(await evaluate(\"str{k1:1          }\")).to.be.Text(\"[[Namespace of 1 item]]\");\n                expect(await evaluate(\"str{              }\")).to.be.Text(\"[[Namespace of 0 items]]\");\n            });\n            \n            it(\"should return `str(NS.__str__(NS))` if `NS.__str__` is a Func item\", async () => {\n                expect(await evaluate(\"str{t:456, __str__: self -> self.t}\")).to.be.Text(\"456\");\n                expect(await evaluate(\"str{t:456, __str__: 'abc'}\")).to.be.Text(\"[[Namespace of 2 items]]\");\n            });\n        });\n    });\n    \n    describe(\"size: Mapping m -> Numb n\", () => {\n        \n        it(\"should return the number of characters if m is a Text item\", async () => {\n            expect(await evaluate(\"size 'abc'\")).to.be.Numb(3);\n        });\n        \n        it(\"should return the number of items if m is a List item\", async () => {\n            expect(await evaluate(\"size [10,20,30]\")).to.be.Numb(3);\n        });\n        \n        it(\"should return the number of name:value pairs if m is a Namespace item\", async () => {\n            expect(await evaluate(\"size {a:2,b:4,c:6}\")).to.be.Numb(3);\n        });\n\n        it(\"should return Undefined Number if the argument is not a mapping\", async () => {\n            expect(await evaluate(\"size TRUE\")).to.be.Undefined(\"Number\");\n            expect(await evaluate(\"size 123\")).to.be.Undefined(\"Number\");\n            expect(await evaluate(\"size(x->x)\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply to the first items only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"size('ABC','Defg')\")).to.be.Numb(3);\n        });                        \n    });\n\n    describe(\"dom: Mapping m -> Tuple t\", () => {\n        \n        it(\"should return (0,1,2,...,Len-1) if m is a Text item\", async () => {\n            expect(await evaluate(\"dom 'abc'\")).to.be.Tuple([0,1,2]);\n        });\n        \n        it(\"should return (0,1,2,...,Len-1) if m is a List item\", async () => {\n            expect(await evaluate(\"dom [10,20,30]\")).to.be.Tuple([0,1,2]);\n        });\n        \n        it(\"should return the tuple of name:value pairs if m is a Namespace item\", async () => {\n            expect(await evaluate(\"dom {a:2,b:4,c:6}\")).to.be.Tuple(['a','b','c']);\n        });\n\n        it(\"should return Undefined Term if the argument is not a mapping\", async () => {\n            expect(await evaluate(\"dom TRUE\")).to.be.Undefined(\"Term\");\n            expect(await evaluate(\"dom 123\")).to.be.Undefined(\"Term\");\n            expect(await evaluate(\"dom(x->x)\")).to.be.Undefined(\"Term\");\n        });\n\n        it(\"should apply to the first items only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"dom('ABC','Defg')\")).to.be.Tuple([0,1,2]);\n        });                        \n    });\n\n    describe(\"type: Item x -> Text t\", () => {\n        \n        it(\"should return the type name of the passed item\", async () => {\n            expect(await evaluate(\"type(1==1)\")).to.be.Text(\"Bool\");\n            expect(await evaluate(\"type 10   \")).to.be.Text(\"Numb\");\n            expect(await evaluate(\"type 'abc'\")).to.be.Text(\"Text\");\n            expect(await evaluate(\"type [10] \")).to.be.Text(\"List\");\n            expect(await evaluate(\"type {a:1}\")).to.be.Text(\"Namespace\");\n            expect(await evaluate(\"type(x->x)\")).to.be.Text(\"Func\");\n            expect(await evaluate(\"type(2*[])\")).to.be.Text(\"Undefined\");\n        });\n        \n        it(\"should return a tuple of strings if the argument is a tuple\", async () => {\n            expect(await evaluate(\"type(10,'abc',[])\")).to.be.Tuple([\"Numb\",\"Text\",\"List\"]);\n            expect(await evaluate(\"type()\")).to.be.Tuple([]);\n        });\n    \n    });    \n    \n    describe(\"range: Numb n -> Numb Tuple r\", () => {\n        \n        it(\"should return a tuple of integer numbers between 0 and n (excluded)\", async () => {\n            expect(await evaluate(\"range 4\")).to.be.Tuple([0,1,2,3]);\n            expect(await evaluate(\"range 4.1\")).to.be.Tuple([0,1,2,3,4]);\n        });\n        \n        it(\"should return Undefined Tuple if n is not a Numb item\", async () => {\n            expect(await evaluate(\"range 'abc'\")).to.be.Undefined(\"Tuple\");\n        });\n        \n        it(\"should apply only to the first item if n is a tuple\", async () => {\n            expect(await evaluate(\"range(4,2)\")).to.be.Tuple([0,1,2,3]);\n        });\n    });\n\n    describe(\"undefined: Tuple t -> Undefined u\", () => {\n        \n        it(\"should return and Undefined data type\", async () => {\n            expect(await evaluate(\"undefined('Test',1,2)\")).to.be.Undefined(\"Test\", (...args) => {\n                expect(args.length).to.equal(2);\n                expect(args[0]).to.equal(1);\n                expect(args[1]).to.equal(2);\n            })\n        });\n    });    \n    \n    describe(\"require: Text id -> Namespace m\", () => {\n        \n        it(\"should return the standard library module identified by the passed module id\", async () => {\n            \n            // Test content\n            const time1 = __webpack_require__(/*! ../lib/modules/time */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/time.js\")(types);\n            const time2 = await evaluate(\"require 'time'\");\n            expect(time2).to.be.instanceof(types.Namespace);\n            for (let key in time1) {\n                expect(typeof time1[key]).to.equal(typeof time2.vget(key));\n            }\n            \n            // Test in action\n            expect(await evaluate(\"require 'numb' .max (1,22,3,4) \")).to.be.Numb(22);\n            expect(await evaluate(\"require 'text' .size 'abc'     \")).to.be.Numb(3);\n            expect(await evaluate(\"require 'list' .size [10,20,30]\")).to.be.Numb(3);\n            expect(await evaluate(\"require 'time' .to_ISO_string 1639513675.900\")).to.be.Text(\"2021-12-14T20:27:55.900Z\");\n            expect(await evaluate(\"type(require 'debug' .log [])\")).to.be.Text(\"Text\");\n        });\n    });\n});\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/builtins.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/expect.js":
  /*!************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/expect.js ***!
    \************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const chai = __webpack_require__(/*! chai */ \"../../node_modules/chai/index.js\")\nconst expect = module.exports = chai.expect;\n\nconst {\n    Term,\n        Tuple,\n        Item,\n            Bool, \n            Numb, \n            Func, \n            Undefined, \n            Mapping, \n                Sequence, \n                    Text, \n                    List, \n                Namespace,\n                \n    wrap, unwrap \n} = __webpack_require__(/*! ../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\n\nchai.use(function (chai, utils) {\n    \n    chai.Assertion.addMethod('Bool', function (value) {\n        let item = utils.flag(this, 'object').normalize();\n        expect(item).to.be.instanceof(Bool)\n        expect(unwrap(item)).to.equal(value);\n    });\n    \n    chai.Assertion.addMethod('Numb', function (value) {\n        let item = utils.flag(this, 'object').normalize();\n        expect(item).to.be.instanceof(Numb)\n        expect(unwrap(item)).to.equal(value);\n    });\n    \n    chai.Assertion.addMethod('Text', function (value) {\n        const item = utils.flag(this, 'object').normalize();\n        expect(item).to.be.instanceof(Text)\n        expect(unwrap(item)).to.equal(value);\n    });\n    \n    chai.Assertion.addMethod('List', function (array) {\n        const item = utils.flag(this, 'object').normalize();\n        expect(item).to.be.instanceof(List)\n        expect(unwrap(item)).to.deep.equal(array);\n    });\n\n    chai.Assertion.addMethod('Namespace', function (object) {\n        const item = utils.flag(this, 'object').normalize();\n        expect(item).to.be.instanceof(Namespace)\n        expect(Object.assign({}, unwrap(item))).to.deep.equal(object);\n    });\n    \n    chai.Assertion.addMethod('Tuple', function (itemArray) {\n        var obj = utils.flag(this, 'object');\n        expect(obj).to.be.instanceof(Tuple);\n        expect(Array.from(obj.items()).map(unwrap)).to.deep.equal(itemArray);\n    });\n    \n    chai.Assertion.addMethod('Undefined', function (type, test) {\n        var obj = utils.flag(this, 'object').normalize();\n        expect(obj).to.be.instanceof(Undefined);\n        expect(obj.type).to.equal(type);\n        if (typeof test === \"function\") test(...obj.args);\n    });\n    \n    chai.Assertion.addMethod('UndefinedSyntax', function (errorMessage) {\n        var obj = utils.flag(this, 'object');\n        expect(obj).to.be.instanceof(Undefined);\n        expect(obj.type).to.equal(\"Syntax\");\n        expect(obj.value).to.be.instanceof(Error);\n        expect(obj.value.message).to.equal(errorMessage);\n    });    \n});\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/expect.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/index.js":
  /*!***********************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/index.js ***!
    \***********************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("var expect = (__webpack_require__(/*! chai */ \"../../node_modules/chai/index.js\").expect);\nvar swan = __webpack_require__(/*! ../index */ \"../../node_modules/@onlabsorg/swan-js/index.js\");\n\ndescribe(\"SWAN LANGUAGE\", () => {\n    __webpack_require__(/*! ./types */ \"../../node_modules/@onlabsorg/swan-js/test/types.js\");\n    __webpack_require__(/*! ./interpreter */ \"../../node_modules/@onlabsorg/swan-js/test/interpreter.js\");\n    \n    describe(\"modules\", () => {\n        __webpack_require__(/*! ./modules/numb */ \"../../node_modules/@onlabsorg/swan-js/test/modules/numb.js\");\n        __webpack_require__(/*! ./modules/text */ \"../../node_modules/@onlabsorg/swan-js/test/modules/text.js\");\n        __webpack_require__(/*! ./modules/list */ \"../../node_modules/@onlabsorg/swan-js/test/modules/list.js\");        \n        __webpack_require__(/*! ./modules/json */ \"../../node_modules/@onlabsorg/swan-js/test/modules/json.js\");\n        __webpack_require__(/*! ./modules/time */ \"../../node_modules/@onlabsorg/swan-js/test/modules/time.js\");\n        __webpack_require__(/*! ./modules/debug */ \"../../node_modules/@onlabsorg/swan-js/test/modules/debug.js\");\n    });\n\n    __webpack_require__(/*! ./builtins */ \"../../node_modules/@onlabsorg/swan-js/test/builtins.js\");\n    \n    describe(\"Swan API\", () => {\n        \n        describe(\"createContext(...namespaces)\", () => {\n            \n            it(\"should extend the builtins\", () => {\n                const builtins = __webpack_require__(/*! ../lib/builtins */ \"../../node_modules/@onlabsorg/swan-js/lib/builtins.js\");\n                const context = swan.createContext({});\n                for (let key in builtins) {\n                    expect(context[key]).to.equal(builtins[key]);\n                }\n            });\n            \n            it(\"should contain all the properties of the passed namespaces\", () => {\n                const context = swan.createContext({x:10,y:20}, {x:11,z:31});\n                expect(context.x).to.equal(11);\n                expect(context.y).to.equal(20);\n                expect(context.z).to.equal(31);\n            });\n        });\n        \n        describe(\"parse(expression)(context)\", () => {\n            \n            it(\"should return an evaluate function that returns js values\", async () => {\n                const evaluate = swan.parse(\"2+x\");\n                expect(evaluate).to.be.a(\"function\");\n                expect(await evaluate({x:10})).to.equal(12);\n                \n                expect(await swan.parse(\"2+1\")()).to.equal(3)\n            });\n        });\n        \n        describe(\"types\", () => {\n            \n            it(\"should contain the exports of the types module\", () => {\n                expect(swan.types).to.equal(__webpack_require__(/*! ../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\"));\n            });\n        });\n    });\n});\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/interpreter.js":
  /*!*****************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/interpreter.js ***!
    \*****************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ./expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst parse = __webpack_require__(/*! ../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\n\nconst {\n    Term,\n        Tuple,\n        Item,\n            Bool, \n            Numb, \n            Applicable,\n                Mapping, \n                    Sequence, \n                        Text, \n                        List, \n                    Namespace,\n                Func, \n            Undefined, \n                \n    wrap, unwrap \n} = __webpack_require__(/*! ../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\n\n\n\ndescribe(\"SWAN EXPRESSION INTERPRETER\", () => {\n\n\n    // CORE\n\n    describe(\"numeric literals\", () => {\n\n        it(\"should evaluate decimal numeric literals to numbers\", async () => {\n            expect(await parse(\"10\"   )()).to.be.Numb(10);\n            expect(await parse(\"0\"    )()).to.be.Numb(0);\n            expect(await parse(\"3.2\"  )()).to.be.Numb(3.2);\n            expect(await parse(\"1.2e3\")()).to.be.Numb(1200);\n        });\n    });\n\n    describe(\"string literals\", () => {\n\n        it(`should evaluate string literals between double quotes '\"\"'`, async () => {\n            expect(await parse(`\"abc\"`)()).to.be.Text(\"abc\");\n            expect(await parse(`\"\"`   )()).to.be.Text(\"\");\n        });\n\n        it(\"should evaluate string literals between single quotes `''`\", async () => {\n            expect(await parse(`'def'`)()).to.be.Text(\"def\");\n            expect(await parse(`''`   )()).to.be.Text(\"\");\n        });\n    });\n\n    describe(\"tuples: `exp1, exp2, exp3, ...`\", () => {\n    \n        it(\"should return the comma-separated values as a Tuple\", async () => {\n            expect(await parse(\"10,'abc'\")()).to.be.Tuple([10,'abc']);\n        });\n    \n        it(\"should flatten tuples of tuples: `(X,Y),Z` results in `X,Y,Z`\", async () => {\n            expect(await parse(\"1,(2,3),4,(5,(6,7)),8,9\")()).to.be.Tuple([1,2,3,4,5,6,7,8,9]);\n        });\n    \n        it(\"should ignore empty tuples when flattening tuples: `X,(),Y` results in `X,Y`\", async () => {\n            expect(await parse(\"1,(),2\")()).to.be.Tuple([1,2]);\n            expect(await parse(\"(),(1,(),2),(),3\")()).to.be.Tuple([1,2,3]);\n        });\n    \n        it(\"should evaluate empty tuples `()` as null\", async () => {\n            expect(await parse(\"\"          )()).to.be.Tuple([]);\n            expect(await parse(\"()\"        )()).to.be.Tuple([]);\n            expect(await parse(\"(), (), ()\")()).to.be.Tuple([]);\n        });\n    \n        it(\"should evaluate 1-uples (x,()) as x\", async () => {\n            expect(await parse(\"(), 10, ()\")()).to.be.Numb(10);\n        });\n    });\n    \n    describe(\"lists: `[expression]`\", () => {\n    \n        it(\"should return an array\", async () => {\n            expect(await parse(\"[1,'abc',3]\")()).to.be.List([1,\"abc\",3]);\n            expect(await parse(\"[1]\"        )()).to.be.List([1]);\n            expect(await parse(\"[]\"         )()).to.be.List([]);\n        });\n    \n        it(\"should not flatten deep lists\", async () => {\n            expect(await parse(\"[[1,2],3,4,[]]\")()).to.be.List([[1,2],3,4,[]]);\n        });\n    });\n    \n    describe(\"name resolution\", () => {\n    \n        it(\"should return the value mapped to the name in the current context\", async () => {\n            var context = {a:10, _b:20, __c__:\"xxx\"};\n            expect(await parse(\"a\"    )(context)).to.be.Numb(10);\n            expect(await parse(\"_b\"   )(context)).to.be.Numb(20);\n            expect(await parse(\"__c__\")(context)).to.be.Text(\"xxx\");\n        });\n    \n        it(\"should return `Undefined Mapping` if the name is not mapped\", async () => {\n            expect( await parse(\"undefined_key\")({a:10, _b:20}) ).to.be.Undefined(\"NameReference\", arg0 => {\n                expect(arg0).to.equal(\"undefined_key\");                \n            });\n        });\n    \n        it(\"should return `Undefined Mapping` if name is a property inherited from Object\", async () => {\n            \n            expect( await parse(\"isPrototypeOf\")({}) ).to.be.Undefined(\"NameReference\", arg0 => {\n                expect(arg0).to.equal(\"isPrototypeOf\");                \n            });\n            \n            expect( await parse(\"hasOwnProperty\")({}) ).to.be.Undefined(\"NameReference\", arg0 => {\n                expect(arg0).to.equal(\"hasOwnProperty\");                \n            });\n        });\n    \n        describe(\"name resolution in a child context\", () => {\n    \n            it(\"should return the child name value if name is mapped in the child context\", async () => {\n                var context = Object.assign(Object.create({a:10, b:20}), {a:100});\n                expect(await parse(\"a\")(context)).to.be.Numb(100);\n            });\n    \n            it(\"should return the parent name value if name is not mapped in the child context\", async () => {\n                var context = Object.assign(Object.create({a:10, b:20}), {a:100});\n                expect(await parse(\"b\")(context)).to.be.Numb(20);\n            });\n    \n            it(\"should return `Undefined Mapping` if the name is not mapped in the child context nor in the parent context\", async () => {\n                var context = Object.assign(Object.create({a:10, b:20}), {a:100});\n                expect( await parse(\"undefined_key\")(context) ).to.be.Undefined(\"NameReference\", arg0 => {\n                    expect(arg0).to.equal(\"undefined_key\");\n                });\n            });\n        });\n    });\n    \n    describe(\"labelling operation `name: expression`\", () => {\n    \n        it(\"should create a new name in the current context and map it to the given value\", async () => {\n            var context = {};\n            await parse(\"x: 10\")(context);\n            expect(await parse(\"x\")(context)).to.be.Numb(10);\n            expect(context.x).to.equal(10);\n        });\n    \n        it(\"should assign a tuple of values to a tuple of names\", async () => {\n            var context = {};\n            var value = await parse(\"(a,b,c) : (1,2,3)\")(context);\n\n            expect(await parse(\"a\")(context)).to.be.Numb(1);\n            expect(context.a).to.equal(1);\n            \n            expect(await parse(\"b\")(context)).to.be.Numb(2);\n            expect(context.b).to.equal(2);\n            \n            expect(await parse(\"c\")(context)).to.be.Numb(3);\n            expect(context.c).to.equal(3);\n        });\n    \n        it(\"should assign null to the last names if the values tuple is smaller than the names tuple\", async () => {\n            var context = {};\n            await parse(\"(a,b,c,d) : (10,20)\")(context);\n            \n            expect(await parse(\"a\")(context)).to.be.Numb(10);\n            expect(context.a).to.equal(10);\n            \n            expect(await parse(\"b\")(context)).to.be.Numb(20);\n            expect(context.b).to.equal(20);\n\n            expect(await parse(\"c\")(context)).to.be.Tuple([]);\n            expect(context.c).to.be.null;\n            \n            expect(await parse(\"d\")(context)).to.be.Tuple([]);\n            expect(context.d).to.be.null;\n            \n            await parse(\"(e,f) : ()\")(context);\n            expect(context.e).to.be.null;\n            expect(context.f).to.be.null;\n        });\n    \n        it(\"should assign to the last name the tuple of remaining values if the names tuple is smaller than the values tuple\", async () => {\n            var context = {};\n    \n            await parse(\"(a,b) : (100,200,300)\")(context);\n            \n            expect(await parse(\"a\")(context)).to.be.Numb(100);\n            expect(context.a).to.equal(100);\n            \n            expect(await parse(\"b\")(context)).to.be.Tuple([200,300]);\n            expect(context.b).to.be.Tuple([200,300]);\n    \n            await parse(\"c : (10,20,30)\")(context);\n            \n            expect(await parse(\"c\")(context)).to.be.Tuple([10,20,30]);\n            expect(context.c).to.be.Tuple([10,20,30]);\n        });\n    \n        it(\"should overwrite an existing name-value mapping\", async () => {\n            var context = {};\n            await parse(\"a : 2\")(context);\n            await parse(\"a : 3\")(context);\n            \n            expect(await parse(\"a\")(context)).to.be.Numb(3);\n            expect(context.a).to.equal(3);\n        });\n    \n        it(\"should return the expression value\", async () => {\n            expect(await parse(\"x: 10\"                )()).to.be.Numb(10);\n            expect(await parse(\"(a,b,c) : (1,2,3)\"    )()).to.be.Tuple([1,2,3]);\n            expect(await parse(\"(a,b,c,d) : (10,20)\"  )()).to.be.Tuple([10,20]);\n            expect(await parse(\"(a,b) : (100,200,300)\")()).to.be.Tuple([100,200,300]);\n            expect(await parse(\"c : (10,20,30)\"       )()).to.be.Tuple([10,20,30]);\n        });\n        \n        it(\"should return `Undefined` when non valid names are provided at the left-hand side of the expression\", async () => {\n            \n            expect( await parse(\"'abc' : 2\")() ).to.be.Undefined('LabellingOperation', (arg0, arg1) => {\n                expect(arg0).to.be.Undefined('StringLiteral')\n                expect(arg1).to.equal(2);\n            });\n\n            expect( await parse(\"3*2 : 2\")() ).to.be.Undefined('LabellingOperation', (arg0, arg1) => {\n                expect(arg0).to.be.Undefined('MulOperation', (arg00, arg01) => {\n                    expect(arg00).to.be.Undefined('NumberLiteral', arg000 => {\n                        expect(arg000).to.equal(3);\n                    });\n                    expect(arg01).to.be.Undefined('NumberLiteral', arg010 => {\n                        expect(arg010).to.equal(2);\n                    });\n                });\n                expect(arg1).to.equal(2);\n            });\n        });        \n    });\n    \n    describe(\"assignment operation: name = expression\", () => {\n        \n        it(\"should create a new name in the current context and map it to the given value\", async () => {\n            var context = {};\n            await parse(\"x = 10\")(context);\n            expect(await parse(\"x\")(context)).to.be.Numb(10);\n            expect(context.x).to.equal(10);\n        });\n    \n        it(\"should assign a tuple of values to a tuple of names\", async () => {\n            var context = {};\n            var value = await parse(\"(a,b,c) = (1,2,3)\")(context);\n\n            expect(await parse(\"a\")(context)).to.be.Numb(1);\n            expect(context.a).to.equal(1);\n            \n            expect(await parse(\"b\")(context)).to.be.Numb(2);\n            expect(context.b).to.equal(2);\n            \n            expect(await parse(\"c\")(context)).to.be.Numb(3);\n            expect(context.c).to.equal(3);\n        });\n    \n        it(\"should assign null to the last names if the values tuple is smaller than the names tuple\", async () => {\n            var context = {};\n            await parse(\"(a,b,c,d) = (10,20)\")(context);\n            \n            expect(await parse(\"a\")(context)).to.be.Numb(10);\n            expect(context.a).to.equal(10);\n            \n            expect(await parse(\"b\")(context)).to.be.Numb(20);\n            expect(context.b).to.equal(20);\n\n            expect(await parse(\"c\")(context)).to.be.Tuple([]);\n            expect(context.c).to.be.null;\n            \n            expect(await parse(\"d\")(context)).to.be.Tuple([]);\n            expect(context.d).to.be.null;\n\n            await parse(\"(e,f) = ()\")(context);\n            expect(context.e).to.be.null;\n            expect(context.f).to.be.null;\n        });\n    \n        it(\"should assign to the last name the tuple of remaining values if the names tuple is smaller than the values tuple\", async () => {\n            var context = {};\n    \n            await parse(\"(a,b) = (100,200,300)\")(context);\n            \n            expect(await parse(\"a\")(context)).to.be.Numb(100);\n            expect(context.a).to.equal(100);\n            \n            expect(await parse(\"b\")(context)).to.be.Tuple([200,300]);\n            expect(context.b).to.be.Tuple([200,300]);\n    \n            await parse(\"c = (10,20,30)\")(context);\n            \n            expect(await parse(\"c\")(context)).to.be.Tuple([10,20,30]);\n            expect(context.c).to.be.Tuple([10,20,30]);\n        });\n    \n        it(\"should overwrite an existing name-value mapping\", async () => {\n            var context = {};\n            await parse(\"a = 2\")(context);\n            await parse(\"a = 3\")(context);\n            \n            expect(await parse(\"a\")(context)).to.be.Numb(3);\n            expect(context.a).to.equal(3);\n        });\n\n        it(\"should return an empty tuple\", async () => {\n            expect(await parse(\"x = 10\"               )()).to.be.Tuple([]);\n            expect(await parse(\"(a,b,c) = (1,2,3)\"    )()).to.be.Tuple([]);\n            expect(await parse(\"(a,b,c,d) = (10,20)\"  )()).to.be.Tuple([]);\n            expect(await parse(\"(a,b) = (100,200,300)\")()).to.be.Tuple([]);\n            expect(await parse(\"c = (10,20,30)\"       )()).to.be.Tuple([]);\n        });\n        \n        it(\"should return `Undefined AssignmentOperation` when non valid names are provided at the left-hand side of the expression\", async () => {\n            \n            expect( await parse(\"'abc' = 2\")() ).to.be.Undefined('AssignmentOperation', (arg0, arg1) => {\n                expect(arg0).to.be.Undefined('StringLiteral')\n                expect(arg1).to.equal(2);\n            });\n\n            expect( await parse(\"3*2 = 2\")() ).to.be.Undefined('AssignmentOperation', (arg0, arg1) => {\n                expect(arg0).to.be.Undefined('MulOperation', (arg00, arg01) => {\n                    expect(arg00).to.be.Undefined('NumberLiteral', arg000 => {\n                        expect(arg000).to.equal(3);\n                    });\n                    expect(arg01).to.be.Undefined('NumberLiteral', arg010 => {\n                        expect(arg010).to.equal(2);\n                    });\n                });\n                expect(arg1).to.equal(2);\n            });\n        });\n    });\n    \n    describe(\"namespace definition: {expression}\", () => {\n    \n        it(\"return an object with the mapped names\", async () => {\n            expect(await parse(\"{x=1, y:2, z=3}\")()).to.be.Namespace({x:1,y:2,z:3});\n        });\n    \n        it(\"should ignore the non-assignment operations\", async () => {\n            expect(await parse(\"{x=1, 10, y=2, z=3}\")()).to.be.Namespace({x:1,y:2,z:3});\n        });\n    \n        it(\"should not assign the names to the parent context\", async () => {\n            var context = {x:10};\n            await parse(\"{x=20}\")(context);\n\n            expect(await parse('x')(context)).to.be.Numb(10);\n            expect(context.x).to.equal(10);\n        });\n    });\n    \n    describe(\"function definition: names_tuple -> expression\", () => {\n    \n        it(\"should return a function resolving the expression in a context augumented with the argument names\", async () => {\n            var foo = await parse(\"(x, y) -> [y,x]\")();\n            expect(foo).to.be.instanceof(Func);\n            expect(await unwrap(foo)(10,20)).to.be.List([20,10]);\n        });\n        \n        it(\"should follow the assignment rules when mapping argument names to parameters\", async () => {    \n            var retval, foo = await parse(\"(x, y) -> {a=x,b=y}\")();\n            \n            retval = await unwrap(foo)(10);\n            expect(retval).to.be.Namespace({a:10, b:null});\n            expect(unwrap(retval).a).to.equal(10);\n            expect(unwrap(retval).b).to.be.null;\n    \n            retval = await unwrap(foo)(10,20,30);\n            expect(unwrap(retval).a).to.equal(10);\n            expect(unwrap(retval).b).to.be.Tuple([20,30]);\n        });\n    \n        it(\"should add a `self` function to the function context, pointing to the function itself\", async () => {\n            const count = await parse(\"((n, head, tail) -> head == () ? n ; self(n+1, tail))(0, 10,20,30)\")()\n            expect(count).to.be.Numb(3);\n            \n            // self should be overriden by parameters with the same name\n            expect(await parse(\"(self -> 2*self)(10)\")()).to.be.Numb(20);\n        });\n    \n\n        it(\"should be righ-to-left associative\", async () => {\n            var foo = await parse(\"x -> y -> {a=x,b=y}\")();\n            var foo10 = await unwrap(foo)(10);\n            expect(foo10).to.be.instanceof(Func);\n            expect(await unwrap(foo10)(20)).to.be.Namespace({a:10, b:20});\n        });\n        \n        it(\"should return Undefined FunctionDefinition when non-valid name are defined as parameters\", async () => {\n            expect( await parse(\"'abc' -> 2\")() ).to.be.Undefined('FunctionDefinition', arg0 => {\n                expect(arg0).to.be.Undefined('StringLiteral')\n            });\n        });\n    });\n    \n    describe(\"'apply' operation: Y X`\", () => {\n    \n        describe(\"when `Y` is a function\", () => {\n    \n            it(\"should call F with the parameter X and return its return value\", async () => {\n                var context = {\n                    double: x => 2 * x,\n                    sum: (x,y) => x + y\n                };\n                expect(await parse(\"(x -> [x]) 10\"            )(context)).to.be.List([10]);\n                expect(await parse(\"((x, y) -> [y,x])(10, 20)\")(context)).to.be.List([20,10]);\n                expect(await parse(\"double 25\"                )(context)).to.be.Numb(50);\n                expect(await parse(\"sum(10, 20)\"              )(context)).to.be.Numb(30);\n            });\n    \n            it(\"should return Undefined if F throws an error\", async () => {\n                var error = new Error('Test error');\n                var context = {fn: x => {throw error}};\n                expect( await parse('fn 10')(context) ).to.be.Undefined('Term', arg0 => {\n                    expect(arg0).to.equal(error);\n                });\n            });\n    \n            it(\"should return Undefined if F returns Undefined\", async () => {\n                var undef = new Undefined();\n                var context = {fn: x => undef};\n                expect(await parse('fn 10')(context)).to.equal(undef);\n            });\n        });\n        \n        describe(\"when `Y` is a string\", () => {\n            \n            it(\"should return the X-th character if X is an integer\", async () => {\n                expect(await parse(\"'abcdef' 2\")({})).to.be.Text('c');\n            });\n    \n            it(\"should return Undefined Term if X is an out of range number or not a natural number\", async () => {\n                \n                for (let i of [100, -1, 1.2, '1', [], {}, new Undefined()]) {\n                    expect(await parse(\"'abc'(i)\")({i})).to.be.Undefined(\"Mapping\", arg0 => {\n                        expect(arg0).to.equal(i);                    \n                    });\n                }\n            });\n    \n            it(\"should return an tuple ot characters if X is a tuple\", async () => {\n                expect(await parse(\"'abcdef'(1,5,3)\")()).to.be.Tuple(['b','f','d']);\n            });            \n        })\n        \n        describe(\"when `Y` is a list\", () => {\n            \n            it(\"should return the X-th item if X is an integer\", async () => {\n                expect(await parse(\"[10, 20, 30, 40, 50, 60](2)\")()).to.be.Numb(30);\n            });\n    \n            it(\"should return Undefined Term if X is an out of range number or not a natural number\", async () => {\n                \n                for (let i of [100, -1, '1', [], {}, 1.2, -1.2, new Undefined()]) {\n                    expect( await parse(\"[10, 20, 30](i)\")({i}) ).to.be.Undefined(\"Mapping\", arg0 => {\n                        expect(arg0).to.equal(i);                    \n                    });\n                }\n            });\n    \n            it(\"should return a tuple of list items if X is a tuple\", async () => {\n                const context = {\n                    list: [10, 20, 30, 40, 50, 60],\n                }\n                expect(await parse(\"list(1,5,3)\")(context)).to.be.Tuple([20,60,40]);\n            });            \n        })\n        \n        describe(\"when `Y` is a namespace\", () => {\n            \n            it(\"should return the value mapped to X if X is a valid name\", async () => {\n                var context = {\n                    ns: {abc:10, def:20}\n                };\n                expect(await parse(\"ns 'abc'\" )(context)).to.be.Numb(10);\n                expect(await parse(\"ns('def')\")(context)).to.be.Numb(20);\n            });\n            \n            it(\"shoudl return Undefined Mapping if X is not a valid name or a name not mapped to a value\", async () => {\n                const context = {ns: {a:1, b:2, $c:3}}\n                \n                for (let name of ['$c', '123', 123, [1,2,3], new Undefined(), ]) {\n                    context.name = name;\n                    expect( await parse(\"ns(name)\")(context) ).to.be.Undefined(\"Mapping\", arg0 => {\n                        expect(arg0).to.equal(name);\n                    });\n                }\n            });\n\n            it(\"shoudl return Undefined Mapping if X is not an own property\", async () => {\n                const ns = Object.assign(Object.create({a:10}), {b:20});\n\n                for (let name of ['a', 'isPrototypeOf', 'hasOwnProperty']) {\n                    expect( await parse(\"ns(name)\")({ns, name})).to.be.Undefined(\"Mapping\", arg0 => {\n                        expect(arg0).to.equal(name);\n                    });\n                }\n            });\n\n            it(\"shoudl return a tuple of value if X is a tuple with more than one item\", async () => {\n                var context = {\n                    ns: {abc:10, def:20, ghi:30}\n                };\n                expect(await parse(\"ns('abc','ghi','def')\" )(context)).to.be.Tuple([10, 30, 20]);\n            });\n        });\n    \n        describe(\"when Y is of any other type\", () => {\n    \n            it(\"should return Undefined ApplyOperation\", async () => {\n                for (let Y of [true, false, 10, new Undefined]) {\n                    expect( await parse(\"Y(1)\")({Y}) ).to.be.Undefined('ApplyOperation', (arg0, arg1) => {\n                        expect(arg0).to.equal(Y);\n                        expect(arg1).to.equal(1);                        \n                    });\n                }\n            });            \n        });\n    \n        describe(\"when Y is a tuple\", () => {\n    \n            it(\"should return a tuple obtained applying each item of Y to X\", async () => {\n                var context = {\n                    f: (x,y) => x+y,\n                    s: 'abc'\n                };\n                var tuple = await parse('(f,s)(1,2)')(context);\n                expect(tuple).to.be.Tuple([3,'b','c']);\n            });\n        });\n    });\n    \n    describe(\"tuple mapping operation: X => Y\", () => {\n        \n        it(\"should apply Y to each item of X and return the resulting tuple\", async () => {\n            expect(await parse(\"(1,2,3) => x -> 2*x\")()).to.be.Tuple([2,4,6]);\n            expect(await parse(\"(1,2,3) => 'abcdef'\")()).to.be.Tuple(['b','c','d']);\n            expect(await parse(\"(1,2,3) => (x->2*x,x->3*x)\")()).to.be.Tuple([2,3,4,6,6,9]);\n        });\n    });\n    \n    describe(\"Function composition: G << F\", () => {\n        \n        it(\"should return the function X -> G(F(X))\", async () => {\n            var context = {f: x=>2*x, g: x=>[x]};\n            expect(await parse(\"g << f\")(context)).to.be.instanceof(Func);\n            expect(await parse(\"(g << f) 2\")(context)).to.be.List([4]);\n        });\n        \n        it(\"should work with tuples of functions\", async () => {\n            var context = {f2: x=>2*x, f3: x=>3*x, f4: x=>4*x, g: (...x)=>[...new Tuple(...x)]};\n            expect(await parse(\"g << (f2,f3,f4)\")(context)).to.be.instanceof(Func);\n            expect(await parse(\"(g << (f2,f3,f4)) 2\")(context)).to.be.List([4, 6, 8]);\n        });\n        \n        it(\"should be righ-to-left associative\", async () => {\n            var context = {f: x=>2*x, g: x=>x**2, h: x=>[x]};\n            \n            expect(await parse(\"h << g << f\")(context)).to.be.instanceof(Func);\n            expect(await parse(\"(h << g << f) 2\")(context)).to.be.List([16]);\n\n            expect(await parse(\"h << f << g\")(context)).to.be.instanceof(Func);\n            expect(await parse(\"(h << f << g) 2\")(context)).to.be.List([8]);\n        });\n    });\n\n    describe(\"Function piping: F >> G\", () => {\n        \n        it(\"should return the function X -> G(F(X))\", async () => {\n            var context = {f: x=>2*x, g: x=>[x]};\n            expect(await parse(\"f >> g\")(context)).to.be.instanceof(Func);\n            expect(await parse(\"(f >> g) 2\")(context)).to.be.List([4]);\n        });\n\n        it(\"should work with tuples of functions\", async () => {\n            var context = {f2: x=>2*x, f3: x=>3*x, f4: x=>4*x, g: (...x)=>[...new Tuple(...x)]};\n            expect(await parse(\"(f2,f3,f4) >> g\")(context)).to.be.instanceof(Func);\n            expect(await parse(\"((f2,f3,f4) >> g) 2\")(context)).to.be.List([4, 6, 8]);\n        });\n    });    \n\n    describe(\"sub-contexting: X.Y\", () => {\n    \n        describe(\"when X is a namespace\", () => {\n            \n            it(\"should evaluate 'Y' in the 'X' context if 'X' is a namespace\", async () => {\n                var context = {x: 10, u:new Undefined()};\n                await parse(\"ns = {y=20, z=30, _h=40}\")(context);\n                expect(await parse(\"ns.y      \")(context)).to.be.Numb(20);\n                expect(await parse(\"ns.[1,y,z]\")(context)).to.be.List([1,20,30]);\n                expect(await parse(\"ns.x      \")(context)).to.be.Numb(10);\n                expect(await parse(\"ns._h     \")(context)).to.be.Numb(40);\n                expect(await parse(\"ns.u      \")(context)).to.equal(context.u);\n        \n                var context = { ns:{x:10,y:20,z:30} };\n                expect(await parse(\"ns.[x,y,z]\")(context)).to.be.List([10,20,30]);\n            });\n        \n            it(\"should see the global contexts\", async () => {\n                var context = {x:10};\n                await parse(\"ns = {y=20}\")(context);\n                expect(await parse(\"ns.x\")(context)).to.be.Numb(10);\n                expect(await parse(\"ns.y\")(context)).to.be.Numb(20);\n            });\n        \n            it(\"should see the function parameters in a function expressions\", async () => {\n                var context = {x:10};\n                await parse(\"ns = {x=10}, nsp = {x=20}\")(context);\n                await parse(\"f = nsp -> nsp.x\")(context);\n                expect(await parse(\"f ns\")(context)).to.be.Numb(10);\n            });            \n        });\n    \n        describe(\"when X is of any other type\", () => {\n            \n            it(\"should return Undefined SubcontextingOperation\", async () => {\n                \n                for (let X of [10, [1,2,3], \"abc\", x=>2*x, new Undefined()]) {\n                    expect( await parse(\"X.name\")({X}) ).to.be.Undefined(\"SubcontextingOperation\", arg0 => {\n                        expect(arg0).to.equal(X);\n                    });                    \n                }\n            });\n        });\n\n        describe(\"when X is a tuple\", () => {\n            \n            it(\"should return a tuple of items, one for each item of X\", async () => {\n                expect(await parse(`({a:1},{a:2},{a:3}).a`)({})).to.be.Tuple([1,2,3]);\n            });\n        });\n    });\n    \n    describe(\"comments\", () => {\n    \n        it(\"should ignore the text following the `#` character up to the end of the line or of the expression\", async () => {\n            var expression = `\n                # this is a comment\n                12.345 # this is another comment\n                # this is the last comment`\n            expect(await parse(expression)({})).to.be.Numb(12.345);\n        });\n    \n        it(\"should not parse `#` characters in a string as comments\", async () => {\n            expect(await parse(\"'this # is a string'\")({})).to.be.Text(\"this # is a string\");\n            expect(await parse(`\"this # is a string\"`)({})).to.be.Text(\"this # is a string\");\n        });\n    });\n\n\n\n    // UNARY OPERATORS\n    \n    describe(\"+X\", () => {\n    \n        it(\"should return X\", async () => {\n            for (let X of [true, false, \"abc\", [1,2,3], {x:1}, x=>x, new Undefined()]) {\n                expect(unwrap( await parse(\"+X\")({X}) )).to.deep.equal(X);\n            }\n            expect(await parse(\"+(1,2,3)\")({})).to.be.Tuple([1,2,3]);\n            expect(await parse(\"+()\")({})).to.be.Tuple([]);\n        });\n    });\n    \n    describe(\"-X\", () => {\n    \n        it(\"should return -1*X if X is a number\", async () => {\n            expect(await parse(\"-3\")({})).to.be.Numb(-3);\n            expect(await parse(\"-x\")({x:10})).to.be.Numb(-10);\n        });\n    \n        it(\"should return Undefined NegationOperation if X is not a number\", async () => {\n            for (let X of [true, false, \"abc\", [1,2,3], {x:1}, x=>x, new Undefined()]) {\n                expect( await parse(\"-X\")({X}) ).to.be.Undefined('NegationOperation', arg0 => {\n                    expect(arg0).to.equal(X);\n                });\n            }\n        });\n    \n        it(\"should apply the operator to each item of X if X is a Tuple\", async () => {\n            expect(await parse(\"-(10, -2, 3)\")({})).to.be.Tuple([-10, 2, -3]);\n            \n            const tuple = await parse(\"-(3, x, s)\")({x:-10, s:'abc'});\n            expect(Array.from(tuple)[0]).to.equal(-3);\n            expect(Array.from(tuple)[1]).to.equal(10);\n            expect(Array.from(tuple)[2]).to.be.Undefined('NegationOperation', arg0 => {\n                expect(arg0).to.equal('abc');\n            });\n        });\n    });\n    \n    \n    \n    // LOGIC OPERATORS\n    \n    describe(\"X | Y\", () => {\n    \n        it(\"should return X if it booleanizes to true\", async () => {\n            const context = {TRUE:true, FALSE:false};\n    \n            // true or true\n            expect(await parse(\"TRUE | TRUE\")(context)).to.be.Bool(true);\n            expect(await parse(\"TRUE | 10\"  )(context)).to.be.Bool(true);\n            expect(await parse(\"10 | TTRUE\" )(context)).to.be.Numb(10);\n            expect(await parse(\"10 | 10\"    )(context)).to.be.Numb(10);\n    \n            // true or false\n            expect(await parse(\"TRUE | FALSE\")(context)).to.be.Bool(true);\n            expect(await parse(\"TRUE | 0\"    )(context)).to.be.Bool(true);\n            expect(await parse(\"10 | FALSE\"  )(context)).to.be.Numb(10);\n            expect(await parse(\"10 | 0\"      )(context)).to.be.Numb(10);    \n        })\n    \n        it(\"should return Y if X booleanizes to false\", async () => {\n            const context = {TRUE:true, FALSE:false};\n    \n            // false or true\n            expect(await parse(\"FALSE | TRUE\")(context)).to.be.Bool(true);\n            expect(await parse(\"FALSE | 10\"  )(context)).to.be.Numb(10);\n            expect(await parse(\"0 | TRUE\"    )(context)).to.be.Bool(true);\n            expect(await parse(\"0 | 10\"      )(context)).to.be.Numb(10);\n    \n            // false or false\n            expect(await parse(\"FALSE | FALSE\")(context)).to.be.Bool(false);\n            expect(await parse(\"FALSE | 0\"    )(context)).to.be.Numb(0);\n            expect(await parse(\"0 | FALSE\"    )(context)).to.be.Bool(false);\n            expect(await parse(\"0 | 0\"        )(context)).to.be.Numb(0);\n        })\n    });\n    \n    describe(\"X & Y\", () => {\n    \n        it(\"should return Y if X booleanizes to true\", async () => {\n            const context = {TRUE:true, FALSE:false};\n    \n            // true or true\n            expect(await parse(\"TRUE & TRUE\")(context)).to.be.Bool(true);\n            expect(await parse(\"TRUE & 10\"  )(context)).to.be.Numb(10);\n            expect(await parse(\"10 & TRUE\"  )(context)).to.be.Bool(true);\n            expect(await parse(\"10 & 10\"    )(context)).to.be.Numb(10);\n    \n            // true or false\n            expect(await parse(\"TRUE & FALSE\")(context)).to.be.Bool(false);\n            expect(await parse(\"TRUE & 0\"    )(context)).to.be.Numb(0);\n            expect(await parse(\"10 & FALSE\"  )(context)).to.be.Bool(false);\n            expect(await parse(\"10 & 0\"      )(context)).to.be.Numb(0);\n        });\n    \n        it(\"should return X if it booleanizes to false\", async () => {\n            const context = {TRUE:true, FALSE:false};\n    \n            // false or true\n            expect(await parse(\"FALSE & TRUE\")(context)).to.be.Bool(false);\n            expect(await parse(\"FALSE & 10\"  )(context)).to.be.Bool(false);\n            expect(await parse(\"0 & TRUE\"    )(context)).to.be.Numb(0);\n            expect(await parse(\"0 & 10\"      )(context)).to.be.Numb(0);\n    \n            // false or false\n            expect(await parse(\"FALSE & FALSE\")(context)).to.be.Bool(false);\n            expect(await parse(\"FALSE & 0\"    )(context)).to.be.Bool(false);\n            expect(await parse(\"0 & FALSE\"    )(context)).to.be.Numb(0);\n            expect(await parse(\"0 & 0\"        )(context)).to.be.Numb(0);\n        });\n    });\n    \n    describe(\"X ? Y\", () => {\n    \n        it(\"should return Y is X booleanizes to true\", async () => {\n            const context = {TRUE:true, FALSE:false};\n    \n            expect(await parse(\"TRUE ? [1,2,3]\")(context)).to.be.List([1,2,3]);\n            expect(await parse(\"10 ? [1,2,3]\"  )(context)).to.be.List([1,2,3]);\n        });\n    \n        it(\"should return Undefined Term if X booleanizes to false\", async () => {\n            const context = {TRUE:true, FALSE:false};\n    \n            expect(await parse(\"FALSE ? [1,2,3]\")(context)).to.be.Undefined('Term');\n            expect(await parse(\"0 ? [1,2,3]\"    )(context)).to.be.Undefined('Term');\n        });\n    });\n    \n    describe(\"X ; Y\", () => {\n    \n        it(\"should return X if it is not Undefined\", async () => {\n            expect(await parse(\"[1,2,3] ; [3,4,5]\")({})).to.be.List([1,2,3]);\n        });\n    \n        it(\"should return Y if X is Undefined\", async () => {\n            expect(await parse(\"(2:2) ; [3,4,5]\")({})).to.be.List([3,4,5]);\n        });\n    });\n    \n    \n    \n    // ARITHMETIC OPERATIONS\n    \n    describe(\"X + Y\", () => {\n    \n        it(\"shoudl return () if both X and Y are ()\", async () => {\n            expect(await parse(\"() + ()\")()).to.be.Tuple([]);\n        });\n    \n        it(\"should return `X OR Y` if both X and Y are booleans\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"T + T\")(context)).to.be.Bool(true);\n            expect(await parse(\"T + F\")(context)).to.be.Bool(true);\n            expect(await parse(\"F + T\")(context)).to.be.Bool(true);\n            expect(await parse(\"F + F\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return `X+Y` if both X and Y are numbers\", async () => {\n            expect(await parse(\"10 + 1\"   )()).to.be.Numb(11);\n            expect(await parse(\"10 + 0\"   )()).to.be.Numb(10);\n            expect(await parse(\"10 + (-2)\")()).to.be.Numb(8);\n        });\n    \n        it(\"should concatenate X and Y if they are both strings\", async () => {\n            expect(await parse(\"'abc' + 'def'\")()).to.be.Text(\"abcdef\");\n            expect(await parse(\"'abc' + ''\"   )()).to.be.Text(\"abc\");\n            expect(await parse(\"'' + 'def'\"   )()).to.be.Text(\"def\");\n        });\n    \n        it(\"should concatenate X and Y if they are both lists\", async () => {\n            expect(await parse(\"[1,2,3] + [4,5,6]\")()).to.be.List([1,2,3,4,5,6]);\n            expect(await parse(\"[1,2,3] + []\"     )()).to.be.List([1,2,3]);\n            expect(await parse(\"[] + [4,5,6]\"     )()).to.be.List([4,5,6]);\n        });\n    \n        it(\"should merge X and Y if they are both namespaces\", async () => {\n            expect(await parse(\"{a=1,b=2} + {b=20,c=30}\")()).to.be.Namespace({a:1,b:20,c:30});\n            expect(await parse(\"{a=1,b=2} + {}\"         )()).to.be.Namespace({a:1,b:2});\n            expect(await parse(\"{} + {b=20,c=30}\"       )()).to.be.Namespace({b:20,c:30});\n    \n            var context = {\n                ns1: {a:1, un: new Undefined()},\n                ns2: {b:2, un: new Undefined()},\n            }\n            expect(await parse(\"ns1 + ns2\")(context)).to.be.Namespace({a:1, b:2, un:context.ns2.un});\n        });\n    \n        it(\"should return Undefined for all the other type combinations\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined(), no=null;\n            for (let [L,R] of [\n                             [no,T], [n ,F], [no,n ], [no,s ], [no,ls], [no,ns], [no,fn], [no,u ],\n                    [T ,no],                 [T ,n ], [T ,s ], [T ,ls], [T ,ns], [T ,fn], [T ,u ],\n                    [F ,no],                 [F ,n ], [F ,s ], [F ,ls], [F ,ns], [F ,fn], [F ,u ],\n                    [n ,no], [n ,T], [n ,F],          [n ,s ], [n ,ls], [n ,ns], [n ,fn], [n ,u ],\n                    [s ,no], [s ,T], [s ,F], [s ,n ],          [s ,ls], [s ,ns], [s ,fn], [s ,u ],\n                    [ls,no], [ls,T], [ls,F], [ls,n ], [ls,s ],          [ls,ns], [ls,fn], [ls,u ],\n                    [ns,no], [ns,T], [ns,F], [ns,n ], [ns,s ], [ns,ls],          [ns,fn], [ns,u ],\n                    [fn,no], [fn,T], [fn,F], [fn,n ], [fn,s ], [fn,ls], [fn,ns],          [fn,u ],\n                    [u ,no], [u ,T], [u ,F], [u ,n ], [u ,s ], [u ,ls], [u ,ns], [u ,fn], [u ,u ] ]) {\n    \n                expect( await parse(\"L + R\")({L,R}) ).to.be.Undefined('SumOperation', (arg0, arg1) => {\n                    expect(arg0).to.deep.equal(L);\n                    expect(arg1).to.deep.equal(R);\n                });\n            }\n        });\n    \n        it(\"should return (x1+y1, x2+y2, ...) if X and/or Y is a tuple\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"(T, 1, 'a', [1], {a=1}) + (F, 2, 'b', [2], {b=2})\")(context)).to.be.Tuple([true, 3, \"ab\", [1,2], {a:1,b:2}])\n    \n            // partial exception\n            var tuple = await parse(\"(10,20,30) + (1,2,[])\")();\n            expect(Array.from(tuple)[0]).to.equal(11);\n            expect(Array.from(tuple)[1]).to.equal(22);\n            expect(Array.from(tuple)[2]).to.be.Undefined('SumOperation', (arg0, arg1) => {\n                expect(arg0).to.equal(30);\n                expect(arg1).to.deep.equal([]);\n            });\n        });\n    });\n    \n    describe(\"X - Y\", () => {\n        \n        it(\"shoudl return () if both X and Y are ()\", async () => {\n            expect(await parse(\"() - ()\")()).to.be.Tuple([]);\n        });\n    \n        it(\"should return `X-Y` if both X and Y are numbers\", async () => {\n            expect(await parse(\"10 - 1\"   )()).to.be.Numb(9);\n            expect(await parse(\"20 - 0\"   )()).to.be.Numb(20);\n            expect(await parse(\"10 - (-7)\")()).to.be.Numb(17);\n        });\n    \n        it(\"should return Undefined for all the other type combinations\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined(), no=null;\n            for (let [L,R] of [\n                             [no,T], [n ,F], [no,n ], [no,s], [no,ls], [no,ns], [no,fn], [no,u ],\n                    [T ,no], [T ,T], [T, F], [T ,n ], [T ,s], [T ,ls], [T ,ns], [T ,fn], [T ,u ],\n                    [F ,no], [F ,T], [F, F], [F ,n ], [F ,s], [F ,ls], [F ,ns], [F ,fn], [F ,u ],\n                    [n ,no], [n ,T], [n ,F],          [n ,s], [n ,ls], [n ,ns], [n ,fn], [n ,u ],\n                    [s ,no], [s ,T], [s ,F], [s ,n ], [s, s], [s ,ls], [s ,ns], [s ,fn], [s ,u ],\n                    [ls,no], [ls,T], [ls,F], [ls,n ], [ls,s], [ls,ls], [ls,ns], [ls,fn], [ls,u ],\n                    [ns,no], [ns,T], [ns,F], [ns,n ], [ns,s], [ns,ls], [ns,ns], [ns,fn], [ns,u ],\n                    [fn,no], [fn,T], [fn,F], [fn,n ], [fn,s], [fn,ls], [fn,ns], [fn,fn], [fn,u ],\n                    [u ,no], [u ,T], [u ,F], [u ,n ], [u ,s], [u ,ls], [u ,ns], [u ,fn], [u ,u ] ]) {\n    \n                expect( await parse(\"L - R\")({L,R}) ).to.be.Undefined('SubOperation', (arg0, arg1) => {\n                    expect(arg0).to.deep.equal(L);\n                    expect(arg1).to.deep.equal(R);\n                });\n            }\n        });\n    \n        it(\"should return (x1-y1, x2-y2, ...) if X and/or Y is a tuple\", async () => {\n            expect(await parse(\"(10,20,30) - (1,2,3)\")(context)).to.be.Tuple([9,18,27]);\n    \n            // partial exception\n            var tuple = await parse(\"(10,20,30) - (1,2,[])\")();\n            expect(Array.from(tuple)[0]).to.equal(9);\n            expect(Array.from(tuple)[1]).to.equal(18);\n            expect(Array.from(tuple)[2]).to.be.Undefined('SubOperation', (arg0, arg1) => {\n                expect(arg0).to.equal(30);\n                expect(arg1).to.deep.equal([]);\n            });\n        });\n    });\n    \n    describe(\"X * Y\", () => {\n    \n        it(\"should return () if both X and Y are ()\", async () => {\n            expect(await parse(\"() * ()\")()).to.be.Tuple([]);\n        });\n    \n        it(\"should return `X AND Y` if both X and Y are booleans\", async () => {\n            var context = {T:true, F:false,\n                    un: new Undefined()};    \n            expect(await parse(\"T * T\")(context)).to.be.Bool(true);\n            expect(await parse(\"T * F\")(context)).to.be.Bool(false);\n            expect(await parse(\"F * T\")(context)).to.be.Bool(false);\n            expect(await parse(\"F * F\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return `X*Y` if both X and Y are numbers\", async () => {\n            expect(await parse(\"10 * 2\"   )()).to.be.Numb(20);\n            expect(await parse(\"10 * 0\"   )()).to.be.Numb(0);\n            expect(await parse(\"10 * (-2)\")()).to.be.Numb(-20);\n        });\n    \n        it(\"should return Undefined MulOperation for all the other type combinations\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined(), no=null;\n            for (let [L,R] of [\n                             [no,T], [n ,F], [no,n ], [no,s], [no,ls], [no,ns], [no,fn], [no,u ],\n                    [T ,no],                 [T ,n ], [T ,s], [T ,ls], [T ,ns], [T ,fn], [T ,u ],\n                    [F ,no],                 [F ,n ], [F ,s], [F ,ls], [F ,ns], [F ,fn], [F ,u ],\n                    [n ,no], [n ,T], [n ,F],          [n ,s], [n ,ls], [n ,ns], [n ,fn], [n ,u ],\n                    [s ,no], [s ,T], [s ,F], [s ,n ], [s, s], [s ,ls], [s ,ns], [s ,fn], [s ,u ],\n                    [ls,no], [ls,T], [ls,F], [ls,n ], [ls,s], [ls,ls], [ls,ns], [ls,fn], [ls,u ],\n                    [ns,no], [ns,T], [ns,F], [ns,n ], [ns,s], [ns,ls], [ns,ns], [ns,fn], [ns,u ],\n                    [fn,no], [fn,T], [fn,F], [fn,n ], [fn,s], [fn,ls], [fn,ns], [fn,fn], [fn,u ],\n                    [u ,no], [u ,T], [u ,F], [u ,n ], [u ,s], [u ,ls], [u ,ns], [u ,fn], [u ,u ] ]) {\n    \n                expect( await parse(\"L * R\")({L,R}) ).to.be.Undefined('MulOperation', (arg0, arg1) => {\n                    expect(arg0).to.deep.equal(L);\n                    expect(arg1).to.deep.equal(R);\n                });\n            }\n        });\n    \n        it(\"should return (x1*y1, x2*y2, ...) if X and/or Y is a tuple\", async () => {\n            expect(await parse(\"(10,20,30) * (2,3,4)\")(context)).to.be.Tuple([20,60,120]);\n    \n            // partial exception\n            var tuple = await parse(\"(10,20,30) * (1,2,{})\")();\n            expect(Array.from(tuple)[0]).to.equal(10);\n            expect(Array.from(tuple)[1]).to.equal(40);\n            expect(Array.from(tuple)[2]).to.be.Undefined('MulOperation', (arg0, arg1) => {\n                expect(arg0).to.equal(30);\n                expect(arg1).to.deep.equal({});\n            });\n        });\n    });\n    \n    describe(\"X / Y\", () => {\n    \n        it(\"should return () if both X and Y are nothing\", async () => {\n            expect(await parse(\"() / ()\")(context)).to.be.Tuple([]);\n        });\n    \n        it(\"should return `X/Y` if both X and Y are numbers\", async () => {\n            expect(await parse(\"10 / 2\"   )()).to.be.Numb(5);\n            expect(await parse(\"10 / 5\"   )()).to.be.Numb(2);\n            expect(await parse(\"10 / (-2)\")()).to.be.Numb(-5);\n            expect(await parse(\"10 / 0\"   )()).to.be.Numb(Infinity);\n        });\n    \n        it(\"should return Undefined DivOperation for all the other type combinations\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined(), no=null;\n            for (let [L,R] of [\n                             [no,T], [n ,F], [no,n ], [no,s], [no,ls], [no,ns], [no,fn], [no,u ],\n                    [T ,no], [T ,T], [T, F], [T ,n ], [T ,s], [T ,ls], [T ,ns], [T ,fn], [T ,u ],\n                    [F ,no], [F ,T], [F, F], [F ,n ], [F ,s], [F ,ls], [F ,ns], [F ,fn], [F ,u ],\n                    [n ,no], [n ,T], [n ,F],          [n ,s], [n ,ls], [n ,ns], [n ,fn], [n ,u ],\n                    [s ,no], [s ,T], [s ,F], [s ,n ], [s, s], [s ,ls], [s ,ns], [s ,fn], [s ,u ],\n                    [ls,no], [ls,T], [ls,F], [ls,n ], [ls,s], [ls,ls], [ls,ns], [ls,fn], [ls,u ],\n                    [ns,no], [ns,T], [ns,F], [ns,n ], [ns,s], [ns,ls], [ns,ns], [ns,fn], [ns,u ],\n                    [fn,no], [fn,T], [fn,F], [fn,n ], [fn,s], [fn,ls], [fn,ns], [fn,fn], [fn,u ],\n                    [u ,no], [u ,T], [u ,F], [u ,n ], [u ,s], [u ,ls], [u ,ns], [u ,fn], [u ,u ] ]) {\n    \n                expect( await parse(\"L / R\")({L,R}) ).to.be.Undefined('DivOperation', (arg0, arg1) => {\n                    expect(arg0).to.deep.equal(L);\n                    expect(arg1).to.deep.equal(R);\n                });\n            }\n        });\n    \n        it(\"should return (x1/y1, x2/y2, ...) if X and/or Y is a tuple\", async () => {\n            expect(await parse(\"(10,20,30) / (2,5,3)\")(context)).to.be.Tuple([5,4,10]);\n    \n            // partial exception\n            var tuple = await parse(\"(10,20,30) / (2,5)\")();\n            expect(Array.from(tuple)[0]).to.equal(5);\n            expect(Array.from(tuple)[1]).to.equal(4);\n            expect(Array.from(tuple)[2]).to.be.Undefined('DivOperation', (arg0, arg1) => {\n                expect(arg0).to.equal(30);\n                expect(arg1).to.equal(null);\n            });\n        });\n    });\n    \n    describe(\"X ** Y\", () => {\n    \n        it(\"should return () if both X and Y are ()\", async () => {\n            expect(await parse(\"() ** ()\")()).to.be.Tuple([]);\n        });\n    \n        it(\"should return `X**Y` if both X and Y are numbers\", async () => {\n            expect(await parse(\"10 ** 2\"   )()).to.be.Numb(100);\n            expect(await parse(\"10 ** 0\"   )()).to.be.Numb(1);\n            expect(await parse(\"10 ** (-2)\")()).to.be.Numb(0.01);\n        });\n    \n        it(\"should return Undefined PowOperation for all the other type combinations\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined(), no=null;\n            for (let [L,R] of [\n                             [no,T], [n ,F], [no,n ], [no,s], [no,ls], [no,ns], [no,fn], [no,u ],\n                    [T ,no], [T ,T], [T, F], [T ,n ], [T ,s], [T ,ls], [T ,ns], [T ,fn], [T ,u ],\n                    [F ,no], [F ,T], [F, F], [F ,n ], [F ,s], [F ,ls], [F ,ns], [F ,fn], [F ,u ],\n                    [n ,no], [n ,T], [n ,F],          [n ,s], [n ,ls], [n ,ns], [n ,fn], [n ,u ],\n                    [s ,no], [s ,T], [s ,F], [s ,n ], [s, s], [s ,ls], [s ,ns], [s ,fn], [s ,u ],\n                    [ls,no], [ls,T], [ls,F], [ls,n ], [ls,s], [ls,ls], [ls,ns], [ls,fn], [ls,u ],\n                    [ns,no], [ns,T], [ns,F], [ns,n ], [ns,s], [ns,ls], [ns,ns], [ns,fn], [ns,u ],\n                    [fn,no], [fn,T], [fn,F], [fn,n ], [fn,s], [fn,ls], [fn,ns], [fn,fn], [fn,u ],\n                    [u ,no], [u ,T], [u ,F], [u ,n ], [u ,s], [u ,ls], [u ,ns], [u ,fn], [u ,u ] ]) {\n    \n                expect( await parse(\"L ** R\")({L,R}) ).to.be.Undefined('PowOperation', (arg0, arg1) => {\n                    expect(arg0).to.deep.equal(L);\n                    expect(arg1).to.deep.equal(R);\n                });\n            }\n        });\n    \n        it(\"should return (x1*y1, x2*y2, ...) if X and/or Y is a tuple\", async () => {\n            expect(await parse(\"(10,20,30) * (2,3,4)\")(context)).to.be.Tuple([20,60,120]);\n    \n            // partial exception\n            var tuple = await parse(\"(10,20,30) ** (1,2,{})\")();\n            expect(Array.from(tuple)[0]).to.equal(10);\n            expect(Array.from(tuple)[1]).to.equal(400);\n            expect(Array.from(tuple)[2]).to.be.Undefined('PowOperation', (arg0, arg1) => {\n                expect(arg0).to.equal(30);\n                expect(arg1).to.deep.equal({});\n            });\n        });\n    });\n    \n    describe(\"X % Y\", () => {\n        \n        it(\"should return () if both X and Y are nothing\", async () => {\n            expect(await parse(\"() % ()\")(context)).to.be.Tuple([]);\n        });\n\n        it(\"should return the reminder of X/Y if both X and Y are numbers\", async () => {\n            expect(await parse(\"10 % 4\"   )()).to.be.Numb(2);\n            expect(await parse(\"10 % 5\"   )()).to.be.Numb(0);\n            expect(await parse(\"10 % (-4)\")()).to.be.Numb(2);\n            expect(await parse(\"10 % 0\"   )()).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should return Undefined ModOperation if X and Y are of any other type\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined(), no=null;\n            for (let [L,R] of [\n                             [no,T], [n ,F], [no,n ], [no,s], [no,ls], [no,ns], [no,fn], [no,u ],\n                    [T ,no], [T ,T], [T, F], [T ,n ], [T ,s], [T ,ls], [T ,ns], [T ,fn], [T ,u ],\n                    [F ,no], [F ,T], [F, F], [F ,n ], [F ,s], [F ,ls], [F ,ns], [F ,fn], [F ,u ],\n                    [n ,no], [n ,T], [n ,F],          [n ,s], [n ,ls], [n ,ns], [n ,fn], [n ,u ],\n                    [s ,no], [s ,T], [s ,F], [s ,n ], [s, s], [s ,ls], [s ,ns], [s ,fn], [s ,u ],\n                    [ls,no], [ls,T], [ls,F], [ls,n ], [ls,s], [ls,ls], [ls,ns], [ls,fn], [ls,u ],\n                    [ns,no], [ns,T], [ns,F], [ns,n ], [ns,s], [ns,ls], [ns,ns], [ns,fn], [ns,u ],\n                    [fn,no], [fn,T], [fn,F], [fn,n ], [fn,s], [fn,ls], [fn,ns], [fn,fn], [fn,u ],\n                    [u ,no], [u ,T], [u ,F], [u ,n ], [u ,s], [u ,ls], [u ,ns], [u ,fn], [u ,u ] ]) {\n    \n                expect( await parse(\"L % R\")({L,R}) ).to.be.Undefined('ModOperation', (arg0, arg1) => {\n                    expect(arg0).to.deep.equal(L);\n                    expect(arg1).to.deep.equal(R);\n                });\n            }            \n        });\n\n        it(\"should return (x1%y1, x2%y2, ...) if X and/or Y is a tuple\", async () => {\n            expect(await parse(\"(10,20,30) % (4,7,6)\")(context)).to.be.Tuple([2,6,0]);\n    \n            // partial exception\n            var tuple = await parse(\"(10,20,30) % (4,7)\")();\n            expect(Array.from(tuple)[0]).to.equal(2);\n            expect(Array.from(tuple)[1]).to.equal(6);\n            expect(Array.from(tuple)[2]).to.be.Undefined('ModOperation', (arg0, arg1) => {\n                expect(arg0).to.equal(30);\n                expect(arg1).to.equal(null);\n            });            \n        });\n    });\n    \n    \n    \n    // COMPARISON OPERATIONS\n    \n    describe(\"X == Y\", () => {\n    \n        it(\"should return true if both X and Y are nothing\", async () => {\n            expect(await parse(\"() == ()\")()).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both true or both false\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"T == T\")(context)).to.be.Bool(true);\n            expect(await parse(\"F == F\")(context)).to.be.Bool(true);\n            expect(await parse(\"T == F\")(context)).to.be.Bool(false);\n            expect(await parse(\"F == T\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are the same number\", async () => {\n            expect(await parse(\"3 == 3\"  )()).to.be.Bool(true);\n            expect(await parse(\"0 == 0\"  )()).to.be.Bool(true);\n            expect(await parse(\"-3 == -3\")()).to.be.Bool(true);\n            expect(await parse(\"3 == 2\"  )()).to.be.Bool(false);\n            expect(await parse(\"0 == -4\" )()).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are the same string\", async () => {\n            expect(await parse(\"'abc' == 'abc'\")()).to.be.Bool(true);\n            expect(await parse(\"'' == ''\"      )()).to.be.Bool(true);\n            expect(await parse(\"'abc' == 'def'\")()).to.be.Bool(false);\n            expect(await parse(\"'abc' == ''\"   )()).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are both lists with equal items\", async () => {\n            expect(await parse(\"[1,2,3] == [1,2,3]\")()).to.be.Bool(true);\n            expect(await parse(\"[] == []\"          )()).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] == [4,5,6]\")()).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] == []\"     )()).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are both namespaces with sname name:value pairs\", async () => {\n            expect(await parse(\"{a=1,b=2} == {a=1,b=2}\")()).to.be.Bool(true);\n            expect(await parse(\"{} == {}\"              )()).to.be.Bool(true);\n            expect(await parse(\"{a=1,b=2} == {a=1,c=2}\")()).to.be.Bool(false);\n            expect(await parse(\"{a=1,b=2} == {a=1,b=3}\")()).to.be.Bool(false);\n            expect(await parse(\"{a=1,b=2} == {a=1}\"    )()).to.be.Bool(false);\n            expect(await parse(\"{a=1,b=2} == {}\"       )()).to.be.Bool(false);\n            expect(await parse(\"{a=1} == {a=1,b=2}\"    )()).to.be.Bool(false);\n            expect(await parse(\"{} == {a=1,b=2}\"       )()).to.be.Bool(false);\n    \n            // Should not include inherited properties in the comparison\n            var context = {};\n            context.ns1 = {x:10};\n            context.ns2 = Object.assign(Object.create(context.ns1), {y:20});\n            expect(await parse(\"ns2 == {x:10,y:20}\")(context)).to.be.Bool(false);\n    \n            // Should ignore non-valid swan names\n            var context = {};\n            context.ns1 = {x:10, y:20};\n            context.ns2 = {x:10, y:20, $z:30};\n            expect(await parse(\"ns1 == ns2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are the same function\", async () => {\n            var context = {fn1:x=>2*x, fn2:x=>2*x};\n            expect(await parse(\"fn1 == fn1\"          )(context)).to.be.Bool(true);\n            expect(await parse(\"fn1 == fn2\"          )(context)).to.be.Bool(false);\n            expect(await parse(\"(x->2*x) == (x->2*x)\")(context)).to.be.Bool(false);\n            expect(await parse(\"(x->2*x) == fn1\"     )(context)).to.be.Bool(false);\n            expect(await parse(\"fn1 == (x->2*x)\"     )(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are the same Undefined object\", async () => {\n            var context = {un1: new Undefined(), un2: new Undefined};\n            expect(await parse(\"un1 == un1\")(context)).to.be.Bool(true);\n            expect(await parse(\"un1 == un2\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false if X and Y are of different types\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined();\n            for (let [L,R] of [\n                                    [T, n], [T, s], [T, ls], [T, ns], [T, fn], [T, u],\n                                    [F, n], [F, s], [F, ls], [F, ns], [F, fn], [F, u],\n                    [n, T], [n, F],         [n, s], [n, ls], [n, ns], [n, fn], [n, u],\n                    [s, T], [s, F], [s, n],         [s, ls], [s, ns], [s, fn], [s, u],\n                    [ls,T], [ls,F], [ls,n], [ls,s],          [ls,ns], [ls,fn], [ls,u],\n                    [ns,T], [ns,F], [ns,n], [ns,s], [ns,ls],          [ns,fn], [ns,u],\n                    [fn,T], [fn,F], [fn,n], [fn,s], [fn,ls], [fn,ns],          [fn,u],\n                    [u, T], [u, F], [u, n], [u, s], [u, ls], [u, ns], [u,fn]         ]) {\n    \n                expect(await parse(\"L == R\")({L,R})).to.be.Bool(false);\n            }\n        });\n    \n        it(\"should compare tuples with lexicographical criteria\", async () => {\n            expect(await parse(\"(1,2,3) == (1,2,3)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) == (1,2)\"  )()).to.be.Bool(false);\n            expect(await parse(\"(1,2) == (1,2,3)\"  )()).to.be.Bool(false);\n            expect(await parse(\"1 == (1,2,3)\"      )()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) == 1\"      )()).to.be.Bool(false);\n        });\n    });\n    \n    describe(\"X != Y\", () => {\n    \n        it(\"should return false if both X and Y are nothing\", async () => {\n            expect(await parse(\"() != ()\")()).to.be.Bool(false);\n        });\n    \n        it(\"should return false if X and Y are both false or both true\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"T != T\")(context)).to.be.Bool(false);\n            expect(await parse(\"F != F\")(context)).to.be.Bool(false);\n            expect(await parse(\"T != F\")(context)).to.be.Bool(true);\n            expect(await parse(\"F != T\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false if X and Y are the same number\", async () => {\n            expect(await parse(\"3 != 3\"  )()).to.be.Bool(false);\n            expect(await parse(\"0 != 0\"  )()).to.be.Bool(false);\n            expect(await parse(\"-3 != -3\")()).to.be.Bool(false);\n            expect(await parse(\"3 != 2\"  )()).to.be.Bool(true);\n            expect(await parse(\"0 != -4\" )()).to.be.Bool(true);\n        });\n    \n        it(\"should return false if X and Y are the same string\", async () => {\n            expect(await parse(\"'abc' != 'abc'\")()).to.be.Bool(false);\n            expect(await parse(\"'' != ''\"      )()).to.be.Bool(false);\n            expect(await parse(\"'abc' != 'def'\")()).to.be.Bool(true);\n            expect(await parse(\"'abc' != ''\"   )()).to.be.Bool(true);\n        });\n    \n        it(\"should return false if X and Y are both lists with equal items\", async () => {\n            expect(await parse(\"[1,2,3] != [1,2,3]\")()).to.be.Bool(false);\n            expect(await parse(\"[] != []\"          )()).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] != [4,5,6]\")()).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] != []\"     )()).to.be.Bool(true);\n        });\n    \n        it(\"should return false if X and Y are both namespace with sname name:value pairs\", async () => {\n            expect(await parse(\"{a=1,b=2} != {a=1,b=2}\")()).to.be.Bool(false);\n            expect(await parse(\"{} != {}\"              )()).to.be.Bool(false);\n            expect(await parse(\"{a=1,b=2} != {a=1,c=2}\")()).to.be.Bool(true);\n            expect(await parse(\"{a=1,b=2} != {a=1,b=3}\")()).to.be.Bool(true);\n            expect(await parse(\"{a=1,b=2} != {a=1}\"    )()).to.be.Bool(true);\n            expect(await parse(\"{a=1,b=2} != {}\"       )()).to.be.Bool(true);\n            expect(await parse(\"{a=1} != {a=1,b=2}\"    )()).to.be.Bool(true);\n            expect(await parse(\"{} != {a=1,b=2}\"       )()).to.be.Bool(true);\n        });\n    \n        it(\"should return false if X and Y are the same function\", async () => {\n            var context = {fn1:x=>2*x, fn2:x=>2*x};\n            expect(await parse(\"fn1 != fn1\"          )(context)).to.be.Bool(false);\n            expect(await parse(\"fn1 != fn2\"          )(context)).to.be.Bool(true);\n            expect(await parse(\"(x->2*x) != (x->2*x)\")(context)).to.be.Bool(true);\n            expect(await parse(\"(x->2*x) != fn1\"     )(context)).to.be.Bool(true);\n            expect(await parse(\"fn1 != (x->2*x)\"     )(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false if X and Y are the same Undefined object\", async () => {\n            var context = {un1: new Undefined(), un2: new Undefined};\n            expect(await parse(\"un1 != un1\")(context)).to.be.Bool(false);\n            expect(await parse(\"un1 != un2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are of different types\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined();\n            for (let [L,R] of [\n                                    [T, n], [T, s], [T, ls], [T, ns], [T, fn], [T, u],\n                                    [F, n], [F, s], [F, ls], [F, ns], [F, fn], [F, u],\n                    [n, T], [n, F],         [n, s], [n, ls], [n, ns], [n, fn], [n, u],\n                    [s, T], [s, F], [s, n],         [s, ls], [s, ns], [s, fn], [s, u],\n                    [ls,T], [ls,F], [ls,n], [ls,s],          [ls,ns], [ls,fn], [ls,u],\n                    [ns,T], [ns,F], [ns,n], [ns,s], [ns,ls],          [ns,fn], [ns,u],\n                    [fn,T], [fn,F], [fn,n], [fn,s], [fn,ls], [fn,ns],          [fn,u],\n                    [u, T], [u, F], [u, n], [u, s], [u, ls], [u, ns], [u,fn]         ]) {\n    \n                expect(await parse(\"L != R\")({L,R})).to.be.Bool(true);\n            }\n        });\n    \n        it(\"should compare tuples with lexicographical criteria\", async () => {\n            expect(await parse(\"(1,2,3) != (1,2,3)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) != (1,2)\"  )()).to.be.Bool(true);\n            expect(await parse(\"(1,2) != (1,2,3)\"  )()).to.be.Bool(true);\n            expect(await parse(\"1 != (1,2,3)\"      )()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) != 1\"      )()).to.be.Bool(true);\n        });\n    });\n    \n    describe(\"X < Y\", () => {\n    \n        it(\"should return false if both X and Y are nothing\", async () => {\n            expect(await parse(\"() < ()\")()).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X is false and Y is true\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"T < T\")(context)).to.be.Bool(false);\n            expect(await parse(\"F < F\")(context)).to.be.Bool(false);\n            expect(await parse(\"T < F\")(context)).to.be.Bool(false);\n            expect(await parse(\"F < T\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X is a lower number than Y\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"1  < 2   \")(context)).to.be.Bool(true);\n            expect(await parse(\"0  < 2   \")(context)).to.be.Bool(true);\n            expect(await parse(\"-1 < 2   \")(context)).to.be.Bool(true);\n            expect(await parse(\"2  < 1   \")(context)).to.be.Bool(false);\n            expect(await parse(\"2  < 0   \")(context)).to.be.Bool(false);\n            expect(await parse(\"2  < (-2)\")(context)).to.be.Bool(false);\n            expect(await parse(\"2  < 2   \")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are both strings and X precedes Y alphabetically\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"'abc' < 'def'\")(context)).to.be.Bool(true);\n            expect(await parse(\"'abc' < 'abd'\")(context)).to.be.Bool(true);\n            expect(await parse(\"'ab'  < 'abc'\")(context)).to.be.Bool(true);\n            expect(await parse(\"''    < 'abc'\")(context)).to.be.Bool(true);\n            expect(await parse(\"'abc' < 'abc'\")(context)).to.be.Bool(false);\n            expect(await parse(\"'abd' < 'abc'\")(context)).to.be.Bool(false);\n            expect(await parse(\"'abc' < 'ab' \")(context)).to.be.Bool(false);\n            expect(await parse(\"'abc' < ''   \")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are both lists and X precedes Y lexicographically\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"[1,2,3] < [4,5,6]\")(context)).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] < [1,2,4]\")(context)).to.be.Bool(true);\n            expect(await parse(\"[1,2]   < [1,2,4]\")(context)).to.be.Bool(true);\n            expect(await parse(\"[]      < [1,2,3]\")(context)).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] < [1,2,3]\")(context)).to.be.Bool(false);\n            expect(await parse(\"[1,2,4] < [1,2,3]\")(context)).to.be.Bool(false);\n            expect(await parse(\"[1,2,4] < [1,2]  \")(context)).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] < []     \")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false if both X and Y are namespaces\", async () => {\n            const context = {ns1:{}, ns2:{a:1}};\n            expect(await parse(\"ns1 < ns2\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns2 < ns1\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns1 < ns1\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns2 < ns2\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false if both X and Y are functions\", async () => {\n            const context = {fn1:x=>2*x, fn2:(x,y)=>x+y};\n            expect(await parse(\"fn1 < fn2\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn2 < fn1\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn1 < fn1\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn2 < fn2\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false if both X and Y are unfefined\", async () => {\n            const context = {un1:new Undefined(\"Op1\",1,2), un2:new Undefined(\"Op2\",1,2,3)};\n            expect(await parse(\"un1 < un2\")(context)).to.be.Bool(false);\n            expect(await parse(\"un2 < un1\")(context)).to.be.Bool(false);\n            expect(await parse(\"un1 < un1\")(context)).to.be.Bool(false);\n            expect(await parse(\"un2 < un2\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X is nothing and Y is not\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"() < ()\"    )(context)).to.be.Bool(false);\n            expect(await parse(\"() < T\"     )(context)).to.be.Bool(true);\n            expect(await parse(\"() < F\"     )(context)).to.be.Bool(true);\n            expect(await parse(\"() < 1\"     )(context)).to.be.Bool(true);\n            expect(await parse(\"() < 'abc'\" )(context)).to.be.Bool(true);\n            expect(await parse(\"() < ls\"    )(context)).to.be.Bool(true);\n            expect(await parse(\"() < ns\"    )(context)).to.be.Bool(true);\n            expect(await parse(\"() < fn\"    )(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false if Y is nothing and X is not\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"()    < ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"T     < ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"F     < ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"1     < ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"'abc' < ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"ls    < ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns    < ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn    < ()\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false for any other type combination\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined();\n            for (let [L,R] of [\n                                    [T, n], [T, s], [T, ls], [T, ns], [T, fn], [T, u],\n                                    [F, n], [F, s], [F, ls], [F, ns], [F, fn], [F, u],\n                    [n, T], [n, F],         [n, s], [n, ls], [n, ns], [n, fn], [n, u],\n                    [s, T], [s, F], [s, n],         [s, ls], [s, ns], [s, fn], [s, u],\n                    [ls,T], [ls,F], [ls,n], [ls,s],          [ls,ns], [ls,fn], [ls,u],\n                    [ns,T], [ns,F], [ns,n], [ns,s], [ns,ls],          [ns,fn], [ns,u],\n                    [fn,T], [fn,F], [fn,n], [fn,s], [fn,ls], [fn,ns],          [fn,u],\n                    [u, T], [u, F], [u, n], [u, s], [u, ls], [u, ns], [u, fn]        ]) {\n    \n                expect(await parse(\"L < R\")({L,R})).to.be.Bool(false);\n            }\n        });\n    \n        it(\"should compare tuples with lexicographical criteria\", async () => {\n            expect(await parse(\"(1,2,3) < (4,5,6)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) < (1,2,4)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2)   < (1,2,4)\")()).to.be.Bool(true);\n            expect(await parse(\"()      < (1,2,3)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) < (1,2,3)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,4) < (1,2,3)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,4) < (1,2)  \")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) < ()     \")()).to.be.Bool(false);\n        });\n    });\n    \n    describe(\"X >= Y\", () => {\n    \n        it(\"should return true if both X and Y are nothing\", async () => {\n            expect(await parse(\"() >= ()\")()).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both booleans and X is true and Y either true or false\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"T >= T\")(context)).to.be.Bool(true);\n            expect(await parse(\"F >= F\")(context)).to.be.Bool(true);\n            expect(await parse(\"T >= F\")(context)).to.be.Bool(true);\n            expect(await parse(\"F >= T\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are both numbers and X is a either a greater number than Y or equal to Y\", async () => {\n            expect(await parse(\"1  >= 2   \")()).to.be.Bool(false);\n            expect(await parse(\"0  >= 2   \")()).to.be.Bool(false);\n            expect(await parse(\"-1 >= 2   \")()).to.be.Bool(false);\n            expect(await parse(\"2  >= 1   \")()).to.be.Bool(true);\n            expect(await parse(\"2  >= 0   \")()).to.be.Bool(true);\n            expect(await parse(\"2  >= (-2)\")()).to.be.Bool(true);\n            expect(await parse(\"2  >= 2   \")()).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both strings and X either precedes Y alphabetically or is equal to Y\", async () => {\n            expect(await parse(\"'abc' >= 'def'\")()).to.be.Bool(false);\n            expect(await parse(\"'abc' >= 'abd'\")()).to.be.Bool(false);\n            expect(await parse(\"'ab'  >= 'abc'\")()).to.be.Bool(false);\n            expect(await parse(\"''    >= 'abc'\")()).to.be.Bool(false);\n            expect(await parse(\"'abc' >= 'abc'\")()).to.be.Bool(true);\n            expect(await parse(\"'abd' >= 'abc'\")()).to.be.Bool(true);\n            expect(await parse(\"'abc' >= 'ab' \")()).to.be.Bool(true);\n            expect(await parse(\"'abc' >= ''   \")()).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both lists and either X preceeds Y lexicographically or is equal to Y\", async () => {\n            expect(await parse(\"[1,2,3] >= [4,5,6]\")()).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] >= [1,2,4]\")()).to.be.Bool(false);\n            expect(await parse(\"[1,2]   >= [1,2,4]\")()).to.be.Bool(false);\n            expect(await parse(\"[]      >= [1,2,3]\")()).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] >= [1,2,3]\")()).to.be.Bool(true);\n            expect(await parse(\"[1,2,4] >= [1,2,3]\")()).to.be.Bool(true);\n            expect(await parse(\"[1,2,4] >= [1,2]  \")()).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] >= []     \")()).to.be.Bool(true);\n        });\n    \n        it(\"should return true if both X and Y are namespaces, but only if they are the same object\", async () => {\n            const context = {ns1:{}, ns2:{a:1}};\n            expect(await parse(\"ns1 >= ns2\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns2 >= ns1\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns1 >= ns1\")(context)).to.be.Bool(true);\n            expect(await parse(\"ns2 >= ns2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if both X and Y are functions, but only if they are the same object\", async () => {\n            const context = {fn1:x=>2*x, fn2:(x,y)=>x+y};\n            expect(await parse(\"fn1 >= fn2\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn2 >= fn1\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn1 >= fn1\")(context)).to.be.Bool(true);\n            expect(await parse(\"fn2 >= fn2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if both X and Y are unfefined, but only if they are the same object\", async () => {\n            const context = {un1:new Undefined(\"Op1\",1,2), un2:new Undefined(\"Op2\",1,2,3)};\n            expect(await parse(\"un1 >= un2\")(context)).to.be.Bool(false);\n            expect(await parse(\"un2 >= un1\")(context)).to.be.Bool(false);\n            expect(await parse(\"un1 >= un1\")(context)).to.be.Bool(true);\n            expect(await parse(\"un2 >= un2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false if X is nothing and Y is not\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"() >= ()   \")(context)).to.be.Bool(true);\n            expect(await parse(\"() >= T    \")(context)).to.be.Bool(false);\n            expect(await parse(\"() >= F    \")(context)).to.be.Bool(false);\n            expect(await parse(\"() >= 1    \")(context)).to.be.Bool(false);\n            expect(await parse(\"() >= 'abc'\")(context)).to.be.Bool(false);\n            expect(await parse(\"() >= ls   \")(context)).to.be.Bool(false);\n            expect(await parse(\"() >= ns   \")(context)).to.be.Bool(false);\n            expect(await parse(\"() >= fn   \")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if Y is nothing\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"()    >= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"T     >= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"F     >= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"1     >= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"'abc' >= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"ls    >= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"ns    >= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"fn    >= ()\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false for any other type combination\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined();\n            for (let [L,R] of [\n                                    [T, n], [T, s], [T, ls], [T, ns], [T, fn], [T, u],\n                                    [F, n], [F, s], [F, ls], [F, ns], [F, fn], [F, u],\n                    [n, T], [n, F],         [n, s], [n, ls], [n, ns], [n, fn], [n, u],\n                    [s, T], [s, F], [s, n],         [s, ls], [s, ns], [s, fn], [s, u],\n                    [ls,T], [ls,F], [ls,n], [ls,s],          [ls,ns], [ls,fn], [ls,u],\n                    [ns,T], [ns,F], [ns,n], [ns,s], [ns,ls],          [ns,fn], [ns,u],\n                    [fn,T], [fn,F], [fn,n], [fn,s], [fn,ls], [fn,ns],          [fn,u],\n                    [u, T], [u, F], [u, n], [u, s], [u, ls], [u, ns], [u, fn]        ]) {\n    \n                expect(await parse(\"L >= R\")({L,R})).to.be.Bool(false);\n            }\n        });\n    \n        it(\"should compare tuples with lexicographical criteria\", async () => {\n            expect(await parse(\"(1,2,3) >= (4,5,6)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) >= (1,2,4)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2)   >= (1,2,4)\")()).to.be.Bool(false);\n            expect(await parse(\"()      >= (1,2,3)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) >= (1,2,3)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,4) >= (1,2,3)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,4) >= (1,2)  \")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) >= ()     \")()).to.be.Bool(true);\n        });\n    });\n    \n    describe(\"X > Y\", () => {\n    \n        it(\"should return false if both X and Y are nothing\", async () => {\n            expect(await parse(\"() > ()\")()).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X is true and Y is false\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"T > T\")(context)).to.be.Bool(false);\n            expect(await parse(\"F > F\")(context)).to.be.Bool(false);\n            expect(await parse(\"T > F\")(context)).to.be.Bool(true);\n            expect(await parse(\"F > T\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X is a higher number than Y\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"1  > 2   \")(context)).to.be.Bool(false);\n            expect(await parse(\"0  > 2   \")(context)).to.be.Bool(false);\n            expect(await parse(\"-1 > 2   \")(context)).to.be.Bool(false);\n            expect(await parse(\"2  > 1   \")(context)).to.be.Bool(true);\n            expect(await parse(\"2  > 0   \")(context)).to.be.Bool(true);\n            expect(await parse(\"2  > (-2)\")(context)).to.be.Bool(true);\n            expect(await parse(\"2  > 2   \")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are both strings and X precedes Y alphabetically\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"'abc' > 'def'\")(context)).to.be.Bool(false);\n            expect(await parse(\"'abc' > 'abd'\")(context)).to.be.Bool(false);\n            expect(await parse(\"'ab'  > 'abc'\")(context)).to.be.Bool(false);\n            expect(await parse(\"''    > 'abc'\")(context)).to.be.Bool(false);\n            expect(await parse(\"'abc' > 'abc'\")(context)).to.be.Bool(false);\n            expect(await parse(\"'abd' > 'abc'\")(context)).to.be.Bool(true);\n            expect(await parse(\"'abc' > 'ab' \")(context)).to.be.Bool(true);\n            expect(await parse(\"'abc' > ''   \")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both lists and X follows Y lexicographically\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"[1,2,3] > [4,5,6]\")(context)).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] > [1,2,4]\")(context)).to.be.Bool(false);\n            expect(await parse(\"[1,2]   > [1,2,4]\")(context)).to.be.Bool(false);\n            expect(await parse(\"[]      > [1,2,3]\")(context)).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] > [1,2,3]\")(context)).to.be.Bool(false);\n            expect(await parse(\"[1,2,4] > [1,2,3]\")(context)).to.be.Bool(true);\n            expect(await parse(\"[1,2,4] > [1,2]  \")(context)).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] > []     \")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false if both X and Y are namespaces\", async () => {\n            const context = {ns1:{}, ns2:{a:1}};\n            expect(await parse(\"ns1 > ns2\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns2 > ns1\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns1 > ns1\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns2 > ns2\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false if both X and Y are functions\", async () => {\n            const context = {fn1:x=>2*x, fn2:(x,y)=>x+y};\n            expect(await parse(\"fn1 > fn2\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn2 > fn1\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn1 > fn1\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn2 > fn2\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false if both X and Y are unfefined\", async () => {\n            const context = {un1:new Undefined(\"Op1\",1,2), un2:new Undefined(\"Op2\",1,2,3)};\n            expect(await parse(\"un1 > un2\")(context)).to.be.Bool(false);\n            expect(await parse(\"un2 > un1\")(context)).to.be.Bool(false);\n            expect(await parse(\"un1 > un1\")(context)).to.be.Bool(false);\n            expect(await parse(\"un2 > un2\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false if X is nothing\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"() > ()\"    )(context)).to.be.Bool(false);\n            expect(await parse(\"() > T\"     )(context)).to.be.Bool(false);\n            expect(await parse(\"() > F\"     )(context)).to.be.Bool(false);\n            expect(await parse(\"() > 1\"     )(context)).to.be.Bool(false);\n            expect(await parse(\"() > 'abc'\" )(context)).to.be.Bool(false);\n            expect(await parse(\"() > ls\"    )(context)).to.be.Bool(false);\n            expect(await parse(\"() > ns\"    )(context)).to.be.Bool(false);\n            expect(await parse(\"() > fn\"    )(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return true if Y is nothing and X is not\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"()    > ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"T     > ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"F     > ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"1     > ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"'abc' > ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"ls    > ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"ns    > ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"fn    > ()\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false for any other type combination\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined();\n            for (let [L,R] of [\n                                    [T, n], [T, s], [T, ls], [T, ns], [T, fn], [T, u],\n                                    [F, n], [F, s], [F, ls], [F, ns], [F, fn], [F, u],\n                    [n, T], [n, F],         [n, s], [n, ls], [n, ns], [n, fn], [n, u],\n                    [s, T], [s, F], [s, n],         [s, ls], [s, ns], [s, fn], [s, u],\n                    [ls,T], [ls,F], [ls,n], [ls,s],          [ls,ns], [ls,fn], [ls,u],\n                    [ns,T], [ns,F], [ns,n], [ns,s], [ns,ls],          [ns,fn], [ns,u],\n                    [fn,T], [fn,F], [fn,n], [fn,s], [fn,ls], [fn,ns],          [fn,u],\n                    [u, T], [u, F], [u, n], [u, s], [u, ls], [u, ns], [u, fn]        ]) {\n    \n                expect(await parse(\"L > R\")({L,R})).to.be.Bool(false);\n            }\n        });\n    \n        it(\"should compare tuples with lexicographical criteria\", async () => {\n            expect(await parse(\"(1,2,3) > (4,5,6)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) > (1,2,4)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2)   > (1,2,4)\")()).to.be.Bool(false);\n            expect(await parse(\"()      > (1,2,3)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) > (1,2,3)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,4) > (1,2,3)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,4) > (1,2)  \")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) > ()     \")()).to.be.Bool(true);\n        });\n    });\n    \n    describe(\"X <= Y\", () => {\n    \n        it(\"should return true if both X and Y are nothing\", async () => {\n            expect(await parse(\"() <= ()\")()).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both booleans and X is false and Y either true or false\", async () => {\n            var context = {T:true, F:false};\n            expect(await parse(\"T <= T\")(context)).to.be.Bool(true);\n            expect(await parse(\"F <= F\")(context)).to.be.Bool(true);\n            expect(await parse(\"T <= F\")(context)).to.be.Bool(false);\n            expect(await parse(\"F <= T\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both numbers and X is a either a smaller number than Y or equal to Y\", async () => {\n            expect(await parse(\"1  <= 2   \")()).to.be.Bool(true);\n            expect(await parse(\"0  <= 2   \")()).to.be.Bool(true);\n            expect(await parse(\"-1 <= 2   \")()).to.be.Bool(true);\n            expect(await parse(\"2  <= 1   \")()).to.be.Bool(false);\n            expect(await parse(\"2  <= 0   \")()).to.be.Bool(false);\n            expect(await parse(\"2  <= (-2)\")()).to.be.Bool(false);\n            expect(await parse(\"2  <= 2   \")()).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X and Y are both strings and X either follows Y alphabetically or is equal to Y\", async () => {\n            expect(await parse(\"'abc' <= 'def'\")()).to.be.Bool(true);\n            expect(await parse(\"'abc' <= 'abd'\")()).to.be.Bool(true);\n            expect(await parse(\"'ab'  <= 'abc'\")()).to.be.Bool(true);\n            expect(await parse(\"''    <= 'abc'\")()).to.be.Bool(true);\n            expect(await parse(\"'abc' <= 'abc'\")()).to.be.Bool(true);\n            expect(await parse(\"'abd' <= 'abc'\")()).to.be.Bool(false);\n            expect(await parse(\"'abc' <= 'ab' \")()).to.be.Bool(false);\n            expect(await parse(\"'abc' <= ''   \")()).to.be.Bool(false);\n        });\n    \n        it(\"should return true if X and Y are both lists and either X preceeds Y lexicographically or is equal to Y\", async () => {\n            expect(await parse(\"[1,2,3] <= [4,5,6]\")()).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] <= [1,2,4]\")()).to.be.Bool(true);\n            expect(await parse(\"[1,2]   <= [1,2,4]\")()).to.be.Bool(true);\n            expect(await parse(\"[]      <= [1,2,3]\")()).to.be.Bool(true);\n            expect(await parse(\"[1,2,3] <= [1,2,3]\")()).to.be.Bool(true);\n            expect(await parse(\"[1,2,4] <= [1,2,3]\")()).to.be.Bool(false);\n            expect(await parse(\"[1,2,4] <= [1,2]  \")()).to.be.Bool(false);\n            expect(await parse(\"[1,2,3] <= []     \")()).to.be.Bool(false);\n        });\n    \n        it(\"should return true if both X and Y are namespaces, but only if they are the same object\", async () => {\n            const context = {ns1:{}, ns2:{a:1}};\n            expect(await parse(\"ns1 <= ns2\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns2 <= ns1\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns1 <= ns1\")(context)).to.be.Bool(true);\n            expect(await parse(\"ns2 <= ns2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if both X and Y are functions, but only if they are the same object\", async () => {\n            const context = {fn1:x=>2*x, fn2:(x,y)=>x+y};\n            expect(await parse(\"fn1 <= fn2\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn2 <= fn1\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn1 <= fn1\")(context)).to.be.Bool(true);\n            expect(await parse(\"fn2 <= fn2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if both X and Y are unfefined, but only if they are the same object\", async () => {\n            const context = {un1:new Undefined(\"Op1\",1,2), un2:new Undefined(\"Op2\",1,2,3)};\n            expect(await parse(\"un1 <= un2\")(context)).to.be.Bool(false);\n            expect(await parse(\"un2 <= un1\")(context)).to.be.Bool(false);\n            expect(await parse(\"un1 <= un1\")(context)).to.be.Bool(true);\n            expect(await parse(\"un2 <= un2\")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return true if X is nothing\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"() <= ()   \")(context)).to.be.Bool(true);\n            expect(await parse(\"() <= T    \")(context)).to.be.Bool(true);\n            expect(await parse(\"() <= F    \")(context)).to.be.Bool(true);\n            expect(await parse(\"() <= 1    \")(context)).to.be.Bool(true);\n            expect(await parse(\"() <= 'abc'\")(context)).to.be.Bool(true);\n            expect(await parse(\"() <= ls   \")(context)).to.be.Bool(true);\n            expect(await parse(\"() <= ns   \")(context)).to.be.Bool(true);\n            expect(await parse(\"() <= fn   \")(context)).to.be.Bool(true);\n        });\n    \n        it(\"should return false if Y is nothing and X is not\", async () => {\n            var context = {fn:()=>{}, ls:[1,2,3], ns:{a:1,b:2,c:3}, T:true, F:false};\n            expect(await parse(\"()    <= ()\")(context)).to.be.Bool(true);\n            expect(await parse(\"T     <= ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"F     <= ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"1     <= ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"'abc' <= ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"ls    <= ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"ns    <= ()\")(context)).to.be.Bool(false);\n            expect(await parse(\"fn    <= ()\")(context)).to.be.Bool(false);\n        });\n    \n        it(\"should return false for any other type combination\", async () => {\n            var T=true, F=false, n=10, s=\"abc\", ls=[1,2,3], ns={a:1}, fn=x=>x, u=new Undefined();\n            for (let [L,R] of [\n                                    [T, n], [T, s], [T, ls], [T, ns], [T, fn], [T, u],\n                                    [F, n], [F, s], [F, ls], [F, ns], [F, fn], [F, u],\n                    [n, T], [n, F],         [n, s], [n, ls], [n, ns], [n, fn], [n, u],\n                    [s, T], [s, F], [s, n],         [s, ls], [s, ns], [s, fn], [s, u],\n                    [ls,T], [ls,F], [ls,n], [ls,s],          [ls,ns], [ls,fn], [ls,u],\n                    [ns,T], [ns,F], [ns,n], [ns,s], [ns,ls],          [ns,fn], [ns,u],\n                    [fn,T], [fn,F], [fn,n], [fn,s], [fn,ls], [fn,ns],          [fn,u],\n                    [u, T], [u, F], [u, n], [u, s], [u, ls], [u, ns], [u, fn]        ]) {\n    \n                expect(await parse(\"L <= R\")({L,R})).to.be.Bool(false);\n            }\n        });\n    \n        it(\"should compare tuples with lexicographical criteria\", async () => {\n            expect(await parse(\"(1,2,3) <= (4,5,6)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) <= (1,2,4)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2)   <= (1,2,4)\")()).to.be.Bool(true);\n            expect(await parse(\"()      <= (1,2,3)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,3) <= (1,2,3)\")()).to.be.Bool(true);\n            expect(await parse(\"(1,2,4) <= (1,2,3)\")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,4) <= (1,2)  \")()).to.be.Bool(false);\n            expect(await parse(\"(1,2,3) <= ()     \")()).to.be.Bool(false);\n        });\n    });\n    \n    \n    \n    // MISCELLANEOUS\n    \n    describe(\"string templates\", () => {\n    \n        it(\"should evaluate string literals between accent quotes '``'\", async () => {\n            expect(await parse(\"`ab\\nc`\")()).to.be.Text(\"ab\\nc\");\n            expect(await parse(\"``\")()).to.be.Text(\"\");\n        });\n    \n        it(\"should replace expressions between `${` and `}` with their value\", async () => {\n            expect(await parse(\"`aaa ${2*x} bbb`\")({x:10})).to.be.Text(\"aaa 20 bbb\");\n        });\n    });\n    \n    describe(\"precedence\", () => {\n    \n        describe(\"Arithmetic operations\", () => {\n    \n            it(\"should execute `+` and `-` with the same precedence\", async () => {\n                expect(await parse(\"3+5-2\")()).to.be.Numb(6);\n            });\n    \n            it(\"should execute `*` and `/` with the same precedence\", async () => {\n                expect(await parse(\"10*2/5\")()).to.be.Numb(4);\n                expect(await parse(\"10/2*5\")()).to.be.Numb(25);\n            });\n    \n            it(\"should execute `*` and `/` before `+` and `-`\", async () => {\n                expect(await parse(\"3+2*4\")()).to.be.Numb(11);\n                expect(await parse(\"2*4+3\")()).to.be.Numb(11);\n                expect(await parse(\"8+6/2\")()).to.be.Numb(11);\n                expect(await parse(\"6/2+8\")()).to.be.Numb(11);\n            });\n            \n            it(\"should execute `**` before `*` and `/`\", async () => {\n                expect(await parse(\"3*2**4\")()).to.be.Numb(48);\n                expect(await parse(\"2**4*3\")()).to.be.Numb(48);\n            });            \n        });\n    \n        describe(\"Parenthesis\", () => {\n    \n            it(\"Should execute parenthesis first\", async () => {\n                expect(await parse(\"3*(6-1)\")()).to.be.Numb(15);\n            });            \n        });\n    \n        describe(\"Apply and Subcontexting\", () => {\n    \n            it(\"should execute apply operations before arithmetic operations\", async () => {\n                const context = {fn:x=>2*x, ns:{a:10, b:20, fn:x=>10*x}, ls:[10,20,30]}\n    \n                expect(await parse(\"fn 3+5\")(context)).to.be.Numb(11);\n                expect(await parse(\"fn(3+5)\")(context)).to.be.Numb(16);\n    \n                expect(await parse(\"ls 1 + 1\")(context)).to.be.Numb(21);\n                expect(await parse(\"ls(1+1)\")(context)).to.be.Numb(30);\n    \n                expect(await parse(\"ns 'a' + 1\")(context)).to.be.Numb(11);\n                expect(await parse(\"ns('a'+1)\")(context)).to.be.Undefined('Mapping');                \n            });\n    \n            it(\"should execute subcontexting operations before arithmetic operations\", async () => {\n                const context = {ns:{a:10, b:20, fn:x=>10*x}, b:2}\n                expect(await parse(\"ns.a + b\")(context)).to.be.Numb(12);\n                expect(await parse(\"ns.(a + b)\")(context)).to.be.Numb(30);                \n            });\n    \n            it(\"should execute apply and subcontexting operations with the same precedence\", async () => {\n                const context = {fn:x=>2*x, ns:{a:10, b:20, fn:x=>10*x}, b:2}\n                expect(await parse(\"ns.fn b\")(context)).to.be.Numb(20);\n                expect(await parse(\"ns.(fn b)\")(context)).to.be.Numb(200);\n                expect(await parse(\"fn ns.a\")(context)).to.be.Undefined('SubcontextingOperation');\n                expect(await parse(\"fn(ns.a)\")(context)).to.be.Numb(20);                \n            });\n        });\n    \n        describe(\"Comparison operations\", () => {\n    \n            it(\"should execute comparison operations after arithmetic operations\", async () => {\n                expect(await parse(\"3 + 2 == 1 + 4\")()).to.be.Bool(true);\n                expect(await parse(\"3 + 2 != 1 + 1\")()).to.be.Bool(true);\n                expect(await parse(\"3 + 2 <  5 + 4\")()).to.be.Bool(true);\n                expect(await parse(\"3 + 2 <= 5 + 4\")()).to.be.Bool(true);\n                expect(await parse(\"3 + 7 >  1 + 4\")()).to.be.Bool(true);\n                expect(await parse(\"3 + 2 >= 1 + 4\")()).to.be.Bool(true);\n            });\n    \n            it(\"should execute comparison operations after apply operations\", async () => {\n                const context = {fn2:x=>2*x, fn10:x=>10*x};\n                expect(await parse(\"fn2 10 == fn10 2\")(context)).to.be.Bool(true);\n            });\n    \n            it(\"should execute comparison operations after subcontexting operations\", async () => {\n                const context = {ns:{a:10, b:20}, a:2, b:1};\n                expect(await parse(\"ns . a < ns . b\")(context)).to.be.Bool(true);\n            });\n        });\n    \n        describe(\"Logic operations\", () => {\n    \n            it(\"shoudl execute `|` and `&` with the same precedence\", async () => {\n                expect(await parse(\"1 | 2 & 3  \")()).to.be.Numb(3);\n                expect(await parse(\"1 | (2 & 3)\")()).to.be.Numb(1);\n            });\n    \n            it(\"shoudl execute `?` after `|` and `&`\", async () => {\n                expect(await parse(\"1 | 0 ? 3  \")()).to.be.Numb(3);\n                expect(await parse(\"1 | (0 ? 3)\")()).to.be.Numb(1);\n                expect(await parse(\"1 & 2 ? 3  \")()).to.be.Numb(3);\n            });\n    \n            it(\"shoudl execute `;` after `?`\", async () => {\n                expect(await parse(\"1 ? 2 ; 3 \")()).to.be.Numb(2);\n                expect(await parse(\"0 ? 2 ; 3 \")()).to.be.Numb(3);                \n                expect(await parse(\"1 ; 2 ? 3 \")()).to.be.Numb(1);  \n                expect(await parse(\"(2:2) ; 2 ? 3\")()).to.be.Numb(3);  \n            });\n    \n            it(\"should execute logic operations after comparison operations\", async () => {\n                expect(await parse(\"1 < 2 & 3 > 2 ? 4 ; 5\")()).to.be.Numb(4);\n                expect(await parse(\"1 > 2 | 3 < 2 ? 4 ; 5\")()).to.be.Numb(5);\n            });\n        });\n    \n        describe(\"Function definition\", () => {\n    \n            it(\"should execute after logic operations\", async () => {\n                expect(await parse(\"(x -> x ? 1 ; 2)(10)\")()).to.be.Numb(1);\n                expect(await parse(\"(x -> x ? 1 ; 2)(0) \")()).to.be.Numb(2);\n            });\n    \n            it(\"should be right-associative\", async () => {\n                expect(await parse(\"(x -> y -> x - y)(10)(3)\")()).to.be.Numb(7);\n            });\n        });\n    \n        describe(\"Assignment and labelling operations\", () => {\n    \n            it(\"should execute `:` and `=` with the same precedence\", async () => {\n                const context = {};\n                expect(await parse(\"x = y : 10\")()).to.be.Undefined(\"LabellingOperation\");\n                expect(await parse(\"x = (y : 10)\")(context)).to.be.Tuple([]);\n                expect(context.x).to.equal(10);\n                expect(context.y).to.equal(10);\n            });\n    \n            it(\"should execute `:` and `=` after function definitions\", async () => {\n                const context = {};\n    \n                await parse(\"f : x -> 2 * x\")(context);\n                expect(await context.f(2)).to.be.Numb(4);\n    \n                await parse(\"g = x -> 3 * x\")(context);\n                expect(await context.g(2)).to.be.Numb(6);\n            });\n        });\n    \n        describe(\"Pairing operation\", () => {\n    \n            it(\"should always be executed with lowest priority\", async () => {\n                const context = {};\n                await parse(\"x = 1 , y = 2\")(context);\n                expect(context.x).to.equal(1);\n                expect(context.y).to.equal(2);\n            });\n        });\n    });\n    \n    describe(\"parsing errors\", () => {\n    \n        // Lexer Errors\n    \n        it(\"should throw a Syntax Error on missing closing quote\", async () => {\n            try {\n                parse(\"\\n'abc\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Closing quote expected @2:4\")\n            }\n        });\n    \n        it(\"should throw a Syntax Error on missing numeric literal exponent\", async () => {\n            try {\n                parse(\"123E+\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Expected exponent value @1:5\");\n            }\n        });\n    \n        it(\"should throw a Syntax Error on invalid numeric literal\", async () => {\n            try {\n                parse(\"1abc\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Invalid number @1:0\");\n            }\n        });\n    \n        it(\"should throw a Syntax Error on unexpected period\", async () => {\n            try {\n                parse(\"12.34.56\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Unexpected period @1:5\");\n            }\n        });\n    \n        it(\"should throw a Syntax Error on invalid identifier\", async () => {\n            try {\n                parse(\"$a\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Unexpected character '$' @1:0\");\n            }\n        });\n    \n    \n        // Parsing Errors\n    \n        it(\"should throw a Syntax Error on missing operand\", async () => {\n            try {\n                parse(\"125 +\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Operand expected @1:5\");\n            }\n\n            try {\n                parse(\"(125 +\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Operand expected @1:6\");\n            }\n            \n            try {\n                parse(\"125 + *\")\n                throw new Error(\"It didn not throw!\");\n            } catch (e) {\n                expect(e.message).to.equal(\"Operand expected @1:6\");\n            }\n        });\n    });\n    \n    describe(\"Undefined Operation\", () => {\n        \n        it(\"Should contain the source position of the undefined operation\", async () => {\n            const source = \"{} - []\";\n            const undef = await parse(\"{} - []\")();\n            expect(undef).to.be.Undefined(\"SubOperation\");\n            expect(undef.position).to.deep.equal({\n                source: source,\n                index: 3\n            })\n        });\n    });\n});\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/interpreter.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/modules/debug.js":
  /*!*******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/modules/debug.js ***!
    \*******************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ../expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst types = __webpack_require__(/*! ../../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst parse = __webpack_require__(/*! ../../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst debug = __webpack_require__(/*! ../../lib/modules/debug */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/debug.js\")(types);\n\nconst evaluate = async (expression, presets={}) => {\n    const context = Object.assign({debug}, presets);\n    return await parse(expression)(context);\n}\n\n\ndescribe(\"debug module\", function () {\n    \n    describe(\"debug.log\", () => {\n        var jslog, logId, logged;\n        \n        before(() => {\n            jslog = console.log;\n            console.log = (id, value) => {\n                logId = id;\n                logged = value;\n            }\n        });\n        \n        it(\"should log the passed arguments to the console\", async () => {\n            await evaluate(\"debug.log(1,'abc',[1,2,3],{a:1})\");            \n            expect(logId).to.equal(\"Log 1:\");\n            expect(logged).to.be.Tuple([1,'abc',[1,2,3],{a:1}]);\n\n            await evaluate(\"debug.log(11)\");            \n            expect(logId).to.equal(\"Log 2:\");\n            expect(logged).to.be.Numb(11);\n        });\n        \n        it(\"should return the log number\", async () => {\n            expect(await evaluate(\"debug.log(1,'abc',[1,2,3],{a:1})\")).to.be.Text(\"[[Log 3]]\");\n        });\n        \n        after(() => {\n            console.log = jslog;\n        });\n    });\n    \n    describe(\"debug.inspect\", () => {\n        \n        describe(\"when the argument is a Bool\", () => {\n            \n            it(\"should return an object with type and value\", async () => {\n                expect(await evaluate(\"debug.inspect(1==1)\")).to.be.Namespace({\n                    type: \"Bool\",\n                    value: true\n                })\n            });\n        });\n        \n        describe(\"when the argument is a Numb\", () => {\n            \n            it(\"should return an object with type and value\", async () => {\n                expect(await evaluate(\"debug.inspect 123\")).to.be.Namespace({\n                    type: \"Numb\",\n                    value: 123\n                })\n            });            \n        });\n        \n        describe(\"when the argument is a Text\", () => {\n            \n            it(\"should return an object with type and value\", async () => {\n                expect(await evaluate(\"debug.inspect 'abc'\")).to.be.Namespace({\n                    type: \"Text\",\n                    value: \"abc\"\n                })\n            });            \n        });\n        \n        describe(\"when the argument is a List\", () => {\n\n            it(\"should return an object with type and an array of inspection info as value\", async () => {\n                expect(await evaluate(\"debug.inspect [1, 'abc', 2]\")).to.be.Namespace({\n                    type: \"List\",\n                    value: [\n                        {type:\"Numb\", value:1},\n                        {type:\"Text\", value:\"abc\"},\n                        {type:\"Numb\", value:2}\n                    ]\n                })\n            });                        \n        });\n        \n        describe(\"when the argument is a Namespace\", () => {\n            \n            it(\"should return an object with type and an mapping of inspection info as value\", async () => {\n                expect(await evaluate(\"debug.inspect {a:1, b:2, c:3}\")).to.be.Namespace({\n                    type: \"Namespace\",\n                    value: {\n                        a: {type:\"Numb\", value:1},\n                        b: {type:\"Numb\", value:2},\n                        c: {type:\"Numb\", value:3}\n                    }\n                })\n            });                                    \n        });\n        \n        describe(\"when the argument is a Func\", () => {\n            \n            it(\"should return an object with type='Func'\", async () => {\n                expect(await evaluate(\"debug.inspect(x->x)\")).to.be.Namespace({\n                    type: \"Func\",\n                })\n            });                                    \n        });\n        \n        describe(\"when the argument is a Tuple\", () => {\n            \n            it(\"should return an object with type and an array of inspection info as value\", async () => {\n                expect(await evaluate(\"debug.inspect(1, 2, 3)\")).to.be.Namespace({\n                    type: \"Tuple\",\n                    value: [\n                        {type:\"Numb\", value:1},\n                        {type:\"Numb\", value:2},\n                        {type:\"Numb\", value:3}\n                    ]\n                })\n            });                        \n\n            it(\"should return an the first item inspection info if it is made of one item only\", async () => {\n                expect(await evaluate(\"debug.inspect(10, ())\")).to.be.Namespace({\n                    type: \"Numb\",\n                    value: 10\n                })\n            });                        \n\n            it(\"should return the object {type:'Nothing'} if it is an empty tuple\", async () => {\n                expect(await evaluate(\"debug.inspect()\")).to.be.Namespace({\n                    type: \"Nothing\"\n                })\n            });                        \n        });\n        \n        describe(\"when the argument is an Undefined term\", () => {\n            \n            it(\"should return the info object {Text type, Text operation, List arguments}\", async () => {\n                const presets = {undefined: (type, ...args) => new types.Undefined(type, ...args)};\n                expect(await evaluate(\"debug.inspect(undefined('DummyOp', 1, 2))\", presets)).to.be.Namespace({\n                    type: \"Undefined\",\n                    operation: \"DummyOp\",\n                    arguments: [\n                        {type:\"Numb\", value:1},\n                        {type:\"Numb\", value:2},\n                    ]\n                })\n            });            \n\n            it(\"should return the info object containing also {Text source, Numb position} if the Undefined item contains a position\", async () => {\n                expect(await evaluate(`debug.inspect(\n                        unknown_func())\n                        `)).to.be.Namespace({\n                    type: \"Undefined\",\n                    operation: \"ApplyOperation\",\n                    arguments: [\n                        {\n                            type: \"Undefined\",\n                            operation: \"NameReference\",\n                            arguments: [\n                                {type:'Text', value:\"unknown_func\"}\n                            ],\n                            source: \"                        unknown_func())\",\n                            position: 36\n                        },\n                        {type:\"Nothing\"}\n                    ],\n                    source: \"                        unknown_func())\",\n                    position: 36\n                })\n            });            \n        });\n    });\n});\n\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/modules/debug.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/modules/json.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/modules/json.js ***!
    \******************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ../expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst types = __webpack_require__(/*! ../../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst parse = __webpack_require__(/*! ../../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst json = __webpack_require__(/*! ../../lib/modules/json */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/json.js\")(types);\n\nconst evaluate = async (expression, presets={}) => {\n    const context = Object.assign({json}, presets);\n    return await parse(expression)(context);\n}\n\n\n\ndescribe(\"json module\", () => {\n\n    describe(\"json.parse: Text t -> Namespace ns\", () => {\n        \n        it(\"should return the the Namespace represented by the JSON string t\", async () => {\n            const ns = {n:10, s:\"abc\", ls:[1,2,3], ns:{y:20}};\n            const t = JSON.stringify(ns)\n            expect(await evaluate(`json.parse '`+t+`'`)).to.be.Namespace(ns);\n        });        \n    });    \n\n    describe(\"json.parse: Text t -> Namespace ns\", () => {\n        \n        it(\"should return the the JSON string representing the given term\", async () => {\n            const ns = {n:10, s:\"abc\", ns:{y:20}};\n            const t = await evaluate(`json.serialize ns`, {ns});\n            expect(JSON.parse(t)).to.deep.equal(ns);\n            \n            const tf = `{\\n` +\n                       `  \"n\": 10,\\n` +\n                       `  \"s\": \"abc\",\\n` +\n                       `  \"ns\": {\\n` +\n                       `    \"y\": 20\\n` +\n                       `  }\\n` +\n                       `}`;\n            expect(await evaluate(`json.serialize ns`, {ns})).to.be.Text(tf);\n        });        \n        \n        it(\"should return Undefined Text if t is a Func or an Undefined item\", async () => {\n            expect(await evaluate(\"json.serialize(x->x)\")).to.be.Undefined('Text');\n            expect(await evaluate(\"json.serialize(1/[])\")).to.be.Undefined('Text');\n        });\n        \n        it(\"should return a Tuple of strings if t is a tuple\", async () => {\n            expect(await evaluate(\"json.serialize(10,[],{})\")).to.be.Tuple([\n                \"10\", \"[]\", \"{}\"\n            ]);\n            expect(await evaluate(\"json.serialize()\")).to.be.Tuple([]);            \n        });\n    });    \n});\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/modules/json.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/modules/list.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/modules/list.js ***!
    \******************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ../expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst types = __webpack_require__(/*! ../../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst parse = __webpack_require__(/*! ../../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst list = __webpack_require__(/*! ../../lib/modules/list */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/list.js\")(types);\n\nconst evaluate = async (expression, presets={}) => {\n    const context = Object.assign({list}, presets);\n    return await parse(expression)(context);\n}\n\n\n\ndescribe(\"list module\", () => {\n\n    describe(\"L2 = list.reverse L1\", () => {\n\n        it(\"should return a new array with the items of L in reversed order\", async () => {\n            expect(await evaluate(\"list.reverse [1,2,3]\")).to.be.List([3,2,1]);\n        });\n        \n        it(\"should return Undefined List if the argument is not a List\", async () => {\n            expect(await evaluate(\"list.reverse 123\")).to.be.Undefined(\"List\");\n        });\n\n        it(\"should apply only to the first item, if the parameter is a tuple\", async () => {\n            expect(await evaluate(\"list.reverse([1,2,3],[4,5,6])\")).to.be.List([3,2,1]);\n        });                        \n    });\n\n    describe(\"f = list.find x\", () => {\n        \n        describe(\"when the argument is an item\", () => {\n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"list.find 123\")).to.be.instanceof(types.Func);\n            });\n\n            describe(\"i = f L \", () => {\n\n                it(\"should return the first index of x in L\", async () => {\n                    expect(await evaluate(\"list.find 20 [10,20,30,20,10]\")).to.be.Numb(1);\n                });\n\n                it(\"should return -1 if no match is found\", async () => {\n                    expect(await evaluate(\"list.find 10 [1,2,3]\")).to.be.Numb(-1);\n                });\n\n                it(\"should return Undefined Number if `L` is not a list\", async () => {\n                    expect(await evaluate(\"list.find 'abc' 10\")).to.be.Undefined(\"Number\");\n                });\n\n                it(\"should apply only to the first item, if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"list.find 7 ([1,7,8,7,5], [6,8,8,7,7])\")).to.be.Numb(1);\n                });\n            });\n        });\n\n        describe(\"when the argument is a tuple\", () => {\n            \n            it(\"should apply only to the first item\", async () => {\n                const F = await evaluate(\"list.find(10,20)\");\n                expect(F).to.be.instanceof(types.Func);\n                expect(await evaluate(\"list.find(8,2) [1,8,2,2]\")).to.be.Numb(1);\n                expect(await evaluate(\"list.find(8,2)([1,8,2,2], [0,1,8,1])\")).to.be.Numb(1);\n            });\n        });    \n    });    \n\n    describe(\"f = list.rfind s1\", () => {\n    \n        describe(\"when s1 is an item\", () => {\n    \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"list.rfind 123\")).to.be.instanceof(types.Func);\n            });\n    \n            describe(\"i = f L \", () => {\n    \n                it(\"should return the las index of x in L\", async () => {\n                    expect(await evaluate(\"list.rfind 20 [10,20,30,20,10]\")).to.be.Numb(3);\n                });\n    \n                it(\"should return -1 if no match is found\", async () => {\n                    expect(await evaluate(\"list.rfind 10 [1,2,3]\")).to.be.Numb(-1);\n                });\n    \n                it(\"should return Undefined Number if `L` is not a list\", async () => {\n                    expect(await evaluate(\"list.rfind 'abc' 10\")).to.be.Undefined(\"Number\");\n                });\n    \n                it(\"should apply only to the first item, if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"list.rfind 7 ([1,7,8,7,5], [6,8,8,7,7])\")).to.be.Numb(3);\n                });\n            });\n        });\n    \n        describe(\"when the argument is a tuple\", () => {\n    \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"list.rfind(10,20)\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"list.rfind(1,2) [1,1,2,2]\")).to.be.Numb(1);\n                expect(await evaluate(\"list.rfind(1,2)([1,1,2,2], [0,1,0,1])\")).to.be.Numb(1);                    \n            });\n        });    \n    });    \n    \n    describe(\"f = list.head n\", () => {\n    \n        describe(\"when n is an item\", () => {\n    \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"list.head 3\")).to.be.instanceof(types.Func);\n            });\n    \n            describe(\"l = f L \", () => {\n    \n                it(\"should return the first n items of L\", async () => {\n                    expect(await evaluate(\"list.head 3 [1,2,3,4,5,6]\")).to.be.List([1,2,3]);\n                });\n    \n                it(\"should consider negative indices as relative to the end of the list\", async () => {\n                    expect(await evaluate(\"list.head (-2) [1,2,3,4,5,6]\")).to.be.List([1,2,3,4]);\n                });\n    \n                it(\"should return Undefined List if `n` is not a number\", async () => {\n                    expect(await evaluate(\"list.head 'abc'\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"list.head 'abc' [1,2,3]\")).to.be.Undefined(\"List\");\n                });\n    \n                it(\"should return Undefined List if `L` is not a List item\", async () => {\n                    expect(await evaluate(\"list.head 3 10\")).to.be.Undefined(\"List\");\n                });\n    \n                it(\"should apply only to the first item, if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"list.head 2 ([1,2,3], [4,5,6])\")).to.be.List([1,2]);\n                });\n            });\n        });\n    \n        describe(\"when the argument is a tuple\", () => {\n    \n            it(\"should return one `f` function for each item of the argument\", async () => {\n                expect(await evaluate(\"list.head(2,3)\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"list.head(2,3) [1,2,3,4]\")).to.be.List([1,2]);\n                expect(await evaluate(\"list.head(2,3)([1,2,3,4],[5,6,7,8])\")).to.be.List([1,2]);\n            });\n        });    \n    });              \n    \n    describe(\"f = list.tail n\", () => {\n    \n        describe(\"when n is an item\", () => {\n    \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"list.tail 3\")).to.be.instanceof(types.Func);\n            });\n    \n            describe(\"l = f L \", () => {\n    \n                it(\"should return the last items of L, starting with the n-th\", async () => {\n                    expect(await evaluate(\"list.tail 2 [1,2,3,4,5,6]\")).to.be.List([3,4,5,6]);\n                });\n    \n                it(\"should consider negative indices as relative to the end of the list\", async () => {\n                    expect(await evaluate(\"list.tail (-2) [1,2,3,4,5,6]\")).to.be.List([5,6]);\n                });\n    \n                it(\"should return Undefined List if `n` is not a number\", async () => {\n                    expect(await evaluate(\"list.tail 'abc'\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"list.tail 'abc' [1,2,3]\")).to.be.Undefined(\"List\");\n                });\n    \n                it(\"should return Undefined List if `L` is not a List item\", async () => {\n                    expect(await evaluate(\"list.tail 3 10\")).to.be.Undefined(\"List\");\n                });\n    \n                it(\"should apply only to the first item, if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"list.tail (-2) ([1,2,3], [4,5,6])\")).to.be.List([2,3]);\n                });\n            });\n        });\n    \n        describe(\"when the argument is a tuple\", () => {\n    \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"list.tail(2,3)\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"list.tail(-2,-3) [1,2,3,4]\")).to.be.List([3,4]);\n                expect(await evaluate(\"list.tail(-2,-3)([1,2,3,4],[5,6,7,8])\")).to.be.List([3,4]);                    \n            });\n        });    \n    });              \n    \n    describe(\"f = list.join s\", () => {\n    \n        describe(\"when s is an item\", () => {\n    \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"list.join ':'\")).to.be.instanceof(types.Func);\n            });\n    \n            describe(\"S = f L \", () => {\n    \n                it(\"should concatenate the text items of L with interposed separator s\", async () => {\n                    expect(await evaluate(\"list.join ':' ['aa','bb','cc']\")).to.be.Text(\"aa:bb:cc\");\n                });\n    \n                it(\"should return Undefined Text if `s` is not a Text item\", async () => {\n                    expect(await evaluate(\"list.join 10\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"list.join 10 ['a','b','c']\")).to.be.Undefined(\"Text\");\n                });\n    \n                it(\"should return Undefined Text if any item of `L` is not a Text item\", async () => {\n                    expect(await evaluate(\"list.join ':' ['a',1,'b']\")).to.be.Undefined(\"Text\");\n                });\n    \n                it(\"should apply only to the first item, if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"list.join ':' (['a','b'],['c','d'])\")).to.be.Text(\"a:b\");\n                });\n            });\n        });\n    \n        describe(\"when the argument is a tuple\", () => {\n    \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"list.join(':','~')\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"list.join(':','~') ['a','b']\")).to.be.Text(\"a:b\");\n                expect(await evaluate(\"list.join(':','~')(['a','b'],['c','d'])\")).to.be.Text(\"a:b\");                    \n            });\n        });    \n    });              \n});\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/modules/list.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/modules/numb.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/modules/numb.js ***!
    \******************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ../expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst types = __webpack_require__(/*! ../../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst parse = __webpack_require__(/*! ../../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst numb = __webpack_require__(/*! ../../lib/modules/numb */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/numb.js\")(types);\n\nconst evaluate = async (expression, presets={}) => {\n    const context = Object.assign({numb}, presets);\n    return await parse(expression)(context);\n}\n\n\n\ndescribe(\"numb module\", () => {\n\n    describe(\"numb.INFINITY - constant\", () => {\n        it(\"should return Infinity wrapped as a Numb\", async () => {\n            expect(await evaluate(\"numb.INFINITY\")).to.be.Numb(Infinity);\n        });\n    });\n\n    describe(\"numb.E - contant\", () => {\n        it(\"should return the Euler's number\", async () => {\n            expect(await evaluate(\"numb.E\")).to.be.Numb(Math.E);\n        });\n    });\n\n    describe(\"numb.PI - constant\", () => {\n        it(\"should return the Pi number\", async () => {\n            expect(await evaluate(\"numb.PI\")).to.be.Numb(Math.PI);\n        });\n    });\n    \n    describe(\"numb.parse - function\", () => {\n        \n        it(\"should convert a string representation of a number to a number\", async () => {\n            expect(await evaluate(\"numb.parse '12'\")).to.be.Numb(12);\n            expect(await evaluate(\"numb.parse '-12e1'\")).to.be.Numb(-120);\n            expect(await evaluate(\"numb.parse '0b11'\")).to.be.Numb(3);\n            expect(await evaluate(\"numb.parse '0o33'\")).to.be.Numb(27);\n            expect(await evaluate(\"numb.parse '0xA2'\")).to.be.Numb(162);\n        });\n        \n        it(\"should return Undefined Number if the argument is not a valid string\", async () => {\n            expect(await evaluate(\"numb.parse 'abc'\")).to.be.Undefined(\"Number\");\n            expect(await evaluate(\"numb.parse 10\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.parse('10', '0b11', '0o33')\")).to.be.Numb(10);\n        });            \n    });\n\n    describe(\"numb.abs - function\", () => {\n        \n        it(\"should return the absolute value of a number\", async () => {\n            expect(await evaluate(\"numb.abs(-123.45)\")).to.be.Numb(123.45);\n            expect(await evaluate(\"numb.abs 0\")).to.be.Numb(0);\n            expect(await evaluate(\"numb.abs 123.45\")).to.be.Numb(123.45);\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.abs 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.abs(-1, 0, 1)\")).to.be.Numb(1);\n        });            \n    });\n\n    describe(\"numb.acos - function\", () => {\n\n        it(\"should return the arc-cosine of a number\", async () => {\n            expect(await evaluate(\"numb.acos 0.5\")).to.be.Numb(Math.acos(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.acos 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.acos(0.5, 0.6, 1)\")).to.be.Numb(Math.acos(0.5));\n        });            \n    });\n\n    describe(\"numb.acosh - function\", () => {\n        \n        it(\"should return the hyperbolic arc-cosine of a number\", async () => {\n            expect(await evaluate(\"numb.acosh 1.5\")).to.be.Numb(Math.acosh(1.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.acosh 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.acosh(1, 1.5, 2)\")).to.be.Numb(Math.acosh(1));\n        });            \n    });\n\n    describe(\"numb.asin - function\", () => {\n        \n        it(\"should return the arc-sine of a number\", async () => {\n            expect(await evaluate(\"numb.asin 0.5\")).to.be.Numb(Math.asin(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.asin 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.asin(0.4, 0.5, 1)\")).to.be.Numb(Math.asin(0.4));\n        });            \n    });\n\n    describe(\"numb.asinh - function\", () => {\n        \n        it(\"should return the hyperbolic arc-sine of a number\", async () => {\n            expect(await evaluate(\"numb.asinh 0.5\")).to.be.Numb(Math.asinh(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.asinh 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.asinh(0.4, 0.5, 1)\")).to.be.Numb(Math.asinh(0.4));\n        });            \n    });\n\n    describe(\"numb.atan - function\", () => {\n        \n        it(\"should return the arc-tangent of a number\", async () => {\n            expect(await evaluate(\"numb.atan 0.5\")).to.be.Numb(Math.atan(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.atan 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.atan(0.4, 0.5, 1)\")).to.be.Numb(Math.atan(0.4));\n        });            \n    });\n\n    describe(\"numb.atanh - function\", () => {\n        \n        it(\"should return the hyperbolic arc-tangent of a number\", async () => {\n            expect(await evaluate(\"numb.atanh 0.5\")).to.be.Numb(Math.atanh(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.atanh 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.atanh(0.4, 0.5, 1)\")).to.be.Numb(Math.atanh(0.4));\n        });            \n    });\n\n    describe(\"numb.ceil - function\", () => {\n        \n        it(\"should round up a number to the closest largest integer\", async () => {\n            expect(await evaluate(\"numb.ceil 12.345  \")).to.be.Numb(13);\n            expect(await evaluate(\"numb.ceil(-12.345)\")).to.be.Numb(-12);\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.ceil 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.ceil(12.3,1.4,2.1)\")).to.be.Numb(13);\n        });            \n    });\n\n    describe(\"numb.cos - function\", () => {\n        \n        it(\"should return the cosine of a number\", async () => {\n            expect(await evaluate(\"numb.cos 0.5\")).to.be.Numb(Math.cos(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.cos 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.cos(0.4, 0.5, 1)\")).to.be.Numb(Math.cos(0.4));\n        });            \n    });\n\n    describe(\"numb.cosh - function\", () => {\n        \n        it(\"should return the hyperbolic cosine of a number\", async () => {\n            expect(await evaluate(\"numb.cosh 0.5\")).to.be.Numb(Math.cosh(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.cosh 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.cosh(0.4, 0.5, 1)\")).to.be.Numb(Math.cosh(0.4));\n        });            \n    });\n\n    describe(\"numb.exp - function\", () => {\n        \n        it(\"should return the exponential of a number\", async () => {\n            expect(await evaluate(\"numb.exp 0.5\")).to.be.Numb(Math.exp(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.exp 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.exp(0.4, 0.5, 1)\")).to.be.Numb(Math.exp(0.4));\n        });            \n    });\n\n    describe(\"numb.floor - function\", () => {\n        \n        it(\"should round up a number to the closest smallest integer\", async () => {\n            expect(await evaluate(\"numb.floor 12.345  \")).to.be.Numb(12);\n            expect(await evaluate(\"numb.floor(-12.345)\")).to.be.Numb(-13);\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.floor 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.floor(12.3,1.4,2.1)\")).to.be.Numb(12);\n        });            \n    });\n\n    describe(\"numb.log - function\", () => {\n\n        it(\"should return the natural logarithm of a number\", async () => {\n            expect(await evaluate(\"numb.log 0.5\")).to.be.Numb(Math.log(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.log 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.log(0.1, 0.5, 1)\")).to.be.Numb(Math.log(0.1));\n        });            \n    });\n\n    describe(\"numb.log10 - function\", () => {\n\n        it(\"should return the base-10 logarithm of a number\", async () => {\n            expect(await evaluate(\"numb.log10 0.5\")).to.be.Numb(Math.log10(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.log10 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.log10(0.1, 0.5, 1)\")).to.be.Numb(Math.log10(0.1));\n        });            \n    });\n\n    describe(\"numb.max - function\", () => {\n        \n        it(\"should return the maximum of a list of numbers\", async () => {\n            expect(await evaluate(\"numb.max(23,1,13,56,22,-108)\")).to.be.Numb(56);\n        });\n        \n        it(\"should return Undefined Number if any of the arguments is not a number\", async () => {\n            expect(await evaluate(\"numb.max(23,1,'xxx',56,22,-108)\")).to.be.Undefined(\"Number\");\n        });\n    });\n\n    describe(\"numb.min - function\", () => {\n        \n        it(\"should return the maximum of a list of numbers\", async () => {\n            expect(await evaluate(\"numb.min(23,1,13,56,22,-108)\")).to.be.Numb(-108);\n        });\n        \n        it(\"should return Undefined Number if any of the arguments is not a number\", async () => {\n            expect(await evaluate(\"numb.min(23,1,'xxx',56,22,-108)\")).to.be.Undefined(\"Number\");\n        });\n    });\n\n    describe(\"numb.random - function\", () => {\n        it(\"should return a random number between 0 and x\", async () => {\n            \n            const item1 = await evaluate(\"numb.random 2\");\n            expect(item1).to.be.instanceof(types.Numb);\n            const value1 = item1.unwrap();\n            expect(0 <= value1 && value1 <= 2).to.be.true;\n            \n            const value2 = types.unwrap(await evaluate(\"numb.random 2\"));\n            const value3 = types.unwrap(await evaluate(\"numb.random 2\"));\n            expect(value1).to.not.equal(value2);\n            expect(value1).to.not.equal(value3);\n            expect(value2).to.not.equal(value3);\n        });\n\n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.random 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            const item1 = await evaluate(\"numb.random(2,5,7)\");\n            expect(item1).to.be.instanceof(types.Numb);\n            const value1 = item1.unwrap();\n            expect(0 <= value1 && value1 <= 2).to.be.true;\n            \n            const value2 = types.unwrap(await evaluate(\"numb.random(2,5,7)\"));\n            const value3 = types.unwrap(await evaluate(\"numb.random(2,5,7)\"));\n            expect(value1).to.not.equal(value2);\n            expect(value1).to.not.equal(value3);\n            expect(value2).to.not.equal(value3);\n        });            \n    });\n\n    describe(\"numb.round - function\", () => {\n        \n        it(\"should round the given number to the closest integer\", async () => {\n\n            expect(await evaluate(\"numb.round 12.345\")).to.be.Numb(12);\n            expect(await evaluate(\"numb.round 6.789 \")).to.be.Numb(7);\n            expect(await evaluate(\"numb.round 10.5  \")).to.be.Numb(11);\n\n            expect(await evaluate(\"numb.round(-12.345)\")).to.be.Numb(-12);\n            expect(await evaluate(\"numb.round(-6.789) \")).to.be.Numb(-7);\n            expect(await evaluate(\"numb.round(-10.5)  \")).to.be.Numb(-10);\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.round 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.round(12.3,1.6,2.5)\")).to.be.Numb(12);\n        });            \n    });\n\n    describe(\"numb.sin - function\", () => {\n        \n        it(\"should return the sine of a number\", async () => {\n            expect(await evaluate(\"numb.sin 0.5\")).to.be.Numb(Math.sin(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.sin 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.sin(0.4, 0.5, 1)\")).to.be.Numb(Math.sin(0.4));\n        });            \n    });\n\n    describe(\"numb.sinh - function\", () => {\n        \n        it(\"should return the hyperbolic sine of a number\", async () => {\n            expect(await evaluate(\"numb.sinh 0.5\")).to.be.Numb(Math.sinh(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.sinh 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.sinh(0.4, 0.5, 1)\")).to.be.Numb(Math.sinh(0.4));\n        });            \n    });\n\n    describe(\"numb.sqrt - function\", () => {\n        \n        it(\"should return the sine of a number\", async () => {\n            expect(await evaluate(\"numb.sqrt 4   \")).to.be.Numb(2);\n            expect(await evaluate(\"numb.sqrt 34.5\")).to.be.Numb(34.5**0.5);\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.sqrt 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.sqrt(4, 9, 160)\")).to.be.Numb(2);\n            expect(await evaluate(\"numb.sqrt(4, 9, 'x')\")).to.be.Numb(2);\n        });                        \n    });\n\n    describe(\"numb.tan - function\", () => {\n        \n        it(\"should return the tangent of a number\", async () => {\n            expect(await evaluate(\"numb.tan 0.5\")).to.be.Numb(Math.tan(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.tan 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.tan(0.4, 0.5, 1)\")).to.be.Numb(Math.tan(0.4));\n        });            \n    });\n\n    describe(\"numb.tanh - function\", () => {\n        \n        it(\"should return the hyperbolic tangent of a number\", async () => {\n            expect(await evaluate(\"numb.tanh 0.5\")).to.be.Numb(Math.tanh(0.5));\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.tanh 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.tanh(0.4, 0.5, 1)\")).to.be.Numb(Math.tanh(0.4));\n        });            \n    });\n\n    describe(\"numb.trunc - function\", () => {\n        \n        it(\"should return the integer part of a number\", async () => {\n\n            expect(await evaluate(\"numb.trunc 12.345\")).to.be.Numb(12);\n            expect(await evaluate(\"numb.trunc 6.789 \")).to.be.Numb(6);\n            expect(await evaluate(\"numb.trunc 10.5  \")).to.be.Numb(10);\n\n            expect(await evaluate(\"numb.trunc(-12.345)\")).to.be.Numb(-12);\n            expect(await evaluate(\"numb.trunc(-6.789) \")).to.be.Numb(-6);\n            expect(await evaluate(\"numb.trunc(-10.5)  \")).to.be.Numb(-10);\n        });\n        \n        it(\"should return Undefined Number if the argument is not a number\", async () => {\n            expect(await evaluate(\"numb.trunc 'abc'\")).to.be.Undefined(\"Number\");\n        });\n\n        it(\"should apply the first item only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"numb.trunc(12.3,1.6,2.5)\")).to.be.Numb(12);\n        });            \n    });\n});\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/modules/numb.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/modules/text.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/modules/text.js ***!
    \******************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ../expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst types = __webpack_require__(/*! ../../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst parse = __webpack_require__(/*! ../../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst text = __webpack_require__(/*! ../../lib/modules/text */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/text.js\")(types);\n\nconst evaluate = async (expression, presets={}) => {\n    const context = Object.assign({text}, presets);\n    return await parse(expression)(context);\n}\n\n\n\ndescribe(\"text module\", () => {\n\n    describe(\"f = text.find s1\", () => {\n        \n        describe(\"when s1 is an item\", () => {\n            \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"text.find 'Abc'\")).to.be.instanceof(types.Func);\n            });\n\n            describe(\"i = f s2 \", () => {\n    \n                it(\"should return the first index of s1 in s2\", async () => {\n                    expect(await evaluate(\"text.find 'Abc' '__Abc__def__Abc'\")).to.be.Numb(2);\n                });\n    \n                it(\"should return -1 if no match is found\", async () => {\n                    expect(await evaluate(\"text.find 'xxx' '__Abc__def__Abc'\")).to.be.Numb(-1);\n                });\n    \n                it(\"should return Undefined Number if `s1` is not a string\", async () => {\n                    expect(await evaluate(\"text.find 10\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"text.find 10 'abc'\")).to.be.Undefined(\"Number\");\n                });\n\n                it(\"should return Undefined Number if `s2` is not a string\", async () => {\n                    expect(await evaluate(\"text.find 'abc' 10\")).to.be.Undefined(\"Number\");\n                });\n\n                it(\"should apply only to the first item if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"text.find 'Abc' ('__Abc__def__Abc', '01234Abc__')\")).to.be.Numb(2);\n                });\n            });\n        });\n\n        describe(\"when the argument is a tuple\", () => {\n            \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"text.find('Abc','Def')\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"text.find('Abc','Def') '__Abc__def__Def'\")).to.be.Numb(2);\n                expect(await evaluate(\"text.find('Abc','Def')('__Abc__Def__Abc', '01234Abc__')\")).to.be.Numb(2);                    \n            });\n        });    \n    });    \n\n    describe(\"f = text.rfind s1\", () => {\n        \n        describe(\"when s1 is an item\", () => {\n            \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"text.rfind 'Abc'\")).to.be.instanceof(types.Func);\n            });\n\n            describe(\"i = f s2 \", () => {\n    \n                it(\"should return the last index of s1 in s2\", async () => {\n                    expect(await evaluate(\"text.rfind 'Abc' '__Abc__def__Abc'\")).to.be.Numb(12);\n                });\n    \n                it(\"should return -1 if no match is found\", async () => {\n                    expect(await evaluate(\"text.rfind 'xxx' '__Abc__def__Abc'\")).to.be.Numb(-1);\n                });\n    \n                it(\"should return Undefined Number if `s1` is not a string\", async () => {\n                    expect(await evaluate(\"text.rfind 10\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"text.rfind 10 'abc'\")).to.be.Undefined(\"Number\");\n                });\n\n                it(\"should return Undefined Number if `s2` is not a string\", async () => {\n                    expect(await evaluate(\"text.rfind 'abc' 10\")).to.be.Undefined(\"Number\");\n                });\n\n                it(\"should apply only to the first item if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"text.rfind 'Abc' ('__Abc__def__Abc', '01234Abc__')\")).to.be.Numb(12);\n                });\n            });\n        });\n\n        describe(\"when the argument is a tuple\", () => {\n            \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"text.rfind('Abc','Def')\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"text.rfind('Abc','Def') '__Abc__Def__Abc'\")).to.be.Numb(12);\n                expect(await evaluate(\"text.rfind('Abc','Def')('__Abc__Def__Abc', '01234Abc__')\")).to.be.Numb(12);\n            });\n        });    \n    });    \n\n    describe(\"text.lower - function\", () => {\n\n        it(\"should return the given string converted to lower case characters\", async () => {\n            expect(await evaluate(\"text.lower 'AbcDef'\")).to.be.Text(\"abcdef\");\n        });\n        \n        it(\"should return Undefined Text if the argument is not a string\", async () => {\n            expect(await evaluate(\"text.lower 123\")).to.be.Undefined(\"Text\");\n        });\n\n        it(\"should apply to the first items only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"text.lower('ABC','Def')\")).to.be.Text(\"abc\");\n        });                        \n    });    \n\n    describe(\"text.upper - function\", () => {\n\n        it(\"should return the given string converted to lower case characters\", async () => {\n            expect(await evaluate(\"text.upper 'AbcDef'\")).to.be.Text(\"ABCDEF\");\n        });\n        \n        it(\"should return Undefined Text if the argument is not a string\", async () => {\n            expect(await evaluate(\"text.upper 123\")).to.be.Undefined(\"Text\");\n        });\n\n        it(\"should apply to the first items only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"text.upper('abc','Def')\")).to.be.Text(\"ABC\");\n        });                        \n    });    \n\n    describe(\"s2 = text.trim_head s1\", () => {\n        \n        it(\"should return `s1` without leading spaces\", async () => {\n            expect(await evaluate(\"text.trim_head '   abc   '\")).to.be.Text(\"abc   \");\n        });\n        \n        it(\"should return Undefined Text if the argument is not a string\", async () => {\n            expect(await evaluate(\"text.trim_head 123\")).to.be.Undefined(\"Text\");\n        });\n\n        it(\"should apply to the first items only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"text.trim_head(' abc ',' Def ')\")).to.be.Text(\"abc \");\n        });                        \n    });   \n\n    describe(\"s2 = text.trim_tail s1\", () => {\n        \n        it(\"should return `s1` without trailing spaces\", async () => {\n            expect(await evaluate(\"text.trim_tail '   abc   '\")).to.be.Text(\"   abc\");\n        });\n        \n        it(\"should return Undefined Text if the argument is not a string\", async () => {\n            expect(await evaluate(\"text.trim_tail 123\")).to.be.Undefined(\"Text\");\n        });\n\n        it(\"should apply to the first items only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"text.trim_tail(' abc ',' Def ')\")).to.be.Text(\" abc\");\n        });                        \n    });   \n\n    describe(\"s2 = text.trim s1\", () => {\n        \n        it(\"should return `s1` without leading and trailing spaces\", async () => {\n            expect(await evaluate(\"text.trim '   abc   '\")).to.be.Text(\"abc\");\n        });\n        \n        it(\"should return Undefined Text if the argument is not a string\", async () => {\n            expect(await evaluate(\"text.trim 123\")).to.be.Undefined(\"Text\");\n        });\n\n        it(\"should apply to the first items only, if the argument is a truple\", async () => {\n            expect(await evaluate(\"text.trim(' abc ',' Def ')\")).to.be.Text(\"abc\");\n        });                        \n    });   \n\n    describe(\"f = text.head n\", () => {\n\n        describe(\"when n is an item\", () => {\n            \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"text.head 3\")).to.be.instanceof(types.Func);\n            });\n\n            describe(\"s2 = f s1 \", () => {\n    \n                it(\"should return the first n characters of s1\", async () => {\n                    expect(await evaluate(\"text.head 3 'abcdef'\")).to.be.Text('abc');\n                });\n    \n                it(\"should consider n relative to the end of the string if it is negative\", async () => {\n                    expect(await evaluate(\"text.head (-2) 'abcdef'\")).to.be.Text('abcd');\n                });\n\n                it(\"should return Undefined Text if `n` is not a number\", async () => {\n                    expect(await evaluate(\"text.head 'abc'\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"text.head 'abc' 'def'\")).to.be.Undefined(\"Text\");\n                });\n\n                it(\"should return Undefined Text if `s1` is not a string\", async () => {\n                    expect(await evaluate(\"text.head 3 10\")).to.be.Undefined(\"Text\");\n                });\n\n                it(\"should apply only to the first item if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"text.head 2 ('abc', 'def', 'ghi')\")).to.be.Text('ab');\n                });\n            });\n        });\n\n        describe(\"when the argument is a tuple\", () => {\n            \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"text.head(2,3)\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"text.head(2,3) 'abcdef'\")).to.be.Text('ab');\n                expect(await evaluate(\"text.head(2,3)('abcdef', 'ghijkl')\")).to.be.Text('ab');                    \n            });\n        });    \n    });              \n\n    describe(\"f = text.tail n\", () => {\n\n        describe(\"when n is an item\", () => {\n            \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"text.tail 3\")).to.be.instanceof(types.Func);\n            });\n\n            describe(\"s2 = f s1 \", () => {\n    \n                it(\"should return the last characters of s1, starting with the n-th\", async () => {\n                    expect(await evaluate(\"text.tail 2 'abcdef'\")).to.be.Text('cdef');\n                });\n    \n                it(\"should consider n relative to the end of the string if it is negative\", async () => {\n                    expect(await evaluate(\"text.tail (-2) 'abcdef'\")).to.be.Text('ef');\n                });\n\n                it(\"should return Undefined Text if `n` is not a number\", async () => {\n                    expect(await evaluate(\"text.tail 'abc'\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"text.tail 'abc' 'def'\")).to.be.Undefined(\"Text\");\n                });\n\n                it(\"should return Undefined Text if `s1` is not a string\", async () => {\n                    expect(await evaluate(\"text.tail 3 10\")).to.be.Undefined(\"Text\");\n                });\n\n                it(\"should apply only to the first item if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"text.tail (-2) ('abc', 'def', 'ghi')\")).to.be.Text('bc');\n                });\n            });\n        });\n\n        describe(\"when the argument is a tuple\", () => {\n            \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"text.tail(2,3)\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"text.tail(-2,-3) 'abcdef'\")).to.be.Text('ef');\n                expect(await evaluate(\"text.tail(-2,-3)('abcdef', 'ghijkl')\")).to.be.Text('ef');                    \n            });\n        });    \n    });              \n\n    describe(\"f = text.split s1\", () => {\n\n        describe(\"when s1 is an item\", () => {\n            \n            it(\"should return a function\", async () => {\n                expect(await evaluate(\"text.split '::'\")).to.be.instanceof(types.Func);\n            });\n\n            describe(\"l = f s2 \", () => {\n    \n                it(\"should return the list of the s2 substrings separated by s1\", async () => {\n                    expect(await evaluate(\"text.split '::' 'ab::cd::ef'\")).to.be.List([\"ab\",\"cd\",\"ef\"]);\n                    expect(await evaluate(\"text.split '::' 'abcdef'\")).to.be.List([\"abcdef\"]);\n                });\n\n                it(\"should return Undefined Text if `s1` is not a string\", async () => {\n                    expect(await evaluate(\"text.split 10\")).to.be.instanceof(types.Func);\n                    expect(await evaluate(\"text.split 10 'def'\")).to.be.Undefined(\"Text\");\n                });\n\n                it(\"should return Undefined Text if `s2` is not a string\", async () => {\n                    expect(await evaluate(\"text.split '::' 10\")).to.be.Undefined(\"Text\");\n                });\n\n                it(\"should apply only to the first item if the parameter is a tuple\", async () => {\n                    expect(await evaluate(\"text.split '::' ('ab::cd', 'de::fg')\")).to.be.List([\"ab\",\"cd\"]);\n                });\n            });\n        });\n\n        describe(\"when s1 is a tuple\", () => {\n            \n            it(\"should apply only to the first item\", async () => {\n                expect(await evaluate(\"text.split('::','!!')\")).to.be.instanceof(types.Func);\n                expect(await evaluate(\"text.split('::','!!') 'a!!b::c!!d'\")).to.be.List([\"a!!b\",\"c!!d\"]);\n                expect(await evaluate(\"text.split('::','!!')('ab::cd!!ef', 'gh::ij!!kl')\")).to.be.List([\"ab\",\"cd!!ef\"]);\n            });\n        });    \n    });              \n});\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/modules/text.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/modules/time.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/modules/time.js ***!
    \******************************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ../expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\nconst types = __webpack_require__(/*! ../../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\nconst parse = __webpack_require__(/*! ../../lib/interpreter */ \"../../node_modules/@onlabsorg/swan-js/lib/interpreter.js\");\nconst time = __webpack_require__(/*! ../../lib/modules/time */ \"../../node_modules/@onlabsorg/swan-js/lib/modules/time.js\")(types);\n\nconst evaluate = async (expression, presets={}) => {\n    const context = Object.assign({time}, presets);\n    return await parse(expression)(context);\n}\n\n\n\ndescribe(\"time module\", () => {\n\n    describe(\"time.now()\", () => {\n        \n        it(\"should return the current time in seconds\", async () => {\n            const t1 = await evaluate(\"time.now()\");\n            const t2 = Date.now()/1000;\n            expect(t1).to.be.instanceof(types.Numb);\n            expect(Math.round(types.unwrap(t1),2)).to.equal(Math.round(t2,2));\n        });\n    });\n\n    describe(\"time.timezone()\", () => {\n        \n        it(\"should return the current time-zone offset in hours\", async () => {\n            expect(await evaluate(\"time.timezone()\")).to.be.Numb(-(new Date()).getTimezoneOffset() / 60);\n        });\n    });\n\n    describe(\"time.to_date(t)\", () => {\n        \n        it(\"should convert the given och time (in seconds) to a local date namespace\", async () => {\n            expect(await evaluate(\"time.to_date 1642290213.284\")).to.be.Namespace({\n                year: 2022,\n                month: 01,\n                day: 16,\n                hours: 0,\n                minutes: 43,\n                seconds: 33.284\n            });\n        });\n        \n        it(\"should return Undefined Date if the parameter is not a Number\", async () => {\n            expect(await evaluate(\"time.to_date 'abc'\")).to.be.Undefined(\"Date\");\n        });\n    });\n\n    describe(\"time.to_UTC_date(t)\", () => {\n        \n        it(\"should convert the given epoch time (in seconds) to a UTC date namespace\", async () => {\n            expect(await evaluate(\"time.to_UTC_date 1642290213.284\")).to.be.Namespace({\n                year: 2022,\n                month: 01,\n                day: 15,\n                hours: 23,\n                minutes: 43,\n                seconds: 33.284\n            });\n        });\n        \n        it(\"should return Undefined Date if the parameter is not a Number\", async () => {\n            expect(await evaluate(\"time.to_UTC_date 'abc'\")).to.be.Undefined(\"Date\");\n        });\n    });\n\n    describe(\"time.from_date(d)\", () => {\n        \n        it(\"should convert the given local date namespace to the corresponding epoch time in seconds\", async () => {\n            expect(await evaluate(`time.from_date {\n                year: 2022,\n                month: 01,\n                day: 16,\n                hours: 0,\n                minutes: 43,\n                seconds: 33.284                \n            }`)).to.be.Numb(1642290213.284);\n        });\n        \n        it(\"should return Undefined Number if the parameter is not a Namespace\", async () => {\n            expect(await evaluate(\"time.from_date 'abc'\")).to.be.Undefined(\"Number\");\n        });\n    });\n\n    describe(\"time.from_UTC_date(d)\", () => {\n        \n        it(\"should convert the given UTC date namespace to the corresponding epoch time in seconds\", async () => {\n            expect(await evaluate(`time.from_UTC_date {\n                year: 2022,\n                month: 01,\n                day: 15,\n                hours: 23,\n                minutes: 43,\n                seconds: 33.284\n            }`)).to.be.Numb(1642290213.284);\n        });\n        \n        it(\"should return Undefined Number if the parameter is not a Namespace\", async () => {\n            expect(await evaluate(\"time.from_UTC_date 'abc'\")).to.be.Undefined(\"Number\");\n        });\n    });\n\n    describe(\"time.to_ISO_string(t)\", () => {\n        \n        it(\"should convert the give epoch time in seconds to its date string representation\", async () => {\n            expect(await evaluate(`time.to_ISO_string 1639513675.900`)).to.be.Text(\"2021-12-14T20:27:55.900Z\")\n        });\n        \n        it(\"should return Undefined Text if the parameter is not a Number\", async () => {\n            expect(await evaluate(\"time.to_ISO_string 'abc'\")).to.be.Undefined(\"Text\");\n        });\n    });\n\n    describe(\"time.from_string(s)\", () => {\n        \n        it(\"should convert the give date string to the corresponding epoch time in seconds\", async () => {\n            expect(await evaluate(`time.from_string \"2021-12-14T20:27:55.900Z\"`)).to.be.Numb(1639513675.900)\n        });\n        \n        it(\"should return Undefined Number if the parameter is not a Text item\", async () => {\n            expect(await evaluate(\"time.from_string 10\")).to.be.Undefined(\"Number\");\n        });\n    });\n\n    describe(\"time.week_day(t)\", () => {\n        \n        it(\"should return the day of the week, given an epoch time in seconds\", async () => {\n            expect(await evaluate(`time.week_day 1639513675.900`)).to.be.Numb(2)\n        });\n        \n        it(\"should return Undefined Number if the parameter is not a Numb item\", async () => {\n            expect(await evaluate(\"time.week_day 'abc'\")).to.be.Undefined(\"Number\");\n        });\n    });\n\n    describe(\"time.week_number(t)\", () => {\n        \n        it(\"should return the number of the week, given an epoch time in seconds\", async () => {\n            expect(await evaluate(`time.week_number 1639513675.900`)).to.be.Numb(50)\n        });\n        \n        it(\"should return Undefined Number if the parameter is not a Numb item\", async () => {\n            expect(await evaluate(\"time.week_number 'abc'\")).to.be.Undefined(\"Number\");\n        });\n    });\n});\n\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/modules/time.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/@onlabsorg/swan-js/test/types.js":
  /*!***********************************************************!*\
    !*** ../../node_modules/@onlabsorg/swan-js/test/types.js ***!
    \***********************************************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = __webpack_require__(/*! ./expect */ \"../../node_modules/@onlabsorg/swan-js/test/expect.js\");\n\n\nconst {\n    Term,\n        Tuple,\n        Item,\n            Bool, \n            Numb, \n            Func, \n            Undefined, \n            Mapping, \n                Sequence, \n                    Text, \n                    List, \n                Namespace,\n                \n    wrap, unwrap \n} = __webpack_require__(/*! ../lib/types */ \"../../node_modules/@onlabsorg/swan-js/lib/types.js\");\n\n\ndescribe(\"types\", () => {\n    \n    describe(\"Bool\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the item itself\", () => {\n                const item = new Bool(true);\n                expect(item.items()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.items())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Bool(true);\n                expect(item.values()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.values())).to.deep.equal([true]);\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Bool(true);\n                expect(Array.from(item)).to.deep.equal([true]);\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const item1 = new Bool(true);\n                const item2 = new Bool(false);\n                expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(item1.iterPairs(item2));\n                expect(pairs.length).to.equal(1);\n                expect(pairs[0][0]).to.be.Bool(true);\n                expect(pairs[0][1]).to.be.Bool(false);\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item and return the wrapped output\", () => {\n                const item = new Bool(true);\n                const fn = item => [item.unwrap()];\n                expect(item.imapSync(fn)).to.be.List([true]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item value and return the wrapped output\", () => {\n                const item = new Bool(true);\n                const fn = value => [value];\n                expect(item.vmapSync(fn)).to.be.List([true]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item and return the wrapped output\", async () => {\n                const item = new Bool(true);\n                const fn = async item => [item.unwrap()];\n                expect(await item.imapAsync(fn)).to.be.List([true]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item value and return the wrapped output\", async () => {\n                const item = new Bool(true);\n                const fn = async value => [value];\n                expect(await item.vmapAsync(fn)).to.be.List([true]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return the term value\", () => {\n                expect((new Bool(true)).toBoolean()).to.be.true;\n                expect((new Bool(false)).toBoolean()).to.be.false;\n            });\n        });\n\n        describe(\".toString()\", () => {\n            \n            it(\"should return 'TRUE' if the value is true\", () => {\n                expect((new Bool(true)).toString()).to.equal(\"TRUE\")\n            });\n\n            it(\"should return 'FALSE' if the value is true\", () => {\n                expect((new Bool(false)).toString()).to.equal(\"FALSE\")\n            });\n        });\n        \n        describe(\".typeName\", () => {\n            \n            it(\"should return the item class name\", () => {\n                expect(new Bool(true).typeName).to.equal(\"Bool\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return false\", () => {\n                expect(new Bool(true).isNothing()).to.be.false;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new Bool(true);\n                expect(item.normalize()).to.equal(item);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return the item value\", () => {\n                expect(new Bool(true).unwrap() ).to.equal(true);\n                expect(new Bool(false).unwrap()).to.equal(false);\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should return the logical OR\", () => {\n                const TRUE = new Bool(true);\n                const FALSE = new Bool(false);\n                expect(TRUE.sum(TRUE)  ).to.be.Bool(true);\n                expect(TRUE.sum(FALSE) ).to.be.Bool(true);\n                expect(FALSE.sum(TRUE) ).to.be.Bool(true);\n                expect(FALSE.sum(FALSE)).to.be.Bool(false);\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Bool(true);\n                expect(item.negate).to.be.undefined;\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should return true if the item is FALSE\", () => {\n                expect(new Bool(true).isNull()).to.be.false;\n                expect(new Bool(false).isNull()).to.be.true;\n            });\n        });\n        \n        describe(\"Bool.null\", () => {\n            \n            it(\"should return FALSE\", () => {\n                expect(Bool.null).to.be.Bool(false);\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n\n            it(\"should return the logical AND\", () => {\n                const TRUE = new Bool(true);\n                const FALSE = new Bool(false);\n                expect(TRUE.mul(TRUE)  ).to.be.Bool(true);\n                expect(TRUE.mul(FALSE) ).to.be.Bool(false);\n                expect(FALSE.mul(TRUE) ).to.be.Bool(false);\n                expect(FALSE.mul(FALSE)).to.be.Bool(false);\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Bool(true);\n                expect(item.invert).to.be.undefined;\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should return true if the item is TRUE\", () => {\n                expect(new Bool(true).isUnit()).to.be.true;\n                expect(new Bool(false).isUnit()).to.be.false;\n            });\n        });\n        \n        describe(\"Bool.unit\", () => {\n            \n            it(\"should return TRUE\", () => {\n                expect(Bool.unit).to.be.Bool(true);\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Bool(true);\n                expect(item.pow).to.be.undefined;\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n            \n            it(\"should return '=' if the items are both TRUE or both FALSE\", () => {\n                const TRUE = new Bool(true);\n                const FALSE = new Bool(false);\n                expect(TRUE.compare(TRUE)).to.equal('=');\n                expect(FALSE.compare(FALSE)).to.equal('=');\n            });\n            \n            it(\"should consider FALSE less than TRUE\", () => {\n                const TRUE = new Bool(true);\n                const FALSE = new Bool(false);\n                expect(TRUE.compare(FALSE)).to.equal('>');\n                expect(FALSE.compare(TRUE)).to.equal('<');\n            });\n        });\n    });\n\n    describe(\"Numb\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the item itself\", () => {\n                const item = new Numb(10);\n                expect(item.items()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.items())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Numb(10);\n                expect(item.values()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.values())).to.deep.equal([10]);\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Numb(10);\n                expect(Array.from(item)).to.deep.equal([10]);\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const item1 = new Numb(10);\n                const item2 = new Numb(20);\n                expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(item1.iterPairs(item2));\n                expect(pairs.length).to.equal(1);\n                expect(pairs[0][0]).to.be.Numb(10);\n                expect(pairs[0][1]).to.be.Numb(20);\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item and return the wrapped output\", () => {\n                const item = new Numb(10);\n                const fn = item => [item.unwrap()];\n                expect(item.imapSync(fn)).to.be.List([10]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item value and return the wrapped output\", () => {\n                const item = new Numb(10);\n                const fn = value => [value];\n                expect(item.vmapSync(fn)).to.be.List([10]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item and return the wrapped output\", async () => {\n                const item = new Numb(10);\n                const fn = async item => [item.unwrap()];\n                expect(await item.imapAsync(fn)).to.be.List([10]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item value and return the wrapped output\", async () => {\n                const item = new Numb(10);\n                const fn = async value => [value];\n                expect(await item.vmapAsync(fn)).to.be.List([10]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return true if the number is not null\", () => {\n                expect((new Numb(9)).toBoolean()).to.be.true;\n                expect((new Numb(0)).toBoolean()).to.be.false;\n            });\n        });\n        \n        describe(\".toString()\", () => {\n            \n            it(\"should return the stringified value\", () => {\n                expect((new Numb(-1.23)).toString()).to.equal(\"-1.23\");\n            });\n        });\n        \n        describe(\".typeName\", () => {\n            \n            it(\"should return the item class name\", () => {\n                expect(new Numb(10).typeName).to.equal(\"Numb\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return false\", () => {\n                expect(new Numb(10).isNothing()).to.be.false;\n                expect(new Numb( 0).isNothing()).to.be.false;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new Numb(10);\n                expect(item.normalize()).to.equal(item);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return the item value\", () => {\n                expect(new Numb(10).unwrap()).to.equal(10);\n                expect(new Numb( 0).unwrap()).to.equal( 0);\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should return the sum of the two numbers\", () => {\n                const item1 = new Numb(10);\n                const item2 = new Numb(20);\n                expect(item1.sum(item2)).to.be.Numb(30);\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should return the negation of the item\", () => {\n                const item = new Numb(10);\n                expect(item.negate()).to.be.Numb(-10);\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should return true if the item is 0\", () => {\n                expect(new Numb(10).isNull()).to.be.false;\n                expect(new Numb( 0).isNull()).to.be.true;\n            });\n        });\n        \n        describe(\"Numb.null\", () => {\n            \n            it(\"should return 0\", () => {\n                expect(Numb.null).to.be.Numb(0);\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n\n            it(\"should return the product of the two numbers\", () => {\n                const item1 = new Numb(10);\n                const item2 = new Numb(20);\n                expect(item1.mul(item2)).to.be.Numb(200);\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should return the reciprocal of the Numb item\", () => {\n                const item = new Numb(10);\n                expect(item.invert()).to.be.Numb(0.1);\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should return true if the item is 1\", () => {\n                expect(new Numb(1).isUnit()).to.be.true;\n                expect(new Numb(0).isUnit()).to.be.false;\n            });\n        });\n        \n        describe(\"Numb.unit\", () => {\n            \n            it(\"should return 1\", () => {\n                expect(Numb.unit).to.be.Numb(1);\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should return the exponentiation of the two numbers\", () => {\n                const item1 = new Numb(10);\n                const item2 = new Numb(3);\n                expect(item1.pow(item2)).to.be.Numb(1000);\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n            \n            it(\"should compare the two numbers according to the real numbers order rules\", () => {\n                const item1 = new Numb(10);\n                const item2 = new Numb(20);\n                expect(item1.compare(item1)).to.equal('=');\n                expect(item2.compare(item2)).to.equal('=');\n                expect(item1.compare(item2)).to.equal('<');\n                expect(item2.compare(item1)).to.equal('>');\n            });\n        });\n    });\n    \n    describe(\"Text\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the item itself\", () => {\n                const item = new Text(\"abc\");\n                expect(item.items()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.items())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Text(\"abc\");\n                expect(item.values()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.values())).to.deep.equal([\"abc\"]);\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Text(\"abc\");\n                expect(Array.from(item)).to.deep.equal([\"abc\"]);\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const item1 = new Text(\"abc\");\n                const item2 = new Text(\"def\");\n                expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(item1.iterPairs(item2));\n                expect(pairs.length).to.equal(1);\n                expect(pairs[0][0]).to.be.Text(\"abc\");\n                expect(pairs[0][1]).to.be.Text(\"def\");\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item and return the wrapped output\", () => {\n                const item = new Text(\"abc\");\n                const fn = item => [item.unwrap()];\n                expect(item.imapSync(fn)).to.be.List([\"abc\"]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item value and return the wrapped output\", () => {\n                const item = new Text(\"abc\");\n                const fn = value => [value];\n                expect(item.vmapSync(fn)).to.be.List([\"abc\"]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item and return the wrapped output\", async () => {\n                const item = new Text(\"abc\");\n                const fn = async item => [item.unwrap()];\n                expect(await item.imapAsync(fn)).to.be.List([\"abc\"]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item value and return the wrapped output\", async () => {\n                const item = new Text(\"abc\");\n                const fn = async value => [value];\n                expect(await item.vmapAsync(fn)).to.be.List([\"abc\"]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return true if the string value is not empty\", () => {\n                expect((new Text(\"abc\")).toBoolean()).to.be.true;\n                expect((new Text(\"\")).toBoolean()).to.be.false;\n            });\n        });\n        \n        describe(\".toString()\", () => {\n            \n            it(\"should return the text value as it is\", () => {\n                expect((new Text(\"abc\")).toString()).to.equal(\"abc\");\n            });\n        });\n        \n        describe(\".typeName\", () => {\n            \n            it(\"should return the item class name\", () => {\n                expect(new Text(\"abc\").typeName).to.equal(\"Text\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return false\", () => {\n                expect(new Text(\"abc\").isNothing()).to.be.false;\n                expect(new Text(\"\"   ).isNothing()).to.be.false;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new Text(\"abc\");\n                expect(item.normalize()).to.equal(item);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return the item value\", () => {\n                expect(new Text(\"abc\").unwrap()).to.equal(\"abc\");\n                expect(new Text(\"\"   ).unwrap()).to.equal(\"\");\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should concatenate the two strings\", () => {\n                const item1 = new Text(\"abc\");\n                const item2 = new Text(\"def\");\n                expect(item1.sum(item2)).to.be.Text(\"abcdef\");\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Text(\"abc\");\n                expect(item.negate).to.be.undefined;\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should return true if the string is empty\", () => {\n                expect(new Text(\"abc\").isNull()).to.be.false;\n                expect(new Text(\"\"   ).isNull()).to.be.true;\n            });\n        });\n        \n        describe(\"Text.null\", () => {\n            \n            it(\"should return an empty Text item\", () => {\n                expect(Text.null).to.be.Text(\"\");\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Text(\"abc\");\n                expect(item.mul).to.be.undefined;\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Text(\"abc\");\n                expect(item.invert).to.be.undefined;\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Text(\"abc\");\n                expect(item.isUnit).to.be.undefined;\n            });\n        });\n        \n        describe(\"Text.unit\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Text.unit).to.be.undefined;\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Text(\"abc\");\n                expect(item.pow).to.be.undefined;\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n                        \n            it(\"should compare the two strings alphabetically\", () => {\n                const item1 = new Text(\"abc\");\n                const item2 = new Text(\"def\");\n                expect(item1.compare(item1)).to.equal('=');\n                expect(item2.compare(item2)).to.equal('=');\n                expect(item1.compare(item2)).to.equal('<');\n                expect(item2.compare(item1)).to.equal('>');\n                \n                expect(new Text(\"aaa\").compare(new Text(\"aa\"))).to.equal('>');\n            });\n        });\n        \n        describe(\".domain\", () => {\n            \n            it(\"should return the array of integers between 0 and the string length minus one\", () => {\n                expect(new Text(\"abc\").domain).to.deep.equal([0,1,2]);\n                expect(new Text(\"\"   ).domain).to.deep.equal([]);\n            });\n        });\n\n        describe(\".vget(i)\", () => {\n            \n            it(\"should return i-th character of the string\", () => {\n                expect(new Text(\"abc\").vget(1)).to.equal('b')\n            });\n\n            it(\"should return undefined if i is not in the Text domain\", () => {\n                const item = new Text(\"abc\");\n                expect(item.vget(-1)).to.be.undefined;\n                expect(item.vget(10)).to.be.undefined;\n                expect(item.vget('xx')).to.be.undefined;\n            });\n        });\n        \n        describe(\".size\", () => {\n            \n            it(\"should contain the number of characters of the string\", () => {\n                expect(new Text(\"abc\").size).to.equal(3);\n                expect(new Text(\"\").size).to.equal(0);\n            });\n        });\n        \n        describe(\".image\", () => {\n            \n            it(\"should return the tuple of characters of the string\", () => {\n                const item = new Text(\"abc\");\n                expect(item.image).to.be.List(['a','b','c']);\n            });\n        });\n        \n        describe(\".apply(...X)\", () => {\n            \n            it(\"should return the tuple of Text characters mapped to the arguments\", () => {\n                const item = new Text(\"abcdef\");\n                expect(item.apply(1,3,5)).to.be.Tuple(['b','d','f']);\n            });\n            \n            it(\"should normalize the returned tuple\", () => {\n                const item = new Text(\"abcdef\");\n                expect(item.apply(1)).to.be.Text('b');\n            });\n            \n            it(\"should return Undefined Mapping if the index is not in the Text item domain\", () => {\n                const item = new Text(\"abcdef\");\n                expect(item.apply(-1)).to.be.Undefined('Mapping', arg0 => {\n                    expect(arg0).to.equal(-1);\n                });\n                \n                const tuple = item.apply(1, -1, 3);\n                expect(tuple).to.be.instanceof(Tuple);\n                expect(Array.from(tuple)[0]).to.equal('b');\n                expect(Array.from(tuple)[1]).to.be.Undefined('Mapping', arg0 => {\n                    expect(arg0).to.equal(-1);\n                });\n                expect(Array.from(tuple)[2]).to.equal('d');\n            });\n        })\n    });\n\n    describe(\"List\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the item itself\", () => {\n                const item = new List([10,20,30]);\n                expect(item.items()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.items())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new List([10,20,30]);\n                expect(item.values()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.values())).to.deep.equal([[10,20,30]]);\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new List([10,20,30]);\n                expect(Array.from(item)).to.deep.equal([[10,20,30]]);\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const item1 = new List([10,20,30]);\n                const item2 = new List([40,50,60]);\n                expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(item1.iterPairs(item2));\n                expect(pairs.length).to.equal(1);\n                expect(pairs[0][0]).to.be.List([10,20,30]);\n                expect(pairs[0][1]).to.be.List([40,50,60]);\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item and return the wrapped output\", () => {\n                const item = new List([10,20,30]);\n                const fn = item => [item.unwrap()];\n                expect(item.imapSync(fn)).to.be.List([[10,20,30]]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item value and return the wrapped output\", () => {\n                const item = new List([10,20,30]);\n                const fn = value => [value];\n                expect(item.vmapSync(fn)).to.be.List([[10,20,30]]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item and return the wrapped output\", async () => {\n                const item = new List([10,20,30]);\n                const fn = async item => [item.unwrap()];\n                expect(await item.imapAsync(fn)).to.be.List([[10,20,30]]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item value and return the wrapped output\", async () => {\n                const item = new List([10,20,30]);\n                const fn = async value => [value];\n                expect(await item.vmapAsync(fn)).to.be.List([[10,20,30]]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return true if the array value is not empty\", () => {\n                expect((new List([10,20,30])).toBoolean()).to.be.true;\n                expect((new List([        ])).toBoolean()).to.be.false;\n            });\n        });\n        \n        describe(\".toString()\", () => {\n            \n            it(\"should return '[[List of n items]]'\", () => {\n                expect(new List([10,20,30]).toString()).to.equal(\"[[List of 3 items]]\");\n                expect(new List([10      ]).toString()).to.equal(\"[[List of 1 item]]\");\n                expect(new List([        ]).toString()).to.equal(\"[[List of 0 items]]\");\n            });\n        });\n        \n        describe(\".typeName\", () => {\n            \n            it(\"should return the item class name\", () => {\n                expect(new List([10,20,30]).typeName).to.equal(\"List\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return false\", () => {\n                expect(new List([10,20,30]).isNothing()).to.be.false;\n                expect(new List([        ]).isNothing()).to.be.false;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new List([10,20,30]);\n                expect(item.normalize()).to.equal(item);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return the item value\", () => {\n                expect(new List([10,20,30]).unwrap()).to.deep.equal([10,20,30]);\n                expect(new List([        ]).unwrap()).to.deep.equal([]);\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should concatenate the two lists\", () => {\n                const item1 = new List([10,20,30]);\n                const item2 = new List([40,50,60]);\n                expect(item1.sum(item2)).to.be.List([10,20,30,40,50,60]);\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new List([10,20,30]);\n                expect(item.negate).to.be.undefined;\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should return true if the list is empty\", () => {\n                expect(new List([10,20,30]).isNull()).to.be.false;\n                expect(new List([        ]).isNull()).to.be.true;\n            });\n        });\n        \n        describe(\"List.null\", () => {\n            \n            it(\"should return an empty Text item\", () => {\n                expect(List.null).to.be.List([]);\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new List([10,20,30]);\n                expect(item.mul).to.be.undefined;\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new List([10,20,30]);\n                expect(item.invert).to.be.undefined;\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new List([10,20,30]);\n                expect(item.isUnit).to.be.undefined;\n            });\n        });\n        \n        describe(\"List.unit\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(List.unit).to.be.undefined;\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new List([10,20,30]);\n                expect(item.pow).to.be.undefined;\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n                        \n            it(\"should compare the two lists lexicographically\", () => {\n                const item1 = new List([10,20,30]);\n                const item2 = new List([40,50,60]);\n                expect(item1.compare(item1)).to.equal('=');\n                expect(item2.compare(item2)).to.equal('=');\n                expect(item1.compare(item2)).to.equal('<');\n                expect(item2.compare(item1)).to.equal('>');\n                \n                expect(new List([10,10,10]).compare(new List([10,10]))).to.equal('>');\n            });\n        });\n        \n        describe(\".domain\", () => {\n            \n            it(\"should return the array of integers between 0 and the list length minus one\", () => {\n                expect(new List([10,20,30]).domain).to.deep.equal([0,1,2]);\n                expect(new List([        ]).domain).to.deep.equal([]);\n            });\n        });\n\n        describe(\".vget(i)\", () => {\n            \n            it(\"should return i-th value of the list\", () => {\n                expect(new List([10,20,30]).vget(1)).to.equal(20)\n            });\n\n            it(\"should return undefined if i is not in the List domain\", () => {\n                const item = new List([10,20,30]);\n                expect(item.vget(-1)).to.be.undefined;\n                expect(item.vget(10)).to.be.undefined;\n                expect(item.vget('xx')).to.be.undefined;\n            });\n        });\n        \n        describe(\".size\", () => {\n            \n            it(\"should contain the number of items of the list\", () => {\n                expect(new List([10,20,30]).size).to.equal(3);\n                expect(new List([        ]).size).to.equal(0);\n            });\n        });\n        \n        describe(\".image\", () => {\n            \n            it(\"should return the tuple of characters of the string\", () => {\n                const item = new List([10,20,30]);\n                expect(item.image).to.be.List([10,20,30]);\n            });\n        });\n        \n        describe(\".apply(...X)\", () => {\n            \n            it(\"should return the tuple of List items mapped to the arguments\", () => {\n                const item = new List([10,20,30,40,50,60]);\n                expect(item.apply(1,3,5)).to.be.Tuple([20,40,60]);\n            });\n            \n            it(\"should normalize the returned tuple\", () => {\n                const item = new List([10,20,30,40,50,60]);\n                expect(item.apply(1)).to.be.Numb(20);\n            });\n            \n            it(\"should return Undefined Mapping if the index is not in the List item domain\", () => {\n                const item = new List([10,20,30,40,50,60]);\n                expect(item.apply(-1)).to.be.Undefined('Mapping', arg0 => {\n                    expect(arg0).to.equal(-1);\n                });\n                \n                const tuple = item.apply(1, -1, 3);\n                expect(tuple).to.be.instanceof(Tuple);\n                expect(Array.from(tuple)[0]).to.equal(20);\n                expect(Array.from(tuple)[1]).to.be.Undefined('Mapping', arg0 => {\n                    expect(arg0).to.equal(-1);\n                });\n                expect(Array.from(tuple)[2]).to.equal(40);\n            });\n        })\n    });\n\n    describe(\"Namespace\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the item itself\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.items()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.items())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.values()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.values())).to.deep.equal([{k1:1, k2:2, k3:3}]);\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(Array.from(item)).to.deep.equal([{k1:1, k2:2, k3:3}]);\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const item1 = new Namespace({k1:1, k2:2, k3:3});\n                const item2 = new Namespace({k4:4, k5:5, k6:6});\n                expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(item1.iterPairs(item2));\n                expect(pairs.length).to.equal(1);\n                expect(pairs[0][0]).to.be.Namespace({k1:1, k2:2, k3:3});\n                expect(pairs[0][1]).to.be.Namespace({k4:4, k5:5, k6:6});\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item and return the wrapped output\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                const fn = item => [item.unwrap()];\n                expect(item.imapSync(fn)).to.be.List([{k1:1, k2:2, k3:3}]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item value and return the wrapped output\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                const fn = value => [value];\n                expect(item.vmapSync(fn)).to.be.List([{k1:1, k2:2, k3:3}]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item and return the wrapped output\", async () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                const fn = async item => [item.unwrap()];\n                expect(await item.imapAsync(fn)).to.be.List([{k1:1, k2:2, k3:3}]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item value and return the wrapped output\", async () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                const fn = async value => [value];\n                expect(await item.vmapAsync(fn)).to.be.List([{k1:1, k2:2, k3:3}]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return true if the namespace value is not empty\", () => {\n                expect((new Namespace({a:1})).toBoolean()).to.be.true;\n                expect((new Namespace({})).toBoolean()).to.be.false;\n            });\n            \n            it(\"should consider empty a namespace containing only non-valid identifiers\", () => {\n                expect((new Namespace({$key:1})).toBoolean()).to.be.false;\n            });\n        });\n        \n        describe(\".toString()\", () => {\n            \n            it(\"should retun '[[Namespace of n items]]'\", () => {\n                expect((new Namespace({key1:1, key2:2, key3:3, $key4:4})).toString()).to.equal(\"[[Namespace of 3 items]]\");\n                expect((new Namespace({key1:1                         })).toString()).to.equal(\"[[Namespace of 1 item]]\");\n                expect((new Namespace({                               })).toString()).to.equal(\"[[Namespace of 0 items]]\");\n            });\n        });\n        \n        describe(\".typeName\", () => {\n            \n            it(\"should return the item class name\", () => {\n                expect(new Namespace({k1:1, k2:2, k3:3}).typeName).to.equal(\"Namespace\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return false\", () => {\n                expect(new Namespace({k1:1, k2:2, k3:3}).isNothing()).to.be.false;\n                expect(new Namespace({                }).isNothing()).to.be.false;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.normalize()).to.equal(item);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return the item value\", () => {\n                expect(new Namespace({k1:1, k2:2, k3:3}).unwrap()).to.deep.equal({k1:1, k2:2, k3:3});\n                expect(new Namespace({                }).unwrap()).to.deep.equal({});\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should concatenate the two lists\", () => {\n                const item1 = new Namespace({k1:1, k2:2, k3:3});\n                const item2 = new Namespace({k3:4, k4:5, k5:6});\n                expect(item1.sum(item2)).to.be.Namespace({k1:1, k2:2, k3:4, k4:5, k5:6});\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.negate).to.be.undefined;\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should return true if the list is empty\", () => {\n                expect(new Namespace({k1:1, k2:2, k3:3}).isNull()).to.be.false;\n                expect(new Namespace({                }).isNull()).to.be.true;\n            });\n        });\n        \n        describe(\"Namespace.null\", () => {\n            \n            it(\"should return an empty Text item\", () => {\n                expect(Namespace.null).to.be.Namespace({});\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.mul).to.be.undefined;\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.invert).to.be.undefined;\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.isUnit).to.be.undefined;\n            });\n        });\n        \n        describe(\"Namespace.unit\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Namespace.unit).to.be.undefined;\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3});\n                expect(item.pow).to.be.undefined;\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n                        \n            it(\"should return equal if two namespace have the same identifiers and equal values\", () => {\n                const item1 = new Namespace({k1:1, k2:2, k3:3});\n                const item2 = new Namespace({k4:4, k5:5, k6:6});\n                expect(item1.compare(item1)).to.equal('=');\n                expect(item2.compare(item2)).to.equal('=');\n                expect(item1.compare(item2)).to.equal('#');\n                expect(item2.compare(item1)).to.equal('#');\n                \n                expect(new Namespace({k1:1, k2:2, $k3:3}).compare(new Namespace({k1:1, k2:2}))).to.equal('=');\n            });\n        });\n        \n        describe(\".domain\", () => {\n            \n            it(\"should return the array of the namespace identifiers\", () => {\n                expect(new Namespace({k1:1, k2:2, k3:3}).domain).to.deep.equal(['k1','k2','k3']);\n                expect(new Namespace({                }).domain).to.deep.equal([]);\n            });\n        });\n\n        describe(\".vget(key)\", () => {\n            \n            it(\"should return the value mapped to the given identifier\", () => {\n                expect(new Namespace({k1:1, k2:2, k3:3}).vget('k2')).to.equal(2)\n            });\n\n            it(\"should return undefined if key is not in the Namespace domain\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3, $k4:4});\n                expect(item.vget(10)).to.be.undefined;\n                expect(item.vget('xx')).to.be.undefined;\n                expect(item.vget('$k4')).to.be.undefined;\n            });\n        });\n        \n        describe(\".size\", () => {\n            \n            it(\"should contain the number of names in the namespace\", () => {\n                expect(new Namespace({x:10,y:20,z:30}).size).to.equal(3);\n                expect(new Namespace({}).size).to.equal(0);\n            });\n            \n            it(\"should ignore non-valid identifiers\", () => {\n                expect(new Namespace({x:10,y:20,$z:30}).size).to.equal(2);\n            });\n        });\n        \n        describe(\".image\", () => {\n            \n            it(\"should return the array of values of the namespace\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3, $k4:4});\n                expect(item.image).to.be.List([1,2,3]);\n            });\n        });\n        \n        describe(\".apply(...X)\", () => {\n            \n            it(\"should return the tuple of values mapped to the arguments\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3, k4:4, k5:5, k6:6});\n                expect(item.apply('k2','k4','k6')).to.be.Tuple([2,4,6]);\n            });\n            \n            it(\"should normalize the returned tuple\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3, k4:4, k5:5, k6:6});\n                expect(item.apply('k2')).to.be.Numb(2);\n            });\n            \n            it(\"should return Undefined Mapping if the key is not in the Namespace domain\", () => {\n                const item = new Namespace({k1:1, k2:2, k3:3, k4:4, k5:5, k6:6});\n                expect(item.apply(-1)).to.be.Undefined('Mapping', arg0 => {\n                    expect(arg0).to.equal(-1);\n                });\n                \n                const tuple = item.apply('k2', -1, 'k4');\n                expect(tuple).to.be.instanceof(Tuple);\n                expect(Array.from(tuple)[0]).to.equal(2);\n                expect(Array.from(tuple)[1]).to.be.Undefined('Mapping', arg0 => {\n                    expect(arg0).to.equal(-1);\n                });\n                expect(Array.from(tuple)[2]).to.equal(4);\n            });\n        })        \n    });\n    \n    describe(\"Func\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the item itself\", () => {\n                const item = new Func(x=>x);\n                expect(item.items()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.items())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Func(x=>x);\n                expect(item.values()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.values())).to.deep.equal([item.unwrap()]);\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Func(x=>x);\n                expect(Array.from(item)).to.deep.equal([item.unwrap()]);\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const item1 = new Func(x=>x);\n                const item2 = new Func(x=>x);\n                expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(item1.iterPairs(item2));\n                expect(pairs.length).to.equal(1);\n                expect(pairs[0][0]).to.equal(item1);\n                expect(pairs[0][1]).to.equal(item2);\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item and return the wrapped output\", () => {\n                const item = new Func(x=>x);\n                const fn = item => [item.unwrap()];\n                expect(item.imapSync(fn)).to.be.List([item.unwrap()]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item value and return the wrapped output\", () => {\n                const item = new Func(x=>x);\n                const fn = value => [value];\n                expect(item.vmapSync(fn)).to.be.List([item.unwrap()]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item and return the wrapped output\", async () => {\n                const item = new Func(x=>x);\n                const fn = async item => [item.unwrap()];\n                expect(await item.imapAsync(fn)).to.be.List([item.unwrap()]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item value and return the wrapped output\", async () => {\n                const item = new Func(x=>x);\n                const fn = async value => [value];\n                expect(await item.vmapAsync(fn)).to.be.List([item.unwrap()]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return true\", () => {\n                expect((new Func(x=>x)).toBoolean()).to.be.true;\n            });\n        });\n        \n        describe(\".toString()\", () => {\n            \n            it(\"should return '[[Func]]'\", () => {\n                expect((new Func(x=>x)).toString()).to.equal(\"[[Func]]\");\n            });\n        });\n\n        describe(\".typeName\", () => {\n            \n            it(\"should return the item class name\", () => {\n                expect(new Func(x=>x).typeName).to.equal(\"Func\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return false\", () => {\n                expect(new Func(x=>x).isNothing()).to.be.false;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new Func(x=>x);\n                expect(item.normalize()).to.equal(item);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return the item value\", () => {\n                const fn = x => x;\n                expect(new Func(fn).unwrap()).to.equal(fn);\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Func(x=>x);\n                expect(item.sum).to.be.undefined;\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Func(x=>x);\n                expect(item.negate).to.be.undefined;\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Func(x=>x);\n                expect(item.isNull).to.be.undefined;\n            });\n        });\n        \n        describe(\"Func.null\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Func.null).to.be.undefined;\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Func(x=>x);\n                expect(item.mul).to.be.undefined;\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Func(x=>x);\n                expect(item.invert).to.be.undefined;\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Func(x=>x);\n                expect(item.isUnit).to.be.undefined;\n            });\n        });\n        \n        describe(\"Func.unit\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Func.unit).to.be.undefined;\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Func(x=>x);\n                expect(item.pow).to.be.undefined;\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n                        \n            it(\"should return equal if two Func items wrap the same function\", () => {\n                const item1 = new Func(x=>x);\n                const item2 = new Func(x=>x);\n                expect(item1.compare(item1)).to.equal('=');\n                expect(item2.compare(item2)).to.equal('=');\n                expect(item1.compare(item2)).to.equal('#');\n                expect(item2.compare(item1)).to.equal('#');\n            });\n        });        \n    });\n\n    describe(\"Undefined\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the item itself\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.items()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.items())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.values()[Symbol.iterator]).to.be.a(\"function\");\n                expect(Array.from(item.values())).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(Array.from(item)).to.deep.equal([item]);\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const item1 = new Undefined(\"TestOperation1\", 10, 20);\n                const item2 = new Undefined(\"TestOperation2\", 10, 20);\n                expect(item1.iterPairs(item2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(item1.iterPairs(item2));\n                expect(pairs.length).to.equal(1);\n                expect(pairs[0][0]).to.be.Undefined(\"TestOperation1\");\n                expect(pairs[0][1]).to.be.Undefined(\"TestOperation2\");\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item and return the wrapped output\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                const fn = item => [item];\n                expect(item.imapSync(fn)).to.be.List([item]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to the item value and return the wrapped output\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                const fn = value => [value];\n                expect(item.vmapSync(fn)).to.be.List([item]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item and return the wrapped output\", async () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                const fn = async item => [item];\n                expect(await item.imapAsync(fn)).to.be.List([item]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to the item value and return the wrapped output\", async () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                const fn = async value => [value];\n                expect(await item.vmapAsync(fn)).to.be.List([item]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return true\", () => {\n                expect((new Undefined()).toBoolean()).to.be.false;\n            });\n        });\n        \n        describe(\".toString()\", () => {\n            \n            it(\"should return '[[Undefined <type-name>]]'\", () => {\n                expect((new Undefined(\"TestOperation\")).toString()).to.equal(\"[[Undefined TestOperation]]\");\n            });\n        });\n        \n        describe(\".typeName\", () => {\n            \n            it(\"should return the item class name\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.typeName).to.equal(\"Undefined\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return false\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.isNothing()).to.be.false;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.normalize()).to.equal(item);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return the item as it is\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.unwrap()).to.equal(item);\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.sum).to.be.undefined;\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.negate).to.be.undefined;\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.isNull).to.be.undefined;\n            });\n        });\n        \n        describe(\"Undefined.null\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Undefined.null).to.be.undefined;\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.mul).to.be.undefined;\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.invert).to.be.undefined;\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.isUnit).to.be.undefined;\n            });\n        });\n        \n        describe(\"Undefined.unit\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Undefined.unit).to.be.undefined;\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.pow).to.be.undefined;\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n                        \n            it(\"should return equal if two Undefined items are the same item\", () => {\n                const item1 = new Undefined(\"TestOperation\", 10, 20);\n                const item2 = new Undefined(\"TestOperation\", 10, 20);\n                expect(item1.compare(item1)).to.equal('=');\n                expect(item2.compare(item2)).to.equal('=');\n                expect(item1.compare(item2)).to.equal('#');\n                expect(item2.compare(item1)).to.equal('#');\n            });\n        });  \n        \n        describe(\".type\", () => {\n            \n            it(\"should contain the undefined operation type name\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.type).to.equal(\"TestOperation\");\n            });\n        })      \n        \n        describe(\".args\", () => {\n            \n            it(\"should contain the array of the undefined operation operands\", () => {\n                const item = new Undefined(\"TestOperation\", 10, 20);\n                expect(item.args).to.deep.equal([10,20]);\n            });\n        })      \n    });\n\n    describe(\"Tuple\", () => {\n        \n        describe(\".items()\", () => {\n            \n            it(\"should yield the items of the tuple\", () => {\n                const tuple = new Tuple(10, 20, 'abc');\n                expect(tuple.items()[Symbol.iterator]).to.be.a(\"function\");\n                const items = Array.from(tuple.items());\n                expect(items[0]).to.be.Numb(10);\n                expect(items[1]).to.be.Numb(20);\n                expect(items[2]).to.be.Text('abc');\n            });\n        });\n        \n        describe(\".values()\", () => {\n            \n            it(\"should yield the item values of the the tuple\", () => {\n                const tuple = new Tuple(10, 20, 'abc');\n                expect(tuple.values()[Symbol.iterator]).to.be.a(\"function\");\n                const values = Array.from(tuple.values());\n                expect(values[0]).to.equal(10);\n                expect(values[1]).to.equal(20);\n                expect(values[2]).to.equal('abc');\n            });\n        });\n        \n        describe(\"[Symbol.iterator]()\", () => {\n            \n            it(\"should yield the item value\", () => {\n                const tuple = new Tuple(10, 20, 'abc');\n                const values = Array.from(tuple);\n                expect(values[0]).to.equal(10);\n                expect(values[1]).to.equal(20);\n                expect(values[2]).to.equal('abc');\n            });\n        });\n        \n        describe(\".iterPairs(other)\", () => {\n            \n            it(\"should yield corresponding pairs of the two terms\", () => {\n                const tuple1 = new Tuple(11,12,13);\n                const tuple2 = new Tuple(21,22,23);\n                expect(tuple1.iterPairs(tuple2)[Symbol.iterator]).to.be.a(\"function\");\n                const pairs = Array.from(tuple1.iterPairs(tuple2));\n                expect(pairs.length).to.equal(3);\n                \n                expect(pairs[0][0]).to.be.Numb(11);\n                expect(pairs[0][1]).to.be.Numb(21);\n\n                expect(pairs[1][0]).to.be.Numb(12);\n                expect(pairs[1][1]).to.be.Numb(22);\n\n                expect(pairs[2][0]).to.be.Numb(13);\n                expect(pairs[2][1]).to.be.Numb(23);\n            });\n            \n            it(\"should pair items with Nothing when the two tuples do not have the same length\", () => {\n                var tuple1 = new Tuple(11,12,13);\n                var tuple2 = new Tuple(21,22);\n                var pairs = Array.from(tuple1.iterPairs(tuple2));                \n                expect(pairs[0][0]).to.be.Numb(11);\n                expect(pairs[0][1]).to.be.Numb(21);\n                expect(pairs[1][0]).to.be.Numb(12);\n                expect(pairs[1][1]).to.be.Numb(22);\n                expect(pairs[2][0]).to.be.Numb(13);\n                expect(pairs[2][1]).to.be.Tuple([]);\n\n                var tuple1 = new Tuple(11,12);\n                var tuple2 = new Tuple(21,22,23);\n                var pairs = Array.from(tuple1.iterPairs(tuple2));                \n                expect(pairs[0][0]).to.be.Numb(11);\n                expect(pairs[0][1]).to.be.Numb(21);\n                expect(pairs[1][0]).to.be.Numb(12);\n                expect(pairs[1][1]).to.be.Numb(22);\n                expect(pairs[2][0]).to.be.Tuple([]);\n                expect(pairs[2][1]).to.be.Numb(23);\n            });\n        });\n        \n        describe(\".imapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to all the items of the tuple\", () => {\n                const tuple = new Tuple(10,20,30);\n                const fn = item => 2*item.unwrap();\n                expect(tuple.imapSync(fn)).to.be.Tuple([20,40,60]);\n            });\n        });\n\n        describe(\".vmapSync(fn)\", () => {\n            \n            it(\"should synchronously apply fn to all the item values of the tuple\", () => {\n                const tuple = new Tuple(10,20,30);\n                const fn = value => 2*value;\n                expect(tuple.vmapSync(fn)).to.be.Tuple([20,40,60]);\n            });\n        });\n\n        describe(\".imapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to all the items of the tuple\", async () => {\n                const tuple = new Tuple(10,20,30);\n                const fn = async item => 2*item.unwrap();\n                expect(await tuple.imapAsync(fn)).to.be.Tuple([20,40,60]);\n            });\n        });\n\n        describe(\".vmapAsync(fn)\", () => {\n            \n            it(\"should asynchronously apply fn to all the item values of the tuple\", async () => {\n                const tuple = new Tuple(10,20,30);\n                const fn = async value => 2*value;\n                expect(await tuple.vmapAsync(fn)).to.be.Tuple([20,40,60]);\n            });\n        });\n\n        describe(\".toBoolean()\", () => {\n            \n            it(\"should return true if at least one item booleanizes to true\", () => {\n                expect((new Tuple(1,2,3)).toBoolean()).to.be.true;\n                expect((new Tuple(1)).toBoolean()).to.be.true;\n\n                expect((new Tuple(0,\"\",[])).toBoolean()).to.be.false;\n                expect((new Tuple(0)).toBoolean()).to.be.false;\n                expect((new Tuple()).toBoolean()).to.be.false;\n            });\n        });\n        \n        describe(\".toString()\", () => {\n            \n            it(\"should return the concatenation of the stringified items\", () => {\n                expect((new Tuple(\"abc\",0,true)).toString()).to.equal(\"abc0TRUE\");\n                expect((new Tuple()).toString()).to.equal(\"\");\n            });\n        });\n        \n        describe(\".typeName\", () => {\n            \n            it(\"should return 'Nothing' if the tuple is empty\", () => {\n                const tuple = new Tuple();\n                expect(tuple.typeName).to.equal(\"Nothing\");\n            });\n\n            it(\"should return the item typeName if the tuple contains only than one element\", () => {\n                const tuple = new Tuple(1);\n                expect(tuple.typeName).to.equal(\"Numb\");\n            });\n\n            it(\"should return the 'Tuple' if the tuple contains more than one element\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.typeName).to.equal(\"Tuple\");\n            });\n        });\n        \n        describe(\".isNothing()\", () => {\n            \n            it(\"should return true if the tuple is empty\", () => {\n                expect(new Tuple(1,2,3).isNothing()).to.be.false;\n                expect(new Tuple().isNothing()).to.be.true;\n            });\n        });\n        \n        describe(\".normalize()\", () => {\n            \n            it(\"should return the tuple as it is if it has no items\", () => {\n                const tuple = new Tuple();\n                expect(tuple.normalize()).to.equal(tuple);\n            });\n            \n            it(\"should return the item if the tuple has only one item\", () => {\n                expect(new Tuple(true   ).normalize()).to.be.Bool(true);\n                expect(new Tuple(10     ).normalize()).to.be.Numb(10);\n                expect(new Tuple('abc'  ).normalize()).to.be.Text('abc');\n                expect(new Tuple([1,2,3]).normalize()).to.be.List([1,2,3]);\n                expect(new Tuple({a:1}  ).normalize()).to.be.Namespace({a:1});\n            });\n\n            it(\"should return the tuple as it is if it has more than one item\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.normalize()).to.equal(tuple);\n            });\n        });\n        \n        describe(\".unwrap()\", () => {\n            \n            it(\"should return null if it has no items\", () => {\n                const tuple = new Tuple();\n                expect(tuple.unwrap()).to.equal(null);\n            });\n            \n            it(\"should return the item value if the tuple has only one item\", () => {\n                expect(new Tuple(true).unwrap()).to.equal(true);\n                expect(new Tuple(10).unwrap()).to.equal(10);\n                expect(new Tuple('abc').unwrap()).to.equal('abc');\n                expect(new Tuple([1,2,3]).unwrap()).to.deep.equal([1,2,3]);\n                expect(new Tuple({a:1}).unwrap()).to.deep.equal({a:1});\n            });\n\n            it(\"should return the tuple as it is if it has more than one item\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.unwrap()).to.equal(tuple);\n            });\n        });\n        \n        describe(\".sum(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.sum).to.be.undefined;\n            });\n        });\n        \n        describe(\".negate()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.negate).to.be.undefined;\n            });\n        });\n        \n        describe(\".isNull()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.isNull).to.be.undefined;\n            });\n        });\n        \n        describe(\"Tuple.null\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Tuple.null).to.be.undefined;\n            });\n        });\n        \n        describe(\".mul(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.mul).to.be.undefined;\n            });\n        });\n        \n        describe(\".invert()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.invert).to.be.undefined;\n            });\n        });\n        \n        describe(\".isUnit()\", () => {\n            \n            it(\"should not be defined\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.isUnit).to.be.undefined;\n            });\n        });\n        \n        describe(\"Tuple.unit\", () => {\n            \n            it(\"should not be defined\", () => {\n                expect(Tuple.unit).to.be.undefined;\n            });\n        });\n        \n        describe(\".pow(other)\", () => {\n            \n            it(\"should not be defined\", () => {\n                const tuple = new Tuple(1,2,3);\n                expect(tuple.pow).to.be.undefined;\n            });\n        });\n        \n        describe(\".compare(other)\", () => {\n                        \n            it(\"should compare the two tuple lexicographically\", () => {\n                const tuple1 = new Tuple(10,20,30);\n                const tuple2 = new Tuple(40,50,60);\n                expect(tuple1.compare(tuple1)).to.equal('=');\n                expect(tuple2.compare(tuple2)).to.equal('=');\n                expect(tuple1.compare(tuple2)).to.equal('<');\n                expect(tuple2.compare(tuple1)).to.equal('>');\n                \n                expect(new Tuple(10,10,10).compare(new Tuple(10,10))).to.equal('>');\n                expect(new Tuple(10,10,10).compare(new Numb(10))).to.equal('>');\n            });\n        });  \n    });\n    \n    describe(\"wrap\", () => {\n        \n        it(\"should convert a javascript object to its corresponding swan type\", () => {\n            \n            expect(wrap(null)).to.be.Tuple([]);\n            expect(wrap(undefined)).to.be.Tuple([]);\n\n            expect(wrap(NaN)).to.be.Undefined(\"Number\");\n            \n            expect(wrap(true)).to.be.Bool(true);\n            expect(wrap(10)).to.be.Numb(10);\n            expect(wrap('abc')).to.be.Text('abc');\n            expect(wrap([1,2,3])).to.be.List([1,2,3]);\n            expect(wrap({a:1})).to.be.Namespace({a:1})\n            \n            let fn = x => x;\n            expect(wrap(fn)).to.be.instanceof(Func);\n            expect(wrap(fn).unwrap()).to.equal(fn);\n            \n            expect(wrap(new Boolean(true))).to.be.Bool(true);\n            expect(wrap(new Number(10))).to.be.Numb(10);\n            expect(wrap(new String('abc'))).to.be.Text('abc');\n            expect(wrap(new Array(1,2,3))).to.be.List([1,2,3]);\n\n            fn = new Function(x => x);\n            expect(wrap(fn)).to.be.instanceof(Func);\n            expect(wrap(fn).unwrap()).to.equal(fn);\n        });\n\n        it(\"should return an already wrapped type as it is\", () => {\n            for (let term of [\n                new Bool(true), new Numb(10), new Text('abc'), new List([1,2,3]),\n                new Namespace({a:1}), new Undefined(), new Tuple(1,2,3)\n            ]) {\n                expect(wrap(term)).to.equal(term);\n            }\n        });\n    });\n\n    describe(\"unwrap\", () => {\n        \n        it(\"should convert a swan type to its corresponding javascript value\", () => {\n            \n            expect(unwrap(new Bool(true))).to.equal(true);\n            expect(unwrap(new Numb(10))).to.equal(10);\n            expect(unwrap(new Text('abc'))).to.equal('abc');\n            expect(unwrap(new List([1,2,3]))).to.deep.equal([1,2,3]);\n            \n            const fn = x => x;\n            expect(unwrap(new Func(fn))).to.equal(fn);\n            \n            expect(unwrap(new Tuple(1,2,3))).to.be.Tuple([1,2,3]);\n            expect(unwrap(new Tuple(1))).to.equal(1);\n            expect(unwrap(new Tuple())).to.equal(null);\n        });\n\n        it(\"should return an already unwrapped value as it is\", () => {\n            \n            for (let value of [null, true, 10, 'abc', [1,2,3], {a:1}, new Undefined(), new Tuple(1,2,3)]) {\n                expect(unwrap(value)).to.equal(value);\n            }\n        });\n    });\n});\n\n//# sourceURL=webpack:///../../node_modules/@onlabsorg/swan-js/test/types.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/assertion-error/index.js":
  /*!***************************************************!*\
    !*** ../../node_modules/assertion-error/index.js ***!
    \***************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * assertion-error\n * Copyright(c) 2013 Jake Luer <jake@qualiancy.com>\n * MIT Licensed\n */\n\n/*!\n * Return a function that will copy properties from\n * one object to another excluding any originally\n * listed. Returned function will create a new `{}`.\n *\n * @param {String} excluded properties ...\n * @return {Function}\n */\n\nfunction exclude () {\n  var excludes = [].slice.call(arguments);\n\n  function excludeProps (res, obj) {\n    Object.keys(obj).forEach(function (key) {\n      if (!~excludes.indexOf(key)) res[key] = obj[key];\n    });\n  }\n\n  return function extendExclude () {\n    var args = [].slice.call(arguments)\n      , i = 0\n      , res = {};\n\n    for (; i < args.length; i++) {\n      excludeProps(res, args[i]);\n    }\n\n    return res;\n  };\n};\n\n/*!\n * Primary Exports\n */\n\nmodule.exports = AssertionError;\n\n/**\n * ### AssertionError\n *\n * An extension of the JavaScript `Error` constructor for\n * assertion and validation scenarios.\n *\n * @param {String} message\n * @param {Object} properties to include (optional)\n * @param {callee} start stack function (optional)\n */\n\nfunction AssertionError (message, _props, ssf) {\n  var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')\n    , props = extend(_props || {});\n\n  // default values\n  this.message = message || 'Unspecified AssertionError';\n  this.showDiff = false;\n\n  // copy from properties\n  for (var key in props) {\n    this[key] = props[key];\n  }\n\n  // capture stack trace\n  ssf = ssf || AssertionError;\n  if (Error.captureStackTrace) {\n    Error.captureStackTrace(this, ssf);\n  } else {\n    try {\n      throw new Error();\n    } catch(e) {\n      this.stack = e.stack;\n    }\n  }\n}\n\n/*!\n * Inherit from Error.prototype\n */\n\nAssertionError.prototype = Object.create(Error.prototype);\n\n/*!\n * Statically set name\n */\n\nAssertionError.prototype.name = 'AssertionError';\n\n/*!\n * Ensure correct constructor\n */\n\nAssertionError.prototype.constructor = AssertionError;\n\n/**\n * Allow errors to be converted to JSON for static transfer.\n *\n * @param {Boolean} include stack (default: `true`)\n * @return {Object} object that can be `JSON.stringify`\n */\n\nAssertionError.prototype.toJSON = function (stack) {\n  var extend = exclude('constructor', 'toJSON', 'stack')\n    , props = extend({ name: this.name }, this);\n\n  // include stack if exists and not turned off\n  if (false !== stack && this.stack) {\n    props.stack = this.stack;\n  }\n\n  return props;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/assertion-error/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/index.js":
  /*!****************************************!*\
    !*** ../../node_modules/chai/index.js ***!
    \****************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("module.exports = __webpack_require__(/*! ./lib/chai */ \"../../node_modules/chai/lib/chai.js\");\n\n\n//# sourceURL=webpack:///../../node_modules/chai/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai.js":
  /*!*******************************************!*\
    !*** ../../node_modules/chai/lib/chai.js ***!
    \*******************************************/
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
  
  eval("/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar used = [];\n\n/*!\n * Chai version\n */\n\nexports.version = '4.3.3';\n\n/*!\n * Assertion Error\n */\n\nexports.AssertionError = __webpack_require__(/*! assertion-error */ \"../../node_modules/assertion-error/index.js\");\n\n/*!\n * Utils for plugins (not exported)\n */\n\nvar util = __webpack_require__(/*! ./chai/utils */ \"../../node_modules/chai/lib/chai/utils/index.js\");\n\n/**\n * # .use(function)\n *\n * Provides a way to extend the internals of Chai.\n *\n * @param {Function}\n * @returns {this} for chaining\n * @api public\n */\n\nexports.use = function (fn) {\n  if (!~used.indexOf(fn)) {\n    fn(exports, util);\n    used.push(fn);\n  }\n\n  return exports;\n};\n\n/*!\n * Utility Functions\n */\n\nexports.util = util;\n\n/*!\n * Configuration\n */\n\nvar config = __webpack_require__(/*! ./chai/config */ \"../../node_modules/chai/lib/chai/config.js\");\nexports.config = config;\n\n/*!\n * Primary `Assertion` prototype\n */\n\nvar assertion = __webpack_require__(/*! ./chai/assertion */ \"../../node_modules/chai/lib/chai/assertion.js\");\nexports.use(assertion);\n\n/*!\n * Core Assertions\n */\n\nvar core = __webpack_require__(/*! ./chai/core/assertions */ \"../../node_modules/chai/lib/chai/core/assertions.js\");\nexports.use(core);\n\n/*!\n * Expect interface\n */\n\nvar expect = __webpack_require__(/*! ./chai/interface/expect */ \"../../node_modules/chai/lib/chai/interface/expect.js\");\nexports.use(expect);\n\n/*!\n * Should interface\n */\n\nvar should = __webpack_require__(/*! ./chai/interface/should */ \"../../node_modules/chai/lib/chai/interface/should.js\");\nexports.use(should);\n\n/*!\n * Assert interface\n */\n\nvar assert = __webpack_require__(/*! ./chai/interface/assert */ \"../../node_modules/chai/lib/chai/interface/assert.js\");\nexports.use(assert);\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/assertion.js":
  /*!*****************************************************!*\
    !*** ../../node_modules/chai/lib/chai/assertion.js ***!
    \*****************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * chai\n * http://chaijs.com\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar config = __webpack_require__(/*! ./config */ \"../../node_modules/chai/lib/chai/config.js\");\n\nmodule.exports = function (_chai, util) {\n  /*!\n   * Module dependencies.\n   */\n\n  var AssertionError = _chai.AssertionError\n    , flag = util.flag;\n\n  /*!\n   * Module export.\n   */\n\n  _chai.Assertion = Assertion;\n\n  /*!\n   * Assertion Constructor\n   *\n   * Creates object for chaining.\n   *\n   * `Assertion` objects contain metadata in the form of flags. Three flags can\n   * be assigned during instantiation by passing arguments to this constructor:\n   *\n   * - `object`: This flag contains the target of the assertion. For example, in\n   *   the assertion `expect(numKittens).to.equal(7);`, the `object` flag will\n   *   contain `numKittens` so that the `equal` assertion can reference it when\n   *   needed.\n   *\n   * - `message`: This flag contains an optional custom error message to be\n   *   prepended to the error message that's generated by the assertion when it\n   *   fails.\n   *\n   * - `ssfi`: This flag stands for \"start stack function indicator\". It\n   *   contains a function reference that serves as the starting point for\n   *   removing frames from the stack trace of the error that's created by the\n   *   assertion when it fails. The goal is to provide a cleaner stack trace to\n   *   end users by removing Chai's internal functions. Note that it only works\n   *   in environments that support `Error.captureStackTrace`, and only when\n   *   `Chai.config.includeStack` hasn't been set to `false`.\n   *\n   * - `lockSsfi`: This flag controls whether or not the given `ssfi` flag\n   *   should retain its current value, even as assertions are chained off of\n   *   this object. This is usually set to `true` when creating a new assertion\n   *   from within another assertion. It's also temporarily set to `true` before\n   *   an overwritten assertion gets called by the overwriting assertion.\n   *\n   * @param {Mixed} obj target of the assertion\n   * @param {String} msg (optional) custom error message\n   * @param {Function} ssfi (optional) starting point for removing stack frames\n   * @param {Boolean} lockSsfi (optional) whether or not the ssfi flag is locked\n   * @api private\n   */\n\n  function Assertion (obj, msg, ssfi, lockSsfi) {\n    flag(this, 'ssfi', ssfi || Assertion);\n    flag(this, 'lockSsfi', lockSsfi);\n    flag(this, 'object', obj);\n    flag(this, 'message', msg);\n\n    return util.proxify(this);\n  }\n\n  Object.defineProperty(Assertion, 'includeStack', {\n    get: function() {\n      console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');\n      return config.includeStack;\n    },\n    set: function(value) {\n      console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');\n      config.includeStack = value;\n    }\n  });\n\n  Object.defineProperty(Assertion, 'showDiff', {\n    get: function() {\n      console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');\n      return config.showDiff;\n    },\n    set: function(value) {\n      console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');\n      config.showDiff = value;\n    }\n  });\n\n  Assertion.addProperty = function (name, fn) {\n    util.addProperty(this.prototype, name, fn);\n  };\n\n  Assertion.addMethod = function (name, fn) {\n    util.addMethod(this.prototype, name, fn);\n  };\n\n  Assertion.addChainableMethod = function (name, fn, chainingBehavior) {\n    util.addChainableMethod(this.prototype, name, fn, chainingBehavior);\n  };\n\n  Assertion.overwriteProperty = function (name, fn) {\n    util.overwriteProperty(this.prototype, name, fn);\n  };\n\n  Assertion.overwriteMethod = function (name, fn) {\n    util.overwriteMethod(this.prototype, name, fn);\n  };\n\n  Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {\n    util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);\n  };\n\n  /**\n   * ### .assert(expression, message, negateMessage, expected, actual, showDiff)\n   *\n   * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.\n   *\n   * @name assert\n   * @param {Philosophical} expression to be tested\n   * @param {String|Function} message or function that returns message to display if expression fails\n   * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails\n   * @param {Mixed} expected value (remember to check for negation)\n   * @param {Mixed} actual (optional) will default to `this.obj`\n   * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails\n   * @api private\n   */\n\n  Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {\n    var ok = util.test(this, arguments);\n    if (false !== showDiff) showDiff = true;\n    if (undefined === expected && undefined === _actual) showDiff = false;\n    if (true !== config.showDiff) showDiff = false;\n\n    if (!ok) {\n      msg = util.getMessage(this, arguments);\n      var actual = util.getActual(this, arguments);\n      var assertionErrorObjectProperties = {\n          actual: actual\n        , expected: expected\n        , showDiff: showDiff\n      };\n\n      var operator = util.getOperator(this, arguments);\n      if (operator) {\n        assertionErrorObjectProperties.operator = operator;\n      }\n\n      throw new AssertionError(\n        msg,\n        assertionErrorObjectProperties,\n        (config.includeStack) ? this.assert : flag(this, 'ssfi'));\n    }\n  };\n\n  /*!\n   * ### ._obj\n   *\n   * Quick reference to stored `actual` value for plugin developers.\n   *\n   * @api private\n   */\n\n  Object.defineProperty(Assertion.prototype, '_obj',\n    { get: function () {\n        return flag(this, 'object');\n      }\n    , set: function (val) {\n        flag(this, 'object', val);\n      }\n  });\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/assertion.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/config.js":
  /*!**************************************************!*\
    !*** ../../node_modules/chai/lib/chai/config.js ***!
    \**************************************************/
  /***/ ((module) => {
  
  eval("module.exports = {\n\n  /**\n   * ### config.includeStack\n   *\n   * User configurable property, influences whether stack trace\n   * is included in Assertion error message. Default of false\n   * suppresses stack trace in the error message.\n   *\n   *     chai.config.includeStack = true;  // enable stack on error\n   *\n   * @param {Boolean}\n   * @api public\n   */\n\n  includeStack: false,\n\n  /**\n   * ### config.showDiff\n   *\n   * User configurable property, influences whether or not\n   * the `showDiff` flag should be included in the thrown\n   * AssertionErrors. `false` will always be `false`; `true`\n   * will be true when the assertion has requested a diff\n   * be shown.\n   *\n   * @param {Boolean}\n   * @api public\n   */\n\n  showDiff: true,\n\n  /**\n   * ### config.truncateThreshold\n   *\n   * User configurable property, sets length threshold for actual and\n   * expected values in assertion errors. If this threshold is exceeded, for\n   * example for large data structures, the value is replaced with something\n   * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`.\n   *\n   * Set it to zero if you want to disable truncating altogether.\n   *\n   * This is especially userful when doing assertions on arrays: having this\n   * set to a reasonable large value makes the failure messages readily\n   * inspectable.\n   *\n   *     chai.config.truncateThreshold = 0;  // disable truncating\n   *\n   * @param {Number}\n   * @api public\n   */\n\n  truncateThreshold: 40,\n\n  /**\n   * ### config.useProxy\n   *\n   * User configurable property, defines if chai will use a Proxy to throw\n   * an error when a non-existent property is read, which protects users\n   * from typos when using property-based assertions.\n   *\n   * Set it to false if you want to disable this feature.\n   *\n   *     chai.config.useProxy = false;  // disable use of Proxy\n   *\n   * This feature is automatically disabled regardless of this config value\n   * in environments that don't support proxies.\n   *\n   * @param {Boolean}\n   * @api public\n   */\n\n  useProxy: true,\n\n  /**\n   * ### config.proxyExcludedKeys\n   *\n   * User configurable property, defines which properties should be ignored\n   * instead of throwing an error if they do not exist on the assertion.\n   * This is only applied if the environment Chai is running in supports proxies and\n   * if the `useProxy` configuration setting is enabled.\n   * By default, `then` and `inspect` will not throw an error if they do not exist on the\n   * assertion object because the `.inspect` property is read by `util.inspect` (for example, when\n   * using `console.log` on the assertion object) and `.then` is necessary for promise type-checking.\n   *\n   *     // By default these keys will not throw an error if they do not exist on the assertion object\n   *     chai.config.proxyExcludedKeys = ['then', 'inspect'];\n   *\n   * @param {Array}\n   * @api public\n   */\n\n  proxyExcludedKeys: ['then', 'catch', 'inspect', 'toJSON']\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/config.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/core/assertions.js":
  /*!***********************************************************!*\
    !*** ../../node_modules/chai/lib/chai/core/assertions.js ***!
    \***********************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * chai\n * http://chaijs.com\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, _) {\n  var Assertion = chai.Assertion\n    , AssertionError = chai.AssertionError\n    , flag = _.flag;\n\n  /**\n   * ### Language Chains\n   *\n   * The following are provided as chainable getters to improve the readability\n   * of your assertions.\n   *\n   * **Chains**\n   *\n   * - to\n   * - be\n   * - been\n   * - is\n   * - that\n   * - which\n   * - and\n   * - has\n   * - have\n   * - with\n   * - at\n   * - of\n   * - same\n   * - but\n   * - does\n   * - still\n   * - also\n   *\n   * @name language chains\n   * @namespace BDD\n   * @api public\n   */\n\n  [ 'to', 'be', 'been', 'is'\n  , 'and', 'has', 'have', 'with'\n  , 'that', 'which', 'at', 'of'\n  , 'same', 'but', 'does', 'still', \"also\" ].forEach(function (chain) {\n    Assertion.addProperty(chain);\n  });\n\n  /**\n   * ### .not\n   *\n   * Negates all assertions that follow in the chain.\n   *\n   *     expect(function () {}).to.not.throw();\n   *     expect({a: 1}).to.not.have.property('b');\n   *     expect([1, 2]).to.be.an('array').that.does.not.include(3);\n   *\n   * Just because you can negate any assertion with `.not` doesn't mean you\n   * should. With great power comes great responsibility. It's often best to\n   * assert that the one expected output was produced, rather than asserting\n   * that one of countless unexpected outputs wasn't produced. See individual\n   * assertions for specific guidance.\n   *\n   *     expect(2).to.equal(2); // Recommended\n   *     expect(2).to.not.equal(1); // Not recommended\n   *\n   * @name not\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('not', function () {\n    flag(this, 'negate', true);\n  });\n\n  /**\n   * ### .deep\n   *\n   * Causes all `.equal`, `.include`, `.members`, `.keys`, and `.property`\n   * assertions that follow in the chain to use deep equality instead of strict\n   * (`===`) equality. See the `deep-eql` project page for info on the deep\n   * equality algorithm: https://github.com/chaijs/deep-eql.\n   *\n   *     // Target object deeply (but not strictly) equals `{a: 1}`\n   *     expect({a: 1}).to.deep.equal({a: 1});\n   *     expect({a: 1}).to.not.equal({a: 1});\n   *\n   *     // Target array deeply (but not strictly) includes `{a: 1}`\n   *     expect([{a: 1}]).to.deep.include({a: 1});\n   *     expect([{a: 1}]).to.not.include({a: 1});\n   *\n   *     // Target object deeply (but not strictly) includes `x: {a: 1}`\n   *     expect({x: {a: 1}}).to.deep.include({x: {a: 1}});\n   *     expect({x: {a: 1}}).to.not.include({x: {a: 1}});\n   *\n   *     // Target array deeply (but not strictly) has member `{a: 1}`\n   *     expect([{a: 1}]).to.have.deep.members([{a: 1}]);\n   *     expect([{a: 1}]).to.not.have.members([{a: 1}]);\n   *\n   *     // Target set deeply (but not strictly) has key `{a: 1}`\n   *     expect(new Set([{a: 1}])).to.have.deep.keys([{a: 1}]);\n   *     expect(new Set([{a: 1}])).to.not.have.keys([{a: 1}]);\n   *\n   *     // Target object deeply (but not strictly) has property `x: {a: 1}`\n   *     expect({x: {a: 1}}).to.have.deep.property('x', {a: 1});\n   *     expect({x: {a: 1}}).to.not.have.property('x', {a: 1});\n   *\n   * @name deep\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('deep', function () {\n    flag(this, 'deep', true);\n  });\n\n  /**\n   * ### .nested\n   *\n   * Enables dot- and bracket-notation in all `.property` and `.include`\n   * assertions that follow in the chain.\n   *\n   *     expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]');\n   *     expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'});\n   *\n   * If `.` or `[]` are part of an actual property name, they can be escaped by\n   * adding two backslashes before them.\n   *\n   *     expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\\\.a.\\\\[b\\\\]');\n   *     expect({'.a': {'[b]': 'x'}}).to.nested.include({'\\\\.a.\\\\[b\\\\]': 'x'});\n   *\n   * `.nested` cannot be combined with `.own`.\n   *\n   * @name nested\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('nested', function () {\n    flag(this, 'nested', true);\n  });\n\n  /**\n   * ### .own\n   *\n   * Causes all `.property` and `.include` assertions that follow in the chain\n   * to ignore inherited properties.\n   *\n   *     Object.prototype.b = 2;\n   *\n   *     expect({a: 1}).to.have.own.property('a');\n   *     expect({a: 1}).to.have.property('b');\n   *     expect({a: 1}).to.not.have.own.property('b');\n   *\n   *     expect({a: 1}).to.own.include({a: 1});\n   *     expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2});\n   *\n   * `.own` cannot be combined with `.nested`.\n   *\n   * @name own\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('own', function () {\n    flag(this, 'own', true);\n  });\n\n  /**\n   * ### .ordered\n   *\n   * Causes all `.members` assertions that follow in the chain to require that\n   * members be in the same order.\n   *\n   *     expect([1, 2]).to.have.ordered.members([1, 2])\n   *       .but.not.have.ordered.members([2, 1]);\n   *\n   * When `.include` and `.ordered` are combined, the ordering begins at the\n   * start of both arrays.\n   *\n   *     expect([1, 2, 3]).to.include.ordered.members([1, 2])\n   *       .but.not.include.ordered.members([2, 3]);\n   *\n   * @name ordered\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('ordered', function () {\n    flag(this, 'ordered', true);\n  });\n\n  /**\n   * ### .any\n   *\n   * Causes all `.keys` assertions that follow in the chain to only require that\n   * the target have at least one of the given keys. This is the opposite of\n   * `.all`, which requires that the target have all of the given keys.\n   *\n   *     expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');\n   *\n   * See the `.keys` doc for guidance on when to use `.any` or `.all`.\n   *\n   * @name any\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('any', function () {\n    flag(this, 'any', true);\n    flag(this, 'all', false);\n  });\n\n  /**\n   * ### .all\n   *\n   * Causes all `.keys` assertions that follow in the chain to require that the\n   * target have all of the given keys. This is the opposite of `.any`, which\n   * only requires that the target have at least one of the given keys.\n   *\n   *     expect({a: 1, b: 2}).to.have.all.keys('a', 'b');\n   *\n   * Note that `.all` is used by default when neither `.all` nor `.any` are\n   * added earlier in the chain. However, it's often best to add `.all` anyway\n   * because it improves readability.\n   *\n   * See the `.keys` doc for guidance on when to use `.any` or `.all`.\n   *\n   * @name all\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('all', function () {\n    flag(this, 'all', true);\n    flag(this, 'any', false);\n  });\n\n  /**\n   * ### .a(type[, msg])\n   *\n   * Asserts that the target's type is equal to the given string `type`. Types\n   * are case insensitive. See the `type-detect` project page for info on the\n   * type detection algorithm: https://github.com/chaijs/type-detect.\n   *\n   *     expect('foo').to.be.a('string');\n   *     expect({a: 1}).to.be.an('object');\n   *     expect(null).to.be.a('null');\n   *     expect(undefined).to.be.an('undefined');\n   *     expect(new Error).to.be.an('error');\n   *     expect(Promise.resolve()).to.be.a('promise');\n   *     expect(new Float32Array).to.be.a('float32array');\n   *     expect(Symbol()).to.be.a('symbol');\n   *\n   * `.a` supports objects that have a custom type set via `Symbol.toStringTag`.\n   *\n   *     var myObj = {\n   *       [Symbol.toStringTag]: 'myCustomType'\n   *     };\n   *\n   *     expect(myObj).to.be.a('myCustomType').but.not.an('object');\n   *\n   * It's often best to use `.a` to check a target's type before making more\n   * assertions on the same target. That way, you avoid unexpected behavior from\n   * any assertion that does different things based on the target's type.\n   *\n   *     expect([1, 2, 3]).to.be.an('array').that.includes(2);\n   *     expect([]).to.be.an('array').that.is.empty;\n   *\n   * Add `.not` earlier in the chain to negate `.a`. However, it's often best to\n   * assert that the target is the expected type, rather than asserting that it\n   * isn't one of many unexpected types.\n   *\n   *     expect('foo').to.be.a('string'); // Recommended\n   *     expect('foo').to.not.be.an('array'); // Not recommended\n   *\n   * `.a` accepts an optional `msg` argument which is a custom error message to\n   * show when the assertion fails. The message can also be given as the second\n   * argument to `expect`.\n   *\n   *     expect(1).to.be.a('string', 'nooo why fail??');\n   *     expect(1, 'nooo why fail??').to.be.a('string');\n   *\n   * `.a` can also be used as a language chain to improve the readability of\n   * your assertions.\n   *\n   *     expect({b: 2}).to.have.a.property('b');\n   *\n   * The alias `.an` can be used interchangeably with `.a`.\n   *\n   * @name a\n   * @alias an\n   * @param {String} type\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function an (type, msg) {\n    if (msg) flag(this, 'message', msg);\n    type = type.toLowerCase();\n    var obj = flag(this, 'object')\n      , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';\n\n    this.assert(\n        type === _.type(obj).toLowerCase()\n      , 'expected #{this} to be ' + article + type\n      , 'expected #{this} not to be ' + article + type\n    );\n  }\n\n  Assertion.addChainableMethod('an', an);\n  Assertion.addChainableMethod('a', an);\n\n  /**\n   * ### .include(val[, msg])\n   *\n   * When the target is a string, `.include` asserts that the given string `val`\n   * is a substring of the target.\n   *\n   *     expect('foobar').to.include('foo');\n   *\n   * When the target is an array, `.include` asserts that the given `val` is a\n   * member of the target.\n   *\n   *     expect([1, 2, 3]).to.include(2);\n   *\n   * When the target is an object, `.include` asserts that the given object\n   * `val`'s properties are a subset of the target's properties.\n   *\n   *     expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2});\n   *\n   * When the target is a Set or WeakSet, `.include` asserts that the given `val` is a\n   * member of the target. SameValueZero equality algorithm is used.\n   *\n   *     expect(new Set([1, 2])).to.include(2);\n   *\n   * When the target is a Map, `.include` asserts that the given `val` is one of\n   * the values of the target. SameValueZero equality algorithm is used.\n   *\n   *     expect(new Map([['a', 1], ['b', 2]])).to.include(2);\n   *\n   * Because `.include` does different things based on the target's type, it's\n   * important to check the target's type before using `.include`. See the `.a`\n   * doc for info on testing a target's type.\n   *\n   *     expect([1, 2, 3]).to.be.an('array').that.includes(2);\n   *\n   * By default, strict (`===`) equality is used to compare array members and\n   * object properties. Add `.deep` earlier in the chain to use deep equality\n   * instead (WeakSet targets are not supported). See the `deep-eql` project\n   * page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql.\n   *\n   *     // Target array deeply (but not strictly) includes `{a: 1}`\n   *     expect([{a: 1}]).to.deep.include({a: 1});\n   *     expect([{a: 1}]).to.not.include({a: 1});\n   *\n   *     // Target object deeply (but not strictly) includes `x: {a: 1}`\n   *     expect({x: {a: 1}}).to.deep.include({x: {a: 1}});\n   *     expect({x: {a: 1}}).to.not.include({x: {a: 1}});\n   *\n   * By default, all of the target's properties are searched when working with\n   * objects. This includes properties that are inherited and/or non-enumerable.\n   * Add `.own` earlier in the chain to exclude the target's inherited\n   * properties from the search.\n   *\n   *     Object.prototype.b = 2;\n   *\n   *     expect({a: 1}).to.own.include({a: 1});\n   *     expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2});\n   *\n   * Note that a target object is always only searched for `val`'s own\n   * enumerable properties.\n   *\n   * `.deep` and `.own` can be combined.\n   *\n   *     expect({a: {b: 2}}).to.deep.own.include({a: {b: 2}});\n   *\n   * Add `.nested` earlier in the chain to enable dot- and bracket-notation when\n   * referencing nested properties.\n   *\n   *     expect({a: {b: ['x', 'y']}}).to.nested.include({'a.b[1]': 'y'});\n   *\n   * If `.` or `[]` are part of an actual property name, they can be escaped by\n   * adding two backslashes before them.\n   *\n   *     expect({'.a': {'[b]': 2}}).to.nested.include({'\\\\.a.\\\\[b\\\\]': 2});\n   *\n   * `.deep` and `.nested` can be combined.\n   *\n   *     expect({a: {b: [{c: 3}]}}).to.deep.nested.include({'a.b[0]': {c: 3}});\n   *\n   * `.own` and `.nested` cannot be combined.\n   *\n   * Add `.not` earlier in the chain to negate `.include`.\n   *\n   *     expect('foobar').to.not.include('taco');\n   *     expect([1, 2, 3]).to.not.include(4);\n   *\n   * However, it's dangerous to negate `.include` when the target is an object.\n   * The problem is that it creates uncertain expectations by asserting that the\n   * target object doesn't have all of `val`'s key/value pairs but may or may\n   * not have some of them. It's often best to identify the exact output that's\n   * expected, and then write an assertion that only accepts that exact output.\n   *\n   * When the target object isn't even expected to have `val`'s keys, it's\n   * often best to assert exactly that.\n   *\n   *     expect({c: 3}).to.not.have.any.keys('a', 'b'); // Recommended\n   *     expect({c: 3}).to.not.include({a: 1, b: 2}); // Not recommended\n   *\n   * When the target object is expected to have `val`'s keys, it's often best to\n   * assert that each of the properties has its expected value, rather than\n   * asserting that each property doesn't have one of many unexpected values.\n   *\n   *     expect({a: 3, b: 4}).to.include({a: 3, b: 4}); // Recommended\n   *     expect({a: 3, b: 4}).to.not.include({a: 1, b: 2}); // Not recommended\n   *\n   * `.include` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect([1, 2, 3]).to.include(4, 'nooo why fail??');\n   *     expect([1, 2, 3], 'nooo why fail??').to.include(4);\n   *\n   * `.include` can also be used as a language chain, causing all `.members` and\n   * `.keys` assertions that follow in the chain to require the target to be a\n   * superset of the expected set, rather than an identical set. Note that\n   * `.members` ignores duplicates in the subset when `.include` is added.\n   *\n   *     // Target object's keys are a superset of ['a', 'b'] but not identical\n   *     expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b');\n   *     expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b');\n   *\n   *     // Target array is a superset of [1, 2] but not identical\n   *     expect([1, 2, 3]).to.include.members([1, 2]);\n   *     expect([1, 2, 3]).to.not.have.members([1, 2]);\n   *\n   *     // Duplicates in the subset are ignored\n   *     expect([1, 2, 3]).to.include.members([1, 2, 2, 2]);\n   *\n   * Note that adding `.any` earlier in the chain causes the `.keys` assertion\n   * to ignore `.include`.\n   *\n   *     // Both assertions are identical\n   *     expect({a: 1}).to.include.any.keys('a', 'b');\n   *     expect({a: 1}).to.have.any.keys('a', 'b');\n   *\n   * The aliases `.includes`, `.contain`, and `.contains` can be used\n   * interchangeably with `.include`.\n   *\n   * @name include\n   * @alias contain\n   * @alias includes\n   * @alias contains\n   * @param {Mixed} val\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function SameValueZero(a, b) {\n    return (_.isNaN(a) && _.isNaN(b)) || a === b;\n  }\n\n  function includeChainingBehavior () {\n    flag(this, 'contains', true);\n  }\n\n  function include (val, msg) {\n    if (msg) flag(this, 'message', msg);\n\n    var obj = flag(this, 'object')\n      , objType = _.type(obj).toLowerCase()\n      , flagMsg = flag(this, 'message')\n      , negate = flag(this, 'negate')\n      , ssfi = flag(this, 'ssfi')\n      , isDeep = flag(this, 'deep')\n      , descriptor = isDeep ? 'deep ' : '';\n\n    flagMsg = flagMsg ? flagMsg + ': ' : '';\n\n    var included = false;\n\n    switch (objType) {\n      case 'string':\n        included = obj.indexOf(val) !== -1;\n        break;\n\n      case 'weakset':\n        if (isDeep) {\n          throw new AssertionError(\n            flagMsg + 'unable to use .deep.include with WeakSet',\n            undefined,\n            ssfi\n          );\n        }\n\n        included = obj.has(val);\n        break;\n\n      case 'map':\n        var isEql = isDeep ? _.eql : SameValueZero;\n        obj.forEach(function (item) {\n          included = included || isEql(item, val);\n        });\n        break;\n\n      case 'set':\n        if (isDeep) {\n          obj.forEach(function (item) {\n            included = included || _.eql(item, val);\n          });\n        } else {\n          included = obj.has(val);\n        }\n        break;\n\n      case 'array':\n        if (isDeep) {\n          included = obj.some(function (item) {\n            return _.eql(item, val);\n          })\n        } else {\n          included = obj.indexOf(val) !== -1;\n        }\n        break;\n\n      default:\n        // This block is for asserting a subset of properties in an object.\n        // `_.expectTypes` isn't used here because `.include` should work with\n        // objects with a custom `@@toStringTag`.\n        if (val !== Object(val)) {\n          throw new AssertionError(\n            flagMsg + 'the given combination of arguments ('\n            + objType + ' and '\n            + _.type(val).toLowerCase() + ')'\n            + ' is invalid for this assertion. '\n            + 'You can use an array, a map, an object, a set, a string, '\n            + 'or a weakset instead of a '\n            + _.type(val).toLowerCase(),\n            undefined,\n            ssfi\n          );\n        }\n\n        var props = Object.keys(val)\n          , firstErr = null\n          , numErrs = 0;\n\n        props.forEach(function (prop) {\n          var propAssertion = new Assertion(obj);\n          _.transferFlags(this, propAssertion, true);\n          flag(propAssertion, 'lockSsfi', true);\n\n          if (!negate || props.length === 1) {\n            propAssertion.property(prop, val[prop]);\n            return;\n          }\n\n          try {\n            propAssertion.property(prop, val[prop]);\n          } catch (err) {\n            if (!_.checkError.compatibleConstructor(err, AssertionError)) {\n              throw err;\n            }\n            if (firstErr === null) firstErr = err;\n            numErrs++;\n          }\n        }, this);\n\n        // When validating .not.include with multiple properties, we only want\n        // to throw an assertion error if all of the properties are included,\n        // in which case we throw the first property assertion error that we\n        // encountered.\n        if (negate && props.length > 1 && numErrs === props.length) {\n          throw firstErr;\n        }\n        return;\n    }\n\n    // Assert inclusion in collection or substring in a string.\n    this.assert(\n      included\n      , 'expected #{this} to ' + descriptor + 'include ' + _.inspect(val)\n      , 'expected #{this} to not ' + descriptor + 'include ' + _.inspect(val));\n  }\n\n  Assertion.addChainableMethod('include', include, includeChainingBehavior);\n  Assertion.addChainableMethod('contain', include, includeChainingBehavior);\n  Assertion.addChainableMethod('contains', include, includeChainingBehavior);\n  Assertion.addChainableMethod('includes', include, includeChainingBehavior);\n\n  /**\n   * ### .ok\n   *\n   * Asserts that the target is a truthy value (considered `true` in boolean context).\n   * However, it's often best to assert that the target is strictly (`===`) or\n   * deeply equal to its expected value.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.be.ok; // Not recommended\n   *\n   *     expect(true).to.be.true; // Recommended\n   *     expect(true).to.be.ok; // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.ok`.\n   *\n   *     expect(0).to.equal(0); // Recommended\n   *     expect(0).to.not.be.ok; // Not recommended\n   *\n   *     expect(false).to.be.false; // Recommended\n   *     expect(false).to.not.be.ok; // Not recommended\n   *\n   *     expect(null).to.be.null; // Recommended\n   *     expect(null).to.not.be.ok; // Not recommended\n   *\n   *     expect(undefined).to.be.undefined; // Recommended\n   *     expect(undefined).to.not.be.ok; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(false, 'nooo why fail??').to.be.ok;\n   *\n   * @name ok\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('ok', function () {\n    this.assert(\n        flag(this, 'object')\n      , 'expected #{this} to be truthy'\n      , 'expected #{this} to be falsy');\n  });\n\n  /**\n   * ### .true\n   *\n   * Asserts that the target is strictly (`===`) equal to `true`.\n   *\n   *     expect(true).to.be.true;\n   *\n   * Add `.not` earlier in the chain to negate `.true`. However, it's often best\n   * to assert that the target is equal to its expected value, rather than not\n   * equal to `true`.\n   *\n   *     expect(false).to.be.false; // Recommended\n   *     expect(false).to.not.be.true; // Not recommended\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.be.true; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(false, 'nooo why fail??').to.be.true;\n   *\n   * @name true\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('true', function () {\n    this.assert(\n        true === flag(this, 'object')\n      , 'expected #{this} to be true'\n      , 'expected #{this} to be false'\n      , flag(this, 'negate') ? false : true\n    );\n  });\n\n  /**\n   * ### .false\n   *\n   * Asserts that the target is strictly (`===`) equal to `false`.\n   *\n   *     expect(false).to.be.false;\n   *\n   * Add `.not` earlier in the chain to negate `.false`. However, it's often\n   * best to assert that the target is equal to its expected value, rather than\n   * not equal to `false`.\n   *\n   *     expect(true).to.be.true; // Recommended\n   *     expect(true).to.not.be.false; // Not recommended\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.be.false; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(true, 'nooo why fail??').to.be.false;\n   *\n   * @name false\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('false', function () {\n    this.assert(\n        false === flag(this, 'object')\n      , 'expected #{this} to be false'\n      , 'expected #{this} to be true'\n      , flag(this, 'negate') ? true : false\n    );\n  });\n\n  /**\n   * ### .null\n   *\n   * Asserts that the target is strictly (`===`) equal to `null`.\n   *\n   *     expect(null).to.be.null;\n   *\n   * Add `.not` earlier in the chain to negate `.null`. However, it's often best\n   * to assert that the target is equal to its expected value, rather than not\n   * equal to `null`.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.be.null; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(42, 'nooo why fail??').to.be.null;\n   *\n   * @name null\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('null', function () {\n    this.assert(\n        null === flag(this, 'object')\n      , 'expected #{this} to be null'\n      , 'expected #{this} not to be null'\n    );\n  });\n\n  /**\n   * ### .undefined\n   *\n   * Asserts that the target is strictly (`===`) equal to `undefined`.\n   *\n   *     expect(undefined).to.be.undefined;\n   *\n   * Add `.not` earlier in the chain to negate `.undefined`. However, it's often\n   * best to assert that the target is equal to its expected value, rather than\n   * not equal to `undefined`.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.be.undefined; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(42, 'nooo why fail??').to.be.undefined;\n   *\n   * @name undefined\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('undefined', function () {\n    this.assert(\n        undefined === flag(this, 'object')\n      , 'expected #{this} to be undefined'\n      , 'expected #{this} not to be undefined'\n    );\n  });\n\n  /**\n   * ### .NaN\n   *\n   * Asserts that the target is exactly `NaN`.\n   *\n   *     expect(NaN).to.be.NaN;\n   *\n   * Add `.not` earlier in the chain to negate `.NaN`. However, it's often best\n   * to assert that the target is equal to its expected value, rather than not\n   * equal to `NaN`.\n   *\n   *     expect('foo').to.equal('foo'); // Recommended\n   *     expect('foo').to.not.be.NaN; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(42, 'nooo why fail??').to.be.NaN;\n   *\n   * @name NaN\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('NaN', function () {\n    this.assert(\n        _.isNaN(flag(this, 'object'))\n        , 'expected #{this} to be NaN'\n        , 'expected #{this} not to be NaN'\n    );\n  });\n\n  /**\n   * ### .exist\n   *\n   * Asserts that the target is not strictly (`===`) equal to either `null` or\n   * `undefined`. However, it's often best to assert that the target is equal to\n   * its expected value.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.exist; // Not recommended\n   *\n   *     expect(0).to.equal(0); // Recommended\n   *     expect(0).to.exist; // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.exist`.\n   *\n   *     expect(null).to.be.null; // Recommended\n   *     expect(null).to.not.exist; // Not recommended\n   *\n   *     expect(undefined).to.be.undefined; // Recommended\n   *     expect(undefined).to.not.exist; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(null, 'nooo why fail??').to.exist;\n   *\n   * The alias `.exists` can be used interchangeably with `.exist`.\n   *\n   * @name exist\n   * @alias exists\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertExist () {\n    var val = flag(this, 'object');\n    this.assert(\n        val !== null && val !== undefined\n      , 'expected #{this} to exist'\n      , 'expected #{this} to not exist'\n    );\n  }\n\n  Assertion.addProperty('exist', assertExist);\n  Assertion.addProperty('exists', assertExist);\n\n  /**\n   * ### .empty\n   *\n   * When the target is a string or array, `.empty` asserts that the target's\n   * `length` property is strictly (`===`) equal to `0`.\n   *\n   *     expect([]).to.be.empty;\n   *     expect('').to.be.empty;\n   *\n   * When the target is a map or set, `.empty` asserts that the target's `size`\n   * property is strictly equal to `0`.\n   *\n   *     expect(new Set()).to.be.empty;\n   *     expect(new Map()).to.be.empty;\n   *\n   * When the target is a non-function object, `.empty` asserts that the target\n   * doesn't have any own enumerable properties. Properties with Symbol-based\n   * keys are excluded from the count.\n   *\n   *     expect({}).to.be.empty;\n   *\n   * Because `.empty` does different things based on the target's type, it's\n   * important to check the target's type before using `.empty`. See the `.a`\n   * doc for info on testing a target's type.\n   *\n   *     expect([]).to.be.an('array').that.is.empty;\n   *\n   * Add `.not` earlier in the chain to negate `.empty`. However, it's often\n   * best to assert that the target contains its expected number of values,\n   * rather than asserting that it's not empty.\n   *\n   *     expect([1, 2, 3]).to.have.lengthOf(3); // Recommended\n   *     expect([1, 2, 3]).to.not.be.empty; // Not recommended\n   *\n   *     expect(new Set([1, 2, 3])).to.have.property('size', 3); // Recommended\n   *     expect(new Set([1, 2, 3])).to.not.be.empty; // Not recommended\n   *\n   *     expect(Object.keys({a: 1})).to.have.lengthOf(1); // Recommended\n   *     expect({a: 1}).to.not.be.empty; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect([1, 2, 3], 'nooo why fail??').to.be.empty;\n   *\n   * @name empty\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('empty', function () {\n    var val = flag(this, 'object')\n      , ssfi = flag(this, 'ssfi')\n      , flagMsg = flag(this, 'message')\n      , itemsCount;\n\n    flagMsg = flagMsg ? flagMsg + ': ' : '';\n\n    switch (_.type(val).toLowerCase()) {\n      case 'array':\n      case 'string':\n        itemsCount = val.length;\n        break;\n      case 'map':\n      case 'set':\n        itemsCount = val.size;\n        break;\n      case 'weakmap':\n      case 'weakset':\n        throw new AssertionError(\n          flagMsg + '.empty was passed a weak collection',\n          undefined,\n          ssfi\n        );\n      case 'function':\n        var msg = flagMsg + '.empty was passed a function ' + _.getName(val);\n        throw new AssertionError(msg.trim(), undefined, ssfi);\n      default:\n        if (val !== Object(val)) {\n          throw new AssertionError(\n            flagMsg + '.empty was passed non-string primitive ' + _.inspect(val),\n            undefined,\n            ssfi\n          );\n        }\n        itemsCount = Object.keys(val).length;\n    }\n\n    this.assert(\n        0 === itemsCount\n      , 'expected #{this} to be empty'\n      , 'expected #{this} not to be empty'\n    );\n  });\n\n  /**\n   * ### .arguments\n   *\n   * Asserts that the target is an `arguments` object.\n   *\n   *     function test () {\n   *       expect(arguments).to.be.arguments;\n   *     }\n   *\n   *     test();\n   *\n   * Add `.not` earlier in the chain to negate `.arguments`. However, it's often\n   * best to assert which type the target is expected to be, rather than\n   * asserting that it’s not an `arguments` object.\n   *\n   *     expect('foo').to.be.a('string'); // Recommended\n   *     expect('foo').to.not.be.arguments; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect({}, 'nooo why fail??').to.be.arguments;\n   *\n   * The alias `.Arguments` can be used interchangeably with `.arguments`.\n   *\n   * @name arguments\n   * @alias Arguments\n   * @namespace BDD\n   * @api public\n   */\n\n  function checkArguments () {\n    var obj = flag(this, 'object')\n      , type = _.type(obj);\n    this.assert(\n        'Arguments' === type\n      , 'expected #{this} to be arguments but got ' + type\n      , 'expected #{this} to not be arguments'\n    );\n  }\n\n  Assertion.addProperty('arguments', checkArguments);\n  Assertion.addProperty('Arguments', checkArguments);\n\n  /**\n   * ### .equal(val[, msg])\n   *\n   * Asserts that the target is strictly (`===`) equal to the given `val`.\n   *\n   *     expect(1).to.equal(1);\n   *     expect('foo').to.equal('foo');\n   *\n   * Add `.deep` earlier in the chain to use deep equality instead. See the\n   * `deep-eql` project page for info on the deep equality algorithm:\n   * https://github.com/chaijs/deep-eql.\n   *\n   *     // Target object deeply (but not strictly) equals `{a: 1}`\n   *     expect({a: 1}).to.deep.equal({a: 1});\n   *     expect({a: 1}).to.not.equal({a: 1});\n   *\n   *     // Target array deeply (but not strictly) equals `[1, 2]`\n   *     expect([1, 2]).to.deep.equal([1, 2]);\n   *     expect([1, 2]).to.not.equal([1, 2]);\n   *\n   * Add `.not` earlier in the chain to negate `.equal`. However, it's often\n   * best to assert that the target is equal to its expected value, rather than\n   * not equal to one of countless unexpected values.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.equal(2); // Not recommended\n   *\n   * `.equal` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect(1).to.equal(2, 'nooo why fail??');\n   *     expect(1, 'nooo why fail??').to.equal(2);\n   *\n   * The aliases `.equals` and `eq` can be used interchangeably with `.equal`.\n   *\n   * @name equal\n   * @alias equals\n   * @alias eq\n   * @param {Mixed} val\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertEqual (val, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    if (flag(this, 'deep')) {\n      var prevLockSsfi = flag(this, 'lockSsfi');\n      flag(this, 'lockSsfi', true);\n      this.eql(val);\n      flag(this, 'lockSsfi', prevLockSsfi);\n    } else {\n      this.assert(\n          val === obj\n        , 'expected #{this} to equal #{exp}'\n        , 'expected #{this} to not equal #{exp}'\n        , val\n        , this._obj\n        , true\n      );\n    }\n  }\n\n  Assertion.addMethod('equal', assertEqual);\n  Assertion.addMethod('equals', assertEqual);\n  Assertion.addMethod('eq', assertEqual);\n\n  /**\n   * ### .eql(obj[, msg])\n   *\n   * Asserts that the target is deeply equal to the given `obj`. See the\n   * `deep-eql` project page for info on the deep equality algorithm:\n   * https://github.com/chaijs/deep-eql.\n   *\n   *     // Target object is deeply (but not strictly) equal to {a: 1}\n   *     expect({a: 1}).to.eql({a: 1}).but.not.equal({a: 1});\n   *\n   *     // Target array is deeply (but not strictly) equal to [1, 2]\n   *     expect([1, 2]).to.eql([1, 2]).but.not.equal([1, 2]);\n   *\n   * Add `.not` earlier in the chain to negate `.eql`. However, it's often best\n   * to assert that the target is deeply equal to its expected value, rather\n   * than not deeply equal to one of countless unexpected values.\n   *\n   *     expect({a: 1}).to.eql({a: 1}); // Recommended\n   *     expect({a: 1}).to.not.eql({b: 2}); // Not recommended\n   *\n   * `.eql` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect({a: 1}).to.eql({b: 2}, 'nooo why fail??');\n   *     expect({a: 1}, 'nooo why fail??').to.eql({b: 2});\n   *\n   * The alias `.eqls` can be used interchangeably with `.eql`.\n   *\n   * The `.deep.equal` assertion is almost identical to `.eql` but with one\n   * difference: `.deep.equal` causes deep equality comparisons to also be used\n   * for any other assertions that follow in the chain.\n   *\n   * @name eql\n   * @alias eqls\n   * @param {Mixed} obj\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertEql(obj, msg) {\n    if (msg) flag(this, 'message', msg);\n    this.assert(\n        _.eql(obj, flag(this, 'object'))\n      , 'expected #{this} to deeply equal #{exp}'\n      , 'expected #{this} to not deeply equal #{exp}'\n      , obj\n      , this._obj\n      , true\n    );\n  }\n\n  Assertion.addMethod('eql', assertEql);\n  Assertion.addMethod('eqls', assertEql);\n\n  /**\n   * ### .above(n[, msg])\n   *\n   * Asserts that the target is a number or a date greater than the given number or date `n` respectively.\n   * However, it's often best to assert that the target is equal to its expected\n   * value.\n   *\n   *     expect(2).to.equal(2); // Recommended\n   *     expect(2).to.be.above(1); // Not recommended\n   *\n   * Add `.lengthOf` earlier in the chain to assert that the target's `length`\n   * or `size` is greater than the given number `n`.\n   *\n   *     expect('foo').to.have.lengthOf(3); // Recommended\n   *     expect('foo').to.have.lengthOf.above(2); // Not recommended\n   *\n   *     expect([1, 2, 3]).to.have.lengthOf(3); // Recommended\n   *     expect([1, 2, 3]).to.have.lengthOf.above(2); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.above`.\n   *\n   *     expect(2).to.equal(2); // Recommended\n   *     expect(1).to.not.be.above(2); // Not recommended\n   *\n   * `.above` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect(1).to.be.above(2, 'nooo why fail??');\n   *     expect(1, 'nooo why fail??').to.be.above(2);\n   *\n   * The aliases `.gt` and `.greaterThan` can be used interchangeably with\n   * `.above`.\n   *\n   * @name above\n   * @alias gt\n   * @alias greaterThan\n   * @param {Number} n\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertAbove (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , doLength = flag(this, 'doLength')\n      , flagMsg = flag(this, 'message')\n      , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')\n      , ssfi = flag(this, 'ssfi')\n      , objType = _.type(obj).toLowerCase()\n      , nType = _.type(n).toLowerCase()\n      , errorMessage\n      , shouldThrow = true;\n\n    if (doLength && objType !== 'map' && objType !== 'set') {\n      new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');\n    }\n\n    if (!doLength && (objType === 'date' && nType !== 'date')) {\n      errorMessage = msgPrefix + 'the argument to above must be a date';\n    } else if (nType !== 'number' && (doLength || objType === 'number')) {\n      errorMessage = msgPrefix + 'the argument to above must be a number';\n    } else if (!doLength && (objType !== 'date' && objType !== 'number')) {\n      var printObj = (objType === 'string') ? \"'\" + obj + \"'\" : obj;\n      errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';\n    } else {\n      shouldThrow = false;\n    }\n\n    if (shouldThrow) {\n      throw new AssertionError(errorMessage, undefined, ssfi);\n    }\n\n    if (doLength) {\n      var descriptor = 'length'\n        , itemsCount;\n      if (objType === 'map' || objType === 'set') {\n        descriptor = 'size';\n        itemsCount = obj.size;\n      } else {\n        itemsCount = obj.length;\n      }\n      this.assert(\n          itemsCount > n\n        , 'expected #{this} to have a ' + descriptor + ' above #{exp} but got #{act}'\n        , 'expected #{this} to not have a ' + descriptor + ' above #{exp}'\n        , n\n        , itemsCount\n      );\n    } else {\n      this.assert(\n          obj > n\n        , 'expected #{this} to be above #{exp}'\n        , 'expected #{this} to be at most #{exp}'\n        , n\n      );\n    }\n  }\n\n  Assertion.addMethod('above', assertAbove);\n  Assertion.addMethod('gt', assertAbove);\n  Assertion.addMethod('greaterThan', assertAbove);\n\n  /**\n   * ### .least(n[, msg])\n   *\n   * Asserts that the target is a number or a date greater than or equal to the given\n   * number or date `n` respectively. However, it's often best to assert that the target is equal to\n   * its expected value.\n   *\n   *     expect(2).to.equal(2); // Recommended\n   *     expect(2).to.be.at.least(1); // Not recommended\n   *     expect(2).to.be.at.least(2); // Not recommended\n   *\n   * Add `.lengthOf` earlier in the chain to assert that the target's `length`\n   * or `size` is greater than or equal to the given number `n`.\n   *\n   *     expect('foo').to.have.lengthOf(3); // Recommended\n   *     expect('foo').to.have.lengthOf.at.least(2); // Not recommended\n   *\n   *     expect([1, 2, 3]).to.have.lengthOf(3); // Recommended\n   *     expect([1, 2, 3]).to.have.lengthOf.at.least(2); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.least`.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.be.at.least(2); // Not recommended\n   *\n   * `.least` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect(1).to.be.at.least(2, 'nooo why fail??');\n   *     expect(1, 'nooo why fail??').to.be.at.least(2);\n   *\n   * The aliases `.gte` and `.greaterThanOrEqual` can be used interchangeably with\n   * `.least`.\n   *\n   * @name least\n   * @alias gte\n   * @alias greaterThanOrEqual\n   * @param {Number} n\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertLeast (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , doLength = flag(this, 'doLength')\n      , flagMsg = flag(this, 'message')\n      , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')\n      , ssfi = flag(this, 'ssfi')\n      , objType = _.type(obj).toLowerCase()\n      , nType = _.type(n).toLowerCase()\n      , errorMessage\n      , shouldThrow = true;\n\n    if (doLength && objType !== 'map' && objType !== 'set') {\n      new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');\n    }\n\n    if (!doLength && (objType === 'date' && nType !== 'date')) {\n      errorMessage = msgPrefix + 'the argument to least must be a date';\n    } else if (nType !== 'number' && (doLength || objType === 'number')) {\n      errorMessage = msgPrefix + 'the argument to least must be a number';\n    } else if (!doLength && (objType !== 'date' && objType !== 'number')) {\n      var printObj = (objType === 'string') ? \"'\" + obj + \"'\" : obj;\n      errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';\n    } else {\n      shouldThrow = false;\n    }\n\n    if (shouldThrow) {\n      throw new AssertionError(errorMessage, undefined, ssfi);\n    }\n\n    if (doLength) {\n      var descriptor = 'length'\n        , itemsCount;\n      if (objType === 'map' || objType === 'set') {\n        descriptor = 'size';\n        itemsCount = obj.size;\n      } else {\n        itemsCount = obj.length;\n      }\n      this.assert(\n          itemsCount >= n\n        , 'expected #{this} to have a ' + descriptor + ' at least #{exp} but got #{act}'\n        , 'expected #{this} to have a ' + descriptor + ' below #{exp}'\n        , n\n        , itemsCount\n      );\n    } else {\n      this.assert(\n          obj >= n\n        , 'expected #{this} to be at least #{exp}'\n        , 'expected #{this} to be below #{exp}'\n        , n\n      );\n    }\n  }\n\n  Assertion.addMethod('least', assertLeast);\n  Assertion.addMethod('gte', assertLeast);\n  Assertion.addMethod('greaterThanOrEqual', assertLeast);\n\n  /**\n   * ### .below(n[, msg])\n   *\n   * Asserts that the target is a number or a date less than the given number or date `n` respectively.\n   * However, it's often best to assert that the target is equal to its expected\n   * value.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.be.below(2); // Not recommended\n   *\n   * Add `.lengthOf` earlier in the chain to assert that the target's `length`\n   * or `size` is less than the given number `n`.\n   *\n   *     expect('foo').to.have.lengthOf(3); // Recommended\n   *     expect('foo').to.have.lengthOf.below(4); // Not recommended\n   *\n   *     expect([1, 2, 3]).to.have.length(3); // Recommended\n   *     expect([1, 2, 3]).to.have.lengthOf.below(4); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.below`.\n   *\n   *     expect(2).to.equal(2); // Recommended\n   *     expect(2).to.not.be.below(1); // Not recommended\n   *\n   * `.below` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect(2).to.be.below(1, 'nooo why fail??');\n   *     expect(2, 'nooo why fail??').to.be.below(1);\n   *\n   * The aliases `.lt` and `.lessThan` can be used interchangeably with\n   * `.below`.\n   *\n   * @name below\n   * @alias lt\n   * @alias lessThan\n   * @param {Number} n\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertBelow (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , doLength = flag(this, 'doLength')\n      , flagMsg = flag(this, 'message')\n      , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')\n      , ssfi = flag(this, 'ssfi')\n      , objType = _.type(obj).toLowerCase()\n      , nType = _.type(n).toLowerCase()\n      , errorMessage\n      , shouldThrow = true;\n\n    if (doLength && objType !== 'map' && objType !== 'set') {\n      new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');\n    }\n\n    if (!doLength && (objType === 'date' && nType !== 'date')) {\n      errorMessage = msgPrefix + 'the argument to below must be a date';\n    } else if (nType !== 'number' && (doLength || objType === 'number')) {\n      errorMessage = msgPrefix + 'the argument to below must be a number';\n    } else if (!doLength && (objType !== 'date' && objType !== 'number')) {\n      var printObj = (objType === 'string') ? \"'\" + obj + \"'\" : obj;\n      errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';\n    } else {\n      shouldThrow = false;\n    }\n\n    if (shouldThrow) {\n      throw new AssertionError(errorMessage, undefined, ssfi);\n    }\n\n    if (doLength) {\n      var descriptor = 'length'\n        , itemsCount;\n      if (objType === 'map' || objType === 'set') {\n        descriptor = 'size';\n        itemsCount = obj.size;\n      } else {\n        itemsCount = obj.length;\n      }\n      this.assert(\n          itemsCount < n\n        , 'expected #{this} to have a ' + descriptor + ' below #{exp} but got #{act}'\n        , 'expected #{this} to not have a ' + descriptor + ' below #{exp}'\n        , n\n        , itemsCount\n      );\n    } else {\n      this.assert(\n          obj < n\n        , 'expected #{this} to be below #{exp}'\n        , 'expected #{this} to be at least #{exp}'\n        , n\n      );\n    }\n  }\n\n  Assertion.addMethod('below', assertBelow);\n  Assertion.addMethod('lt', assertBelow);\n  Assertion.addMethod('lessThan', assertBelow);\n\n  /**\n   * ### .most(n[, msg])\n   *\n   * Asserts that the target is a number or a date less than or equal to the given number\n   * or date `n` respectively. However, it's often best to assert that the target is equal to its\n   * expected value.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.be.at.most(2); // Not recommended\n   *     expect(1).to.be.at.most(1); // Not recommended\n   *\n   * Add `.lengthOf` earlier in the chain to assert that the target's `length`\n   * or `size` is less than or equal to the given number `n`.\n   *\n   *     expect('foo').to.have.lengthOf(3); // Recommended\n   *     expect('foo').to.have.lengthOf.at.most(4); // Not recommended\n   *\n   *     expect([1, 2, 3]).to.have.lengthOf(3); // Recommended\n   *     expect([1, 2, 3]).to.have.lengthOf.at.most(4); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.most`.\n   *\n   *     expect(2).to.equal(2); // Recommended\n   *     expect(2).to.not.be.at.most(1); // Not recommended\n   *\n   * `.most` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect(2).to.be.at.most(1, 'nooo why fail??');\n   *     expect(2, 'nooo why fail??').to.be.at.most(1);\n   *\n   * The aliases `.lte` and `.lessThanOrEqual` can be used interchangeably with\n   * `.most`.\n   *\n   * @name most\n   * @alias lte\n   * @alias lessThanOrEqual\n   * @param {Number} n\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertMost (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , doLength = flag(this, 'doLength')\n      , flagMsg = flag(this, 'message')\n      , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')\n      , ssfi = flag(this, 'ssfi')\n      , objType = _.type(obj).toLowerCase()\n      , nType = _.type(n).toLowerCase()\n      , errorMessage\n      , shouldThrow = true;\n\n    if (doLength && objType !== 'map' && objType !== 'set') {\n      new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');\n    }\n\n    if (!doLength && (objType === 'date' && nType !== 'date')) {\n      errorMessage = msgPrefix + 'the argument to most must be a date';\n    } else if (nType !== 'number' && (doLength || objType === 'number')) {\n      errorMessage = msgPrefix + 'the argument to most must be a number';\n    } else if (!doLength && (objType !== 'date' && objType !== 'number')) {\n      var printObj = (objType === 'string') ? \"'\" + obj + \"'\" : obj;\n      errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';\n    } else {\n      shouldThrow = false;\n    }\n\n    if (shouldThrow) {\n      throw new AssertionError(errorMessage, undefined, ssfi);\n    }\n\n    if (doLength) {\n      var descriptor = 'length'\n        , itemsCount;\n      if (objType === 'map' || objType === 'set') {\n        descriptor = 'size';\n        itemsCount = obj.size;\n      } else {\n        itemsCount = obj.length;\n      }\n      this.assert(\n          itemsCount <= n\n        , 'expected #{this} to have a ' + descriptor + ' at most #{exp} but got #{act}'\n        , 'expected #{this} to have a ' + descriptor + ' above #{exp}'\n        , n\n        , itemsCount\n      );\n    } else {\n      this.assert(\n          obj <= n\n        , 'expected #{this} to be at most #{exp}'\n        , 'expected #{this} to be above #{exp}'\n        , n\n      );\n    }\n  }\n\n  Assertion.addMethod('most', assertMost);\n  Assertion.addMethod('lte', assertMost);\n  Assertion.addMethod('lessThanOrEqual', assertMost);\n\n  /**\n   * ### .within(start, finish[, msg])\n   *\n   * Asserts that the target is a number or a date greater than or equal to the given\n   * number or date `start`, and less than or equal to the given number or date `finish` respectively.\n   * However, it's often best to assert that the target is equal to its expected\n   * value.\n   *\n   *     expect(2).to.equal(2); // Recommended\n   *     expect(2).to.be.within(1, 3); // Not recommended\n   *     expect(2).to.be.within(2, 3); // Not recommended\n   *     expect(2).to.be.within(1, 2); // Not recommended\n   *\n   * Add `.lengthOf` earlier in the chain to assert that the target's `length`\n   * or `size` is greater than or equal to the given number `start`, and less\n   * than or equal to the given number `finish`.\n   *\n   *     expect('foo').to.have.lengthOf(3); // Recommended\n   *     expect('foo').to.have.lengthOf.within(2, 4); // Not recommended\n   *\n   *     expect([1, 2, 3]).to.have.lengthOf(3); // Recommended\n   *     expect([1, 2, 3]).to.have.lengthOf.within(2, 4); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.within`.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.be.within(2, 4); // Not recommended\n   *\n   * `.within` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect(4).to.be.within(1, 3, 'nooo why fail??');\n   *     expect(4, 'nooo why fail??').to.be.within(1, 3);\n   *\n   * @name within\n   * @param {Number} start lower bound inclusive\n   * @param {Number} finish upper bound inclusive\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addMethod('within', function (start, finish, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , doLength = flag(this, 'doLength')\n      , flagMsg = flag(this, 'message')\n      , msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')\n      , ssfi = flag(this, 'ssfi')\n      , objType = _.type(obj).toLowerCase()\n      , startType = _.type(start).toLowerCase()\n      , finishType = _.type(finish).toLowerCase()\n      , errorMessage\n      , shouldThrow = true\n      , range = (startType === 'date' && finishType === 'date')\n          ? start.toISOString() + '..' + finish.toISOString()\n          : start + '..' + finish;\n\n    if (doLength && objType !== 'map' && objType !== 'set') {\n      new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');\n    }\n\n    if (!doLength && (objType === 'date' && (startType !== 'date' || finishType !== 'date'))) {\n      errorMessage = msgPrefix + 'the arguments to within must be dates';\n    } else if ((startType !== 'number' || finishType !== 'number') && (doLength || objType === 'number')) {\n      errorMessage = msgPrefix + 'the arguments to within must be numbers';\n    } else if (!doLength && (objType !== 'date' && objType !== 'number')) {\n      var printObj = (objType === 'string') ? \"'\" + obj + \"'\" : obj;\n      errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';\n    } else {\n      shouldThrow = false;\n    }\n\n    if (shouldThrow) {\n      throw new AssertionError(errorMessage, undefined, ssfi);\n    }\n\n    if (doLength) {\n      var descriptor = 'length'\n        , itemsCount;\n      if (objType === 'map' || objType === 'set') {\n        descriptor = 'size';\n        itemsCount = obj.size;\n      } else {\n        itemsCount = obj.length;\n      }\n      this.assert(\n          itemsCount >= start && itemsCount <= finish\n        , 'expected #{this} to have a ' + descriptor + ' within ' + range\n        , 'expected #{this} to not have a ' + descriptor + ' within ' + range\n      );\n    } else {\n      this.assert(\n          obj >= start && obj <= finish\n        , 'expected #{this} to be within ' + range\n        , 'expected #{this} to not be within ' + range\n      );\n    }\n  });\n\n  /**\n   * ### .instanceof(constructor[, msg])\n   *\n   * Asserts that the target is an instance of the given `constructor`.\n   *\n   *     function Cat () { }\n   *\n   *     expect(new Cat()).to.be.an.instanceof(Cat);\n   *     expect([1, 2]).to.be.an.instanceof(Array);\n   *\n   * Add `.not` earlier in the chain to negate `.instanceof`.\n   *\n   *     expect({a: 1}).to.not.be.an.instanceof(Array);\n   *\n   * `.instanceof` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect(1).to.be.an.instanceof(Array, 'nooo why fail??');\n   *     expect(1, 'nooo why fail??').to.be.an.instanceof(Array);\n   *\n   * Due to limitations in ES5, `.instanceof` may not always work as expected\n   * when using a transpiler such as Babel or TypeScript. In particular, it may\n   * produce unexpected results when subclassing built-in object such as\n   * `Array`, `Error`, and `Map`. See your transpiler's docs for details:\n   *\n   * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes))\n   * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work))\n   *\n   * The alias `.instanceOf` can be used interchangeably with `.instanceof`.\n   *\n   * @name instanceof\n   * @param {Constructor} constructor\n   * @param {String} msg _optional_\n   * @alias instanceOf\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertInstanceOf (constructor, msg) {\n    if (msg) flag(this, 'message', msg);\n\n    var target = flag(this, 'object')\n    var ssfi = flag(this, 'ssfi');\n    var flagMsg = flag(this, 'message');\n\n    try {\n      var isInstanceOf = target instanceof constructor;\n    } catch (err) {\n      if (err instanceof TypeError) {\n        flagMsg = flagMsg ? flagMsg + ': ' : '';\n        throw new AssertionError(\n          flagMsg + 'The instanceof assertion needs a constructor but '\n            + _.type(constructor) + ' was given.',\n          undefined,\n          ssfi\n        );\n      }\n      throw err;\n    }\n\n    var name = _.getName(constructor);\n    if (name === null) {\n      name = 'an unnamed constructor';\n    }\n\n    this.assert(\n        isInstanceOf\n      , 'expected #{this} to be an instance of ' + name\n      , 'expected #{this} to not be an instance of ' + name\n    );\n  };\n\n  Assertion.addMethod('instanceof', assertInstanceOf);\n  Assertion.addMethod('instanceOf', assertInstanceOf);\n\n  /**\n   * ### .property(name[, val[, msg]])\n   *\n   * Asserts that the target has a property with the given key `name`.\n   *\n   *     expect({a: 1}).to.have.property('a');\n   *\n   * When `val` is provided, `.property` also asserts that the property's value\n   * is equal to the given `val`.\n   *\n   *     expect({a: 1}).to.have.property('a', 1);\n   *\n   * By default, strict (`===`) equality is used. Add `.deep` earlier in the\n   * chain to use deep equality instead. See the `deep-eql` project page for\n   * info on the deep equality algorithm: https://github.com/chaijs/deep-eql.\n   *\n   *     // Target object deeply (but not strictly) has property `x: {a: 1}`\n   *     expect({x: {a: 1}}).to.have.deep.property('x', {a: 1});\n   *     expect({x: {a: 1}}).to.not.have.property('x', {a: 1});\n   *\n   * The target's enumerable and non-enumerable properties are always included\n   * in the search. By default, both own and inherited properties are included.\n   * Add `.own` earlier in the chain to exclude inherited properties from the\n   * search.\n   *\n   *     Object.prototype.b = 2;\n   *\n   *     expect({a: 1}).to.have.own.property('a');\n   *     expect({a: 1}).to.have.own.property('a', 1);\n   *     expect({a: 1}).to.have.property('b');\n   *     expect({a: 1}).to.not.have.own.property('b');\n   *\n   * `.deep` and `.own` can be combined.\n   *\n   *     expect({x: {a: 1}}).to.have.deep.own.property('x', {a: 1});\n   *\n   * Add `.nested` earlier in the chain to enable dot- and bracket-notation when\n   * referencing nested properties.\n   *\n   *     expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]');\n   *     expect({a: {b: ['x', 'y']}}).to.have.nested.property('a.b[1]', 'y');\n   *\n   * If `.` or `[]` are part of an actual property name, they can be escaped by\n   * adding two backslashes before them.\n   *\n   *     expect({'.a': {'[b]': 'x'}}).to.have.nested.property('\\\\.a.\\\\[b\\\\]');\n   *\n   * `.deep` and `.nested` can be combined.\n   *\n   *     expect({a: {b: [{c: 3}]}})\n   *       .to.have.deep.nested.property('a.b[0]', {c: 3});\n   *\n   * `.own` and `.nested` cannot be combined.\n   *\n   * Add `.not` earlier in the chain to negate `.property`.\n   *\n   *     expect({a: 1}).to.not.have.property('b');\n   *\n   * However, it's dangerous to negate `.property` when providing `val`. The\n   * problem is that it creates uncertain expectations by asserting that the\n   * target either doesn't have a property with the given key `name`, or that it\n   * does have a property with the given key `name` but its value isn't equal to\n   * the given `val`. It's often best to identify the exact output that's\n   * expected, and then write an assertion that only accepts that exact output.\n   *\n   * When the target isn't expected to have a property with the given key\n   * `name`, it's often best to assert exactly that.\n   *\n   *     expect({b: 2}).to.not.have.property('a'); // Recommended\n   *     expect({b: 2}).to.not.have.property('a', 1); // Not recommended\n   *\n   * When the target is expected to have a property with the given key `name`,\n   * it's often best to assert that the property has its expected value, rather\n   * than asserting that it doesn't have one of many unexpected values.\n   *\n   *     expect({a: 3}).to.have.property('a', 3); // Recommended\n   *     expect({a: 3}).to.not.have.property('a', 1); // Not recommended\n   *\n   * `.property` changes the target of any assertions that follow in the chain\n   * to be the value of the property from the original target object.\n   *\n   *     expect({a: 1}).to.have.property('a').that.is.a('number');\n   *\n   * `.property` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`. When not providing `val`, only use the\n   * second form.\n   *\n   *     // Recommended\n   *     expect({a: 1}).to.have.property('a', 2, 'nooo why fail??');\n   *     expect({a: 1}, 'nooo why fail??').to.have.property('a', 2);\n   *     expect({a: 1}, 'nooo why fail??').to.have.property('b');\n   *\n   *     // Not recommended\n   *     expect({a: 1}).to.have.property('b', undefined, 'nooo why fail??');\n   *\n   * The above assertion isn't the same thing as not providing `val`. Instead,\n   * it's asserting that the target object has a `b` property that's equal to\n   * `undefined`.\n   *\n   * The assertions `.ownProperty` and `.haveOwnProperty` can be used\n   * interchangeably with `.own.property`.\n   *\n   * @name property\n   * @param {String} name\n   * @param {Mixed} val (optional)\n   * @param {String} msg _optional_\n   * @returns value of property for chaining\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertProperty (name, val, msg) {\n    if (msg) flag(this, 'message', msg);\n\n    var isNested = flag(this, 'nested')\n      , isOwn = flag(this, 'own')\n      , flagMsg = flag(this, 'message')\n      , obj = flag(this, 'object')\n      , ssfi = flag(this, 'ssfi')\n      , nameType = typeof name;\n\n    flagMsg = flagMsg ? flagMsg + ': ' : '';\n\n    if (isNested) {\n      if (nameType !== 'string') {\n        throw new AssertionError(\n          flagMsg + 'the argument to property must be a string when using nested syntax',\n          undefined,\n          ssfi\n        );\n      }\n    } else {\n      if (nameType !== 'string' && nameType !== 'number' && nameType !== 'symbol') {\n        throw new AssertionError(\n          flagMsg + 'the argument to property must be a string, number, or symbol',\n          undefined,\n          ssfi\n        );\n      }\n    }\n\n    if (isNested && isOwn) {\n      throw new AssertionError(\n        flagMsg + 'The \"nested\" and \"own\" flags cannot be combined.',\n        undefined,\n        ssfi\n      );\n    }\n\n    if (obj === null || obj === undefined) {\n      throw new AssertionError(\n        flagMsg + 'Target cannot be null or undefined.',\n        undefined,\n        ssfi\n      );\n    }\n\n    var isDeep = flag(this, 'deep')\n      , negate = flag(this, 'negate')\n      , pathInfo = isNested ? _.getPathInfo(obj, name) : null\n      , value = isNested ? pathInfo.value : obj[name];\n\n    var descriptor = '';\n    if (isDeep) descriptor += 'deep ';\n    if (isOwn) descriptor += 'own ';\n    if (isNested) descriptor += 'nested ';\n    descriptor += 'property ';\n\n    var hasProperty;\n    if (isOwn) hasProperty = Object.prototype.hasOwnProperty.call(obj, name);\n    else if (isNested) hasProperty = pathInfo.exists;\n    else hasProperty = _.hasProperty(obj, name);\n\n    // When performing a negated assertion for both name and val, merely having\n    // a property with the given name isn't enough to cause the assertion to\n    // fail. It must both have a property with the given name, and the value of\n    // that property must equal the given val. Therefore, skip this assertion in\n    // favor of the next.\n    if (!negate || arguments.length === 1) {\n      this.assert(\n          hasProperty\n        , 'expected #{this} to have ' + descriptor + _.inspect(name)\n        , 'expected #{this} to not have ' + descriptor + _.inspect(name));\n    }\n\n    if (arguments.length > 1) {\n      this.assert(\n          hasProperty && (isDeep ? _.eql(val, value) : val === value)\n        , 'expected #{this} to have ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'\n        , 'expected #{this} to not have ' + descriptor + _.inspect(name) + ' of #{act}'\n        , val\n        , value\n      );\n    }\n\n    flag(this, 'object', value);\n  }\n\n  Assertion.addMethod('property', assertProperty);\n\n  function assertOwnProperty (name, value, msg) {\n    flag(this, 'own', true);\n    assertProperty.apply(this, arguments);\n  }\n\n  Assertion.addMethod('ownProperty', assertOwnProperty);\n  Assertion.addMethod('haveOwnProperty', assertOwnProperty);\n\n  /**\n   * ### .ownPropertyDescriptor(name[, descriptor[, msg]])\n   *\n   * Asserts that the target has its own property descriptor with the given key\n   * `name`. Enumerable and non-enumerable properties are included in the\n   * search.\n   *\n   *     expect({a: 1}).to.have.ownPropertyDescriptor('a');\n   *\n   * When `descriptor` is provided, `.ownPropertyDescriptor` also asserts that\n   * the property's descriptor is deeply equal to the given `descriptor`. See\n   * the `deep-eql` project page for info on the deep equality algorithm:\n   * https://github.com/chaijs/deep-eql.\n   *\n   *     expect({a: 1}).to.have.ownPropertyDescriptor('a', {\n   *       configurable: true,\n   *       enumerable: true,\n   *       writable: true,\n   *       value: 1,\n   *     });\n   *\n   * Add `.not` earlier in the chain to negate `.ownPropertyDescriptor`.\n   *\n   *     expect({a: 1}).to.not.have.ownPropertyDescriptor('b');\n   *\n   * However, it's dangerous to negate `.ownPropertyDescriptor` when providing\n   * a `descriptor`. The problem is that it creates uncertain expectations by\n   * asserting that the target either doesn't have a property descriptor with\n   * the given key `name`, or that it does have a property descriptor with the\n   * given key `name` but it’s not deeply equal to the given `descriptor`. It's\n   * often best to identify the exact output that's expected, and then write an\n   * assertion that only accepts that exact output.\n   *\n   * When the target isn't expected to have a property descriptor with the given\n   * key `name`, it's often best to assert exactly that.\n   *\n   *     // Recommended\n   *     expect({b: 2}).to.not.have.ownPropertyDescriptor('a');\n   *\n   *     // Not recommended\n   *     expect({b: 2}).to.not.have.ownPropertyDescriptor('a', {\n   *       configurable: true,\n   *       enumerable: true,\n   *       writable: true,\n   *       value: 1,\n   *     });\n   *\n   * When the target is expected to have a property descriptor with the given\n   * key `name`, it's often best to assert that the property has its expected\n   * descriptor, rather than asserting that it doesn't have one of many\n   * unexpected descriptors.\n   *\n   *     // Recommended\n   *     expect({a: 3}).to.have.ownPropertyDescriptor('a', {\n   *       configurable: true,\n   *       enumerable: true,\n   *       writable: true,\n   *       value: 3,\n   *     });\n   *\n   *     // Not recommended\n   *     expect({a: 3}).to.not.have.ownPropertyDescriptor('a', {\n   *       configurable: true,\n   *       enumerable: true,\n   *       writable: true,\n   *       value: 1,\n   *     });\n   *\n   * `.ownPropertyDescriptor` changes the target of any assertions that follow\n   * in the chain to be the value of the property descriptor from the original\n   * target object.\n   *\n   *     expect({a: 1}).to.have.ownPropertyDescriptor('a')\n   *       .that.has.property('enumerable', true);\n   *\n   * `.ownPropertyDescriptor` accepts an optional `msg` argument which is a\n   * custom error message to show when the assertion fails. The message can also\n   * be given as the second argument to `expect`. When not providing\n   * `descriptor`, only use the second form.\n   *\n   *     // Recommended\n   *     expect({a: 1}).to.have.ownPropertyDescriptor('a', {\n   *       configurable: true,\n   *       enumerable: true,\n   *       writable: true,\n   *       value: 2,\n   *     }, 'nooo why fail??');\n   *\n   *     // Recommended\n   *     expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('a', {\n   *       configurable: true,\n   *       enumerable: true,\n   *       writable: true,\n   *       value: 2,\n   *     });\n   *\n   *     // Recommended\n   *     expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('b');\n   *\n   *     // Not recommended\n   *     expect({a: 1})\n   *       .to.have.ownPropertyDescriptor('b', undefined, 'nooo why fail??');\n   *\n   * The above assertion isn't the same thing as not providing `descriptor`.\n   * Instead, it's asserting that the target object has a `b` property\n   * descriptor that's deeply equal to `undefined`.\n   *\n   * The alias `.haveOwnPropertyDescriptor` can be used interchangeably with\n   * `.ownPropertyDescriptor`.\n   *\n   * @name ownPropertyDescriptor\n   * @alias haveOwnPropertyDescriptor\n   * @param {String} name\n   * @param {Object} descriptor _optional_\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertOwnPropertyDescriptor (name, descriptor, msg) {\n    if (typeof descriptor === 'string') {\n      msg = descriptor;\n      descriptor = null;\n    }\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);\n    if (actualDescriptor && descriptor) {\n      this.assert(\n          _.eql(descriptor, actualDescriptor)\n        , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)\n        , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)\n        , descriptor\n        , actualDescriptor\n        , true\n      );\n    } else {\n      this.assert(\n          actualDescriptor\n        , 'expected #{this} to have an own property descriptor for ' + _.inspect(name)\n        , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)\n      );\n    }\n    flag(this, 'object', actualDescriptor);\n  }\n\n  Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);\n  Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);\n\n  /**\n   * ### .lengthOf(n[, msg])\n   *\n   * Asserts that the target's `length` or `size` is equal to the given number\n   * `n`.\n   *\n   *     expect([1, 2, 3]).to.have.lengthOf(3);\n   *     expect('foo').to.have.lengthOf(3);\n   *     expect(new Set([1, 2, 3])).to.have.lengthOf(3);\n   *     expect(new Map([['a', 1], ['b', 2], ['c', 3]])).to.have.lengthOf(3);\n   *\n   * Add `.not` earlier in the chain to negate `.lengthOf`. However, it's often\n   * best to assert that the target's `length` property is equal to its expected\n   * value, rather than not equal to one of many unexpected values.\n   *\n   *     expect('foo').to.have.lengthOf(3); // Recommended\n   *     expect('foo').to.not.have.lengthOf(4); // Not recommended\n   *\n   * `.lengthOf` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect([1, 2, 3]).to.have.lengthOf(2, 'nooo why fail??');\n   *     expect([1, 2, 3], 'nooo why fail??').to.have.lengthOf(2);\n   *\n   * `.lengthOf` can also be used as a language chain, causing all `.above`,\n   * `.below`, `.least`, `.most`, and `.within` assertions that follow in the\n   * chain to use the target's `length` property as the target. However, it's\n   * often best to assert that the target's `length` property is equal to its\n   * expected length, rather than asserting that its `length` property falls\n   * within some range of values.\n   *\n   *     // Recommended\n   *     expect([1, 2, 3]).to.have.lengthOf(3);\n   *\n   *     // Not recommended\n   *     expect([1, 2, 3]).to.have.lengthOf.above(2);\n   *     expect([1, 2, 3]).to.have.lengthOf.below(4);\n   *     expect([1, 2, 3]).to.have.lengthOf.at.least(3);\n   *     expect([1, 2, 3]).to.have.lengthOf.at.most(3);\n   *     expect([1, 2, 3]).to.have.lengthOf.within(2,4);\n   *\n   * Due to a compatibility issue, the alias `.length` can't be chained directly\n   * off of an uninvoked method such as `.a`. Therefore, `.length` can't be used\n   * interchangeably with `.lengthOf` in every situation. It's recommended to\n   * always use `.lengthOf` instead of `.length`.\n   *\n   *     expect([1, 2, 3]).to.have.a.length(3); // incompatible; throws error\n   *     expect([1, 2, 3]).to.have.a.lengthOf(3);  // passes as expected\n   *\n   * @name lengthOf\n   * @alias length\n   * @param {Number} n\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertLengthChain () {\n    flag(this, 'doLength', true);\n  }\n\n  function assertLength (n, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , objType = _.type(obj).toLowerCase()\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi')\n      , descriptor = 'length'\n      , itemsCount;\n\n    switch (objType) {\n      case 'map':\n      case 'set':\n        descriptor = 'size';\n        itemsCount = obj.size;\n        break;\n      default:\n        new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');\n        itemsCount = obj.length;\n    }\n\n    this.assert(\n        itemsCount == n\n      , 'expected #{this} to have a ' + descriptor + ' of #{exp} but got #{act}'\n      , 'expected #{this} to not have a ' + descriptor + ' of #{act}'\n      , n\n      , itemsCount\n    );\n  }\n\n  Assertion.addChainableMethod('length', assertLength, assertLengthChain);\n  Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);\n\n  /**\n   * ### .match(re[, msg])\n   *\n   * Asserts that the target matches the given regular expression `re`.\n   *\n   *     expect('foobar').to.match(/^foo/);\n   *\n   * Add `.not` earlier in the chain to negate `.match`.\n   *\n   *     expect('foobar').to.not.match(/taco/);\n   *\n   * `.match` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect('foobar').to.match(/taco/, 'nooo why fail??');\n   *     expect('foobar', 'nooo why fail??').to.match(/taco/);\n   *\n   * The alias `.matches` can be used interchangeably with `.match`.\n   *\n   * @name match\n   * @alias matches\n   * @param {RegExp} re\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n  function assertMatch(re, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    this.assert(\n        re.exec(obj)\n      , 'expected #{this} to match ' + re\n      , 'expected #{this} not to match ' + re\n    );\n  }\n\n  Assertion.addMethod('match', assertMatch);\n  Assertion.addMethod('matches', assertMatch);\n\n  /**\n   * ### .string(str[, msg])\n   *\n   * Asserts that the target string contains the given substring `str`.\n   *\n   *     expect('foobar').to.have.string('bar');\n   *\n   * Add `.not` earlier in the chain to negate `.string`.\n   *\n   *     expect('foobar').to.not.have.string('taco');\n   *\n   * `.string` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect('foobar').to.have.string('taco', 'nooo why fail??');\n   *     expect('foobar', 'nooo why fail??').to.have.string('taco');\n   *\n   * @name string\n   * @param {String} str\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addMethod('string', function (str, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi');\n    new Assertion(obj, flagMsg, ssfi, true).is.a('string');\n\n    this.assert(\n        ~obj.indexOf(str)\n      , 'expected #{this} to contain ' + _.inspect(str)\n      , 'expected #{this} to not contain ' + _.inspect(str)\n    );\n  });\n\n  /**\n   * ### .keys(key1[, key2[, ...]])\n   *\n   * Asserts that the target object, array, map, or set has the given keys. Only\n   * the target's own inherited properties are included in the search.\n   *\n   * When the target is an object or array, keys can be provided as one or more\n   * string arguments, a single array argument, or a single object argument. In\n   * the latter case, only the keys in the given object matter; the values are\n   * ignored.\n   *\n   *     expect({a: 1, b: 2}).to.have.all.keys('a', 'b');\n   *     expect(['x', 'y']).to.have.all.keys(0, 1);\n   *\n   *     expect({a: 1, b: 2}).to.have.all.keys(['a', 'b']);\n   *     expect(['x', 'y']).to.have.all.keys([0, 1]);\n   *\n   *     expect({a: 1, b: 2}).to.have.all.keys({a: 4, b: 5}); // ignore 4 and 5\n   *     expect(['x', 'y']).to.have.all.keys({0: 4, 1: 5}); // ignore 4 and 5\n   *\n   * When the target is a map or set, each key must be provided as a separate\n   * argument.\n   *\n   *     expect(new Map([['a', 1], ['b', 2]])).to.have.all.keys('a', 'b');\n   *     expect(new Set(['a', 'b'])).to.have.all.keys('a', 'b');\n   *\n   * Because `.keys` does different things based on the target's type, it's\n   * important to check the target's type before using `.keys`. See the `.a` doc\n   * for info on testing a target's type.\n   *\n   *     expect({a: 1, b: 2}).to.be.an('object').that.has.all.keys('a', 'b');\n   *\n   * By default, strict (`===`) equality is used to compare keys of maps and\n   * sets. Add `.deep` earlier in the chain to use deep equality instead. See\n   * the `deep-eql` project page for info on the deep equality algorithm:\n   * https://github.com/chaijs/deep-eql.\n   *\n   *     // Target set deeply (but not strictly) has key `{a: 1}`\n   *     expect(new Set([{a: 1}])).to.have.all.deep.keys([{a: 1}]);\n   *     expect(new Set([{a: 1}])).to.not.have.all.keys([{a: 1}]);\n   *\n   * By default, the target must have all of the given keys and no more. Add\n   * `.any` earlier in the chain to only require that the target have at least\n   * one of the given keys. Also, add `.not` earlier in the chain to negate\n   * `.keys`. It's often best to add `.any` when negating `.keys`, and to use\n   * `.all` when asserting `.keys` without negation.\n   *\n   * When negating `.keys`, `.any` is preferred because `.not.any.keys` asserts\n   * exactly what's expected of the output, whereas `.not.all.keys` creates\n   * uncertain expectations.\n   *\n   *     // Recommended; asserts that target doesn't have any of the given keys\n   *     expect({a: 1, b: 2}).to.not.have.any.keys('c', 'd');\n   *\n   *     // Not recommended; asserts that target doesn't have all of the given\n   *     // keys but may or may not have some of them\n   *     expect({a: 1, b: 2}).to.not.have.all.keys('c', 'd');\n   *\n   * When asserting `.keys` without negation, `.all` is preferred because\n   * `.all.keys` asserts exactly what's expected of the output, whereas\n   * `.any.keys` creates uncertain expectations.\n   *\n   *     // Recommended; asserts that target has all the given keys\n   *     expect({a: 1, b: 2}).to.have.all.keys('a', 'b');\n   *\n   *     // Not recommended; asserts that target has at least one of the given\n   *     // keys but may or may not have more of them\n   *     expect({a: 1, b: 2}).to.have.any.keys('a', 'b');\n   *\n   * Note that `.all` is used by default when neither `.all` nor `.any` appear\n   * earlier in the chain. However, it's often best to add `.all` anyway because\n   * it improves readability.\n   *\n   *     // Both assertions are identical\n   *     expect({a: 1, b: 2}).to.have.all.keys('a', 'b'); // Recommended\n   *     expect({a: 1, b: 2}).to.have.keys('a', 'b'); // Not recommended\n   *\n   * Add `.include` earlier in the chain to require that the target's keys be a\n   * superset of the expected keys, rather than identical sets.\n   *\n   *     // Target object's keys are a superset of ['a', 'b'] but not identical\n   *     expect({a: 1, b: 2, c: 3}).to.include.all.keys('a', 'b');\n   *     expect({a: 1, b: 2, c: 3}).to.not.have.all.keys('a', 'b');\n   *\n   * However, if `.any` and `.include` are combined, only the `.any` takes\n   * effect. The `.include` is ignored in this case.\n   *\n   *     // Both assertions are identical\n   *     expect({a: 1}).to.have.any.keys('a', 'b');\n   *     expect({a: 1}).to.include.any.keys('a', 'b');\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect({a: 1}, 'nooo why fail??').to.have.key('b');\n   *\n   * The alias `.key` can be used interchangeably with `.keys`.\n   *\n   * @name keys\n   * @alias key\n   * @param {...String|Array|Object} keys\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertKeys (keys) {\n    var obj = flag(this, 'object')\n      , objType = _.type(obj)\n      , keysType = _.type(keys)\n      , ssfi = flag(this, 'ssfi')\n      , isDeep = flag(this, 'deep')\n      , str\n      , deepStr = ''\n      , actual\n      , ok = true\n      , flagMsg = flag(this, 'message');\n\n    flagMsg = flagMsg ? flagMsg + ': ' : '';\n    var mixedArgsMsg = flagMsg + 'when testing keys against an object or an array you must give a single Array|Object|String argument or multiple String arguments';\n\n    if (objType === 'Map' || objType === 'Set') {\n      deepStr = isDeep ? 'deeply ' : '';\n      actual = [];\n\n      // Map and Set '.keys' aren't supported in IE 11. Therefore, use .forEach.\n      obj.forEach(function (val, key) { actual.push(key) });\n\n      if (keysType !== 'Array') {\n        keys = Array.prototype.slice.call(arguments);\n      }\n    } else {\n      actual = _.getOwnEnumerableProperties(obj);\n\n      switch (keysType) {\n        case 'Array':\n          if (arguments.length > 1) {\n            throw new AssertionError(mixedArgsMsg, undefined, ssfi);\n          }\n          break;\n        case 'Object':\n          if (arguments.length > 1) {\n            throw new AssertionError(mixedArgsMsg, undefined, ssfi);\n          }\n          keys = Object.keys(keys);\n          break;\n        default:\n          keys = Array.prototype.slice.call(arguments);\n      }\n\n      // Only stringify non-Symbols because Symbols would become \"Symbol()\"\n      keys = keys.map(function (val) {\n        return typeof val === 'symbol' ? val : String(val);\n      });\n    }\n\n    if (!keys.length) {\n      throw new AssertionError(flagMsg + 'keys required', undefined, ssfi);\n    }\n\n    var len = keys.length\n      , any = flag(this, 'any')\n      , all = flag(this, 'all')\n      , expected = keys;\n\n    if (!any && !all) {\n      all = true;\n    }\n\n    // Has any\n    if (any) {\n      ok = expected.some(function(expectedKey) {\n        return actual.some(function(actualKey) {\n          if (isDeep) {\n            return _.eql(expectedKey, actualKey);\n          } else {\n            return expectedKey === actualKey;\n          }\n        });\n      });\n    }\n\n    // Has all\n    if (all) {\n      ok = expected.every(function(expectedKey) {\n        return actual.some(function(actualKey) {\n          if (isDeep) {\n            return _.eql(expectedKey, actualKey);\n          } else {\n            return expectedKey === actualKey;\n          }\n        });\n      });\n\n      if (!flag(this, 'contains')) {\n        ok = ok && keys.length == actual.length;\n      }\n    }\n\n    // Key string\n    if (len > 1) {\n      keys = keys.map(function(key) {\n        return _.inspect(key);\n      });\n      var last = keys.pop();\n      if (all) {\n        str = keys.join(', ') + ', and ' + last;\n      }\n      if (any) {\n        str = keys.join(', ') + ', or ' + last;\n      }\n    } else {\n      str = _.inspect(keys[0]);\n    }\n\n    // Form\n    str = (len > 1 ? 'keys ' : 'key ') + str;\n\n    // Have / include\n    str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;\n\n    // Assertion\n    this.assert(\n        ok\n      , 'expected #{this} to ' + deepStr + str\n      , 'expected #{this} to not ' + deepStr + str\n      , expected.slice(0).sort(_.compareByInspect)\n      , actual.sort(_.compareByInspect)\n      , true\n    );\n  }\n\n  Assertion.addMethod('keys', assertKeys);\n  Assertion.addMethod('key', assertKeys);\n\n  /**\n   * ### .throw([errorLike], [errMsgMatcher], [msg])\n   *\n   * When no arguments are provided, `.throw` invokes the target function and\n   * asserts that an error is thrown.\n   *\n   *     var badFn = function () { throw new TypeError('Illegal salmon!'); };\n   *\n   *     expect(badFn).to.throw();\n   *\n   * When one argument is provided, and it's an error constructor, `.throw`\n   * invokes the target function and asserts that an error is thrown that's an\n   * instance of that error constructor.\n   *\n   *     var badFn = function () { throw new TypeError('Illegal salmon!'); };\n   *\n   *     expect(badFn).to.throw(TypeError);\n   *\n   * When one argument is provided, and it's an error instance, `.throw` invokes\n   * the target function and asserts that an error is thrown that's strictly\n   * (`===`) equal to that error instance.\n   *\n   *     var err = new TypeError('Illegal salmon!');\n   *     var badFn = function () { throw err; };\n   *\n   *     expect(badFn).to.throw(err);\n   *\n   * When one argument is provided, and it's a string, `.throw` invokes the\n   * target function and asserts that an error is thrown with a message that\n   * contains that string.\n   *\n   *     var badFn = function () { throw new TypeError('Illegal salmon!'); };\n   *\n   *     expect(badFn).to.throw('salmon');\n   *\n   * When one argument is provided, and it's a regular expression, `.throw`\n   * invokes the target function and asserts that an error is thrown with a\n   * message that matches that regular expression.\n   *\n   *     var badFn = function () { throw new TypeError('Illegal salmon!'); };\n   *\n   *     expect(badFn).to.throw(/salmon/);\n   *\n   * When two arguments are provided, and the first is an error instance or\n   * constructor, and the second is a string or regular expression, `.throw`\n   * invokes the function and asserts that an error is thrown that fulfills both\n   * conditions as described above.\n   *\n   *     var err = new TypeError('Illegal salmon!');\n   *     var badFn = function () { throw err; };\n   *\n   *     expect(badFn).to.throw(TypeError, 'salmon');\n   *     expect(badFn).to.throw(TypeError, /salmon/);\n   *     expect(badFn).to.throw(err, 'salmon');\n   *     expect(badFn).to.throw(err, /salmon/);\n   *\n   * Add `.not` earlier in the chain to negate `.throw`.\n   *\n   *     var goodFn = function () {};\n   *\n   *     expect(goodFn).to.not.throw();\n   *\n   * However, it's dangerous to negate `.throw` when providing any arguments.\n   * The problem is that it creates uncertain expectations by asserting that the\n   * target either doesn't throw an error, or that it throws an error but of a\n   * different type than the given type, or that it throws an error of the given\n   * type but with a message that doesn't include the given string. It's often\n   * best to identify the exact output that's expected, and then write an\n   * assertion that only accepts that exact output.\n   *\n   * When the target isn't expected to throw an error, it's often best to assert\n   * exactly that.\n   *\n   *     var goodFn = function () {};\n   *\n   *     expect(goodFn).to.not.throw(); // Recommended\n   *     expect(goodFn).to.not.throw(ReferenceError, 'x'); // Not recommended\n   *\n   * When the target is expected to throw an error, it's often best to assert\n   * that the error is of its expected type, and has a message that includes an\n   * expected string, rather than asserting that it doesn't have one of many\n   * unexpected types, and doesn't have a message that includes some string.\n   *\n   *     var badFn = function () { throw new TypeError('Illegal salmon!'); };\n   *\n   *     expect(badFn).to.throw(TypeError, 'salmon'); // Recommended\n   *     expect(badFn).to.not.throw(ReferenceError, 'x'); // Not recommended\n   *\n   * `.throw` changes the target of any assertions that follow in the chain to\n   * be the error object that's thrown.\n   *\n   *     var err = new TypeError('Illegal salmon!');\n   *     err.code = 42;\n   *     var badFn = function () { throw err; };\n   *\n   *     expect(badFn).to.throw(TypeError).with.property('code', 42);\n   *\n   * `.throw` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`. When not providing two arguments, always use\n   * the second form.\n   *\n   *     var goodFn = function () {};\n   *\n   *     expect(goodFn).to.throw(TypeError, 'x', 'nooo why fail??');\n   *     expect(goodFn, 'nooo why fail??').to.throw();\n   *\n   * Due to limitations in ES5, `.throw` may not always work as expected when\n   * using a transpiler such as Babel or TypeScript. In particular, it may\n   * produce unexpected results when subclassing the built-in `Error` object and\n   * then passing the subclassed constructor to `.throw`. See your transpiler's\n   * docs for details:\n   *\n   * - ([Babel](https://babeljs.io/docs/usage/caveats/#classes))\n   * - ([TypeScript](https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work))\n   *\n   * Beware of some common mistakes when using the `throw` assertion. One common\n   * mistake is to accidentally invoke the function yourself instead of letting\n   * the `throw` assertion invoke the function for you. For example, when\n   * testing if a function named `fn` throws, provide `fn` instead of `fn()` as\n   * the target for the assertion.\n   *\n   *     expect(fn).to.throw();     // Good! Tests `fn` as desired\n   *     expect(fn()).to.throw();   // Bad! Tests result of `fn()`, not `fn`\n   *\n   * If you need to assert that your function `fn` throws when passed certain\n   * arguments, then wrap a call to `fn` inside of another function.\n   *\n   *     expect(function () { fn(42); }).to.throw();  // Function expression\n   *     expect(() => fn(42)).to.throw();             // ES6 arrow function\n   *\n   * Another common mistake is to provide an object method (or any stand-alone\n   * function that relies on `this`) as the target of the assertion. Doing so is\n   * problematic because the `this` context will be lost when the function is\n   * invoked by `.throw`; there's no way for it to know what `this` is supposed\n   * to be. There are two ways around this problem. One solution is to wrap the\n   * method or function call inside of another function. Another solution is to\n   * use `bind`.\n   *\n   *     expect(function () { cat.meow(); }).to.throw();  // Function expression\n   *     expect(() => cat.meow()).to.throw();             // ES6 arrow function\n   *     expect(cat.meow.bind(cat)).to.throw();           // Bind\n   *\n   * Finally, it's worth mentioning that it's a best practice in JavaScript to\n   * only throw `Error` and derivatives of `Error` such as `ReferenceError`,\n   * `TypeError`, and user-defined objects that extend `Error`. No other type of\n   * value will generate a stack trace when initialized. With that said, the\n   * `throw` assertion does technically support any type of value being thrown,\n   * not just `Error` and its derivatives.\n   *\n   * The aliases `.throws` and `.Throw` can be used interchangeably with\n   * `.throw`.\n   *\n   * @name throw\n   * @alias throws\n   * @alias Throw\n   * @param {Error|ErrorConstructor} errorLike\n   * @param {String|RegExp} errMsgMatcher error message\n   * @param {String} msg _optional_\n   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n   * @returns error for chaining (null if no error)\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertThrows (errorLike, errMsgMatcher, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , ssfi = flag(this, 'ssfi')\n      , flagMsg = flag(this, 'message')\n      , negate = flag(this, 'negate') || false;\n    new Assertion(obj, flagMsg, ssfi, true).is.a('function');\n\n    if (errorLike instanceof RegExp || typeof errorLike === 'string') {\n      errMsgMatcher = errorLike;\n      errorLike = null;\n    }\n\n    var caughtErr;\n    try {\n      obj();\n    } catch (err) {\n      caughtErr = err;\n    }\n\n    // If we have the negate flag enabled and at least one valid argument it means we do expect an error\n    // but we want it to match a given set of criteria\n    var everyArgIsUndefined = errorLike === undefined && errMsgMatcher === undefined;\n\n    // If we've got the negate flag enabled and both args, we should only fail if both aren't compatible\n    // See Issue #551 and PR #683@GitHub\n    var everyArgIsDefined = Boolean(errorLike && errMsgMatcher);\n    var errorLikeFail = false;\n    var errMsgMatcherFail = false;\n\n    // Checking if error was thrown\n    if (everyArgIsUndefined || !everyArgIsUndefined && !negate) {\n      // We need this to display results correctly according to their types\n      var errorLikeString = 'an error';\n      if (errorLike instanceof Error) {\n        errorLikeString = '#{exp}';\n      } else if (errorLike) {\n        errorLikeString = _.checkError.getConstructorName(errorLike);\n      }\n\n      this.assert(\n          caughtErr\n        , 'expected #{this} to throw ' + errorLikeString\n        , 'expected #{this} to not throw an error but #{act} was thrown'\n        , errorLike && errorLike.toString()\n        , (caughtErr instanceof Error ?\n            caughtErr.toString() : (typeof caughtErr === 'string' ? caughtErr : caughtErr &&\n                                    _.checkError.getConstructorName(caughtErr)))\n      );\n    }\n\n    if (errorLike && caughtErr) {\n      // We should compare instances only if `errorLike` is an instance of `Error`\n      if (errorLike instanceof Error) {\n        var isCompatibleInstance = _.checkError.compatibleInstance(caughtErr, errorLike);\n\n        if (isCompatibleInstance === negate) {\n          // These checks were created to ensure we won't fail too soon when we've got both args and a negate\n          // See Issue #551 and PR #683@GitHub\n          if (everyArgIsDefined && negate) {\n            errorLikeFail = true;\n          } else {\n            this.assert(\n                negate\n              , 'expected #{this} to throw #{exp} but #{act} was thrown'\n              , 'expected #{this} to not throw #{exp}' + (caughtErr && !negate ? ' but #{act} was thrown' : '')\n              , errorLike.toString()\n              , caughtErr.toString()\n            );\n          }\n        }\n      }\n\n      var isCompatibleConstructor = _.checkError.compatibleConstructor(caughtErr, errorLike);\n      if (isCompatibleConstructor === negate) {\n        if (everyArgIsDefined && negate) {\n            errorLikeFail = true;\n        } else {\n          this.assert(\n              negate\n            , 'expected #{this} to throw #{exp} but #{act} was thrown'\n            , 'expected #{this} to not throw #{exp}' + (caughtErr ? ' but #{act} was thrown' : '')\n            , (errorLike instanceof Error ? errorLike.toString() : errorLike && _.checkError.getConstructorName(errorLike))\n            , (caughtErr instanceof Error ? caughtErr.toString() : caughtErr && _.checkError.getConstructorName(caughtErr))\n          );\n        }\n      }\n    }\n\n    if (caughtErr && errMsgMatcher !== undefined && errMsgMatcher !== null) {\n      // Here we check compatible messages\n      var placeholder = 'including';\n      if (errMsgMatcher instanceof RegExp) {\n        placeholder = 'matching'\n      }\n\n      var isCompatibleMessage = _.checkError.compatibleMessage(caughtErr, errMsgMatcher);\n      if (isCompatibleMessage === negate) {\n        if (everyArgIsDefined && negate) {\n            errMsgMatcherFail = true;\n        } else {\n          this.assert(\n            negate\n            , 'expected #{this} to throw error ' + placeholder + ' #{exp} but got #{act}'\n            , 'expected #{this} to throw error not ' + placeholder + ' #{exp}'\n            ,  errMsgMatcher\n            ,  _.checkError.getMessage(caughtErr)\n          );\n        }\n      }\n    }\n\n    // If both assertions failed and both should've matched we throw an error\n    if (errorLikeFail && errMsgMatcherFail) {\n      this.assert(\n        negate\n        , 'expected #{this} to throw #{exp} but #{act} was thrown'\n        , 'expected #{this} to not throw #{exp}' + (caughtErr ? ' but #{act} was thrown' : '')\n        , (errorLike instanceof Error ? errorLike.toString() : errorLike && _.checkError.getConstructorName(errorLike))\n        , (caughtErr instanceof Error ? caughtErr.toString() : caughtErr && _.checkError.getConstructorName(caughtErr))\n      );\n    }\n\n    flag(this, 'object', caughtErr);\n  };\n\n  Assertion.addMethod('throw', assertThrows);\n  Assertion.addMethod('throws', assertThrows);\n  Assertion.addMethod('Throw', assertThrows);\n\n  /**\n   * ### .respondTo(method[, msg])\n   *\n   * When the target is a non-function object, `.respondTo` asserts that the\n   * target has a method with the given name `method`. The method can be own or\n   * inherited, and it can be enumerable or non-enumerable.\n   *\n   *     function Cat () {}\n   *     Cat.prototype.meow = function () {};\n   *\n   *     expect(new Cat()).to.respondTo('meow');\n   *\n   * When the target is a function, `.respondTo` asserts that the target's\n   * `prototype` property has a method with the given name `method`. Again, the\n   * method can be own or inherited, and it can be enumerable or non-enumerable.\n   *\n   *     function Cat () {}\n   *     Cat.prototype.meow = function () {};\n   *\n   *     expect(Cat).to.respondTo('meow');\n   *\n   * Add `.itself` earlier in the chain to force `.respondTo` to treat the\n   * target as a non-function object, even if it's a function. Thus, it asserts\n   * that the target has a method with the given name `method`, rather than\n   * asserting that the target's `prototype` property has a method with the\n   * given name `method`.\n   *\n   *     function Cat () {}\n   *     Cat.prototype.meow = function () {};\n   *     Cat.hiss = function () {};\n   *\n   *     expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow');\n   *\n   * When not adding `.itself`, it's important to check the target's type before\n   * using `.respondTo`. See the `.a` doc for info on checking a target's type.\n   *\n   *     function Cat () {}\n   *     Cat.prototype.meow = function () {};\n   *\n   *     expect(new Cat()).to.be.an('object').that.respondsTo('meow');\n   *\n   * Add `.not` earlier in the chain to negate `.respondTo`.\n   *\n   *     function Dog () {}\n   *     Dog.prototype.bark = function () {};\n   *\n   *     expect(new Dog()).to.not.respondTo('meow');\n   *\n   * `.respondTo` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect({}).to.respondTo('meow', 'nooo why fail??');\n   *     expect({}, 'nooo why fail??').to.respondTo('meow');\n   *\n   * The alias `.respondsTo` can be used interchangeably with `.respondTo`.\n   *\n   * @name respondTo\n   * @alias respondsTo\n   * @param {String} method\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function respondTo (method, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , itself = flag(this, 'itself')\n      , context = ('function' === typeof obj && !itself)\n        ? obj.prototype[method]\n        : obj[method];\n\n    this.assert(\n        'function' === typeof context\n      , 'expected #{this} to respond to ' + _.inspect(method)\n      , 'expected #{this} to not respond to ' + _.inspect(method)\n    );\n  }\n\n  Assertion.addMethod('respondTo', respondTo);\n  Assertion.addMethod('respondsTo', respondTo);\n\n  /**\n   * ### .itself\n   *\n   * Forces all `.respondTo` assertions that follow in the chain to behave as if\n   * the target is a non-function object, even if it's a function. Thus, it\n   * causes `.respondTo` to assert that the target has a method with the given\n   * name, rather than asserting that the target's `prototype` property has a\n   * method with the given name.\n   *\n   *     function Cat () {}\n   *     Cat.prototype.meow = function () {};\n   *     Cat.hiss = function () {};\n   *\n   *     expect(Cat).itself.to.respondTo('hiss').but.not.respondTo('meow');\n   *\n   * @name itself\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('itself', function () {\n    flag(this, 'itself', true);\n  });\n\n  /**\n   * ### .satisfy(matcher[, msg])\n   *\n   * Invokes the given `matcher` function with the target being passed as the\n   * first argument, and asserts that the value returned is truthy.\n   *\n   *     expect(1).to.satisfy(function(num) {\n   *       return num > 0;\n   *     });\n   *\n   * Add `.not` earlier in the chain to negate `.satisfy`.\n   *\n   *     expect(1).to.not.satisfy(function(num) {\n   *       return num > 2;\n   *     });\n   *\n   * `.satisfy` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect(1).to.satisfy(function(num) {\n   *       return num > 2;\n   *     }, 'nooo why fail??');\n   *\n   *     expect(1, 'nooo why fail??').to.satisfy(function(num) {\n   *       return num > 2;\n   *     });\n   *\n   * The alias `.satisfies` can be used interchangeably with `.satisfy`.\n   *\n   * @name satisfy\n   * @alias satisfies\n   * @param {Function} matcher\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function satisfy (matcher, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object');\n    var result = matcher(obj);\n    this.assert(\n        result\n      , 'expected #{this} to satisfy ' + _.objDisplay(matcher)\n      , 'expected #{this} to not satisfy' + _.objDisplay(matcher)\n      , flag(this, 'negate') ? false : true\n      , result\n    );\n  }\n\n  Assertion.addMethod('satisfy', satisfy);\n  Assertion.addMethod('satisfies', satisfy);\n\n  /**\n   * ### .closeTo(expected, delta[, msg])\n   *\n   * Asserts that the target is a number that's within a given +/- `delta` range\n   * of the given number `expected`. However, it's often best to assert that the\n   * target is equal to its expected value.\n   *\n   *     // Recommended\n   *     expect(1.5).to.equal(1.5);\n   *\n   *     // Not recommended\n   *     expect(1.5).to.be.closeTo(1, 0.5);\n   *     expect(1.5).to.be.closeTo(2, 0.5);\n   *     expect(1.5).to.be.closeTo(1, 1);\n   *\n   * Add `.not` earlier in the chain to negate `.closeTo`.\n   *\n   *     expect(1.5).to.equal(1.5); // Recommended\n   *     expect(1.5).to.not.be.closeTo(3, 1); // Not recommended\n   *\n   * `.closeTo` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect(1.5).to.be.closeTo(3, 1, 'nooo why fail??');\n   *     expect(1.5, 'nooo why fail??').to.be.closeTo(3, 1);\n   *\n   * The alias `.approximately` can be used interchangeably with `.closeTo`.\n   *\n   * @name closeTo\n   * @alias approximately\n   * @param {Number} expected\n   * @param {Number} delta\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function closeTo(expected, delta, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi');\n\n    new Assertion(obj, flagMsg, ssfi, true).is.a('number');\n    if (typeof expected !== 'number' || typeof delta !== 'number') {\n      flagMsg = flagMsg ? flagMsg + ': ' : '';\n      var deltaMessage = delta === undefined ? \", and a delta is required\" : \"\";\n      throw new AssertionError(\n          flagMsg + 'the arguments to closeTo or approximately must be numbers' + deltaMessage,\n          undefined,\n          ssfi\n      );\n    }\n\n    this.assert(\n        Math.abs(obj - expected) <= delta\n      , 'expected #{this} to be close to ' + expected + ' +/- ' + delta\n      , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta\n    );\n  }\n\n  Assertion.addMethod('closeTo', closeTo);\n  Assertion.addMethod('approximately', closeTo);\n\n  // Note: Duplicates are ignored if testing for inclusion instead of sameness.\n  function isSubsetOf(subset, superset, cmp, contains, ordered) {\n    if (!contains) {\n      if (subset.length !== superset.length) return false;\n      superset = superset.slice();\n    }\n\n    return subset.every(function(elem, idx) {\n      if (ordered) return cmp ? cmp(elem, superset[idx]) : elem === superset[idx];\n\n      if (!cmp) {\n        var matchIdx = superset.indexOf(elem);\n        if (matchIdx === -1) return false;\n\n        // Remove match from superset so not counted twice if duplicate in subset.\n        if (!contains) superset.splice(matchIdx, 1);\n        return true;\n      }\n\n      return superset.some(function(elem2, matchIdx) {\n        if (!cmp(elem, elem2)) return false;\n\n        // Remove match from superset so not counted twice if duplicate in subset.\n        if (!contains) superset.splice(matchIdx, 1);\n        return true;\n      });\n    });\n  }\n\n  /**\n   * ### .members(set[, msg])\n   *\n   * Asserts that the target array has the same members as the given array\n   * `set`.\n   *\n   *     expect([1, 2, 3]).to.have.members([2, 1, 3]);\n   *     expect([1, 2, 2]).to.have.members([2, 1, 2]);\n   *\n   * By default, members are compared using strict (`===`) equality. Add `.deep`\n   * earlier in the chain to use deep equality instead. See the `deep-eql`\n   * project page for info on the deep equality algorithm:\n   * https://github.com/chaijs/deep-eql.\n   *\n   *     // Target array deeply (but not strictly) has member `{a: 1}`\n   *     expect([{a: 1}]).to.have.deep.members([{a: 1}]);\n   *     expect([{a: 1}]).to.not.have.members([{a: 1}]);\n   *\n   * By default, order doesn't matter. Add `.ordered` earlier in the chain to\n   * require that members appear in the same order.\n   *\n   *     expect([1, 2, 3]).to.have.ordered.members([1, 2, 3]);\n   *     expect([1, 2, 3]).to.have.members([2, 1, 3])\n   *       .but.not.ordered.members([2, 1, 3]);\n   *\n   * By default, both arrays must be the same size. Add `.include` earlier in\n   * the chain to require that the target's members be a superset of the\n   * expected members. Note that duplicates are ignored in the subset when\n   * `.include` is added.\n   *\n   *     // Target array is a superset of [1, 2] but not identical\n   *     expect([1, 2, 3]).to.include.members([1, 2]);\n   *     expect([1, 2, 3]).to.not.have.members([1, 2]);\n   *\n   *     // Duplicates in the subset are ignored\n   *     expect([1, 2, 3]).to.include.members([1, 2, 2, 2]);\n   *\n   * `.deep`, `.ordered`, and `.include` can all be combined. However, if\n   * `.include` and `.ordered` are combined, the ordering begins at the start of\n   * both arrays.\n   *\n   *     expect([{a: 1}, {b: 2}, {c: 3}])\n   *       .to.include.deep.ordered.members([{a: 1}, {b: 2}])\n   *       .but.not.include.deep.ordered.members([{b: 2}, {c: 3}]);\n   *\n   * Add `.not` earlier in the chain to negate `.members`. However, it's\n   * dangerous to do so. The problem is that it creates uncertain expectations\n   * by asserting that the target array doesn't have all of the same members as\n   * the given array `set` but may or may not have some of them. It's often best\n   * to identify the exact output that's expected, and then write an assertion\n   * that only accepts that exact output.\n   *\n   *     expect([1, 2]).to.not.include(3).and.not.include(4); // Recommended\n   *     expect([1, 2]).to.not.have.members([3, 4]); // Not recommended\n   *\n   * `.members` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`.\n   *\n   *     expect([1, 2]).to.have.members([1, 2, 3], 'nooo why fail??');\n   *     expect([1, 2], 'nooo why fail??').to.have.members([1, 2, 3]);\n   *\n   * @name members\n   * @param {Array} set\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addMethod('members', function (subset, msg) {\n    if (msg) flag(this, 'message', msg);\n    var obj = flag(this, 'object')\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi');\n\n    new Assertion(obj, flagMsg, ssfi, true).to.be.an('array');\n    new Assertion(subset, flagMsg, ssfi, true).to.be.an('array');\n\n    var contains = flag(this, 'contains');\n    var ordered = flag(this, 'ordered');\n\n    var subject, failMsg, failNegateMsg;\n\n    if (contains) {\n      subject = ordered ? 'an ordered superset' : 'a superset';\n      failMsg = 'expected #{this} to be ' + subject + ' of #{exp}';\n      failNegateMsg = 'expected #{this} to not be ' + subject + ' of #{exp}';\n    } else {\n      subject = ordered ? 'ordered members' : 'members';\n      failMsg = 'expected #{this} to have the same ' + subject + ' as #{exp}';\n      failNegateMsg = 'expected #{this} to not have the same ' + subject + ' as #{exp}';\n    }\n\n    var cmp = flag(this, 'deep') ? _.eql : undefined;\n\n    this.assert(\n        isSubsetOf(subset, obj, cmp, contains, ordered)\n      , failMsg\n      , failNegateMsg\n      , subset\n      , obj\n      , true\n    );\n  });\n\n  /**\n   * ### .oneOf(list[, msg])\n   *\n   * Asserts that the target is a member of the given array `list`. However,\n   * it's often best to assert that the target is equal to its expected value.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.be.oneOf([1, 2, 3]); // Not recommended\n   *\n   * Comparisons are performed using strict (`===`) equality.\n   *\n   * Add `.not` earlier in the chain to negate `.oneOf`.\n   *\n   *     expect(1).to.equal(1); // Recommended\n   *     expect(1).to.not.be.oneOf([2, 3, 4]); // Not recommended\n   *\n   * It can also be chained with `.contain` or `.include`, which will work with\n   * both arrays and strings:\n   *\n   *     expect('Today is sunny').to.contain.oneOf(['sunny', 'cloudy'])\n   *     expect('Today is rainy').to.not.contain.oneOf(['sunny', 'cloudy'])\n   *     expect([1,2,3]).to.contain.oneOf([3,4,5])\n   *     expect([1,2,3]).to.not.contain.oneOf([4,5,6])\n   *\n   * `.oneOf` accepts an optional `msg` argument which is a custom error message\n   * to show when the assertion fails. The message can also be given as the\n   * second argument to `expect`.\n   *\n   *     expect(1).to.be.oneOf([2, 3, 4], 'nooo why fail??');\n   *     expect(1, 'nooo why fail??').to.be.oneOf([2, 3, 4]);\n   *\n   * @name oneOf\n   * @param {Array<*>} list\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function oneOf (list, msg) {\n    if (msg) flag(this, 'message', msg);\n    var expected = flag(this, 'object')\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi')\n      , contains = flag(this, 'contains')\n      , isDeep = flag(this, 'deep');\n    new Assertion(list, flagMsg, ssfi, true).to.be.an('array');\n\n    if (contains) {\n      this.assert(\n        list.some(function(possibility) { return expected.indexOf(possibility) > -1 })\n        , 'expected #{this} to contain one of #{exp}'\n        , 'expected #{this} to not contain one of #{exp}'\n        , list\n        , expected\n      );\n    } else {\n      if (isDeep) {\n        this.assert(\n          list.some(function(possibility) { return _.eql(expected, possibility) })\n          , 'expected #{this} to deeply equal one of #{exp}'\n          , 'expected #{this} to deeply equal one of #{exp}'\n          , list\n          , expected\n        );\n      } else {\n        this.assert(\n          list.indexOf(expected) > -1\n          , 'expected #{this} to be one of #{exp}'\n          , 'expected #{this} to not be one of #{exp}'\n          , list\n          , expected\n        );\n      }\n    }\n  }\n\n  Assertion.addMethod('oneOf', oneOf);\n\n  /**\n   * ### .change(subject[, prop[, msg]])\n   *\n   * When one argument is provided, `.change` asserts that the given function\n   * `subject` returns a different value when it's invoked before the target\n   * function compared to when it's invoked afterward. However, it's often best\n   * to assert that `subject` is equal to its expected value.\n   *\n   *     var dots = ''\n   *       , addDot = function () { dots += '.'; }\n   *       , getDots = function () { return dots; };\n   *\n   *     // Recommended\n   *     expect(getDots()).to.equal('');\n   *     addDot();\n   *     expect(getDots()).to.equal('.');\n   *\n   *     // Not recommended\n   *     expect(addDot).to.change(getDots);\n   *\n   * When two arguments are provided, `.change` asserts that the value of the\n   * given object `subject`'s `prop` property is different before invoking the\n   * target function compared to afterward.\n   *\n   *     var myObj = {dots: ''}\n   *       , addDot = function () { myObj.dots += '.'; };\n   *\n   *     // Recommended\n   *     expect(myObj).to.have.property('dots', '');\n   *     addDot();\n   *     expect(myObj).to.have.property('dots', '.');\n   *\n   *     // Not recommended\n   *     expect(addDot).to.change(myObj, 'dots');\n   *\n   * Strict (`===`) equality is used to compare before and after values.\n   *\n   * Add `.not` earlier in the chain to negate `.change`.\n   *\n   *     var dots = ''\n   *       , noop = function () {}\n   *       , getDots = function () { return dots; };\n   *\n   *     expect(noop).to.not.change(getDots);\n   *\n   *     var myObj = {dots: ''}\n   *       , noop = function () {};\n   *\n   *     expect(noop).to.not.change(myObj, 'dots');\n   *\n   * `.change` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`. When not providing two arguments, always\n   * use the second form.\n   *\n   *     var myObj = {dots: ''}\n   *       , addDot = function () { myObj.dots += '.'; };\n   *\n   *     expect(addDot).to.not.change(myObj, 'dots', 'nooo why fail??');\n   *\n   *     var dots = ''\n   *       , addDot = function () { dots += '.'; }\n   *       , getDots = function () { return dots; };\n   *\n   *     expect(addDot, 'nooo why fail??').to.not.change(getDots);\n   *\n   * `.change` also causes all `.by` assertions that follow in the chain to\n   * assert how much a numeric subject was increased or decreased by. However,\n   * it's dangerous to use `.change.by`. The problem is that it creates\n   * uncertain expectations by asserting that the subject either increases by\n   * the given delta, or that it decreases by the given delta. It's often best\n   * to identify the exact output that's expected, and then write an assertion\n   * that only accepts that exact output.\n   *\n   *     var myObj = {val: 1}\n   *       , addTwo = function () { myObj.val += 2; }\n   *       , subtractTwo = function () { myObj.val -= 2; };\n   *\n   *     expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended\n   *     expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended\n   *\n   *     expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended\n   *     expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended\n   *\n   * The alias `.changes` can be used interchangeably with `.change`.\n   *\n   * @name change\n   * @alias changes\n   * @param {String} subject\n   * @param {String} prop name _optional_\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertChanges (subject, prop, msg) {\n    if (msg) flag(this, 'message', msg);\n    var fn = flag(this, 'object')\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi');\n    new Assertion(fn, flagMsg, ssfi, true).is.a('function');\n\n    var initial;\n    if (!prop) {\n      new Assertion(subject, flagMsg, ssfi, true).is.a('function');\n      initial = subject();\n    } else {\n      new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop);\n      initial = subject[prop];\n    }\n\n    fn();\n\n    var final = prop === undefined || prop === null ? subject() : subject[prop];\n    var msgObj = prop === undefined || prop === null ? initial : '.' + prop;\n\n    // This gets flagged because of the .by(delta) assertion\n    flag(this, 'deltaMsgObj', msgObj);\n    flag(this, 'initialDeltaValue', initial);\n    flag(this, 'finalDeltaValue', final);\n    flag(this, 'deltaBehavior', 'change');\n    flag(this, 'realDelta', final !== initial);\n\n    this.assert(\n      initial !== final\n      , 'expected ' + msgObj + ' to change'\n      , 'expected ' + msgObj + ' to not change'\n    );\n  }\n\n  Assertion.addMethod('change', assertChanges);\n  Assertion.addMethod('changes', assertChanges);\n\n  /**\n   * ### .increase(subject[, prop[, msg]])\n   *\n   * When one argument is provided, `.increase` asserts that the given function\n   * `subject` returns a greater number when it's invoked after invoking the\n   * target function compared to when it's invoked beforehand. `.increase` also\n   * causes all `.by` assertions that follow in the chain to assert how much\n   * greater of a number is returned. It's often best to assert that the return\n   * value increased by the expected amount, rather than asserting it increased\n   * by any amount.\n   *\n   *     var val = 1\n   *       , addTwo = function () { val += 2; }\n   *       , getVal = function () { return val; };\n   *\n   *     expect(addTwo).to.increase(getVal).by(2); // Recommended\n   *     expect(addTwo).to.increase(getVal); // Not recommended\n   *\n   * When two arguments are provided, `.increase` asserts that the value of the\n   * given object `subject`'s `prop` property is greater after invoking the\n   * target function compared to beforehand.\n   *\n   *     var myObj = {val: 1}\n   *       , addTwo = function () { myObj.val += 2; };\n   *\n   *     expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended\n   *     expect(addTwo).to.increase(myObj, 'val'); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.increase`. However, it's\n   * dangerous to do so. The problem is that it creates uncertain expectations\n   * by asserting that the subject either decreases, or that it stays the same.\n   * It's often best to identify the exact output that's expected, and then\n   * write an assertion that only accepts that exact output.\n   *\n   * When the subject is expected to decrease, it's often best to assert that it\n   * decreased by the expected amount.\n   *\n   *     var myObj = {val: 1}\n   *       , subtractTwo = function () { myObj.val -= 2; };\n   *\n   *     expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended\n   *     expect(subtractTwo).to.not.increase(myObj, 'val'); // Not recommended\n   *\n   * When the subject is expected to stay the same, it's often best to assert\n   * exactly that.\n   *\n   *     var myObj = {val: 1}\n   *       , noop = function () {};\n   *\n   *     expect(noop).to.not.change(myObj, 'val'); // Recommended\n   *     expect(noop).to.not.increase(myObj, 'val'); // Not recommended\n   *\n   * `.increase` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`. When not providing two arguments, always\n   * use the second form.\n   *\n   *     var myObj = {val: 1}\n   *       , noop = function () {};\n   *\n   *     expect(noop).to.increase(myObj, 'val', 'nooo why fail??');\n   *\n   *     var val = 1\n   *       , noop = function () {}\n   *       , getVal = function () { return val; };\n   *\n   *     expect(noop, 'nooo why fail??').to.increase(getVal);\n   *\n   * The alias `.increases` can be used interchangeably with `.increase`.\n   *\n   * @name increase\n   * @alias increases\n   * @param {String|Function} subject\n   * @param {String} prop name _optional_\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertIncreases (subject, prop, msg) {\n    if (msg) flag(this, 'message', msg);\n    var fn = flag(this, 'object')\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi');\n    new Assertion(fn, flagMsg, ssfi, true).is.a('function');\n\n    var initial;\n    if (!prop) {\n      new Assertion(subject, flagMsg, ssfi, true).is.a('function');\n      initial = subject();\n    } else {\n      new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop);\n      initial = subject[prop];\n    }\n\n    // Make sure that the target is a number\n    new Assertion(initial, flagMsg, ssfi, true).is.a('number');\n\n    fn();\n\n    var final = prop === undefined || prop === null ? subject() : subject[prop];\n    var msgObj = prop === undefined || prop === null ? initial : '.' + prop;\n\n    flag(this, 'deltaMsgObj', msgObj);\n    flag(this, 'initialDeltaValue', initial);\n    flag(this, 'finalDeltaValue', final);\n    flag(this, 'deltaBehavior', 'increase');\n    flag(this, 'realDelta', final - initial);\n\n    this.assert(\n      final - initial > 0\n      , 'expected ' + msgObj + ' to increase'\n      , 'expected ' + msgObj + ' to not increase'\n    );\n  }\n\n  Assertion.addMethod('increase', assertIncreases);\n  Assertion.addMethod('increases', assertIncreases);\n\n  /**\n   * ### .decrease(subject[, prop[, msg]])\n   *\n   * When one argument is provided, `.decrease` asserts that the given function\n   * `subject` returns a lesser number when it's invoked after invoking the\n   * target function compared to when it's invoked beforehand. `.decrease` also\n   * causes all `.by` assertions that follow in the chain to assert how much\n   * lesser of a number is returned. It's often best to assert that the return\n   * value decreased by the expected amount, rather than asserting it decreased\n   * by any amount.\n   *\n   *     var val = 1\n   *       , subtractTwo = function () { val -= 2; }\n   *       , getVal = function () { return val; };\n   *\n   *     expect(subtractTwo).to.decrease(getVal).by(2); // Recommended\n   *     expect(subtractTwo).to.decrease(getVal); // Not recommended\n   *\n   * When two arguments are provided, `.decrease` asserts that the value of the\n   * given object `subject`'s `prop` property is lesser after invoking the\n   * target function compared to beforehand.\n   *\n   *     var myObj = {val: 1}\n   *       , subtractTwo = function () { myObj.val -= 2; };\n   *\n   *     expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended\n   *     expect(subtractTwo).to.decrease(myObj, 'val'); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.decrease`. However, it's\n   * dangerous to do so. The problem is that it creates uncertain expectations\n   * by asserting that the subject either increases, or that it stays the same.\n   * It's often best to identify the exact output that's expected, and then\n   * write an assertion that only accepts that exact output.\n   *\n   * When the subject is expected to increase, it's often best to assert that it\n   * increased by the expected amount.\n   *\n   *     var myObj = {val: 1}\n   *       , addTwo = function () { myObj.val += 2; };\n   *\n   *     expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended\n   *     expect(addTwo).to.not.decrease(myObj, 'val'); // Not recommended\n   *\n   * When the subject is expected to stay the same, it's often best to assert\n   * exactly that.\n   *\n   *     var myObj = {val: 1}\n   *       , noop = function () {};\n   *\n   *     expect(noop).to.not.change(myObj, 'val'); // Recommended\n   *     expect(noop).to.not.decrease(myObj, 'val'); // Not recommended\n   *\n   * `.decrease` accepts an optional `msg` argument which is a custom error\n   * message to show when the assertion fails. The message can also be given as\n   * the second argument to `expect`. When not providing two arguments, always\n   * use the second form.\n   *\n   *     var myObj = {val: 1}\n   *       , noop = function () {};\n   *\n   *     expect(noop).to.decrease(myObj, 'val', 'nooo why fail??');\n   *\n   *     var val = 1\n   *       , noop = function () {}\n   *       , getVal = function () { return val; };\n   *\n   *     expect(noop, 'nooo why fail??').to.decrease(getVal);\n   *\n   * The alias `.decreases` can be used interchangeably with `.decrease`.\n   *\n   * @name decrease\n   * @alias decreases\n   * @param {String|Function} subject\n   * @param {String} prop name _optional_\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertDecreases (subject, prop, msg) {\n    if (msg) flag(this, 'message', msg);\n    var fn = flag(this, 'object')\n      , flagMsg = flag(this, 'message')\n      , ssfi = flag(this, 'ssfi');\n    new Assertion(fn, flagMsg, ssfi, true).is.a('function');\n\n    var initial;\n    if (!prop) {\n      new Assertion(subject, flagMsg, ssfi, true).is.a('function');\n      initial = subject();\n    } else {\n      new Assertion(subject, flagMsg, ssfi, true).to.have.property(prop);\n      initial = subject[prop];\n    }\n\n    // Make sure that the target is a number\n    new Assertion(initial, flagMsg, ssfi, true).is.a('number');\n\n    fn();\n\n    var final = prop === undefined || prop === null ? subject() : subject[prop];\n    var msgObj = prop === undefined || prop === null ? initial : '.' + prop;\n\n    flag(this, 'deltaMsgObj', msgObj);\n    flag(this, 'initialDeltaValue', initial);\n    flag(this, 'finalDeltaValue', final);\n    flag(this, 'deltaBehavior', 'decrease');\n    flag(this, 'realDelta', initial - final);\n\n    this.assert(\n      final - initial < 0\n      , 'expected ' + msgObj + ' to decrease'\n      , 'expected ' + msgObj + ' to not decrease'\n    );\n  }\n\n  Assertion.addMethod('decrease', assertDecreases);\n  Assertion.addMethod('decreases', assertDecreases);\n\n  /**\n   * ### .by(delta[, msg])\n   *\n   * When following an `.increase` assertion in the chain, `.by` asserts that\n   * the subject of the `.increase` assertion increased by the given `delta`.\n   *\n   *     var myObj = {val: 1}\n   *       , addTwo = function () { myObj.val += 2; };\n   *\n   *     expect(addTwo).to.increase(myObj, 'val').by(2);\n   *\n   * When following a `.decrease` assertion in the chain, `.by` asserts that the\n   * subject of the `.decrease` assertion decreased by the given `delta`.\n   *\n   *     var myObj = {val: 1}\n   *       , subtractTwo = function () { myObj.val -= 2; };\n   *\n   *     expect(subtractTwo).to.decrease(myObj, 'val').by(2);\n   *\n   * When following a `.change` assertion in the chain, `.by` asserts that the\n   * subject of the `.change` assertion either increased or decreased by the\n   * given `delta`. However, it's dangerous to use `.change.by`. The problem is\n   * that it creates uncertain expectations. It's often best to identify the\n   * exact output that's expected, and then write an assertion that only accepts\n   * that exact output.\n   *\n   *     var myObj = {val: 1}\n   *       , addTwo = function () { myObj.val += 2; }\n   *       , subtractTwo = function () { myObj.val -= 2; };\n   *\n   *     expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended\n   *     expect(addTwo).to.change(myObj, 'val').by(2); // Not recommended\n   *\n   *     expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended\n   *     expect(subtractTwo).to.change(myObj, 'val').by(2); // Not recommended\n   *\n   * Add `.not` earlier in the chain to negate `.by`. However, it's often best\n   * to assert that the subject changed by its expected delta, rather than\n   * asserting that it didn't change by one of countless unexpected deltas.\n   *\n   *     var myObj = {val: 1}\n   *       , addTwo = function () { myObj.val += 2; };\n   *\n   *     // Recommended\n   *     expect(addTwo).to.increase(myObj, 'val').by(2);\n   *\n   *     // Not recommended\n   *     expect(addTwo).to.increase(myObj, 'val').but.not.by(3);\n   *\n   * `.by` accepts an optional `msg` argument which is a custom error message to\n   * show when the assertion fails. The message can also be given as the second\n   * argument to `expect`.\n   *\n   *     var myObj = {val: 1}\n   *       , addTwo = function () { myObj.val += 2; };\n   *\n   *     expect(addTwo).to.increase(myObj, 'val').by(3, 'nooo why fail??');\n   *     expect(addTwo, 'nooo why fail??').to.increase(myObj, 'val').by(3);\n   *\n   * @name by\n   * @param {Number} delta\n   * @param {String} msg _optional_\n   * @namespace BDD\n   * @api public\n   */\n\n  function assertDelta(delta, msg) {\n    if (msg) flag(this, 'message', msg);\n\n    var msgObj = flag(this, 'deltaMsgObj');\n    var initial = flag(this, 'initialDeltaValue');\n    var final = flag(this, 'finalDeltaValue');\n    var behavior = flag(this, 'deltaBehavior');\n    var realDelta = flag(this, 'realDelta');\n\n    var expression;\n    if (behavior === 'change') {\n      expression = Math.abs(final - initial) === Math.abs(delta);\n    } else {\n      expression = realDelta === Math.abs(delta);\n    }\n\n    this.assert(\n      expression\n      , 'expected ' + msgObj + ' to ' + behavior + ' by ' + delta\n      , 'expected ' + msgObj + ' to not ' + behavior + ' by ' + delta\n    );\n  }\n\n  Assertion.addMethod('by', assertDelta);\n\n  /**\n   * ### .extensible\n   *\n   * Asserts that the target is extensible, which means that new properties can\n   * be added to it. Primitives are never extensible.\n   *\n   *     expect({a: 1}).to.be.extensible;\n   *\n   * Add `.not` earlier in the chain to negate `.extensible`.\n   *\n   *     var nonExtensibleObject = Object.preventExtensions({})\n   *       , sealedObject = Object.seal({})\n   *       , frozenObject = Object.freeze({});\n   *\n   *     expect(nonExtensibleObject).to.not.be.extensible;\n   *     expect(sealedObject).to.not.be.extensible;\n   *     expect(frozenObject).to.not.be.extensible;\n   *     expect(1).to.not.be.extensible;\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect(1, 'nooo why fail??').to.be.extensible;\n   *\n   * @name extensible\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('extensible', function() {\n    var obj = flag(this, 'object');\n\n    // In ES5, if the argument to this method is a primitive, then it will cause a TypeError.\n    // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false.\n    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible\n    // The following provides ES6 behavior for ES5 environments.\n\n    var isExtensible = obj === Object(obj) && Object.isExtensible(obj);\n\n    this.assert(\n      isExtensible\n      , 'expected #{this} to be extensible'\n      , 'expected #{this} to not be extensible'\n    );\n  });\n\n  /**\n   * ### .sealed\n   *\n   * Asserts that the target is sealed, which means that new properties can't be\n   * added to it, and its existing properties can't be reconfigured or deleted.\n   * However, it's possible that its existing properties can still be reassigned\n   * to different values. Primitives are always sealed.\n   *\n   *     var sealedObject = Object.seal({});\n   *     var frozenObject = Object.freeze({});\n   *\n   *     expect(sealedObject).to.be.sealed;\n   *     expect(frozenObject).to.be.sealed;\n   *     expect(1).to.be.sealed;\n   *\n   * Add `.not` earlier in the chain to negate `.sealed`.\n   *\n   *     expect({a: 1}).to.not.be.sealed;\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect({a: 1}, 'nooo why fail??').to.be.sealed;\n   *\n   * @name sealed\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('sealed', function() {\n    var obj = flag(this, 'object');\n\n    // In ES5, if the argument to this method is a primitive, then it will cause a TypeError.\n    // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true.\n    // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed\n    // The following provides ES6 behavior for ES5 environments.\n\n    var isSealed = obj === Object(obj) ? Object.isSealed(obj) : true;\n\n    this.assert(\n      isSealed\n      , 'expected #{this} to be sealed'\n      , 'expected #{this} to not be sealed'\n    );\n  });\n\n  /**\n   * ### .frozen\n   *\n   * Asserts that the target is frozen, which means that new properties can't be\n   * added to it, and its existing properties can't be reassigned to different\n   * values, reconfigured, or deleted. Primitives are always frozen.\n   *\n   *     var frozenObject = Object.freeze({});\n   *\n   *     expect(frozenObject).to.be.frozen;\n   *     expect(1).to.be.frozen;\n   *\n   * Add `.not` earlier in the chain to negate `.frozen`.\n   *\n   *     expect({a: 1}).to.not.be.frozen;\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect({a: 1}, 'nooo why fail??').to.be.frozen;\n   *\n   * @name frozen\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('frozen', function() {\n    var obj = flag(this, 'object');\n\n    // In ES5, if the argument to this method is a primitive, then it will cause a TypeError.\n    // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true.\n    // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen\n    // The following provides ES6 behavior for ES5 environments.\n\n    var isFrozen = obj === Object(obj) ? Object.isFrozen(obj) : true;\n\n    this.assert(\n      isFrozen\n      , 'expected #{this} to be frozen'\n      , 'expected #{this} to not be frozen'\n    );\n  });\n\n  /**\n   * ### .finite\n   *\n   * Asserts that the target is a number, and isn't `NaN` or positive/negative\n   * `Infinity`.\n   *\n   *     expect(1).to.be.finite;\n   *\n   * Add `.not` earlier in the chain to negate `.finite`. However, it's\n   * dangerous to do so. The problem is that it creates uncertain expectations\n   * by asserting that the subject either isn't a number, or that it's `NaN`, or\n   * that it's positive `Infinity`, or that it's negative `Infinity`. It's often\n   * best to identify the exact output that's expected, and then write an\n   * assertion that only accepts that exact output.\n   *\n   * When the target isn't expected to be a number, it's often best to assert\n   * that it's the expected type, rather than asserting that it isn't one of\n   * many unexpected types.\n   *\n   *     expect('foo').to.be.a('string'); // Recommended\n   *     expect('foo').to.not.be.finite; // Not recommended\n   *\n   * When the target is expected to be `NaN`, it's often best to assert exactly\n   * that.\n   *\n   *     expect(NaN).to.be.NaN; // Recommended\n   *     expect(NaN).to.not.be.finite; // Not recommended\n   *\n   * When the target is expected to be positive infinity, it's often best to\n   * assert exactly that.\n   *\n   *     expect(Infinity).to.equal(Infinity); // Recommended\n   *     expect(Infinity).to.not.be.finite; // Not recommended\n   *\n   * When the target is expected to be negative infinity, it's often best to\n   * assert exactly that.\n   *\n   *     expect(-Infinity).to.equal(-Infinity); // Recommended\n   *     expect(-Infinity).to.not.be.finite; // Not recommended\n   *\n   * A custom error message can be given as the second argument to `expect`.\n   *\n   *     expect('foo', 'nooo why fail??').to.be.finite;\n   *\n   * @name finite\n   * @namespace BDD\n   * @api public\n   */\n\n  Assertion.addProperty('finite', function(msg) {\n    var obj = flag(this, 'object');\n\n    this.assert(\n        typeof obj === 'number' && isFinite(obj)\n      , 'expected #{this} to be a finite number'\n      , 'expected #{this} to not be a finite number'\n    );\n  });\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/core/assertions.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/interface/assert.js":
  /*!************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/interface/assert.js ***!
    \************************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, util) {\n  /*!\n   * Chai dependencies.\n   */\n\n  var Assertion = chai.Assertion\n    , flag = util.flag;\n\n  /*!\n   * Module export.\n   */\n\n  /**\n   * ### assert(expression, message)\n   *\n   * Write your own test expressions.\n   *\n   *     assert('foo' !== 'bar', 'foo is not bar');\n   *     assert(Array.isArray([]), 'empty arrays are arrays');\n   *\n   * @param {Mixed} expression to test for truthiness\n   * @param {String} message to display on error\n   * @name assert\n   * @namespace Assert\n   * @api public\n   */\n\n  var assert = chai.assert = function (express, errmsg) {\n    var test = new Assertion(null, null, chai.assert, true);\n    test.assert(\n        express\n      , errmsg\n      , '[ negation message unavailable ]'\n    );\n  };\n\n  /**\n   * ### .fail([message])\n   * ### .fail(actual, expected, [message], [operator])\n   *\n   * Throw a failure. Node.js `assert` module-compatible.\n   *\n   *     assert.fail();\n   *     assert.fail(\"custom error message\");\n   *     assert.fail(1, 2);\n   *     assert.fail(1, 2, \"custom error message\");\n   *     assert.fail(1, 2, \"custom error message\", \">\");\n   *     assert.fail(1, 2, undefined, \">\");\n   *\n   * @name fail\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @param {String} operator\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.fail = function (actual, expected, message, operator) {\n    if (arguments.length < 2) {\n        // Comply with Node's fail([message]) interface\n\n        message = actual;\n        actual = undefined;\n    }\n\n    message = message || 'assert.fail()';\n    throw new chai.AssertionError(message, {\n        actual: actual\n      , expected: expected\n      , operator: operator\n    }, assert.fail);\n  };\n\n  /**\n   * ### .isOk(object, [message])\n   *\n   * Asserts that `object` is truthy.\n   *\n   *     assert.isOk('everything', 'everything is ok');\n   *     assert.isOk(false, 'this will fail');\n   *\n   * @name isOk\n   * @alias ok\n   * @param {Mixed} object to test\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isOk = function (val, msg) {\n    new Assertion(val, msg, assert.isOk, true).is.ok;\n  };\n\n  /**\n   * ### .isNotOk(object, [message])\n   *\n   * Asserts that `object` is falsy.\n   *\n   *     assert.isNotOk('everything', 'this will fail');\n   *     assert.isNotOk(false, 'this will pass');\n   *\n   * @name isNotOk\n   * @alias notOk\n   * @param {Mixed} object to test\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotOk = function (val, msg) {\n    new Assertion(val, msg, assert.isNotOk, true).is.not.ok;\n  };\n\n  /**\n   * ### .equal(actual, expected, [message])\n   *\n   * Asserts non-strict equality (`==`) of `actual` and `expected`.\n   *\n   *     assert.equal(3, '3', '== coerces values to strings');\n   *\n   * @name equal\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.equal = function (act, exp, msg) {\n    var test = new Assertion(act, msg, assert.equal, true);\n\n    test.assert(\n        exp == flag(test, 'object')\n      , 'expected #{this} to equal #{exp}'\n      , 'expected #{this} to not equal #{act}'\n      , exp\n      , act\n      , true\n    );\n  };\n\n  /**\n   * ### .notEqual(actual, expected, [message])\n   *\n   * Asserts non-strict inequality (`!=`) of `actual` and `expected`.\n   *\n   *     assert.notEqual(3, 4, 'these numbers are not equal');\n   *\n   * @name notEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notEqual = function (act, exp, msg) {\n    var test = new Assertion(act, msg, assert.notEqual, true);\n\n    test.assert(\n        exp != flag(test, 'object')\n      , 'expected #{this} to not equal #{exp}'\n      , 'expected #{this} to equal #{act}'\n      , exp\n      , act\n      , true\n    );\n  };\n\n  /**\n   * ### .strictEqual(actual, expected, [message])\n   *\n   * Asserts strict equality (`===`) of `actual` and `expected`.\n   *\n   *     assert.strictEqual(true, true, 'these booleans are strictly equal');\n   *\n   * @name strictEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.strictEqual = function (act, exp, msg) {\n    new Assertion(act, msg, assert.strictEqual, true).to.equal(exp);\n  };\n\n  /**\n   * ### .notStrictEqual(actual, expected, [message])\n   *\n   * Asserts strict inequality (`!==`) of `actual` and `expected`.\n   *\n   *     assert.notStrictEqual(3, '3', 'no coercion for strict equality');\n   *\n   * @name notStrictEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notStrictEqual = function (act, exp, msg) {\n    new Assertion(act, msg, assert.notStrictEqual, true).to.not.equal(exp);\n  };\n\n  /**\n   * ### .deepEqual(actual, expected, [message])\n   *\n   * Asserts that `actual` is deeply equal to `expected`.\n   *\n   *     assert.deepEqual({ tea: 'green' }, { tea: 'green' });\n   *\n   * @name deepEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @alias deepStrictEqual\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.deepEqual = assert.deepStrictEqual = function (act, exp, msg) {\n    new Assertion(act, msg, assert.deepEqual, true).to.eql(exp);\n  };\n\n  /**\n   * ### .notDeepEqual(actual, expected, [message])\n   *\n   * Assert that `actual` is not deeply equal to `expected`.\n   *\n   *     assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });\n   *\n   * @name notDeepEqual\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notDeepEqual = function (act, exp, msg) {\n    new Assertion(act, msg, assert.notDeepEqual, true).to.not.eql(exp);\n  };\n\n   /**\n   * ### .isAbove(valueToCheck, valueToBeAbove, [message])\n   *\n   * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`.\n   *\n   *     assert.isAbove(5, 2, '5 is strictly greater than 2');\n   *\n   * @name isAbove\n   * @param {Mixed} valueToCheck\n   * @param {Mixed} valueToBeAbove\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isAbove = function (val, abv, msg) {\n    new Assertion(val, msg, assert.isAbove, true).to.be.above(abv);\n  };\n\n   /**\n   * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message])\n   *\n   * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`.\n   *\n   *     assert.isAtLeast(5, 2, '5 is greater or equal to 2');\n   *     assert.isAtLeast(3, 3, '3 is greater or equal to 3');\n   *\n   * @name isAtLeast\n   * @param {Mixed} valueToCheck\n   * @param {Mixed} valueToBeAtLeast\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isAtLeast = function (val, atlst, msg) {\n    new Assertion(val, msg, assert.isAtLeast, true).to.be.least(atlst);\n  };\n\n   /**\n   * ### .isBelow(valueToCheck, valueToBeBelow, [message])\n   *\n   * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`.\n   *\n   *     assert.isBelow(3, 6, '3 is strictly less than 6');\n   *\n   * @name isBelow\n   * @param {Mixed} valueToCheck\n   * @param {Mixed} valueToBeBelow\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isBelow = function (val, blw, msg) {\n    new Assertion(val, msg, assert.isBelow, true).to.be.below(blw);\n  };\n\n   /**\n   * ### .isAtMost(valueToCheck, valueToBeAtMost, [message])\n   *\n   * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`.\n   *\n   *     assert.isAtMost(3, 6, '3 is less than or equal to 6');\n   *     assert.isAtMost(4, 4, '4 is less than or equal to 4');\n   *\n   * @name isAtMost\n   * @param {Mixed} valueToCheck\n   * @param {Mixed} valueToBeAtMost\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isAtMost = function (val, atmst, msg) {\n    new Assertion(val, msg, assert.isAtMost, true).to.be.most(atmst);\n  };\n\n  /**\n   * ### .isTrue(value, [message])\n   *\n   * Asserts that `value` is true.\n   *\n   *     var teaServed = true;\n   *     assert.isTrue(teaServed, 'the tea has been served');\n   *\n   * @name isTrue\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isTrue = function (val, msg) {\n    new Assertion(val, msg, assert.isTrue, true).is['true'];\n  };\n\n  /**\n   * ### .isNotTrue(value, [message])\n   *\n   * Asserts that `value` is not true.\n   *\n   *     var tea = 'tasty chai';\n   *     assert.isNotTrue(tea, 'great, time for tea!');\n   *\n   * @name isNotTrue\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotTrue = function (val, msg) {\n    new Assertion(val, msg, assert.isNotTrue, true).to.not.equal(true);\n  };\n\n  /**\n   * ### .isFalse(value, [message])\n   *\n   * Asserts that `value` is false.\n   *\n   *     var teaServed = false;\n   *     assert.isFalse(teaServed, 'no tea yet? hmm...');\n   *\n   * @name isFalse\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isFalse = function (val, msg) {\n    new Assertion(val, msg, assert.isFalse, true).is['false'];\n  };\n\n  /**\n   * ### .isNotFalse(value, [message])\n   *\n   * Asserts that `value` is not false.\n   *\n   *     var tea = 'tasty chai';\n   *     assert.isNotFalse(tea, 'great, time for tea!');\n   *\n   * @name isNotFalse\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotFalse = function (val, msg) {\n    new Assertion(val, msg, assert.isNotFalse, true).to.not.equal(false);\n  };\n\n  /**\n   * ### .isNull(value, [message])\n   *\n   * Asserts that `value` is null.\n   *\n   *     assert.isNull(err, 'there was no error');\n   *\n   * @name isNull\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNull = function (val, msg) {\n    new Assertion(val, msg, assert.isNull, true).to.equal(null);\n  };\n\n  /**\n   * ### .isNotNull(value, [message])\n   *\n   * Asserts that `value` is not null.\n   *\n   *     var tea = 'tasty chai';\n   *     assert.isNotNull(tea, 'great, time for tea!');\n   *\n   * @name isNotNull\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotNull = function (val, msg) {\n    new Assertion(val, msg, assert.isNotNull, true).to.not.equal(null);\n  };\n\n  /**\n   * ### .isNaN\n   *\n   * Asserts that value is NaN.\n   *\n   *     assert.isNaN(NaN, 'NaN is NaN');\n   *\n   * @name isNaN\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNaN = function (val, msg) {\n    new Assertion(val, msg, assert.isNaN, true).to.be.NaN;\n  };\n\n  /**\n   * ### .isNotNaN\n   *\n   * Asserts that value is not NaN.\n   *\n   *     assert.isNotNaN(4, '4 is not NaN');\n   *\n   * @name isNotNaN\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n  assert.isNotNaN = function (val, msg) {\n    new Assertion(val, msg, assert.isNotNaN, true).not.to.be.NaN;\n  };\n\n  /**\n   * ### .exists\n   *\n   * Asserts that the target is neither `null` nor `undefined`.\n   *\n   *     var foo = 'hi';\n   *\n   *     assert.exists(foo, 'foo is neither `null` nor `undefined`');\n   *\n   * @name exists\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.exists = function (val, msg) {\n    new Assertion(val, msg, assert.exists, true).to.exist;\n  };\n\n  /**\n   * ### .notExists\n   *\n   * Asserts that the target is either `null` or `undefined`.\n   *\n   *     var bar = null\n   *       , baz;\n   *\n   *     assert.notExists(bar);\n   *     assert.notExists(baz, 'baz is either null or undefined');\n   *\n   * @name notExists\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notExists = function (val, msg) {\n    new Assertion(val, msg, assert.notExists, true).to.not.exist;\n  };\n\n  /**\n   * ### .isUndefined(value, [message])\n   *\n   * Asserts that `value` is `undefined`.\n   *\n   *     var tea;\n   *     assert.isUndefined(tea, 'no tea defined');\n   *\n   * @name isUndefined\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isUndefined = function (val, msg) {\n    new Assertion(val, msg, assert.isUndefined, true).to.equal(undefined);\n  };\n\n  /**\n   * ### .isDefined(value, [message])\n   *\n   * Asserts that `value` is not `undefined`.\n   *\n   *     var tea = 'cup of chai';\n   *     assert.isDefined(tea, 'tea has been defined');\n   *\n   * @name isDefined\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isDefined = function (val, msg) {\n    new Assertion(val, msg, assert.isDefined, true).to.not.equal(undefined);\n  };\n\n  /**\n   * ### .isFunction(value, [message])\n   *\n   * Asserts that `value` is a function.\n   *\n   *     function serveTea() { return 'cup of tea'; };\n   *     assert.isFunction(serveTea, 'great, we can have tea now');\n   *\n   * @name isFunction\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isFunction = function (val, msg) {\n    new Assertion(val, msg, assert.isFunction, true).to.be.a('function');\n  };\n\n  /**\n   * ### .isNotFunction(value, [message])\n   *\n   * Asserts that `value` is _not_ a function.\n   *\n   *     var serveTea = [ 'heat', 'pour', 'sip' ];\n   *     assert.isNotFunction(serveTea, 'great, we have listed the steps');\n   *\n   * @name isNotFunction\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotFunction = function (val, msg) {\n    new Assertion(val, msg, assert.isNotFunction, true).to.not.be.a('function');\n  };\n\n  /**\n   * ### .isObject(value, [message])\n   *\n   * Asserts that `value` is an object of type 'Object' (as revealed by `Object.prototype.toString`).\n   * _The assertion does not match subclassed objects._\n   *\n   *     var selection = { name: 'Chai', serve: 'with spices' };\n   *     assert.isObject(selection, 'tea selection is an object');\n   *\n   * @name isObject\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isObject = function (val, msg) {\n    new Assertion(val, msg, assert.isObject, true).to.be.a('object');\n  };\n\n  /**\n   * ### .isNotObject(value, [message])\n   *\n   * Asserts that `value` is _not_ an object of type 'Object' (as revealed by `Object.prototype.toString`).\n   *\n   *     var selection = 'chai'\n   *     assert.isNotObject(selection, 'tea selection is not an object');\n   *     assert.isNotObject(null, 'null is not an object');\n   *\n   * @name isNotObject\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotObject = function (val, msg) {\n    new Assertion(val, msg, assert.isNotObject, true).to.not.be.a('object');\n  };\n\n  /**\n   * ### .isArray(value, [message])\n   *\n   * Asserts that `value` is an array.\n   *\n   *     var menu = [ 'green', 'chai', 'oolong' ];\n   *     assert.isArray(menu, 'what kind of tea do we want?');\n   *\n   * @name isArray\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isArray = function (val, msg) {\n    new Assertion(val, msg, assert.isArray, true).to.be.an('array');\n  };\n\n  /**\n   * ### .isNotArray(value, [message])\n   *\n   * Asserts that `value` is _not_ an array.\n   *\n   *     var menu = 'green|chai|oolong';\n   *     assert.isNotArray(menu, 'what kind of tea do we want?');\n   *\n   * @name isNotArray\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotArray = function (val, msg) {\n    new Assertion(val, msg, assert.isNotArray, true).to.not.be.an('array');\n  };\n\n  /**\n   * ### .isString(value, [message])\n   *\n   * Asserts that `value` is a string.\n   *\n   *     var teaOrder = 'chai';\n   *     assert.isString(teaOrder, 'order placed');\n   *\n   * @name isString\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isString = function (val, msg) {\n    new Assertion(val, msg, assert.isString, true).to.be.a('string');\n  };\n\n  /**\n   * ### .isNotString(value, [message])\n   *\n   * Asserts that `value` is _not_ a string.\n   *\n   *     var teaOrder = 4;\n   *     assert.isNotString(teaOrder, 'order placed');\n   *\n   * @name isNotString\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotString = function (val, msg) {\n    new Assertion(val, msg, assert.isNotString, true).to.not.be.a('string');\n  };\n\n  /**\n   * ### .isNumber(value, [message])\n   *\n   * Asserts that `value` is a number.\n   *\n   *     var cups = 2;\n   *     assert.isNumber(cups, 'how many cups');\n   *\n   * @name isNumber\n   * @param {Number} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNumber = function (val, msg) {\n    new Assertion(val, msg, assert.isNumber, true).to.be.a('number');\n  };\n\n  /**\n   * ### .isNotNumber(value, [message])\n   *\n   * Asserts that `value` is _not_ a number.\n   *\n   *     var cups = '2 cups please';\n   *     assert.isNotNumber(cups, 'how many cups');\n   *\n   * @name isNotNumber\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotNumber = function (val, msg) {\n    new Assertion(val, msg, assert.isNotNumber, true).to.not.be.a('number');\n  };\n\n   /**\n   * ### .isFinite(value, [message])\n   *\n   * Asserts that `value` is a finite number. Unlike `.isNumber`, this will fail for `NaN` and `Infinity`.\n   *\n   *     var cups = 2;\n   *     assert.isFinite(cups, 'how many cups');\n   *\n   *     assert.isFinite(NaN); // throws\n   *\n   * @name isFinite\n   * @param {Number} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isFinite = function (val, msg) {\n    new Assertion(val, msg, assert.isFinite, true).to.be.finite;\n  };\n\n  /**\n   * ### .isBoolean(value, [message])\n   *\n   * Asserts that `value` is a boolean.\n   *\n   *     var teaReady = true\n   *       , teaServed = false;\n   *\n   *     assert.isBoolean(teaReady, 'is the tea ready');\n   *     assert.isBoolean(teaServed, 'has tea been served');\n   *\n   * @name isBoolean\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isBoolean = function (val, msg) {\n    new Assertion(val, msg, assert.isBoolean, true).to.be.a('boolean');\n  };\n\n  /**\n   * ### .isNotBoolean(value, [message])\n   *\n   * Asserts that `value` is _not_ a boolean.\n   *\n   *     var teaReady = 'yep'\n   *       , teaServed = 'nope';\n   *\n   *     assert.isNotBoolean(teaReady, 'is the tea ready');\n   *     assert.isNotBoolean(teaServed, 'has tea been served');\n   *\n   * @name isNotBoolean\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotBoolean = function (val, msg) {\n    new Assertion(val, msg, assert.isNotBoolean, true).to.not.be.a('boolean');\n  };\n\n  /**\n   * ### .typeOf(value, name, [message])\n   *\n   * Asserts that `value`'s type is `name`, as determined by\n   * `Object.prototype.toString`.\n   *\n   *     assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');\n   *     assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');\n   *     assert.typeOf('tea', 'string', 'we have a string');\n   *     assert.typeOf(/tea/, 'regexp', 'we have a regular expression');\n   *     assert.typeOf(null, 'null', 'we have a null');\n   *     assert.typeOf(undefined, 'undefined', 'we have an undefined');\n   *\n   * @name typeOf\n   * @param {Mixed} value\n   * @param {String} name\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.typeOf = function (val, type, msg) {\n    new Assertion(val, msg, assert.typeOf, true).to.be.a(type);\n  };\n\n  /**\n   * ### .notTypeOf(value, name, [message])\n   *\n   * Asserts that `value`'s type is _not_ `name`, as determined by\n   * `Object.prototype.toString`.\n   *\n   *     assert.notTypeOf('tea', 'number', 'strings are not numbers');\n   *\n   * @name notTypeOf\n   * @param {Mixed} value\n   * @param {String} typeof name\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notTypeOf = function (val, type, msg) {\n    new Assertion(val, msg, assert.notTypeOf, true).to.not.be.a(type);\n  };\n\n  /**\n   * ### .instanceOf(object, constructor, [message])\n   *\n   * Asserts that `value` is an instance of `constructor`.\n   *\n   *     var Tea = function (name) { this.name = name; }\n   *       , chai = new Tea('chai');\n   *\n   *     assert.instanceOf(chai, Tea, 'chai is an instance of tea');\n   *\n   * @name instanceOf\n   * @param {Object} object\n   * @param {Constructor} constructor\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.instanceOf = function (val, type, msg) {\n    new Assertion(val, msg, assert.instanceOf, true).to.be.instanceOf(type);\n  };\n\n  /**\n   * ### .notInstanceOf(object, constructor, [message])\n   *\n   * Asserts `value` is not an instance of `constructor`.\n   *\n   *     var Tea = function (name) { this.name = name; }\n   *       , chai = new String('chai');\n   *\n   *     assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');\n   *\n   * @name notInstanceOf\n   * @param {Object} object\n   * @param {Constructor} constructor\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notInstanceOf = function (val, type, msg) {\n    new Assertion(val, msg, assert.notInstanceOf, true)\n      .to.not.be.instanceOf(type);\n  };\n\n  /**\n   * ### .include(haystack, needle, [message])\n   *\n   * Asserts that `haystack` includes `needle`. Can be used to assert the\n   * inclusion of a value in an array, a substring in a string, or a subset of\n   * properties in an object.\n   *\n   *     assert.include([1,2,3], 2, 'array contains value');\n   *     assert.include('foobar', 'foo', 'string contains substring');\n   *     assert.include({ foo: 'bar', hello: 'universe' }, { foo: 'bar' }, 'object contains property');\n   *\n   * Strict equality (===) is used. When asserting the inclusion of a value in\n   * an array, the array is searched for an element that's strictly equal to the\n   * given value. When asserting a subset of properties in an object, the object\n   * is searched for the given property keys, checking that each one is present\n   * and strictly equal to the given property value. For instance:\n   *\n   *     var obj1 = {a: 1}\n   *       , obj2 = {b: 2};\n   *     assert.include([obj1, obj2], obj1);\n   *     assert.include({foo: obj1, bar: obj2}, {foo: obj1});\n   *     assert.include({foo: obj1, bar: obj2}, {foo: obj1, bar: obj2});\n   *\n   * @name include\n   * @param {Array|String} haystack\n   * @param {Mixed} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.include = function (exp, inc, msg) {\n    new Assertion(exp, msg, assert.include, true).include(inc);\n  };\n\n  /**\n   * ### .notInclude(haystack, needle, [message])\n   *\n   * Asserts that `haystack` does not include `needle`. Can be used to assert\n   * the absence of a value in an array, a substring in a string, or a subset of\n   * properties in an object.\n   *\n   *     assert.notInclude([1,2,3], 4, \"array doesn't contain value\");\n   *     assert.notInclude('foobar', 'baz', \"string doesn't contain substring\");\n   *     assert.notInclude({ foo: 'bar', hello: 'universe' }, { foo: 'baz' }, 'object doesn't contain property');\n   *\n   * Strict equality (===) is used. When asserting the absence of a value in an\n   * array, the array is searched to confirm the absence of an element that's\n   * strictly equal to the given value. When asserting a subset of properties in\n   * an object, the object is searched to confirm that at least one of the given\n   * property keys is either not present or not strictly equal to the given\n   * property value. For instance:\n   *\n   *     var obj1 = {a: 1}\n   *       , obj2 = {b: 2};\n   *     assert.notInclude([obj1, obj2], {a: 1});\n   *     assert.notInclude({foo: obj1, bar: obj2}, {foo: {a: 1}});\n   *     assert.notInclude({foo: obj1, bar: obj2}, {foo: obj1, bar: {b: 2}});\n   *\n   * @name notInclude\n   * @param {Array|String} haystack\n   * @param {Mixed} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notInclude = function (exp, inc, msg) {\n    new Assertion(exp, msg, assert.notInclude, true).not.include(inc);\n  };\n\n  /**\n   * ### .deepInclude(haystack, needle, [message])\n   *\n   * Asserts that `haystack` includes `needle`. Can be used to assert the\n   * inclusion of a value in an array or a subset of properties in an object.\n   * Deep equality is used.\n   *\n   *     var obj1 = {a: 1}\n   *       , obj2 = {b: 2};\n   *     assert.deepInclude([obj1, obj2], {a: 1});\n   *     assert.deepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}});\n   *     assert.deepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 2}});\n   *\n   * @name deepInclude\n   * @param {Array|String} haystack\n   * @param {Mixed} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.deepInclude = function (exp, inc, msg) {\n    new Assertion(exp, msg, assert.deepInclude, true).deep.include(inc);\n  };\n\n  /**\n   * ### .notDeepInclude(haystack, needle, [message])\n   *\n   * Asserts that `haystack` does not include `needle`. Can be used to assert\n   * the absence of a value in an array or a subset of properties in an object.\n   * Deep equality is used.\n   *\n   *     var obj1 = {a: 1}\n   *       , obj2 = {b: 2};\n   *     assert.notDeepInclude([obj1, obj2], {a: 9});\n   *     assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 9}});\n   *     assert.notDeepInclude({foo: obj1, bar: obj2}, {foo: {a: 1}, bar: {b: 9}});\n   *\n   * @name notDeepInclude\n   * @param {Array|String} haystack\n   * @param {Mixed} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notDeepInclude = function (exp, inc, msg) {\n    new Assertion(exp, msg, assert.notDeepInclude, true).not.deep.include(inc);\n  };\n\n  /**\n   * ### .nestedInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' includes 'needle'.\n   * Can be used to assert the inclusion of a subset of properties in an\n   * object.\n   * Enables the use of dot- and bracket-notation for referencing nested\n   * properties.\n   * '[]' and '.' in property names can be escaped using double backslashes.\n   *\n   *     assert.nestedInclude({'.a': {'b': 'x'}}, {'\\\\.a.[b]': 'x'});\n   *     assert.nestedInclude({'a': {'[b]': 'x'}}, {'a.\\\\[b\\\\]': 'x'});\n   *\n   * @name nestedInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.nestedInclude = function (exp, inc, msg) {\n    new Assertion(exp, msg, assert.nestedInclude, true).nested.include(inc);\n  };\n\n  /**\n   * ### .notNestedInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' does not include 'needle'.\n   * Can be used to assert the absence of a subset of properties in an\n   * object.\n   * Enables the use of dot- and bracket-notation for referencing nested\n   * properties.\n   * '[]' and '.' in property names can be escaped using double backslashes.\n   *\n   *     assert.notNestedInclude({'.a': {'b': 'x'}}, {'\\\\.a.b': 'y'});\n   *     assert.notNestedInclude({'a': {'[b]': 'x'}}, {'a.\\\\[b\\\\]': 'y'});\n   *\n   * @name notNestedInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notNestedInclude = function (exp, inc, msg) {\n    new Assertion(exp, msg, assert.notNestedInclude, true)\n      .not.nested.include(inc);\n  };\n\n  /**\n   * ### .deepNestedInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' includes 'needle'.\n   * Can be used to assert the inclusion of a subset of properties in an\n   * object while checking for deep equality.\n   * Enables the use of dot- and bracket-notation for referencing nested\n   * properties.\n   * '[]' and '.' in property names can be escaped using double backslashes.\n   *\n   *     assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});\n   *     assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\\\.a.\\\\[b\\\\]': {x: 1}});\n   *\n   * @name deepNestedInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.deepNestedInclude = function(exp, inc, msg) {\n    new Assertion(exp, msg, assert.deepNestedInclude, true)\n      .deep.nested.include(inc);\n  };\n\n  /**\n   * ### .notDeepNestedInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' does not include 'needle'.\n   * Can be used to assert the absence of a subset of properties in an\n   * object while checking for deep equality.\n   * Enables the use of dot- and bracket-notation for referencing nested\n   * properties.\n   * '[]' and '.' in property names can be escaped using double backslashes.\n   *\n   *     assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 1}})\n   *     assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\\\.a.\\\\[b\\\\]': {y: 2}});\n   *\n   * @name notDeepNestedInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notDeepNestedInclude = function(exp, inc, msg) {\n    new Assertion(exp, msg, assert.notDeepNestedInclude, true)\n      .not.deep.nested.include(inc);\n  };\n\n  /**\n   * ### .ownInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' includes 'needle'.\n   * Can be used to assert the inclusion of a subset of properties in an\n   * object while ignoring inherited properties.\n   *\n   *     assert.ownInclude({ a: 1 }, { a: 1 });\n   *\n   * @name ownInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.ownInclude = function(exp, inc, msg) {\n    new Assertion(exp, msg, assert.ownInclude, true).own.include(inc);\n  };\n\n  /**\n   * ### .notOwnInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' includes 'needle'.\n   * Can be used to assert the absence of a subset of properties in an\n   * object while ignoring inherited properties.\n   *\n   *     Object.prototype.b = 2;\n   *\n   *     assert.notOwnInclude({ a: 1 }, { b: 2 });\n   *\n   * @name notOwnInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notOwnInclude = function(exp, inc, msg) {\n    new Assertion(exp, msg, assert.notOwnInclude, true).not.own.include(inc);\n  };\n\n  /**\n   * ### .deepOwnInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' includes 'needle'.\n   * Can be used to assert the inclusion of a subset of properties in an\n   * object while ignoring inherited properties and checking for deep equality.\n   *\n   *      assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}});\n   *\n   * @name deepOwnInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.deepOwnInclude = function(exp, inc, msg) {\n    new Assertion(exp, msg, assert.deepOwnInclude, true)\n      .deep.own.include(inc);\n  };\n\n   /**\n   * ### .notDeepOwnInclude(haystack, needle, [message])\n   *\n   * Asserts that 'haystack' includes 'needle'.\n   * Can be used to assert the absence of a subset of properties in an\n   * object while ignoring inherited properties and checking for deep equality.\n   *\n   *      assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}});\n   *\n   * @name notDeepOwnInclude\n   * @param {Object} haystack\n   * @param {Object} needle\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notDeepOwnInclude = function(exp, inc, msg) {\n    new Assertion(exp, msg, assert.notDeepOwnInclude, true)\n      .not.deep.own.include(inc);\n  };\n\n  /**\n   * ### .match(value, regexp, [message])\n   *\n   * Asserts that `value` matches the regular expression `regexp`.\n   *\n   *     assert.match('foobar', /^foo/, 'regexp matches');\n   *\n   * @name match\n   * @param {Mixed} value\n   * @param {RegExp} regexp\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.match = function (exp, re, msg) {\n    new Assertion(exp, msg, assert.match, true).to.match(re);\n  };\n\n  /**\n   * ### .notMatch(value, regexp, [message])\n   *\n   * Asserts that `value` does not match the regular expression `regexp`.\n   *\n   *     assert.notMatch('foobar', /^foo/, 'regexp does not match');\n   *\n   * @name notMatch\n   * @param {Mixed} value\n   * @param {RegExp} regexp\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notMatch = function (exp, re, msg) {\n    new Assertion(exp, msg, assert.notMatch, true).to.not.match(re);\n  };\n\n  /**\n   * ### .property(object, property, [message])\n   *\n   * Asserts that `object` has a direct or inherited property named by\n   * `property`.\n   *\n   *     assert.property({ tea: { green: 'matcha' }}, 'tea');\n   *     assert.property({ tea: { green: 'matcha' }}, 'toString');\n   *\n   * @name property\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.property = function (obj, prop, msg) {\n    new Assertion(obj, msg, assert.property, true).to.have.property(prop);\n  };\n\n  /**\n   * ### .notProperty(object, property, [message])\n   *\n   * Asserts that `object` does _not_ have a direct or inherited property named\n   * by `property`.\n   *\n   *     assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');\n   *\n   * @name notProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg, assert.notProperty, true)\n      .to.not.have.property(prop);\n  };\n\n  /**\n   * ### .propertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a direct or inherited property named by\n   * `property` with a value given by `value`. Uses a strict equality check\n   * (===).\n   *\n   *     assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');\n   *\n   * @name propertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.propertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.propertyVal, true)\n      .to.have.property(prop, val);\n  };\n\n  /**\n   * ### .notPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` does _not_ have a direct or inherited property named\n   * by `property` with value given by `value`. Uses a strict equality check\n   * (===).\n   *\n   *     assert.notPropertyVal({ tea: 'is good' }, 'tea', 'is bad');\n   *     assert.notPropertyVal({ tea: 'is good' }, 'coffee', 'is good');\n   *\n   * @name notPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.notPropertyVal, true)\n      .to.not.have.property(prop, val);\n  };\n\n  /**\n   * ### .deepPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a direct or inherited property named by\n   * `property` with a value given by `value`. Uses a deep equality check.\n   *\n   *     assert.deepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' });\n   *\n   * @name deepPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.deepPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.deepPropertyVal, true)\n      .to.have.deep.property(prop, val);\n  };\n\n  /**\n   * ### .notDeepPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` does _not_ have a direct or inherited property named\n   * by `property` with value given by `value`. Uses a deep equality check.\n   *\n   *     assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' });\n   *     assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' });\n   *     assert.notDeepPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' });\n   *\n   * @name notDeepPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notDeepPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.notDeepPropertyVal, true)\n      .to.not.have.deep.property(prop, val);\n  };\n\n  /**\n   * ### .ownProperty(object, property, [message])\n   *\n   * Asserts that `object` has a direct property named by `property`. Inherited\n   * properties aren't checked.\n   *\n   *     assert.ownProperty({ tea: { green: 'matcha' }}, 'tea');\n   *\n   * @name ownProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @api public\n   */\n\n  assert.ownProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg, assert.ownProperty, true)\n      .to.have.own.property(prop);\n  };\n\n  /**\n   * ### .notOwnProperty(object, property, [message])\n   *\n   * Asserts that `object` does _not_ have a direct property named by\n   * `property`. Inherited properties aren't checked.\n   *\n   *     assert.notOwnProperty({ tea: { green: 'matcha' }}, 'coffee');\n   *     assert.notOwnProperty({}, 'toString');\n   *\n   * @name notOwnProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notOwnProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg, assert.notOwnProperty, true)\n      .to.not.have.own.property(prop);\n  };\n\n  /**\n   * ### .ownPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a direct property named by `property` and a value\n   * equal to the provided `value`. Uses a strict equality check (===).\n   * Inherited properties aren't checked.\n   *\n   *     assert.ownPropertyVal({ coffee: 'is good'}, 'coffee', 'is good');\n   *\n   * @name ownPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.ownPropertyVal = function (obj, prop, value, msg) {\n    new Assertion(obj, msg, assert.ownPropertyVal, true)\n      .to.have.own.property(prop, value);\n  };\n\n  /**\n   * ### .notOwnPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` does _not_ have a direct property named by `property`\n   * with a value equal to the provided `value`. Uses a strict equality check\n   * (===). Inherited properties aren't checked.\n   *\n   *     assert.notOwnPropertyVal({ tea: 'is better'}, 'tea', 'is worse');\n   *     assert.notOwnPropertyVal({}, 'toString', Object.prototype.toString);\n   *\n   * @name notOwnPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notOwnPropertyVal = function (obj, prop, value, msg) {\n    new Assertion(obj, msg, assert.notOwnPropertyVal, true)\n      .to.not.have.own.property(prop, value);\n  };\n\n  /**\n   * ### .deepOwnPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a direct property named by `property` and a value\n   * equal to the provided `value`. Uses a deep equality check. Inherited\n   * properties aren't checked.\n   *\n   *     assert.deepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'matcha' });\n   *\n   * @name deepOwnPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.deepOwnPropertyVal = function (obj, prop, value, msg) {\n    new Assertion(obj, msg, assert.deepOwnPropertyVal, true)\n      .to.have.deep.own.property(prop, value);\n  };\n\n  /**\n   * ### .notDeepOwnPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` does _not_ have a direct property named by `property`\n   * with a value equal to the provided `value`. Uses a deep equality check.\n   * Inherited properties aren't checked.\n   *\n   *     assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { black: 'matcha' });\n   *     assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'tea', { green: 'oolong' });\n   *     assert.notDeepOwnPropertyVal({ tea: { green: 'matcha' } }, 'coffee', { green: 'matcha' });\n   *     assert.notDeepOwnPropertyVal({}, 'toString', Object.prototype.toString);\n   *\n   * @name notDeepOwnPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @api public\n   */\n\n  assert.notDeepOwnPropertyVal = function (obj, prop, value, msg) {\n    new Assertion(obj, msg, assert.notDeepOwnPropertyVal, true)\n      .to.not.have.deep.own.property(prop, value);\n  };\n\n  /**\n   * ### .nestedProperty(object, property, [message])\n   *\n   * Asserts that `object` has a direct or inherited property named by\n   * `property`, which can be a string using dot- and bracket-notation for\n   * nested reference.\n   *\n   *     assert.nestedProperty({ tea: { green: 'matcha' }}, 'tea.green');\n   *\n   * @name nestedProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.nestedProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg, assert.nestedProperty, true)\n      .to.have.nested.property(prop);\n  };\n\n  /**\n   * ### .notNestedProperty(object, property, [message])\n   *\n   * Asserts that `object` does _not_ have a property named by `property`, which\n   * can be a string using dot- and bracket-notation for nested reference. The\n   * property cannot exist on the object nor anywhere in its prototype chain.\n   *\n   *     assert.notNestedProperty({ tea: { green: 'matcha' }}, 'tea.oolong');\n   *\n   * @name notNestedProperty\n   * @param {Object} object\n   * @param {String} property\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notNestedProperty = function (obj, prop, msg) {\n    new Assertion(obj, msg, assert.notNestedProperty, true)\n      .to.not.have.nested.property(prop);\n  };\n\n  /**\n   * ### .nestedPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a property named by `property` with value given\n   * by `value`. `property` can use dot- and bracket-notation for nested\n   * reference. Uses a strict equality check (===).\n   *\n   *     assert.nestedPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');\n   *\n   * @name nestedPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.nestedPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.nestedPropertyVal, true)\n      .to.have.nested.property(prop, val);\n  };\n\n  /**\n   * ### .notNestedPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` does _not_ have a property named by `property` with\n   * value given by `value`. `property` can use dot- and bracket-notation for\n   * nested reference. Uses a strict equality check (===).\n   *\n   *     assert.notNestedPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');\n   *     assert.notNestedPropertyVal({ tea: { green: 'matcha' }}, 'coffee.green', 'matcha');\n   *\n   * @name notNestedPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notNestedPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.notNestedPropertyVal, true)\n      .to.not.have.nested.property(prop, val);\n  };\n\n  /**\n   * ### .deepNestedPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` has a property named by `property` with a value given\n   * by `value`. `property` can use dot- and bracket-notation for nested\n   * reference. Uses a deep equality check.\n   *\n   *     assert.deepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { matcha: 'yum' });\n   *\n   * @name deepNestedPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.deepNestedPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.deepNestedPropertyVal, true)\n      .to.have.deep.nested.property(prop, val);\n  };\n\n  /**\n   * ### .notDeepNestedPropertyVal(object, property, value, [message])\n   *\n   * Asserts that `object` does _not_ have a property named by `property` with\n   * value given by `value`. `property` can use dot- and bracket-notation for\n   * nested reference. Uses a deep equality check.\n   *\n   *     assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { oolong: 'yum' });\n   *     assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.green', { matcha: 'yuck' });\n   *     assert.notDeepNestedPropertyVal({ tea: { green: { matcha: 'yum' } } }, 'tea.black', { matcha: 'yum' });\n   *\n   * @name notDeepNestedPropertyVal\n   * @param {Object} object\n   * @param {String} property\n   * @param {Mixed} value\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notDeepNestedPropertyVal = function (obj, prop, val, msg) {\n    new Assertion(obj, msg, assert.notDeepNestedPropertyVal, true)\n      .to.not.have.deep.nested.property(prop, val);\n  }\n\n  /**\n   * ### .lengthOf(object, length, [message])\n   *\n   * Asserts that `object` has a `length` or `size` with the expected value.\n   *\n   *     assert.lengthOf([1,2,3], 3, 'array has length of 3');\n   *     assert.lengthOf('foobar', 6, 'string has length of 6');\n   *     assert.lengthOf(new Set([1,2,3]), 3, 'set has size of 3');\n   *     assert.lengthOf(new Map([['a',1],['b',2],['c',3]]), 3, 'map has size of 3');\n   *\n   * @name lengthOf\n   * @param {Mixed} object\n   * @param {Number} length\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.lengthOf = function (exp, len, msg) {\n    new Assertion(exp, msg, assert.lengthOf, true).to.have.lengthOf(len);\n  };\n\n  /**\n   * ### .hasAnyKeys(object, [keys], [message])\n   *\n   * Asserts that `object` has at least one of the `keys` provided.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'iDontExist', 'baz']);\n   *     assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, iDontExist: 99, baz: 1337});\n   *     assert.hasAnyKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']);\n   *     assert.hasAnyKeys(new Set([{foo: 'bar'}, 'anotherKey']), [{foo: 'bar'}, 'anotherKey']);\n   *\n   * @name hasAnyKeys\n   * @param {Mixed} object\n   * @param {Array|Object} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.hasAnyKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.hasAnyKeys, true).to.have.any.keys(keys);\n  }\n\n  /**\n   * ### .hasAllKeys(object, [keys], [message])\n   *\n   * Asserts that `object` has all and only all of the `keys` provided.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.hasAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'bar', 'baz']);\n   *     assert.hasAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, bar: 99, baz: 1337]);\n   *     assert.hasAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']);\n   *     assert.hasAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}, 'anotherKey']);\n   *\n   * @name hasAllKeys\n   * @param {Mixed} object\n   * @param {String[]} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.hasAllKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.hasAllKeys, true).to.have.all.keys(keys);\n  }\n\n  /**\n   * ### .containsAllKeys(object, [keys], [message])\n   *\n   * Asserts that `object` has all of the `keys` provided but may have more keys not listed.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'baz']);\n   *     assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'bar', 'baz']);\n   *     assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, baz: 1337});\n   *     assert.containsAllKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, bar: 99, baz: 1337});\n   *     assert.containsAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}]);\n   *     assert.containsAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']);\n   *     assert.containsAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}]);\n   *     assert.containsAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{foo: 'bar'}, 'anotherKey']);\n   *\n   * @name containsAllKeys\n   * @param {Mixed} object\n   * @param {String[]} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.containsAllKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.containsAllKeys, true)\n      .to.contain.all.keys(keys);\n  }\n\n  /**\n   * ### .doesNotHaveAnyKeys(object, [keys], [message])\n   *\n   * Asserts that `object` has none of the `keys` provided.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.doesNotHaveAnyKeys({foo: 1, bar: 2, baz: 3}, ['one', 'two', 'example']);\n   *     assert.doesNotHaveAnyKeys({foo: 1, bar: 2, baz: 3}, {one: 1, two: 2, example: 'foo'});\n   *     assert.doesNotHaveAnyKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{one: 'two'}, 'example']);\n   *     assert.doesNotHaveAnyKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{one: 'two'}, 'example']);\n   *\n   * @name doesNotHaveAnyKeys\n   * @param {Mixed} object\n   * @param {String[]} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotHaveAnyKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.doesNotHaveAnyKeys, true)\n      .to.not.have.any.keys(keys);\n  }\n\n  /**\n   * ### .doesNotHaveAllKeys(object, [keys], [message])\n   *\n   * Asserts that `object` does not have at least one of the `keys` provided.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.doesNotHaveAllKeys({foo: 1, bar: 2, baz: 3}, ['one', 'two', 'example']);\n   *     assert.doesNotHaveAllKeys({foo: 1, bar: 2, baz: 3}, {one: 1, two: 2, example: 'foo'});\n   *     assert.doesNotHaveAllKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{one: 'two'}, 'example']);\n   *     assert.doesNotHaveAllKeys(new Set([{foo: 'bar'}, 'anotherKey'], [{one: 'two'}, 'example']);\n   *\n   * @name doesNotHaveAllKeys\n   * @param {Mixed} object\n   * @param {String[]} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotHaveAllKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.doesNotHaveAllKeys, true)\n      .to.not.have.all.keys(keys);\n  }\n\n  /**\n   * ### .hasAnyDeepKeys(object, [keys], [message])\n   *\n   * Asserts that `object` has at least one of the `keys` provided.\n   * Since Sets and Maps can have objects as keys you can use this assertion to perform\n   * a deep comparison.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {one: 'one'});\n   *     assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), [{one: 'one'}, {two: 'two'}]);\n   *     assert.hasAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]);\n   *     assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {one: 'one'});\n   *     assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {three: 'three'}]);\n   *     assert.hasAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]);\n   *\n   * @name hasAnyDeepKeys\n   * @param {Mixed} object\n   * @param {Array|Object} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.hasAnyDeepKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.hasAnyDeepKeys, true)\n      .to.have.any.deep.keys(keys);\n  }\n\n /**\n   * ### .hasAllDeepKeys(object, [keys], [message])\n   *\n   * Asserts that `object` has all and only all of the `keys` provided.\n   * Since Sets and Maps can have objects as keys you can use this assertion to perform\n   * a deep comparison.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.hasAllDeepKeys(new Map([[{one: 'one'}, 'valueOne']]), {one: 'one'});\n   *     assert.hasAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]);\n   *     assert.hasAllDeepKeys(new Set([{one: 'one'}]), {one: 'one'});\n   *     assert.hasAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]);\n   *\n   * @name hasAllDeepKeys\n   * @param {Mixed} object\n   * @param {Array|Object} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.hasAllDeepKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.hasAllDeepKeys, true)\n      .to.have.all.deep.keys(keys);\n  }\n\n /**\n   * ### .containsAllDeepKeys(object, [keys], [message])\n   *\n   * Asserts that `object` contains all of the `keys` provided.\n   * Since Sets and Maps can have objects as keys you can use this assertion to perform\n   * a deep comparison.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.containsAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {one: 'one'});\n   *     assert.containsAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{one: 'one'}, {two: 'two'}]);\n   *     assert.containsAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {one: 'one'});\n   *     assert.containsAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {two: 'two'}]);\n   *\n   * @name containsAllDeepKeys\n   * @param {Mixed} object\n   * @param {Array|Object} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.containsAllDeepKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.containsAllDeepKeys, true)\n      .to.contain.all.deep.keys(keys);\n  }\n\n /**\n   * ### .doesNotHaveAnyDeepKeys(object, [keys], [message])\n   *\n   * Asserts that `object` has none of the `keys` provided.\n   * Since Sets and Maps can have objects as keys you can use this assertion to perform\n   * a deep comparison.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.doesNotHaveAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {thisDoesNot: 'exist'});\n   *     assert.doesNotHaveAnyDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{twenty: 'twenty'}, {fifty: 'fifty'}]);\n   *     assert.doesNotHaveAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {twenty: 'twenty'});\n   *     assert.doesNotHaveAnyDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{twenty: 'twenty'}, {fifty: 'fifty'}]);\n   *\n   * @name doesNotHaveAnyDeepKeys\n   * @param {Mixed} object\n   * @param {Array|Object} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotHaveAnyDeepKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.doesNotHaveAnyDeepKeys, true)\n      .to.not.have.any.deep.keys(keys);\n  }\n\n /**\n   * ### .doesNotHaveAllDeepKeys(object, [keys], [message])\n   *\n   * Asserts that `object` does not have at least one of the `keys` provided.\n   * Since Sets and Maps can have objects as keys you can use this assertion to perform\n   * a deep comparison.\n   * You can also provide a single object instead of a `keys` array and its keys\n   * will be used as the expected set of keys.\n   *\n   *     assert.doesNotHaveAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [1, 2]]), {thisDoesNot: 'exist'});\n   *     assert.doesNotHaveAllDeepKeys(new Map([[{one: 'one'}, 'valueOne'], [{two: 'two'}, 'valueTwo']]), [{twenty: 'twenty'}, {one: 'one'}]);\n   *     assert.doesNotHaveAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), {twenty: 'twenty'});\n   *     assert.doesNotHaveAllDeepKeys(new Set([{one: 'one'}, {two: 'two'}]), [{one: 'one'}, {fifty: 'fifty'}]);\n   *\n   * @name doesNotHaveAllDeepKeys\n   * @param {Mixed} object\n   * @param {Array|Object} keys\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotHaveAllDeepKeys = function (obj, keys, msg) {\n    new Assertion(obj, msg, assert.doesNotHaveAllDeepKeys, true)\n      .to.not.have.all.deep.keys(keys);\n  }\n\n /**\n   * ### .throws(fn, [errorLike/string/regexp], [string/regexp], [message])\n   *\n   * If `errorLike` is an `Error` constructor, asserts that `fn` will throw an error that is an\n   * instance of `errorLike`.\n   * If `errorLike` is an `Error` instance, asserts that the error thrown is the same\n   * instance as `errorLike`.\n   * If `errMsgMatcher` is provided, it also asserts that the error thrown will have a\n   * message matching `errMsgMatcher`.\n   *\n   *     assert.throws(fn, 'Error thrown must have this msg');\n   *     assert.throws(fn, /Error thrown must have a msg that matches this/);\n   *     assert.throws(fn, ReferenceError);\n   *     assert.throws(fn, errorInstance);\n   *     assert.throws(fn, ReferenceError, 'Error thrown must be a ReferenceError and have this msg');\n   *     assert.throws(fn, errorInstance, 'Error thrown must be the same errorInstance and have this msg');\n   *     assert.throws(fn, ReferenceError, /Error thrown must be a ReferenceError and match this/);\n   *     assert.throws(fn, errorInstance, /Error thrown must be the same errorInstance and match this/);\n   *\n   * @name throws\n   * @alias throw\n   * @alias Throw\n   * @param {Function} fn\n   * @param {ErrorConstructor|Error} errorLike\n   * @param {RegExp|String} errMsgMatcher\n   * @param {String} message\n   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.throws = function (fn, errorLike, errMsgMatcher, msg) {\n    if ('string' === typeof errorLike || errorLike instanceof RegExp) {\n      errMsgMatcher = errorLike;\n      errorLike = null;\n    }\n\n    var assertErr = new Assertion(fn, msg, assert.throws, true)\n      .to.throw(errorLike, errMsgMatcher);\n    return flag(assertErr, 'object');\n  };\n\n  /**\n   * ### .doesNotThrow(fn, [errorLike/string/regexp], [string/regexp], [message])\n   *\n   * If `errorLike` is an `Error` constructor, asserts that `fn` will _not_ throw an error that is an\n   * instance of `errorLike`.\n   * If `errorLike` is an `Error` instance, asserts that the error thrown is _not_ the same\n   * instance as `errorLike`.\n   * If `errMsgMatcher` is provided, it also asserts that the error thrown will _not_ have a\n   * message matching `errMsgMatcher`.\n   *\n   *     assert.doesNotThrow(fn, 'Any Error thrown must not have this message');\n   *     assert.doesNotThrow(fn, /Any Error thrown must not match this/);\n   *     assert.doesNotThrow(fn, Error);\n   *     assert.doesNotThrow(fn, errorInstance);\n   *     assert.doesNotThrow(fn, Error, 'Error must not have this message');\n   *     assert.doesNotThrow(fn, errorInstance, 'Error must not have this message');\n   *     assert.doesNotThrow(fn, Error, /Error must not match this/);\n   *     assert.doesNotThrow(fn, errorInstance, /Error must not match this/);\n   *\n   * @name doesNotThrow\n   * @param {Function} fn\n   * @param {ErrorConstructor} errorLike\n   * @param {RegExp|String} errMsgMatcher\n   * @param {String} message\n   * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotThrow = function (fn, errorLike, errMsgMatcher, msg) {\n    if ('string' === typeof errorLike || errorLike instanceof RegExp) {\n      errMsgMatcher = errorLike;\n      errorLike = null;\n    }\n\n    new Assertion(fn, msg, assert.doesNotThrow, true)\n      .to.not.throw(errorLike, errMsgMatcher);\n  };\n\n  /**\n   * ### .operator(val1, operator, val2, [message])\n   *\n   * Compares two values using `operator`.\n   *\n   *     assert.operator(1, '<', 2, 'everything is ok');\n   *     assert.operator(1, '>', 2, 'this will fail');\n   *\n   * @name operator\n   * @param {Mixed} val1\n   * @param {String} operator\n   * @param {Mixed} val2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.operator = function (val, operator, val2, msg) {\n    var ok;\n    switch(operator) {\n      case '==':\n        ok = val == val2;\n        break;\n      case '===':\n        ok = val === val2;\n        break;\n      case '>':\n        ok = val > val2;\n        break;\n      case '>=':\n        ok = val >= val2;\n        break;\n      case '<':\n        ok = val < val2;\n        break;\n      case '<=':\n        ok = val <= val2;\n        break;\n      case '!=':\n        ok = val != val2;\n        break;\n      case '!==':\n        ok = val !== val2;\n        break;\n      default:\n        msg = msg ? msg + ': ' : msg;\n        throw new chai.AssertionError(\n          msg + 'Invalid operator \"' + operator + '\"',\n          undefined,\n          assert.operator\n        );\n    }\n    var test = new Assertion(ok, msg, assert.operator, true);\n    test.assert(\n        true === flag(test, 'object')\n      , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)\n      , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );\n  };\n\n  /**\n   * ### .closeTo(actual, expected, delta, [message])\n   *\n   * Asserts that the target is equal `expected`, to within a +/- `delta` range.\n   *\n   *     assert.closeTo(1.5, 1, 0.5, 'numbers are close');\n   *\n   * @name closeTo\n   * @param {Number} actual\n   * @param {Number} expected\n   * @param {Number} delta\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.closeTo = function (act, exp, delta, msg) {\n    new Assertion(act, msg, assert.closeTo, true).to.be.closeTo(exp, delta);\n  };\n\n  /**\n   * ### .approximately(actual, expected, delta, [message])\n   *\n   * Asserts that the target is equal `expected`, to within a +/- `delta` range.\n   *\n   *     assert.approximately(1.5, 1, 0.5, 'numbers are close');\n   *\n   * @name approximately\n   * @param {Number} actual\n   * @param {Number} expected\n   * @param {Number} delta\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.approximately = function (act, exp, delta, msg) {\n    new Assertion(act, msg, assert.approximately, true)\n      .to.be.approximately(exp, delta);\n  };\n\n  /**\n   * ### .sameMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` have the same members in any order. Uses a\n   * strict equality check (===).\n   *\n   *     assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');\n   *\n   * @name sameMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.sameMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.sameMembers, true)\n      .to.have.same.members(set2);\n  }\n\n  /**\n   * ### .notSameMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` don't have the same members in any order.\n   * Uses a strict equality check (===).\n   *\n   *     assert.notSameMembers([ 1, 2, 3 ], [ 5, 1, 3 ], 'not same members');\n   *\n   * @name notSameMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notSameMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.notSameMembers, true)\n      .to.not.have.same.members(set2);\n  }\n\n  /**\n   * ### .sameDeepMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` have the same members in any order. Uses a\n   * deep equality check.\n   *\n   *     assert.sameDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [{ b: 2 }, { a: 1 }, { c: 3 }], 'same deep members');\n   *\n   * @name sameDeepMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.sameDeepMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.sameDeepMembers, true)\n      .to.have.same.deep.members(set2);\n  }\n\n  /**\n   * ### .notSameDeepMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` don't have the same members in any order.\n   * Uses a deep equality check.\n   *\n   *     assert.notSameDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [{ b: 2 }, { a: 1 }, { f: 5 }], 'not same deep members');\n   *\n   * @name notSameDeepMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notSameDeepMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.notSameDeepMembers, true)\n      .to.not.have.same.deep.members(set2);\n  }\n\n  /**\n   * ### .sameOrderedMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` have the same members in the same order.\n   * Uses a strict equality check (===).\n   *\n   *     assert.sameOrderedMembers([ 1, 2, 3 ], [ 1, 2, 3 ], 'same ordered members');\n   *\n   * @name sameOrderedMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.sameOrderedMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.sameOrderedMembers, true)\n      .to.have.same.ordered.members(set2);\n  }\n\n  /**\n   * ### .notSameOrderedMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` don't have the same members in the same\n   * order. Uses a strict equality check (===).\n   *\n   *     assert.notSameOrderedMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'not same ordered members');\n   *\n   * @name notSameOrderedMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notSameOrderedMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.notSameOrderedMembers, true)\n      .to.not.have.same.ordered.members(set2);\n  }\n\n  /**\n   * ### .sameDeepOrderedMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` have the same members in the same order.\n   * Uses a deep equality check.\n   *\n   *     assert.sameDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { b: 2 }, { c: 3 } ], 'same deep ordered members');\n   *\n   * @name sameDeepOrderedMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.sameDeepOrderedMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.sameDeepOrderedMembers, true)\n      .to.have.same.deep.ordered.members(set2);\n  }\n\n  /**\n   * ### .notSameDeepOrderedMembers(set1, set2, [message])\n   *\n   * Asserts that `set1` and `set2` don't have the same members in the same\n   * order. Uses a deep equality check.\n   *\n   *     assert.notSameDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { b: 2 }, { z: 5 } ], 'not same deep ordered members');\n   *     assert.notSameDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { a: 1 }, { c: 3 } ], 'not same deep ordered members');\n   *\n   * @name notSameDeepOrderedMembers\n   * @param {Array} set1\n   * @param {Array} set2\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notSameDeepOrderedMembers = function (set1, set2, msg) {\n    new Assertion(set1, msg, assert.notSameDeepOrderedMembers, true)\n      .to.not.have.same.deep.ordered.members(set2);\n  }\n\n  /**\n   * ### .includeMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` is included in `superset` in any order. Uses a\n   * strict equality check (===). Duplicates are ignored.\n   *\n   *     assert.includeMembers([ 1, 2, 3 ], [ 2, 1, 2 ], 'include members');\n   *\n   * @name includeMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.includeMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.includeMembers, true)\n      .to.include.members(subset);\n  }\n\n  /**\n   * ### .notIncludeMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` isn't included in `superset` in any order. Uses a\n   * strict equality check (===). Duplicates are ignored.\n   *\n   *     assert.notIncludeMembers([ 1, 2, 3 ], [ 5, 1 ], 'not include members');\n   *\n   * @name notIncludeMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notIncludeMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.notIncludeMembers, true)\n      .to.not.include.members(subset);\n  }\n\n  /**\n   * ### .includeDeepMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` is included in `superset` in any order. Uses a deep\n   * equality check. Duplicates are ignored.\n   *\n   *     assert.includeDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { a: 1 }, { b: 2 } ], 'include deep members');\n   *\n   * @name includeDeepMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.includeDeepMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.includeDeepMembers, true)\n      .to.include.deep.members(subset);\n  }\n\n  /**\n   * ### .notIncludeDeepMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` isn't included in `superset` in any order. Uses a\n   * deep equality check. Duplicates are ignored.\n   *\n   *     assert.notIncludeDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { f: 5 } ], 'not include deep members');\n   *\n   * @name notIncludeDeepMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notIncludeDeepMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.notIncludeDeepMembers, true)\n      .to.not.include.deep.members(subset);\n  }\n\n  /**\n   * ### .includeOrderedMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` is included in `superset` in the same order\n   * beginning with the first element in `superset`. Uses a strict equality\n   * check (===).\n   *\n   *     assert.includeOrderedMembers([ 1, 2, 3 ], [ 1, 2 ], 'include ordered members');\n   *\n   * @name includeOrderedMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.includeOrderedMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.includeOrderedMembers, true)\n      .to.include.ordered.members(subset);\n  }\n\n  /**\n   * ### .notIncludeOrderedMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` isn't included in `superset` in the same order\n   * beginning with the first element in `superset`. Uses a strict equality\n   * check (===).\n   *\n   *     assert.notIncludeOrderedMembers([ 1, 2, 3 ], [ 2, 1 ], 'not include ordered members');\n   *     assert.notIncludeOrderedMembers([ 1, 2, 3 ], [ 2, 3 ], 'not include ordered members');\n   *\n   * @name notIncludeOrderedMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notIncludeOrderedMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.notIncludeOrderedMembers, true)\n      .to.not.include.ordered.members(subset);\n  }\n\n  /**\n   * ### .includeDeepOrderedMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` is included in `superset` in the same order\n   * beginning with the first element in `superset`. Uses a deep equality\n   * check.\n   *\n   *     assert.includeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { b: 2 } ], 'include deep ordered members');\n   *\n   * @name includeDeepOrderedMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.includeDeepOrderedMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.includeDeepOrderedMembers, true)\n      .to.include.deep.ordered.members(subset);\n  }\n\n  /**\n   * ### .notIncludeDeepOrderedMembers(superset, subset, [message])\n   *\n   * Asserts that `subset` isn't included in `superset` in the same order\n   * beginning with the first element in `superset`. Uses a deep equality\n   * check.\n   *\n   *     assert.notIncludeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { a: 1 }, { f: 5 } ], 'not include deep ordered members');\n   *     assert.notIncludeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { a: 1 } ], 'not include deep ordered members');\n   *     assert.notIncludeDeepOrderedMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [ { b: 2 }, { c: 3 } ], 'not include deep ordered members');\n   *\n   * @name notIncludeDeepOrderedMembers\n   * @param {Array} superset\n   * @param {Array} subset\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.notIncludeDeepOrderedMembers = function (superset, subset, msg) {\n    new Assertion(superset, msg, assert.notIncludeDeepOrderedMembers, true)\n      .to.not.include.deep.ordered.members(subset);\n  }\n\n  /**\n   * ### .oneOf(inList, list, [message])\n   *\n   * Asserts that non-object, non-array value `inList` appears in the flat array `list`.\n   *\n   *     assert.oneOf(1, [ 2, 1 ], 'Not found in list');\n   *\n   * @name oneOf\n   * @param {*} inList\n   * @param {Array<*>} list\n   * @param {String} message\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.oneOf = function (inList, list, msg) {\n    new Assertion(inList, msg, assert.oneOf, true).to.be.oneOf(list);\n  }\n\n  /**\n   * ### .changes(function, object, property, [message])\n   *\n   * Asserts that a function changes the value of a property.\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 22 };\n   *     assert.changes(fn, obj, 'val');\n   *\n   * @name changes\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.changes = function (fn, obj, prop, msg) {\n    if (arguments.length === 3 && typeof obj === 'function') {\n      msg = prop;\n      prop = null;\n    }\n\n    new Assertion(fn, msg, assert.changes, true).to.change(obj, prop);\n  }\n\n   /**\n   * ### .changesBy(function, object, property, delta, [message])\n   *\n   * Asserts that a function changes the value of a property by an amount (delta).\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val += 2 };\n   *     assert.changesBy(fn, obj, 'val', 2);\n   *\n   * @name changesBy\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {Number} change amount (delta)\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.changesBy = function (fn, obj, prop, delta, msg) {\n    if (arguments.length === 4 && typeof obj === 'function') {\n      var tmpMsg = delta;\n      delta = prop;\n      msg = tmpMsg;\n    } else if (arguments.length === 3) {\n      delta = prop;\n      prop = null;\n    }\n\n    new Assertion(fn, msg, assert.changesBy, true)\n      .to.change(obj, prop).by(delta);\n  }\n\n   /**\n   * ### .doesNotChange(function, object, property, [message])\n   *\n   * Asserts that a function does not change the value of a property.\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { console.log('foo'); };\n   *     assert.doesNotChange(fn, obj, 'val');\n   *\n   * @name doesNotChange\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotChange = function (fn, obj, prop, msg) {\n    if (arguments.length === 3 && typeof obj === 'function') {\n      msg = prop;\n      prop = null;\n    }\n\n    return new Assertion(fn, msg, assert.doesNotChange, true)\n      .to.not.change(obj, prop);\n  }\n\n  /**\n   * ### .changesButNotBy(function, object, property, delta, [message])\n   *\n   * Asserts that a function does not change the value of a property or of a function's return value by an amount (delta)\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val += 10 };\n   *     assert.changesButNotBy(fn, obj, 'val', 5);\n   *\n   * @name changesButNotBy\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {Number} change amount (delta)\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.changesButNotBy = function (fn, obj, prop, delta, msg) {\n    if (arguments.length === 4 && typeof obj === 'function') {\n      var tmpMsg = delta;\n      delta = prop;\n      msg = tmpMsg;\n    } else if (arguments.length === 3) {\n      delta = prop;\n      prop = null;\n    }\n\n    new Assertion(fn, msg, assert.changesButNotBy, true)\n      .to.change(obj, prop).but.not.by(delta);\n  }\n\n  /**\n   * ### .increases(function, object, property, [message])\n   *\n   * Asserts that a function increases a numeric object property.\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 13 };\n   *     assert.increases(fn, obj, 'val');\n   *\n   * @name increases\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.increases = function (fn, obj, prop, msg) {\n    if (arguments.length === 3 && typeof obj === 'function') {\n      msg = prop;\n      prop = null;\n    }\n\n    return new Assertion(fn, msg, assert.increases, true)\n      .to.increase(obj, prop);\n  }\n\n  /**\n   * ### .increasesBy(function, object, property, delta, [message])\n   *\n   * Asserts that a function increases a numeric object property or a function's return value by an amount (delta).\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val += 10 };\n   *     assert.increasesBy(fn, obj, 'val', 10);\n   *\n   * @name increasesBy\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {Number} change amount (delta)\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.increasesBy = function (fn, obj, prop, delta, msg) {\n    if (arguments.length === 4 && typeof obj === 'function') {\n      var tmpMsg = delta;\n      delta = prop;\n      msg = tmpMsg;\n    } else if (arguments.length === 3) {\n      delta = prop;\n      prop = null;\n    }\n\n    new Assertion(fn, msg, assert.increasesBy, true)\n      .to.increase(obj, prop).by(delta);\n  }\n\n  /**\n   * ### .doesNotIncrease(function, object, property, [message])\n   *\n   * Asserts that a function does not increase a numeric object property.\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 8 };\n   *     assert.doesNotIncrease(fn, obj, 'val');\n   *\n   * @name doesNotIncrease\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotIncrease = function (fn, obj, prop, msg) {\n    if (arguments.length === 3 && typeof obj === 'function') {\n      msg = prop;\n      prop = null;\n    }\n\n    return new Assertion(fn, msg, assert.doesNotIncrease, true)\n      .to.not.increase(obj, prop);\n  }\n\n  /**\n   * ### .increasesButNotBy(function, object, property, delta, [message])\n   *\n   * Asserts that a function does not increase a numeric object property or function's return value by an amount (delta).\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 15 };\n   *     assert.increasesButNotBy(fn, obj, 'val', 10);\n   *\n   * @name increasesButNotBy\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {Number} change amount (delta)\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.increasesButNotBy = function (fn, obj, prop, delta, msg) {\n    if (arguments.length === 4 && typeof obj === 'function') {\n      var tmpMsg = delta;\n      delta = prop;\n      msg = tmpMsg;\n    } else if (arguments.length === 3) {\n      delta = prop;\n      prop = null;\n    }\n\n    new Assertion(fn, msg, assert.increasesButNotBy, true)\n      .to.increase(obj, prop).but.not.by(delta);\n  }\n\n  /**\n   * ### .decreases(function, object, property, [message])\n   *\n   * Asserts that a function decreases a numeric object property.\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 5 };\n   *     assert.decreases(fn, obj, 'val');\n   *\n   * @name decreases\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.decreases = function (fn, obj, prop, msg) {\n    if (arguments.length === 3 && typeof obj === 'function') {\n      msg = prop;\n      prop = null;\n    }\n\n    return new Assertion(fn, msg, assert.decreases, true)\n      .to.decrease(obj, prop);\n  }\n\n  /**\n   * ### .decreasesBy(function, object, property, delta, [message])\n   *\n   * Asserts that a function decreases a numeric object property or a function's return value by an amount (delta)\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val -= 5 };\n   *     assert.decreasesBy(fn, obj, 'val', 5);\n   *\n   * @name decreasesBy\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {Number} change amount (delta)\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.decreasesBy = function (fn, obj, prop, delta, msg) {\n    if (arguments.length === 4 && typeof obj === 'function') {\n      var tmpMsg = delta;\n      delta = prop;\n      msg = tmpMsg;\n    } else if (arguments.length === 3) {\n      delta = prop;\n      prop = null;\n    }\n\n    new Assertion(fn, msg, assert.decreasesBy, true)\n      .to.decrease(obj, prop).by(delta);\n  }\n\n  /**\n   * ### .doesNotDecrease(function, object, property, [message])\n   *\n   * Asserts that a function does not decreases a numeric object property.\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 15 };\n   *     assert.doesNotDecrease(fn, obj, 'val');\n   *\n   * @name doesNotDecrease\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotDecrease = function (fn, obj, prop, msg) {\n    if (arguments.length === 3 && typeof obj === 'function') {\n      msg = prop;\n      prop = null;\n    }\n\n    return new Assertion(fn, msg, assert.doesNotDecrease, true)\n      .to.not.decrease(obj, prop);\n  }\n\n  /**\n   * ### .doesNotDecreaseBy(function, object, property, delta, [message])\n   *\n   * Asserts that a function does not decreases a numeric object property or a function's return value by an amount (delta)\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 5 };\n   *     assert.doesNotDecreaseBy(fn, obj, 'val', 1);\n   *\n   * @name doesNotDecreaseBy\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {Number} change amount (delta)\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.doesNotDecreaseBy = function (fn, obj, prop, delta, msg) {\n    if (arguments.length === 4 && typeof obj === 'function') {\n      var tmpMsg = delta;\n      delta = prop;\n      msg = tmpMsg;\n    } else if (arguments.length === 3) {\n      delta = prop;\n      prop = null;\n    }\n\n    return new Assertion(fn, msg, assert.doesNotDecreaseBy, true)\n      .to.not.decrease(obj, prop).by(delta);\n  }\n\n  /**\n   * ### .decreasesButNotBy(function, object, property, delta, [message])\n   *\n   * Asserts that a function does not decreases a numeric object property or a function's return value by an amount (delta)\n   *\n   *     var obj = { val: 10 };\n   *     var fn = function() { obj.val = 5 };\n   *     assert.decreasesButNotBy(fn, obj, 'val', 1);\n   *\n   * @name decreasesButNotBy\n   * @param {Function} modifier function\n   * @param {Object} object or getter function\n   * @param {String} property name _optional_\n   * @param {Number} change amount (delta)\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.decreasesButNotBy = function (fn, obj, prop, delta, msg) {\n    if (arguments.length === 4 && typeof obj === 'function') {\n      var tmpMsg = delta;\n      delta = prop;\n      msg = tmpMsg;\n    } else if (arguments.length === 3) {\n      delta = prop;\n      prop = null;\n    }\n\n    new Assertion(fn, msg, assert.decreasesButNotBy, true)\n      .to.decrease(obj, prop).but.not.by(delta);\n  }\n\n  /*!\n   * ### .ifError(object)\n   *\n   * Asserts if value is not a false value, and throws if it is a true value.\n   * This is added to allow for chai to be a drop-in replacement for Node's\n   * assert class.\n   *\n   *     var err = new Error('I am a custom error');\n   *     assert.ifError(err); // Rethrows err!\n   *\n   * @name ifError\n   * @param {Object} object\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.ifError = function (val) {\n    if (val) {\n      throw(val);\n    }\n  };\n\n  /**\n   * ### .isExtensible(object)\n   *\n   * Asserts that `object` is extensible (can have new properties added to it).\n   *\n   *     assert.isExtensible({});\n   *\n   * @name isExtensible\n   * @alias extensible\n   * @param {Object} object\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isExtensible = function (obj, msg) {\n    new Assertion(obj, msg, assert.isExtensible, true).to.be.extensible;\n  };\n\n  /**\n   * ### .isNotExtensible(object)\n   *\n   * Asserts that `object` is _not_ extensible.\n   *\n   *     var nonExtensibleObject = Object.preventExtensions({});\n   *     var sealedObject = Object.seal({});\n   *     var frozenObject = Object.freeze({});\n   *\n   *     assert.isNotExtensible(nonExtensibleObject);\n   *     assert.isNotExtensible(sealedObject);\n   *     assert.isNotExtensible(frozenObject);\n   *\n   * @name isNotExtensible\n   * @alias notExtensible\n   * @param {Object} object\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotExtensible = function (obj, msg) {\n    new Assertion(obj, msg, assert.isNotExtensible, true).to.not.be.extensible;\n  };\n\n  /**\n   * ### .isSealed(object)\n   *\n   * Asserts that `object` is sealed (cannot have new properties added to it\n   * and its existing properties cannot be removed).\n   *\n   *     var sealedObject = Object.seal({});\n   *     var frozenObject = Object.seal({});\n   *\n   *     assert.isSealed(sealedObject);\n   *     assert.isSealed(frozenObject);\n   *\n   * @name isSealed\n   * @alias sealed\n   * @param {Object} object\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isSealed = function (obj, msg) {\n    new Assertion(obj, msg, assert.isSealed, true).to.be.sealed;\n  };\n\n  /**\n   * ### .isNotSealed(object)\n   *\n   * Asserts that `object` is _not_ sealed.\n   *\n   *     assert.isNotSealed({});\n   *\n   * @name isNotSealed\n   * @alias notSealed\n   * @param {Object} object\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotSealed = function (obj, msg) {\n    new Assertion(obj, msg, assert.isNotSealed, true).to.not.be.sealed;\n  };\n\n  /**\n   * ### .isFrozen(object)\n   *\n   * Asserts that `object` is frozen (cannot have new properties added to it\n   * and its existing properties cannot be modified).\n   *\n   *     var frozenObject = Object.freeze({});\n   *     assert.frozen(frozenObject);\n   *\n   * @name isFrozen\n   * @alias frozen\n   * @param {Object} object\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isFrozen = function (obj, msg) {\n    new Assertion(obj, msg, assert.isFrozen, true).to.be.frozen;\n  };\n\n  /**\n   * ### .isNotFrozen(object)\n   *\n   * Asserts that `object` is _not_ frozen.\n   *\n   *     assert.isNotFrozen({});\n   *\n   * @name isNotFrozen\n   * @alias notFrozen\n   * @param {Object} object\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotFrozen = function (obj, msg) {\n    new Assertion(obj, msg, assert.isNotFrozen, true).to.not.be.frozen;\n  };\n\n  /**\n   * ### .isEmpty(target)\n   *\n   * Asserts that the target does not contain any values.\n   * For arrays and strings, it checks the `length` property.\n   * For `Map` and `Set` instances, it checks the `size` property.\n   * For non-function objects, it gets the count of own\n   * enumerable string keys.\n   *\n   *     assert.isEmpty([]);\n   *     assert.isEmpty('');\n   *     assert.isEmpty(new Map);\n   *     assert.isEmpty({});\n   *\n   * @name isEmpty\n   * @alias empty\n   * @param {Object|Array|String|Map|Set} target\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isEmpty = function(val, msg) {\n    new Assertion(val, msg, assert.isEmpty, true).to.be.empty;\n  };\n\n  /**\n   * ### .isNotEmpty(target)\n   *\n   * Asserts that the target contains values.\n   * For arrays and strings, it checks the `length` property.\n   * For `Map` and `Set` instances, it checks the `size` property.\n   * For non-function objects, it gets the count of own\n   * enumerable string keys.\n   *\n   *     assert.isNotEmpty([1, 2]);\n   *     assert.isNotEmpty('34');\n   *     assert.isNotEmpty(new Set([5, 6]));\n   *     assert.isNotEmpty({ key: 7 });\n   *\n   * @name isNotEmpty\n   * @alias notEmpty\n   * @param {Object|Array|String|Map|Set} target\n   * @param {String} message _optional_\n   * @namespace Assert\n   * @api public\n   */\n\n  assert.isNotEmpty = function(val, msg) {\n    new Assertion(val, msg, assert.isNotEmpty, true).to.not.be.empty;\n  };\n\n  /*!\n   * Aliases.\n   */\n\n  (function alias(name, as){\n    assert[as] = assert[name];\n    return alias;\n  })\n  ('isOk', 'ok')\n  ('isNotOk', 'notOk')\n  ('throws', 'throw')\n  ('throws', 'Throw')\n  ('isExtensible', 'extensible')\n  ('isNotExtensible', 'notExtensible')\n  ('isSealed', 'sealed')\n  ('isNotSealed', 'notSealed')\n  ('isFrozen', 'frozen')\n  ('isNotFrozen', 'notFrozen')\n  ('isEmpty', 'empty')\n  ('isNotEmpty', 'notEmpty');\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/interface/assert.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/interface/expect.js":
  /*!************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/interface/expect.js ***!
    \************************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, util) {\n  chai.expect = function (val, message) {\n    return new chai.Assertion(val, message);\n  };\n\n  /**\n   * ### .fail([message])\n   * ### .fail(actual, expected, [message], [operator])\n   *\n   * Throw a failure.\n   *\n   *     expect.fail();\n   *     expect.fail(\"custom error message\");\n   *     expect.fail(1, 2);\n   *     expect.fail(1, 2, \"custom error message\");\n   *     expect.fail(1, 2, \"custom error message\", \">\");\n   *     expect.fail(1, 2, undefined, \">\");\n   *\n   * @name fail\n   * @param {Mixed} actual\n   * @param {Mixed} expected\n   * @param {String} message\n   * @param {String} operator\n   * @namespace BDD\n   * @api public\n   */\n\n  chai.expect.fail = function (actual, expected, message, operator) {\n    if (arguments.length < 2) {\n        message = actual;\n        actual = undefined;\n    }\n\n    message = message || 'expect.fail()';\n    throw new chai.AssertionError(message, {\n        actual: actual\n      , expected: expected\n      , operator: operator\n    }, chai.expect.fail);\n  };\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/interface/expect.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/interface/should.js":
  /*!************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/interface/should.js ***!
    \************************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * chai\n * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nmodule.exports = function (chai, util) {\n  var Assertion = chai.Assertion;\n\n  function loadShould () {\n    // explicitly define this method as function as to have it's name to include as `ssfi`\n    function shouldGetter() {\n      if (this instanceof String\n          || this instanceof Number\n          || this instanceof Boolean\n          || typeof Symbol === 'function' && this instanceof Symbol\n          || typeof BigInt === 'function' && this instanceof BigInt) {\n        return new Assertion(this.valueOf(), null, shouldGetter);\n      }\n      return new Assertion(this, null, shouldGetter);\n    }\n    function shouldSetter(value) {\n      // See https://github.com/chaijs/chai/issues/86: this makes\n      // `whatever.should = someValue` actually set `someValue`, which is\n      // especially useful for `global.should = require('chai').should()`.\n      //\n      // Note that we have to use [[DefineProperty]] instead of [[Put]]\n      // since otherwise we would trigger this very setter!\n      Object.defineProperty(this, 'should', {\n        value: value,\n        enumerable: true,\n        configurable: true,\n        writable: true\n      });\n    }\n    // modify Object.prototype to have `should`\n    Object.defineProperty(Object.prototype, 'should', {\n      set: shouldSetter\n      , get: shouldGetter\n      , configurable: true\n    });\n\n    var should = {};\n\n    /**\n     * ### .fail([message])\n     * ### .fail(actual, expected, [message], [operator])\n     *\n     * Throw a failure.\n     *\n     *     should.fail();\n     *     should.fail(\"custom error message\");\n     *     should.fail(1, 2);\n     *     should.fail(1, 2, \"custom error message\");\n     *     should.fail(1, 2, \"custom error message\", \">\");\n     *     should.fail(1, 2, undefined, \">\");\n     *\n     *\n     * @name fail\n     * @param {Mixed} actual\n     * @param {Mixed} expected\n     * @param {String} message\n     * @param {String} operator\n     * @namespace BDD\n     * @api public\n     */\n\n    should.fail = function (actual, expected, message, operator) {\n      if (arguments.length < 2) {\n          message = actual;\n          actual = undefined;\n      }\n\n      message = message || 'should.fail()';\n      throw new chai.AssertionError(message, {\n          actual: actual\n        , expected: expected\n        , operator: operator\n      }, should.fail);\n    };\n\n    /**\n     * ### .equal(actual, expected, [message])\n     *\n     * Asserts non-strict equality (`==`) of `actual` and `expected`.\n     *\n     *     should.equal(3, '3', '== coerces values to strings');\n     *\n     * @name equal\n     * @param {Mixed} actual\n     * @param {Mixed} expected\n     * @param {String} message\n     * @namespace Should\n     * @api public\n     */\n\n    should.equal = function (val1, val2, msg) {\n      new Assertion(val1, msg).to.equal(val2);\n    };\n\n    /**\n     * ### .throw(function, [constructor/string/regexp], [string/regexp], [message])\n     *\n     * Asserts that `function` will throw an error that is an instance of\n     * `constructor`, or alternately that it will throw an error with message\n     * matching `regexp`.\n     *\n     *     should.throw(fn, 'function throws a reference error');\n     *     should.throw(fn, /function throws a reference error/);\n     *     should.throw(fn, ReferenceError);\n     *     should.throw(fn, ReferenceError, 'function throws a reference error');\n     *     should.throw(fn, ReferenceError, /function throws a reference error/);\n     *\n     * @name throw\n     * @alias Throw\n     * @param {Function} function\n     * @param {ErrorConstructor} constructor\n     * @param {RegExp} regexp\n     * @param {String} message\n     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n     * @namespace Should\n     * @api public\n     */\n\n    should.Throw = function (fn, errt, errs, msg) {\n      new Assertion(fn, msg).to.Throw(errt, errs);\n    };\n\n    /**\n     * ### .exist\n     *\n     * Asserts that the target is neither `null` nor `undefined`.\n     *\n     *     var foo = 'hi';\n     *\n     *     should.exist(foo, 'foo exists');\n     *\n     * @name exist\n     * @namespace Should\n     * @api public\n     */\n\n    should.exist = function (val, msg) {\n      new Assertion(val, msg).to.exist;\n    }\n\n    // negation\n    should.not = {}\n\n    /**\n     * ### .not.equal(actual, expected, [message])\n     *\n     * Asserts non-strict inequality (`!=`) of `actual` and `expected`.\n     *\n     *     should.not.equal(3, 4, 'these numbers are not equal');\n     *\n     * @name not.equal\n     * @param {Mixed} actual\n     * @param {Mixed} expected\n     * @param {String} message\n     * @namespace Should\n     * @api public\n     */\n\n    should.not.equal = function (val1, val2, msg) {\n      new Assertion(val1, msg).to.not.equal(val2);\n    };\n\n    /**\n     * ### .throw(function, [constructor/regexp], [message])\n     *\n     * Asserts that `function` will _not_ throw an error that is an instance of\n     * `constructor`, or alternately that it will not throw an error with message\n     * matching `regexp`.\n     *\n     *     should.not.throw(fn, Error, 'function does not throw');\n     *\n     * @name not.throw\n     * @alias not.Throw\n     * @param {Function} function\n     * @param {ErrorConstructor} constructor\n     * @param {RegExp} regexp\n     * @param {String} message\n     * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types\n     * @namespace Should\n     * @api public\n     */\n\n    should.not.Throw = function (fn, errt, errs, msg) {\n      new Assertion(fn, msg).to.not.Throw(errt, errs);\n    };\n\n    /**\n     * ### .not.exist\n     *\n     * Asserts that the target is neither `null` nor `undefined`.\n     *\n     *     var bar = null;\n     *\n     *     should.not.exist(bar, 'bar does not exist');\n     *\n     * @name not.exist\n     * @namespace Should\n     * @api public\n     */\n\n    should.not.exist = function (val, msg) {\n      new Assertion(val, msg).to.not.exist;\n    }\n\n    should['throw'] = should['Throw'];\n    should.not['throw'] = should.not['Throw'];\n\n    return should;\n  };\n\n  chai.should = loadShould;\n  chai.Should = loadShould;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/interface/should.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/addChainableMethod.js":
  /*!********************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/addChainableMethod.js ***!
    \********************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - addChainingMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar addLengthGuard = __webpack_require__(/*! ./addLengthGuard */ \"../../node_modules/chai/lib/chai/utils/addLengthGuard.js\");\nvar chai = __webpack_require__(/*! ../../chai */ \"../../node_modules/chai/lib/chai.js\");\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\nvar proxify = __webpack_require__(/*! ./proxify */ \"../../node_modules/chai/lib/chai/utils/proxify.js\");\nvar transferFlags = __webpack_require__(/*! ./transferFlags */ \"../../node_modules/chai/lib/chai/utils/transferFlags.js\");\n\n/*!\n * Module variables\n */\n\n// Check whether `Object.setPrototypeOf` is supported\nvar canSetPrototype = typeof Object.setPrototypeOf === 'function';\n\n// Without `Object.setPrototypeOf` support, this module will need to add properties to a function.\n// However, some of functions' own props are not configurable and should be skipped.\nvar testFn = function() {};\nvar excludeNames = Object.getOwnPropertyNames(testFn).filter(function(name) {\n  var propDesc = Object.getOwnPropertyDescriptor(testFn, name);\n\n  // Note: PhantomJS 1.x includes `callee` as one of `testFn`'s own properties,\n  // but then returns `undefined` as the property descriptor for `callee`. As a\n  // workaround, we perform an otherwise unnecessary type-check for `propDesc`,\n  // and then filter it out if it's not an object as it should be.\n  if (typeof propDesc !== 'object')\n    return true;\n\n  return !propDesc.configurable;\n});\n\n// Cache `Function` properties\nvar call  = Function.prototype.call,\n    apply = Function.prototype.apply;\n\n/**\n * ### .addChainableMethod(ctx, name, method, chainingBehavior)\n *\n * Adds a method to an object, such that the method can also be chained.\n *\n *     utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {\n *       var obj = utils.flag(this, 'object');\n *       new chai.Assertion(obj).to.be.equal(str);\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);\n *\n * The result can then be used as both a method assertion, executing both `method` and\n * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.\n *\n *     expect(fooStr).to.be.foo('bar');\n *     expect(fooStr).to.be.foo.equal('foo');\n *\n * @param {Object} ctx object to which the method is added\n * @param {String} name of method to add\n * @param {Function} method function to be used for `name`, when called\n * @param {Function} chainingBehavior function to be called every time the property is accessed\n * @namespace Utils\n * @name addChainableMethod\n * @api public\n */\n\nmodule.exports = function addChainableMethod(ctx, name, method, chainingBehavior) {\n  if (typeof chainingBehavior !== 'function') {\n    chainingBehavior = function () { };\n  }\n\n  var chainableBehavior = {\n      method: method\n    , chainingBehavior: chainingBehavior\n  };\n\n  // save the methods so we can overwrite them later, if we need to.\n  if (!ctx.__methods) {\n    ctx.__methods = {};\n  }\n  ctx.__methods[name] = chainableBehavior;\n\n  Object.defineProperty(ctx, name,\n    { get: function chainableMethodGetter() {\n        chainableBehavior.chainingBehavior.call(this);\n\n        var chainableMethodWrapper = function () {\n          // Setting the `ssfi` flag to `chainableMethodWrapper` causes this\n          // function to be the starting point for removing implementation\n          // frames from the stack trace of a failed assertion.\n          //\n          // However, we only want to use this function as the starting point if\n          // the `lockSsfi` flag isn't set.\n          //\n          // If the `lockSsfi` flag is set, then this assertion is being\n          // invoked from inside of another assertion. In this case, the `ssfi`\n          // flag has already been set by the outer assertion.\n          //\n          // Note that overwriting a chainable method merely replaces the saved\n          // methods in `ctx.__methods` instead of completely replacing the\n          // overwritten assertion. Therefore, an overwriting assertion won't\n          // set the `ssfi` or `lockSsfi` flags.\n          if (!flag(this, 'lockSsfi')) {\n            flag(this, 'ssfi', chainableMethodWrapper);\n          }\n\n          var result = chainableBehavior.method.apply(this, arguments);\n          if (result !== undefined) {\n            return result;\n          }\n\n          var newAssertion = new chai.Assertion();\n          transferFlags(this, newAssertion);\n          return newAssertion;\n        };\n\n        addLengthGuard(chainableMethodWrapper, name, true);\n\n        // Use `Object.setPrototypeOf` if available\n        if (canSetPrototype) {\n          // Inherit all properties from the object by replacing the `Function` prototype\n          var prototype = Object.create(this);\n          // Restore the `call` and `apply` methods from `Function`\n          prototype.call = call;\n          prototype.apply = apply;\n          Object.setPrototypeOf(chainableMethodWrapper, prototype);\n        }\n        // Otherwise, redefine all properties (slow!)\n        else {\n          var asserterNames = Object.getOwnPropertyNames(ctx);\n          asserterNames.forEach(function (asserterName) {\n            if (excludeNames.indexOf(asserterName) !== -1) {\n              return;\n            }\n\n            var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);\n            Object.defineProperty(chainableMethodWrapper, asserterName, pd);\n          });\n        }\n\n        transferFlags(this, chainableMethodWrapper);\n        return proxify(chainableMethodWrapper);\n      }\n    , configurable: true\n  });\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/addChainableMethod.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/addLengthGuard.js":
  /*!****************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/addLengthGuard.js ***!
    \****************************************************************/
  /***/ ((module) => {
  
  eval("var fnLengthDesc = Object.getOwnPropertyDescriptor(function () {}, 'length');\n\n/*!\n * Chai - addLengthGuard utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .addLengthGuard(fn, assertionName, isChainable)\n *\n * Define `length` as a getter on the given uninvoked method assertion. The\n * getter acts as a guard against chaining `length` directly off of an uninvoked\n * method assertion, which is a problem because it references `function`'s\n * built-in `length` property instead of Chai's `length` assertion. When the\n * getter catches the user making this mistake, it throws an error with a\n * helpful message.\n *\n * There are two ways in which this mistake can be made. The first way is by\n * chaining the `length` assertion directly off of an uninvoked chainable\n * method. In this case, Chai suggests that the user use `lengthOf` instead. The\n * second way is by chaining the `length` assertion directly off of an uninvoked\n * non-chainable method. Non-chainable methods must be invoked prior to\n * chaining. In this case, Chai suggests that the user consult the docs for the\n * given assertion.\n *\n * If the `length` property of functions is unconfigurable, then return `fn`\n * without modification.\n *\n * Note that in ES6, the function's `length` property is configurable, so once\n * support for legacy environments is dropped, Chai's `length` property can\n * replace the built-in function's `length` property, and this length guard will\n * no longer be necessary. In the mean time, maintaining consistency across all\n * environments is the priority.\n *\n * @param {Function} fn\n * @param {String} assertionName\n * @param {Boolean} isChainable\n * @namespace Utils\n * @name addLengthGuard\n */\n\nmodule.exports = function addLengthGuard (fn, assertionName, isChainable) {\n  if (!fnLengthDesc.configurable) return fn;\n\n  Object.defineProperty(fn, 'length', {\n    get: function () {\n      if (isChainable) {\n        throw Error('Invalid Chai property: ' + assertionName + '.length. Due' +\n          ' to a compatibility issue, \"length\" cannot directly follow \"' +\n          assertionName + '\". Use \"' + assertionName + '.lengthOf\" instead.');\n      }\n\n      throw Error('Invalid Chai property: ' + assertionName + '.length. See' +\n        ' docs for proper usage of \"' + assertionName + '\".');\n    }\n  });\n\n  return fn;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/addLengthGuard.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/addMethod.js":
  /*!***********************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/addMethod.js ***!
    \***********************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - addMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar addLengthGuard = __webpack_require__(/*! ./addLengthGuard */ \"../../node_modules/chai/lib/chai/utils/addLengthGuard.js\");\nvar chai = __webpack_require__(/*! ../../chai */ \"../../node_modules/chai/lib/chai.js\");\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\nvar proxify = __webpack_require__(/*! ./proxify */ \"../../node_modules/chai/lib/chai/utils/proxify.js\");\nvar transferFlags = __webpack_require__(/*! ./transferFlags */ \"../../node_modules/chai/lib/chai/utils/transferFlags.js\");\n\n/**\n * ### .addMethod(ctx, name, method)\n *\n * Adds a method to the prototype of an object.\n *\n *     utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {\n *       var obj = utils.flag(this, 'object');\n *       new chai.Assertion(obj).to.be.equal(str);\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.addMethod('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(fooStr).to.be.foo('bar');\n *\n * @param {Object} ctx object to which the method is added\n * @param {String} name of method to add\n * @param {Function} method function to be used for name\n * @namespace Utils\n * @name addMethod\n * @api public\n */\n\nmodule.exports = function addMethod(ctx, name, method) {\n  var methodWrapper = function () {\n    // Setting the `ssfi` flag to `methodWrapper` causes this function to be the\n    // starting point for removing implementation frames from the stack trace of\n    // a failed assertion.\n    //\n    // However, we only want to use this function as the starting point if the\n    // `lockSsfi` flag isn't set.\n    //\n    // If the `lockSsfi` flag is set, then either this assertion has been\n    // overwritten by another assertion, or this assertion is being invoked from\n    // inside of another assertion. In the first case, the `ssfi` flag has\n    // already been set by the overwriting assertion. In the second case, the\n    // `ssfi` flag has already been set by the outer assertion.\n    if (!flag(this, 'lockSsfi')) {\n      flag(this, 'ssfi', methodWrapper);\n    }\n\n    var result = method.apply(this, arguments);\n    if (result !== undefined)\n      return result;\n\n    var newAssertion = new chai.Assertion();\n    transferFlags(this, newAssertion);\n    return newAssertion;\n  };\n\n  addLengthGuard(methodWrapper, name, false);\n  ctx[name] = proxify(methodWrapper, name);\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/addMethod.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/addProperty.js":
  /*!*************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/addProperty.js ***!
    \*************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - addProperty utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar chai = __webpack_require__(/*! ../../chai */ \"../../node_modules/chai/lib/chai.js\");\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\nvar isProxyEnabled = __webpack_require__(/*! ./isProxyEnabled */ \"../../node_modules/chai/lib/chai/utils/isProxyEnabled.js\");\nvar transferFlags = __webpack_require__(/*! ./transferFlags */ \"../../node_modules/chai/lib/chai/utils/transferFlags.js\");\n\n/**\n * ### .addProperty(ctx, name, getter)\n *\n * Adds a property to the prototype of an object.\n *\n *     utils.addProperty(chai.Assertion.prototype, 'foo', function () {\n *       var obj = utils.flag(this, 'object');\n *       new chai.Assertion(obj).to.be.instanceof(Foo);\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.addProperty('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.be.foo;\n *\n * @param {Object} ctx object to which the property is added\n * @param {String} name of property to add\n * @param {Function} getter function to be used for name\n * @namespace Utils\n * @name addProperty\n * @api public\n */\n\nmodule.exports = function addProperty(ctx, name, getter) {\n  getter = getter === undefined ? function () {} : getter;\n\n  Object.defineProperty(ctx, name,\n    { get: function propertyGetter() {\n        // Setting the `ssfi` flag to `propertyGetter` causes this function to\n        // be the starting point for removing implementation frames from the\n        // stack trace of a failed assertion.\n        //\n        // However, we only want to use this function as the starting point if\n        // the `lockSsfi` flag isn't set and proxy protection is disabled.\n        //\n        // If the `lockSsfi` flag is set, then either this assertion has been\n        // overwritten by another assertion, or this assertion is being invoked\n        // from inside of another assertion. In the first case, the `ssfi` flag\n        // has already been set by the overwriting assertion. In the second\n        // case, the `ssfi` flag has already been set by the outer assertion.\n        //\n        // If proxy protection is enabled, then the `ssfi` flag has already been\n        // set by the proxy getter.\n        if (!isProxyEnabled() && !flag(this, 'lockSsfi')) {\n          flag(this, 'ssfi', propertyGetter);\n        }\n\n        var result = getter.call(this);\n        if (result !== undefined)\n          return result;\n\n        var newAssertion = new chai.Assertion();\n        transferFlags(this, newAssertion);\n        return newAssertion;\n      }\n    , configurable: true\n  });\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/addProperty.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/compareByInspect.js":
  /*!******************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/compareByInspect.js ***!
    \******************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - compareByInspect utility\n * Copyright(c) 2011-2016 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar inspect = __webpack_require__(/*! ./inspect */ \"../../node_modules/chai/lib/chai/utils/inspect.js\");\n\n/**\n * ### .compareByInspect(mixed, mixed)\n *\n * To be used as a compareFunction with Array.prototype.sort. Compares elements\n * using inspect instead of default behavior of using toString so that Symbols\n * and objects with irregular/missing toString can still be sorted without a\n * TypeError.\n *\n * @param {Mixed} first element to compare\n * @param {Mixed} second element to compare\n * @returns {Number} -1 if 'a' should come before 'b'; otherwise 1\n * @name compareByInspect\n * @namespace Utils\n * @api public\n */\n\nmodule.exports = function compareByInspect(a, b) {\n  return inspect(a) < inspect(b) ? -1 : 1;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/compareByInspect.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/expectTypes.js":
  /*!*************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/expectTypes.js ***!
    \*************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - expectTypes utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .expectTypes(obj, types)\n *\n * Ensures that the object being tested against is of a valid type.\n *\n *     utils.expectTypes(this, ['array', 'object', 'string']);\n *\n * @param {Mixed} obj constructed Assertion\n * @param {Array} type A list of allowed types for this assertion\n * @namespace Utils\n * @name expectTypes\n * @api public\n */\n\nvar AssertionError = __webpack_require__(/*! assertion-error */ \"../../node_modules/assertion-error/index.js\");\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\nvar type = __webpack_require__(/*! type-detect */ \"../../node_modules/type-detect/type-detect.js\");\n\nmodule.exports = function expectTypes(obj, types) {\n  var flagMsg = flag(obj, 'message');\n  var ssfi = flag(obj, 'ssfi');\n\n  flagMsg = flagMsg ? flagMsg + ': ' : '';\n\n  obj = flag(obj, 'object');\n  types = types.map(function (t) { return t.toLowerCase(); });\n  types.sort();\n\n  // Transforms ['lorem', 'ipsum'] into 'a lorem, or an ipsum'\n  var str = types.map(function (t, index) {\n    var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a';\n    var or = types.length > 1 && index === types.length - 1 ? 'or ' : '';\n    return or + art + ' ' + t;\n  }).join(', ');\n\n  var objType = type(obj).toLowerCase();\n\n  if (!types.some(function (expected) { return objType === expected; })) {\n    throw new AssertionError(\n      flagMsg + 'object tested must be ' + str + ', but ' + objType + ' given',\n      undefined,\n      ssfi\n    );\n  }\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/expectTypes.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/flag.js":
  /*!******************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/flag.js ***!
    \******************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * Chai - flag utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .flag(object, key, [value])\n *\n * Get or set a flag value on an object. If a\n * value is provided it will be set, else it will\n * return the currently set value or `undefined` if\n * the value is not set.\n *\n *     utils.flag(this, 'foo', 'bar'); // setter\n *     utils.flag(this, 'foo'); // getter, returns `bar`\n *\n * @param {Object} object constructed Assertion\n * @param {String} key\n * @param {Mixed} value (optional)\n * @namespace Utils\n * @name flag\n * @api private\n */\n\nmodule.exports = function flag(obj, key, value) {\n  var flags = obj.__flags || (obj.__flags = Object.create(null));\n  if (arguments.length === 3) {\n    flags[key] = value;\n  } else {\n    return flags[key];\n  }\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/flag.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/getActual.js":
  /*!***********************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/getActual.js ***!
    \***********************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * Chai - getActual utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .getActual(object, [actual])\n *\n * Returns the `actual` value for an Assertion.\n *\n * @param {Object} object (constructed Assertion)\n * @param {Arguments} chai.Assertion.prototype.assert arguments\n * @namespace Utils\n * @name getActual\n */\n\nmodule.exports = function getActual(obj, args) {\n  return args.length > 4 ? args[4] : obj._obj;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/getActual.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/getMessage.js":
  /*!************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/getMessage.js ***!
    \************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - message composition utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\")\n  , getActual = __webpack_require__(/*! ./getActual */ \"../../node_modules/chai/lib/chai/utils/getActual.js\")\n  , objDisplay = __webpack_require__(/*! ./objDisplay */ \"../../node_modules/chai/lib/chai/utils/objDisplay.js\");\n\n/**\n * ### .getMessage(object, message, negateMessage)\n *\n * Construct the error message based on flags\n * and template tags. Template tags will return\n * a stringified inspection of the object referenced.\n *\n * Message template tags:\n * - `#{this}` current asserted object\n * - `#{act}` actual value\n * - `#{exp}` expected value\n *\n * @param {Object} object (constructed Assertion)\n * @param {Arguments} chai.Assertion.prototype.assert arguments\n * @namespace Utils\n * @name getMessage\n * @api public\n */\n\nmodule.exports = function getMessage(obj, args) {\n  var negate = flag(obj, 'negate')\n    , val = flag(obj, 'object')\n    , expected = args[3]\n    , actual = getActual(obj, args)\n    , msg = negate ? args[2] : args[1]\n    , flagMsg = flag(obj, 'message');\n\n  if(typeof msg === \"function\") msg = msg();\n  msg = msg || '';\n  msg = msg\n    .replace(/#\\{this\\}/g, function () { return objDisplay(val); })\n    .replace(/#\\{act\\}/g, function () { return objDisplay(actual); })\n    .replace(/#\\{exp\\}/g, function () { return objDisplay(expected); });\n\n  return flagMsg ? flagMsg + ': ' + msg : msg;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/getMessage.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/getOperator.js":
  /*!*************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/getOperator.js ***!
    \*************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("var type = __webpack_require__(/*! type-detect */ \"../../node_modules/type-detect/type-detect.js\");\n\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\n\nfunction isObjectType(obj) {\n  var objectType = type(obj);\n  var objectTypes = ['Array', 'Object', 'function'];\n\n  return objectTypes.indexOf(objectType) !== -1;\n}\n\n/**\n * ### .getOperator(message)\n *\n * Extract the operator from error message.\n * Operator defined is based on below link\n * https://nodejs.org/api/assert.html#assert_assert.\n *\n * Returns the `operator` or `undefined` value for an Assertion.\n *\n * @param {Object} object (constructed Assertion)\n * @param {Arguments} chai.Assertion.prototype.assert arguments\n * @namespace Utils\n * @name getOperator\n * @api public\n */\n\nmodule.exports = function getOperator(obj, args) {\n  var operator = flag(obj, 'operator');\n  var negate = flag(obj, 'negate');\n  var expected = args[3];\n  var msg = negate ? args[2] : args[1];\n\n  if (operator) {\n    return operator;\n  }\n\n  if (typeof msg === 'function') msg = msg();\n\n  msg = msg || '';\n  if (!msg) {\n    return undefined;\n  }\n\n  if (/\\shave\\s/.test(msg)) {\n    return undefined;\n  }\n\n  var isObject = isObjectType(expected);\n  if (/\\snot\\s/.test(msg)) {\n    return isObject ? 'notDeepStrictEqual' : 'notStrictEqual';\n  }\n\n  return isObject ? 'deepStrictEqual' : 'strictEqual';\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/getOperator.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/getOwnEnumerableProperties.js":
  /*!****************************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/getOwnEnumerableProperties.js ***!
    \****************************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - getOwnEnumerableProperties utility\n * Copyright(c) 2011-2016 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar getOwnEnumerablePropertySymbols = __webpack_require__(/*! ./getOwnEnumerablePropertySymbols */ \"../../node_modules/chai/lib/chai/utils/getOwnEnumerablePropertySymbols.js\");\n\n/**\n * ### .getOwnEnumerableProperties(object)\n *\n * This allows the retrieval of directly-owned enumerable property names and\n * symbols of an object. This function is necessary because Object.keys only\n * returns enumerable property names, not enumerable property symbols.\n *\n * @param {Object} object\n * @returns {Array}\n * @namespace Utils\n * @name getOwnEnumerableProperties\n * @api public\n */\n\nmodule.exports = function getOwnEnumerableProperties(obj) {\n  return Object.keys(obj).concat(getOwnEnumerablePropertySymbols(obj));\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/getOwnEnumerableProperties.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/getOwnEnumerablePropertySymbols.js":
  /*!*********************************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/getOwnEnumerablePropertySymbols.js ***!
    \*********************************************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * Chai - getOwnEnumerablePropertySymbols utility\n * Copyright(c) 2011-2016 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .getOwnEnumerablePropertySymbols(object)\n *\n * This allows the retrieval of directly-owned enumerable property symbols of an\n * object. This function is necessary because Object.getOwnPropertySymbols\n * returns both enumerable and non-enumerable property symbols.\n *\n * @param {Object} object\n * @returns {Array}\n * @namespace Utils\n * @name getOwnEnumerablePropertySymbols\n * @api public\n */\n\nmodule.exports = function getOwnEnumerablePropertySymbols(obj) {\n  if (typeof Object.getOwnPropertySymbols !== 'function') return [];\n\n  return Object.getOwnPropertySymbols(obj).filter(function (sym) {\n    return Object.getOwnPropertyDescriptor(obj, sym).enumerable;\n  });\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/getOwnEnumerablePropertySymbols.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/getProperties.js":
  /*!***************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/getProperties.js ***!
    \***************************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * Chai - getProperties utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .getProperties(object)\n *\n * This allows the retrieval of property names of an object, enumerable or not,\n * inherited or not.\n *\n * @param {Object} object\n * @returns {Array}\n * @namespace Utils\n * @name getProperties\n * @api public\n */\n\nmodule.exports = function getProperties(object) {\n  var result = Object.getOwnPropertyNames(object);\n\n  function addProperty(property) {\n    if (result.indexOf(property) === -1) {\n      result.push(property);\n    }\n  }\n\n  var proto = Object.getPrototypeOf(object);\n  while (proto !== null) {\n    Object.getOwnPropertyNames(proto).forEach(addProperty);\n    proto = Object.getPrototypeOf(proto);\n  }\n\n  return result;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/getProperties.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/index.js":
  /*!*******************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/index.js ***!
    \*******************************************************/
  /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
  
  eval("/*!\n * chai\n * Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Dependencies that are used for multiple exports are required here only once\n */\n\nvar pathval = __webpack_require__(/*! pathval */ \"../../node_modules/pathval/index.js\");\n\n/*!\n * test utility\n */\n\nexports.test = __webpack_require__(/*! ./test */ \"../../node_modules/chai/lib/chai/utils/test.js\");\n\n/*!\n * type utility\n */\n\nexports.type = __webpack_require__(/*! type-detect */ \"../../node_modules/type-detect/type-detect.js\");\n\n/*!\n * expectTypes utility\n */\nexports.expectTypes = __webpack_require__(/*! ./expectTypes */ \"../../node_modules/chai/lib/chai/utils/expectTypes.js\");\n\n/*!\n * message utility\n */\n\nexports.getMessage = __webpack_require__(/*! ./getMessage */ \"../../node_modules/chai/lib/chai/utils/getMessage.js\");\n\n/*!\n * actual utility\n */\n\nexports.getActual = __webpack_require__(/*! ./getActual */ \"../../node_modules/chai/lib/chai/utils/getActual.js\");\n\n/*!\n * Inspect util\n */\n\nexports.inspect = __webpack_require__(/*! ./inspect */ \"../../node_modules/chai/lib/chai/utils/inspect.js\");\n\n/*!\n * Object Display util\n */\n\nexports.objDisplay = __webpack_require__(/*! ./objDisplay */ \"../../node_modules/chai/lib/chai/utils/objDisplay.js\");\n\n/*!\n * Flag utility\n */\n\nexports.flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\n\n/*!\n * Flag transferring utility\n */\n\nexports.transferFlags = __webpack_require__(/*! ./transferFlags */ \"../../node_modules/chai/lib/chai/utils/transferFlags.js\");\n\n/*!\n * Deep equal utility\n */\n\nexports.eql = __webpack_require__(/*! deep-eql */ \"../../node_modules/deep-eql/index.js\");\n\n/*!\n * Deep path info\n */\n\nexports.getPathInfo = pathval.getPathInfo;\n\n/*!\n * Check if a property exists\n */\n\nexports.hasProperty = pathval.hasProperty;\n\n/*!\n * Function name\n */\n\nexports.getName = __webpack_require__(/*! get-func-name */ \"../../node_modules/get-func-name/index.js\");\n\n/*!\n * add Property\n */\n\nexports.addProperty = __webpack_require__(/*! ./addProperty */ \"../../node_modules/chai/lib/chai/utils/addProperty.js\");\n\n/*!\n * add Method\n */\n\nexports.addMethod = __webpack_require__(/*! ./addMethod */ \"../../node_modules/chai/lib/chai/utils/addMethod.js\");\n\n/*!\n * overwrite Property\n */\n\nexports.overwriteProperty = __webpack_require__(/*! ./overwriteProperty */ \"../../node_modules/chai/lib/chai/utils/overwriteProperty.js\");\n\n/*!\n * overwrite Method\n */\n\nexports.overwriteMethod = __webpack_require__(/*! ./overwriteMethod */ \"../../node_modules/chai/lib/chai/utils/overwriteMethod.js\");\n\n/*!\n * Add a chainable method\n */\n\nexports.addChainableMethod = __webpack_require__(/*! ./addChainableMethod */ \"../../node_modules/chai/lib/chai/utils/addChainableMethod.js\");\n\n/*!\n * Overwrite chainable method\n */\n\nexports.overwriteChainableMethod = __webpack_require__(/*! ./overwriteChainableMethod */ \"../../node_modules/chai/lib/chai/utils/overwriteChainableMethod.js\");\n\n/*!\n * Compare by inspect method\n */\n\nexports.compareByInspect = __webpack_require__(/*! ./compareByInspect */ \"../../node_modules/chai/lib/chai/utils/compareByInspect.js\");\n\n/*!\n * Get own enumerable property symbols method\n */\n\nexports.getOwnEnumerablePropertySymbols = __webpack_require__(/*! ./getOwnEnumerablePropertySymbols */ \"../../node_modules/chai/lib/chai/utils/getOwnEnumerablePropertySymbols.js\");\n\n/*!\n * Get own enumerable properties method\n */\n\nexports.getOwnEnumerableProperties = __webpack_require__(/*! ./getOwnEnumerableProperties */ \"../../node_modules/chai/lib/chai/utils/getOwnEnumerableProperties.js\");\n\n/*!\n * Checks error against a given set of criteria\n */\n\nexports.checkError = __webpack_require__(/*! check-error */ \"../../node_modules/check-error/index.js\");\n\n/*!\n * Proxify util\n */\n\nexports.proxify = __webpack_require__(/*! ./proxify */ \"../../node_modules/chai/lib/chai/utils/proxify.js\");\n\n/*!\n * addLengthGuard util\n */\n\nexports.addLengthGuard = __webpack_require__(/*! ./addLengthGuard */ \"../../node_modules/chai/lib/chai/utils/addLengthGuard.js\");\n\n/*!\n * isProxyEnabled helper\n */\n\nexports.isProxyEnabled = __webpack_require__(/*! ./isProxyEnabled */ \"../../node_modules/chai/lib/chai/utils/isProxyEnabled.js\");\n\n/*!\n * isNaN method\n */\n\nexports.isNaN = __webpack_require__(/*! ./isNaN */ \"../../node_modules/chai/lib/chai/utils/isNaN.js\");\n\n/*!\n * getOperator method\n */\n\nexports.getOperator = __webpack_require__(/*! ./getOperator */ \"../../node_modules/chai/lib/chai/utils/getOperator.js\");\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/inspect.js":
  /*!*********************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/inspect.js ***!
    \*********************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("// This is (almost) directly from Node.js utils\n// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js\n\nvar getName = __webpack_require__(/*! get-func-name */ \"../../node_modules/get-func-name/index.js\");\nvar loupe = __webpack_require__(/*! loupe */ \"../../node_modules/loupe/loupe.js\");\nvar config = __webpack_require__(/*! ../config */ \"../../node_modules/chai/lib/chai/config.js\");\n\nmodule.exports = inspect;\n\n/**\n * ### .inspect(obj, [showHidden], [depth], [colors])\n *\n * Echoes the value of a value. Tries to print the value out\n * in the best way possible given the different types.\n *\n * @param {Object} obj The object to print out.\n * @param {Boolean} showHidden Flag that shows hidden (not enumerable)\n *    properties of objects. Default is false.\n * @param {Number} depth Depth in which to descend in object. Default is 2.\n * @param {Boolean} colors Flag to turn on ANSI escape codes to color the\n *    output. Default is false (no coloring).\n * @namespace Utils\n * @name inspect\n */\nfunction inspect(obj, showHidden, depth, colors) {\n  var options = {\n    colors: colors,\n    depth: (typeof depth === 'undefined' ? 2 : depth),\n    showHidden: showHidden,\n    truncate: config.truncateThreshold ? config.truncateThreshold : Infinity,\n  };\n  return loupe.inspect(obj, options);\n}\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/inspect.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/isNaN.js":
  /*!*******************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/isNaN.js ***!
    \*******************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * Chai - isNaN utility\n * Copyright(c) 2012-2015 Sakthipriyan Vairamani <thechargingvolcano@gmail.com>\n * MIT Licensed\n */\n\n/**\n * ### .isNaN(value)\n *\n * Checks if the given value is NaN or not.\n *\n *     utils.isNaN(NaN); // true\n *\n * @param {Value} The value which has to be checked if it is NaN\n * @name isNaN\n * @api private\n */\n\nfunction isNaN(value) {\n  // Refer http://www.ecma-international.org/ecma-262/6.0/#sec-isnan-number\n  // section's NOTE.\n  return value !== value;\n}\n\n// If ECMAScript 6's Number.isNaN is present, prefer that.\nmodule.exports = Number.isNaN || isNaN;\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/isNaN.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/isProxyEnabled.js":
  /*!****************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/isProxyEnabled.js ***!
    \****************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("var config = __webpack_require__(/*! ../config */ \"../../node_modules/chai/lib/chai/config.js\");\n\n/*!\n * Chai - isProxyEnabled helper\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .isProxyEnabled()\n *\n * Helper function to check if Chai's proxy protection feature is enabled. If\n * proxies are unsupported or disabled via the user's Chai config, then return\n * false. Otherwise, return true.\n *\n * @namespace Utils\n * @name isProxyEnabled\n */\n\nmodule.exports = function isProxyEnabled() {\n  return config.useProxy &&\n    typeof Proxy !== 'undefined' &&\n    typeof Reflect !== 'undefined';\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/isProxyEnabled.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/objDisplay.js":
  /*!************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/objDisplay.js ***!
    \************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - flag utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar inspect = __webpack_require__(/*! ./inspect */ \"../../node_modules/chai/lib/chai/utils/inspect.js\");\nvar config = __webpack_require__(/*! ../config */ \"../../node_modules/chai/lib/chai/config.js\");\n\n/**\n * ### .objDisplay(object)\n *\n * Determines if an object or an array matches\n * criteria to be inspected in-line for error\n * messages or should be truncated.\n *\n * @param {Mixed} javascript object to inspect\n * @name objDisplay\n * @namespace Utils\n * @api public\n */\n\nmodule.exports = function objDisplay(obj) {\n  var str = inspect(obj)\n    , type = Object.prototype.toString.call(obj);\n\n  if (config.truncateThreshold && str.length >= config.truncateThreshold) {\n    if (type === '[object Function]') {\n      return !obj.name || obj.name === ''\n        ? '[Function]'\n        : '[Function: ' + obj.name + ']';\n    } else if (type === '[object Array]') {\n      return '[ Array(' + obj.length + ') ]';\n    } else if (type === '[object Object]') {\n      var keys = Object.keys(obj)\n        , kstr = keys.length > 2\n          ? keys.splice(0, 2).join(', ') + ', ...'\n          : keys.join(', ');\n      return '{ Object (' + kstr + ') }';\n    } else {\n      return str;\n    }\n  } else {\n    return str;\n  }\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/objDisplay.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/overwriteChainableMethod.js":
  /*!**************************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/overwriteChainableMethod.js ***!
    \**************************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - overwriteChainableMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar chai = __webpack_require__(/*! ../../chai */ \"../../node_modules/chai/lib/chai.js\");\nvar transferFlags = __webpack_require__(/*! ./transferFlags */ \"../../node_modules/chai/lib/chai/utils/transferFlags.js\");\n\n/**\n * ### .overwriteChainableMethod(ctx, name, method, chainingBehavior)\n *\n * Overwrites an already existing chainable method\n * and provides access to the previous function or\n * property.  Must return functions to be used for\n * name.\n *\n *     utils.overwriteChainableMethod(chai.Assertion.prototype, 'lengthOf',\n *       function (_super) {\n *       }\n *     , function (_super) {\n *       }\n *     );\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.overwriteChainableMethod('foo', fn, fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.have.lengthOf(3);\n *     expect(myFoo).to.have.lengthOf.above(3);\n *\n * @param {Object} ctx object whose method / property is to be overwritten\n * @param {String} name of method / property to overwrite\n * @param {Function} method function that returns a function to be used for name\n * @param {Function} chainingBehavior function that returns a function to be used for property\n * @namespace Utils\n * @name overwriteChainableMethod\n * @api public\n */\n\nmodule.exports = function overwriteChainableMethod(ctx, name, method, chainingBehavior) {\n  var chainableBehavior = ctx.__methods[name];\n\n  var _chainingBehavior = chainableBehavior.chainingBehavior;\n  chainableBehavior.chainingBehavior = function overwritingChainableMethodGetter() {\n    var result = chainingBehavior(_chainingBehavior).call(this);\n    if (result !== undefined) {\n      return result;\n    }\n\n    var newAssertion = new chai.Assertion();\n    transferFlags(this, newAssertion);\n    return newAssertion;\n  };\n\n  var _method = chainableBehavior.method;\n  chainableBehavior.method = function overwritingChainableMethodWrapper() {\n    var result = method(_method).apply(this, arguments);\n    if (result !== undefined) {\n      return result;\n    }\n\n    var newAssertion = new chai.Assertion();\n    transferFlags(this, newAssertion);\n    return newAssertion;\n  };\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/overwriteChainableMethod.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/overwriteMethod.js":
  /*!*****************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/overwriteMethod.js ***!
    \*****************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - overwriteMethod utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar addLengthGuard = __webpack_require__(/*! ./addLengthGuard */ \"../../node_modules/chai/lib/chai/utils/addLengthGuard.js\");\nvar chai = __webpack_require__(/*! ../../chai */ \"../../node_modules/chai/lib/chai.js\");\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\nvar proxify = __webpack_require__(/*! ./proxify */ \"../../node_modules/chai/lib/chai/utils/proxify.js\");\nvar transferFlags = __webpack_require__(/*! ./transferFlags */ \"../../node_modules/chai/lib/chai/utils/transferFlags.js\");\n\n/**\n * ### .overwriteMethod(ctx, name, fn)\n *\n * Overwrites an already existing method and provides\n * access to previous function. Must return function\n * to be used for name.\n *\n *     utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {\n *       return function (str) {\n *         var obj = utils.flag(this, 'object');\n *         if (obj instanceof Foo) {\n *           new chai.Assertion(obj.value).to.equal(str);\n *         } else {\n *           _super.apply(this, arguments);\n *         }\n *       }\n *     });\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.overwriteMethod('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.equal('bar');\n *\n * @param {Object} ctx object whose method is to be overwritten\n * @param {String} name of method to overwrite\n * @param {Function} method function that returns a function to be used for name\n * @namespace Utils\n * @name overwriteMethod\n * @api public\n */\n\nmodule.exports = function overwriteMethod(ctx, name, method) {\n  var _method = ctx[name]\n    , _super = function () {\n      throw new Error(name + ' is not a function');\n    };\n\n  if (_method && 'function' === typeof _method)\n    _super = _method;\n\n  var overwritingMethodWrapper = function () {\n    // Setting the `ssfi` flag to `overwritingMethodWrapper` causes this\n    // function to be the starting point for removing implementation frames from\n    // the stack trace of a failed assertion.\n    //\n    // However, we only want to use this function as the starting point if the\n    // `lockSsfi` flag isn't set.\n    //\n    // If the `lockSsfi` flag is set, then either this assertion has been\n    // overwritten by another assertion, or this assertion is being invoked from\n    // inside of another assertion. In the first case, the `ssfi` flag has\n    // already been set by the overwriting assertion. In the second case, the\n    // `ssfi` flag has already been set by the outer assertion.\n    if (!flag(this, 'lockSsfi')) {\n      flag(this, 'ssfi', overwritingMethodWrapper);\n    }\n\n    // Setting the `lockSsfi` flag to `true` prevents the overwritten assertion\n    // from changing the `ssfi` flag. By this point, the `ssfi` flag is already\n    // set to the correct starting point for this assertion.\n    var origLockSsfi = flag(this, 'lockSsfi');\n    flag(this, 'lockSsfi', true);\n    var result = method(_super).apply(this, arguments);\n    flag(this, 'lockSsfi', origLockSsfi);\n\n    if (result !== undefined) {\n      return result;\n    }\n\n    var newAssertion = new chai.Assertion();\n    transferFlags(this, newAssertion);\n    return newAssertion;\n  }\n\n  addLengthGuard(overwritingMethodWrapper, name, false);\n  ctx[name] = proxify(overwritingMethodWrapper, name);\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/overwriteMethod.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/overwriteProperty.js":
  /*!*******************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/overwriteProperty.js ***!
    \*******************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - overwriteProperty utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar chai = __webpack_require__(/*! ../../chai */ \"../../node_modules/chai/lib/chai.js\");\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\nvar isProxyEnabled = __webpack_require__(/*! ./isProxyEnabled */ \"../../node_modules/chai/lib/chai/utils/isProxyEnabled.js\");\nvar transferFlags = __webpack_require__(/*! ./transferFlags */ \"../../node_modules/chai/lib/chai/utils/transferFlags.js\");\n\n/**\n * ### .overwriteProperty(ctx, name, fn)\n *\n * Overwrites an already existing property getter and provides\n * access to previous value. Must return function to use as getter.\n *\n *     utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {\n *       return function () {\n *         var obj = utils.flag(this, 'object');\n *         if (obj instanceof Foo) {\n *           new chai.Assertion(obj.name).to.equal('bar');\n *         } else {\n *           _super.call(this);\n *         }\n *       }\n *     });\n *\n *\n * Can also be accessed directly from `chai.Assertion`.\n *\n *     chai.Assertion.overwriteProperty('foo', fn);\n *\n * Then can be used as any other assertion.\n *\n *     expect(myFoo).to.be.ok;\n *\n * @param {Object} ctx object whose property is to be overwritten\n * @param {String} name of property to overwrite\n * @param {Function} getter function that returns a getter function to be used for name\n * @namespace Utils\n * @name overwriteProperty\n * @api public\n */\n\nmodule.exports = function overwriteProperty(ctx, name, getter) {\n  var _get = Object.getOwnPropertyDescriptor(ctx, name)\n    , _super = function () {};\n\n  if (_get && 'function' === typeof _get.get)\n    _super = _get.get\n\n  Object.defineProperty(ctx, name,\n    { get: function overwritingPropertyGetter() {\n        // Setting the `ssfi` flag to `overwritingPropertyGetter` causes this\n        // function to be the starting point for removing implementation frames\n        // from the stack trace of a failed assertion.\n        //\n        // However, we only want to use this function as the starting point if\n        // the `lockSsfi` flag isn't set and proxy protection is disabled.\n        //\n        // If the `lockSsfi` flag is set, then either this assertion has been\n        // overwritten by another assertion, or this assertion is being invoked\n        // from inside of another assertion. In the first case, the `ssfi` flag\n        // has already been set by the overwriting assertion. In the second\n        // case, the `ssfi` flag has already been set by the outer assertion.\n        //\n        // If proxy protection is enabled, then the `ssfi` flag has already been\n        // set by the proxy getter.\n        if (!isProxyEnabled() && !flag(this, 'lockSsfi')) {\n          flag(this, 'ssfi', overwritingPropertyGetter);\n        }\n\n        // Setting the `lockSsfi` flag to `true` prevents the overwritten\n        // assertion from changing the `ssfi` flag. By this point, the `ssfi`\n        // flag is already set to the correct starting point for this assertion.\n        var origLockSsfi = flag(this, 'lockSsfi');\n        flag(this, 'lockSsfi', true);\n        var result = getter(_super).call(this);\n        flag(this, 'lockSsfi', origLockSsfi);\n\n        if (result !== undefined) {\n          return result;\n        }\n\n        var newAssertion = new chai.Assertion();\n        transferFlags(this, newAssertion);\n        return newAssertion;\n      }\n    , configurable: true\n  });\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/overwriteProperty.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/proxify.js":
  /*!*********************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/proxify.js ***!
    \*********************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("var config = __webpack_require__(/*! ../config */ \"../../node_modules/chai/lib/chai/config.js\");\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\nvar getProperties = __webpack_require__(/*! ./getProperties */ \"../../node_modules/chai/lib/chai/utils/getProperties.js\");\nvar isProxyEnabled = __webpack_require__(/*! ./isProxyEnabled */ \"../../node_modules/chai/lib/chai/utils/isProxyEnabled.js\");\n\n/*!\n * Chai - proxify utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .proxify(object)\n *\n * Return a proxy of given object that throws an error when a non-existent\n * property is read. By default, the root cause is assumed to be a misspelled\n * property, and thus an attempt is made to offer a reasonable suggestion from\n * the list of existing properties. However, if a nonChainableMethodName is\n * provided, then the root cause is instead a failure to invoke a non-chainable\n * method prior to reading the non-existent property.\n *\n * If proxies are unsupported or disabled via the user's Chai config, then\n * return object without modification.\n *\n * @param {Object} obj\n * @param {String} nonChainableMethodName\n * @namespace Utils\n * @name proxify\n */\n\nvar builtins = ['__flags', '__methods', '_obj', 'assert'];\n\nmodule.exports = function proxify(obj, nonChainableMethodName) {\n  if (!isProxyEnabled()) return obj;\n\n  return new Proxy(obj, {\n    get: function proxyGetter(target, property) {\n      // This check is here because we should not throw errors on Symbol properties\n      // such as `Symbol.toStringTag`.\n      // The values for which an error should be thrown can be configured using\n      // the `config.proxyExcludedKeys` setting.\n      if (typeof property === 'string' &&\n          config.proxyExcludedKeys.indexOf(property) === -1 &&\n          !Reflect.has(target, property)) {\n        // Special message for invalid property access of non-chainable methods.\n        if (nonChainableMethodName) {\n          throw Error('Invalid Chai property: ' + nonChainableMethodName + '.' +\n            property + '. See docs for proper usage of \"' +\n            nonChainableMethodName + '\".');\n        }\n\n        // If the property is reasonably close to an existing Chai property,\n        // suggest that property to the user. Only suggest properties with a\n        // distance less than 4.\n        var suggestion = null;\n        var suggestionDistance = 4;\n        getProperties(target).forEach(function(prop) {\n          if (\n            !Object.prototype.hasOwnProperty(prop) &&\n            builtins.indexOf(prop) === -1\n          ) {\n            var dist = stringDistanceCapped(\n              property,\n              prop,\n              suggestionDistance\n            );\n            if (dist < suggestionDistance) {\n              suggestion = prop;\n              suggestionDistance = dist;\n            }\n          }\n        });\n\n        if (suggestion !== null) {\n          throw Error('Invalid Chai property: ' + property +\n            '. Did you mean \"' + suggestion + '\"?');\n        } else {\n          throw Error('Invalid Chai property: ' + property);\n        }\n      }\n\n      // Use this proxy getter as the starting point for removing implementation\n      // frames from the stack trace of a failed assertion. For property\n      // assertions, this prevents the proxy getter from showing up in the stack\n      // trace since it's invoked before the property getter. For method and\n      // chainable method assertions, this flag will end up getting changed to\n      // the method wrapper, which is good since this frame will no longer be in\n      // the stack once the method is invoked. Note that Chai builtin assertion\n      // properties such as `__flags` are skipped since this is only meant to\n      // capture the starting point of an assertion. This step is also skipped\n      // if the `lockSsfi` flag is set, thus indicating that this assertion is\n      // being called from within another assertion. In that case, the `ssfi`\n      // flag is already set to the outer assertion's starting point.\n      if (builtins.indexOf(property) === -1 && !flag(target, 'lockSsfi')) {\n        flag(target, 'ssfi', proxyGetter);\n      }\n\n      return Reflect.get(target, property);\n    }\n  });\n};\n\n/**\n * # stringDistanceCapped(strA, strB, cap)\n * Return the Levenshtein distance between two strings, but no more than cap.\n * @param {string} strA\n * @param {string} strB\n * @param {number} number\n * @return {number} min(string distance between strA and strB, cap)\n * @api private\n */\n\nfunction stringDistanceCapped(strA, strB, cap) {\n  if (Math.abs(strA.length - strB.length) >= cap) {\n    return cap;\n  }\n\n  var memo = [];\n  // `memo` is a two-dimensional array containing distances.\n  // memo[i][j] is the distance between strA.slice(0, i) and\n  // strB.slice(0, j).\n  for (var i = 0; i <= strA.length; i++) {\n    memo[i] = Array(strB.length + 1).fill(0);\n    memo[i][0] = i;\n  }\n  for (var j = 0; j < strB.length; j++) {\n    memo[0][j] = j;\n  }\n\n  for (var i = 1; i <= strA.length; i++) {\n    var ch = strA.charCodeAt(i - 1);\n    for (var j = 1; j <= strB.length; j++) {\n      if (Math.abs(i - j) >= cap) {\n        memo[i][j] = cap;\n        continue;\n      }\n      memo[i][j] = Math.min(\n        memo[i - 1][j] + 1,\n        memo[i][j - 1] + 1,\n        memo[i - 1][j - 1] +\n          (ch === strB.charCodeAt(j - 1) ? 0 : 1)\n      );\n    }\n  }\n\n  return memo[strA.length][strB.length];\n}\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/proxify.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/test.js":
  /*!******************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/test.js ***!
    \******************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n * Chai - test utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/*!\n * Module dependencies\n */\n\nvar flag = __webpack_require__(/*! ./flag */ \"../../node_modules/chai/lib/chai/utils/flag.js\");\n\n/**\n * ### .test(object, expression)\n *\n * Test and object for expression.\n *\n * @param {Object} object (constructed Assertion)\n * @param {Arguments} chai.Assertion.prototype.assert arguments\n * @namespace Utils\n * @name test\n */\n\nmodule.exports = function test(obj, args) {\n  var negate = flag(obj, 'negate')\n    , expr = args[0];\n  return negate ? !expr : expr;\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/test.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/chai/lib/chai/utils/transferFlags.js":
  /*!***************************************************************!*\
    !*** ../../node_modules/chai/lib/chai/utils/transferFlags.js ***!
    \***************************************************************/
  /***/ ((module) => {
  
  eval("/*!\n * Chai - transferFlags utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .transferFlags(assertion, object, includeAll = true)\n *\n * Transfer all the flags for `assertion` to `object`. If\n * `includeAll` is set to `false`, then the base Chai\n * assertion flags (namely `object`, `ssfi`, `lockSsfi`,\n * and `message`) will not be transferred.\n *\n *\n *     var newAssertion = new Assertion();\n *     utils.transferFlags(assertion, newAssertion);\n *\n *     var anotherAssertion = new Assertion(myObj);\n *     utils.transferFlags(assertion, anotherAssertion, false);\n *\n * @param {Assertion} assertion the assertion to transfer the flags from\n * @param {Object} object the object to transfer the flags to; usually a new assertion\n * @param {Boolean} includeAll\n * @namespace Utils\n * @name transferFlags\n * @api private\n */\n\nmodule.exports = function transferFlags(assertion, object, includeAll) {\n  var flags = assertion.__flags || (assertion.__flags = Object.create(null));\n\n  if (!object.__flags) {\n    object.__flags = Object.create(null);\n  }\n\n  includeAll = arguments.length === 3 ? includeAll : true;\n\n  for (var flag in flags) {\n    if (includeAll ||\n        (flag !== 'object' && flag !== 'ssfi' && flag !== 'lockSsfi' && flag != 'message')) {\n      object.__flags[flag] = flags[flag];\n    }\n  }\n};\n\n\n//# sourceURL=webpack:///../../node_modules/chai/lib/chai/utils/transferFlags.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/check-error/index.js":
  /*!***********************************************!*\
    !*** ../../node_modules/check-error/index.js ***!
    \***********************************************/
  /***/ ((module) => {
  
  "use strict";
  eval("\n\n/* !\n * Chai - checkError utility\n * Copyright(c) 2012-2016 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .checkError\n *\n * Checks that an error conforms to a given set of criteria and/or retrieves information about it.\n *\n * @api public\n */\n\n/**\n * ### .compatibleInstance(thrown, errorLike)\n *\n * Checks if two instances are compatible (strict equal).\n * Returns false if errorLike is not an instance of Error, because instances\n * can only be compatible if they're both error instances.\n *\n * @name compatibleInstance\n * @param {Error} thrown error\n * @param {Error|ErrorConstructor} errorLike object to compare against\n * @namespace Utils\n * @api public\n */\n\nfunction compatibleInstance(thrown, errorLike) {\n  return errorLike instanceof Error && thrown === errorLike;\n}\n\n/**\n * ### .compatibleConstructor(thrown, errorLike)\n *\n * Checks if two constructors are compatible.\n * This function can receive either an error constructor or\n * an error instance as the `errorLike` argument.\n * Constructors are compatible if they're the same or if one is\n * an instance of another.\n *\n * @name compatibleConstructor\n * @param {Error} thrown error\n * @param {Error|ErrorConstructor} errorLike object to compare against\n * @namespace Utils\n * @api public\n */\n\nfunction compatibleConstructor(thrown, errorLike) {\n  if (errorLike instanceof Error) {\n    // If `errorLike` is an instance of any error we compare their constructors\n    return thrown.constructor === errorLike.constructor || thrown instanceof errorLike.constructor;\n  } else if (errorLike.prototype instanceof Error || errorLike === Error) {\n    // If `errorLike` is a constructor that inherits from Error, we compare `thrown` to `errorLike` directly\n    return thrown.constructor === errorLike || thrown instanceof errorLike;\n  }\n\n  return false;\n}\n\n/**\n * ### .compatibleMessage(thrown, errMatcher)\n *\n * Checks if an error's message is compatible with a matcher (String or RegExp).\n * If the message contains the String or passes the RegExp test,\n * it is considered compatible.\n *\n * @name compatibleMessage\n * @param {Error} thrown error\n * @param {String|RegExp} errMatcher to look for into the message\n * @namespace Utils\n * @api public\n */\n\nfunction compatibleMessage(thrown, errMatcher) {\n  var comparisonString = typeof thrown === 'string' ? thrown : thrown.message;\n  if (errMatcher instanceof RegExp) {\n    return errMatcher.test(comparisonString);\n  } else if (typeof errMatcher === 'string') {\n    return comparisonString.indexOf(errMatcher) !== -1; // eslint-disable-line no-magic-numbers\n  }\n\n  return false;\n}\n\n/**\n * ### .getFunctionName(constructorFn)\n *\n * Returns the name of a function.\n * This also includes a polyfill function if `constructorFn.name` is not defined.\n *\n * @name getFunctionName\n * @param {Function} constructorFn\n * @namespace Utils\n * @api private\n */\n\nvar functionNameMatch = /\\s*function(?:\\s|\\s*\\/\\*[^(?:*\\/)]+\\*\\/\\s*)*([^\\(\\/]+)/;\nfunction getFunctionName(constructorFn) {\n  var name = '';\n  if (typeof constructorFn.name === 'undefined') {\n    // Here we run a polyfill if constructorFn.name is not defined\n    var match = String(constructorFn).match(functionNameMatch);\n    if (match) {\n      name = match[1];\n    }\n  } else {\n    name = constructorFn.name;\n  }\n\n  return name;\n}\n\n/**\n * ### .getConstructorName(errorLike)\n *\n * Gets the constructor name for an Error instance or constructor itself.\n *\n * @name getConstructorName\n * @param {Error|ErrorConstructor} errorLike\n * @namespace Utils\n * @api public\n */\n\nfunction getConstructorName(errorLike) {\n  var constructorName = errorLike;\n  if (errorLike instanceof Error) {\n    constructorName = getFunctionName(errorLike.constructor);\n  } else if (typeof errorLike === 'function') {\n    // If `err` is not an instance of Error it is an error constructor itself or another function.\n    // If we've got a common function we get its name, otherwise we may need to create a new instance\n    // of the error just in case it's a poorly-constructed error. Please see chaijs/chai/issues/45 to know more.\n    constructorName = getFunctionName(errorLike).trim() ||\n        getFunctionName(new errorLike()); // eslint-disable-line new-cap\n  }\n\n  return constructorName;\n}\n\n/**\n * ### .getMessage(errorLike)\n *\n * Gets the error message from an error.\n * If `err` is a String itself, we return it.\n * If the error has no message, we return an empty string.\n *\n * @name getMessage\n * @param {Error|String} errorLike\n * @namespace Utils\n * @api public\n */\n\nfunction getMessage(errorLike) {\n  var msg = '';\n  if (errorLike && errorLike.message) {\n    msg = errorLike.message;\n  } else if (typeof errorLike === 'string') {\n    msg = errorLike;\n  }\n\n  return msg;\n}\n\nmodule.exports = {\n  compatibleInstance: compatibleInstance,\n  compatibleConstructor: compatibleConstructor,\n  compatibleMessage: compatibleMessage,\n  getMessage: getMessage,\n  getConstructorName: getConstructorName,\n};\n\n\n//# sourceURL=webpack:///../../node_modules/check-error/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/deep-eql/index.js":
  /*!********************************************!*\
    !*** ../../node_modules/deep-eql/index.js ***!
    \********************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  "use strict";
  eval("\n/* globals Symbol: false, Uint8Array: false, WeakMap: false */\n/*!\n * deep-eql\n * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\nvar type = __webpack_require__(/*! type-detect */ \"../../node_modules/type-detect/type-detect.js\");\nfunction FakeMap() {\n  this._key = 'chai/deep-eql__' + Math.random() + Date.now();\n}\n\nFakeMap.prototype = {\n  get: function getMap(key) {\n    return key[this._key];\n  },\n  set: function setMap(key, value) {\n    if (Object.isExtensible(key)) {\n      Object.defineProperty(key, this._key, {\n        value: value,\n        configurable: true,\n      });\n    }\n  },\n};\n\nvar MemoizeMap = typeof WeakMap === 'function' ? WeakMap : FakeMap;\n/*!\n * Check to see if the MemoizeMap has recorded a result of the two operands\n *\n * @param {Mixed} leftHandOperand\n * @param {Mixed} rightHandOperand\n * @param {MemoizeMap} memoizeMap\n * @returns {Boolean|null} result\n*/\nfunction memoizeCompare(leftHandOperand, rightHandOperand, memoizeMap) {\n  // Technically, WeakMap keys can *only* be objects, not primitives.\n  if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {\n    return null;\n  }\n  var leftHandMap = memoizeMap.get(leftHandOperand);\n  if (leftHandMap) {\n    var result = leftHandMap.get(rightHandOperand);\n    if (typeof result === 'boolean') {\n      return result;\n    }\n  }\n  return null;\n}\n\n/*!\n * Set the result of the equality into the MemoizeMap\n *\n * @param {Mixed} leftHandOperand\n * @param {Mixed} rightHandOperand\n * @param {MemoizeMap} memoizeMap\n * @param {Boolean} result\n*/\nfunction memoizeSet(leftHandOperand, rightHandOperand, memoizeMap, result) {\n  // Technically, WeakMap keys can *only* be objects, not primitives.\n  if (!memoizeMap || isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {\n    return;\n  }\n  var leftHandMap = memoizeMap.get(leftHandOperand);\n  if (leftHandMap) {\n    leftHandMap.set(rightHandOperand, result);\n  } else {\n    leftHandMap = new MemoizeMap();\n    leftHandMap.set(rightHandOperand, result);\n    memoizeMap.set(leftHandOperand, leftHandMap);\n  }\n}\n\n/*!\n * Primary Export\n */\n\nmodule.exports = deepEqual;\nmodule.exports.MemoizeMap = MemoizeMap;\n\n/**\n * Assert deeply nested sameValue equality between two objects of any type.\n *\n * @param {Mixed} leftHandOperand\n * @param {Mixed} rightHandOperand\n * @param {Object} [options] (optional) Additional options\n * @param {Array} [options.comparator] (optional) Override default algorithm, determining custom equality.\n * @param {Array} [options.memoize] (optional) Provide a custom memoization object which will cache the results of\n    complex objects for a speed boost. By passing `false` you can disable memoization, but this will cause circular\n    references to blow the stack.\n * @return {Boolean} equal match\n */\nfunction deepEqual(leftHandOperand, rightHandOperand, options) {\n  // If we have a comparator, we can't assume anything; so bail to its check first.\n  if (options && options.comparator) {\n    return extensiveDeepEqual(leftHandOperand, rightHandOperand, options);\n  }\n\n  var simpleResult = simpleEqual(leftHandOperand, rightHandOperand);\n  if (simpleResult !== null) {\n    return simpleResult;\n  }\n\n  // Deeper comparisons are pushed through to a larger function\n  return extensiveDeepEqual(leftHandOperand, rightHandOperand, options);\n}\n\n/**\n * Many comparisons can be canceled out early via simple equality or primitive checks.\n * @param {Mixed} leftHandOperand\n * @param {Mixed} rightHandOperand\n * @return {Boolean|null} equal match\n */\nfunction simpleEqual(leftHandOperand, rightHandOperand) {\n  // Equal references (except for Numbers) can be returned early\n  if (leftHandOperand === rightHandOperand) {\n    // Handle +-0 cases\n    return leftHandOperand !== 0 || 1 / leftHandOperand === 1 / rightHandOperand;\n  }\n\n  // handle NaN cases\n  if (\n    leftHandOperand !== leftHandOperand && // eslint-disable-line no-self-compare\n    rightHandOperand !== rightHandOperand // eslint-disable-line no-self-compare\n  ) {\n    return true;\n  }\n\n  // Anything that is not an 'object', i.e. symbols, functions, booleans, numbers,\n  // strings, and undefined, can be compared by reference.\n  if (isPrimitive(leftHandOperand) || isPrimitive(rightHandOperand)) {\n    // Easy out b/c it would have passed the first equality check\n    return false;\n  }\n  return null;\n}\n\n/*!\n * The main logic of the `deepEqual` function.\n *\n * @param {Mixed} leftHandOperand\n * @param {Mixed} rightHandOperand\n * @param {Object} [options] (optional) Additional options\n * @param {Array} [options.comparator] (optional) Override default algorithm, determining custom equality.\n * @param {Array} [options.memoize] (optional) Provide a custom memoization object which will cache the results of\n    complex objects for a speed boost. By passing `false` you can disable memoization, but this will cause circular\n    references to blow the stack.\n * @return {Boolean} equal match\n*/\nfunction extensiveDeepEqual(leftHandOperand, rightHandOperand, options) {\n  options = options || {};\n  options.memoize = options.memoize === false ? false : options.memoize || new MemoizeMap();\n  var comparator = options && options.comparator;\n\n  // Check if a memoized result exists.\n  var memoizeResultLeft = memoizeCompare(leftHandOperand, rightHandOperand, options.memoize);\n  if (memoizeResultLeft !== null) {\n    return memoizeResultLeft;\n  }\n  var memoizeResultRight = memoizeCompare(rightHandOperand, leftHandOperand, options.memoize);\n  if (memoizeResultRight !== null) {\n    return memoizeResultRight;\n  }\n\n  // If a comparator is present, use it.\n  if (comparator) {\n    var comparatorResult = comparator(leftHandOperand, rightHandOperand);\n    // Comparators may return null, in which case we want to go back to default behavior.\n    if (comparatorResult === false || comparatorResult === true) {\n      memoizeSet(leftHandOperand, rightHandOperand, options.memoize, comparatorResult);\n      return comparatorResult;\n    }\n    // To allow comparators to override *any* behavior, we ran them first. Since it didn't decide\n    // what to do, we need to make sure to return the basic tests first before we move on.\n    var simpleResult = simpleEqual(leftHandOperand, rightHandOperand);\n    if (simpleResult !== null) {\n      // Don't memoize this, it takes longer to set/retrieve than to just compare.\n      return simpleResult;\n    }\n  }\n\n  var leftHandType = type(leftHandOperand);\n  if (leftHandType !== type(rightHandOperand)) {\n    memoizeSet(leftHandOperand, rightHandOperand, options.memoize, false);\n    return false;\n  }\n\n  // Temporarily set the operands in the memoize object to prevent blowing the stack\n  memoizeSet(leftHandOperand, rightHandOperand, options.memoize, true);\n\n  var result = extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandType, options);\n  memoizeSet(leftHandOperand, rightHandOperand, options.memoize, result);\n  return result;\n}\n\nfunction extensiveDeepEqualByType(leftHandOperand, rightHandOperand, leftHandType, options) {\n  switch (leftHandType) {\n    case 'String':\n    case 'Number':\n    case 'Boolean':\n    case 'Date':\n      // If these types are their instance types (e.g. `new Number`) then re-deepEqual against their values\n      return deepEqual(leftHandOperand.valueOf(), rightHandOperand.valueOf());\n    case 'Promise':\n    case 'Symbol':\n    case 'function':\n    case 'WeakMap':\n    case 'WeakSet':\n    case 'Error':\n      return leftHandOperand === rightHandOperand;\n    case 'Arguments':\n    case 'Int8Array':\n    case 'Uint8Array':\n    case 'Uint8ClampedArray':\n    case 'Int16Array':\n    case 'Uint16Array':\n    case 'Int32Array':\n    case 'Uint32Array':\n    case 'Float32Array':\n    case 'Float64Array':\n    case 'Array':\n      return iterableEqual(leftHandOperand, rightHandOperand, options);\n    case 'RegExp':\n      return regexpEqual(leftHandOperand, rightHandOperand);\n    case 'Generator':\n      return generatorEqual(leftHandOperand, rightHandOperand, options);\n    case 'DataView':\n      return iterableEqual(new Uint8Array(leftHandOperand.buffer), new Uint8Array(rightHandOperand.buffer), options);\n    case 'ArrayBuffer':\n      return iterableEqual(new Uint8Array(leftHandOperand), new Uint8Array(rightHandOperand), options);\n    case 'Set':\n      return entriesEqual(leftHandOperand, rightHandOperand, options);\n    case 'Map':\n      return entriesEqual(leftHandOperand, rightHandOperand, options);\n    default:\n      return objectEqual(leftHandOperand, rightHandOperand, options);\n  }\n}\n\n/*!\n * Compare two Regular Expressions for equality.\n *\n * @param {RegExp} leftHandOperand\n * @param {RegExp} rightHandOperand\n * @return {Boolean} result\n */\n\nfunction regexpEqual(leftHandOperand, rightHandOperand) {\n  return leftHandOperand.toString() === rightHandOperand.toString();\n}\n\n/*!\n * Compare two Sets/Maps for equality. Faster than other equality functions.\n *\n * @param {Set} leftHandOperand\n * @param {Set} rightHandOperand\n * @param {Object} [options] (Optional)\n * @return {Boolean} result\n */\n\nfunction entriesEqual(leftHandOperand, rightHandOperand, options) {\n  // IE11 doesn't support Set#entries or Set#@@iterator, so we need manually populate using Set#forEach\n  if (leftHandOperand.size !== rightHandOperand.size) {\n    return false;\n  }\n  if (leftHandOperand.size === 0) {\n    return true;\n  }\n  var leftHandItems = [];\n  var rightHandItems = [];\n  leftHandOperand.forEach(function gatherEntries(key, value) {\n    leftHandItems.push([ key, value ]);\n  });\n  rightHandOperand.forEach(function gatherEntries(key, value) {\n    rightHandItems.push([ key, value ]);\n  });\n  return iterableEqual(leftHandItems.sort(), rightHandItems.sort(), options);\n}\n\n/*!\n * Simple equality for flat iterable objects such as Arrays, TypedArrays or Node.js buffers.\n *\n * @param {Iterable} leftHandOperand\n * @param {Iterable} rightHandOperand\n * @param {Object} [options] (Optional)\n * @return {Boolean} result\n */\n\nfunction iterableEqual(leftHandOperand, rightHandOperand, options) {\n  var length = leftHandOperand.length;\n  if (length !== rightHandOperand.length) {\n    return false;\n  }\n  if (length === 0) {\n    return true;\n  }\n  var index = -1;\n  while (++index < length) {\n    if (deepEqual(leftHandOperand[index], rightHandOperand[index], options) === false) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/*!\n * Simple equality for generator objects such as those returned by generator functions.\n *\n * @param {Iterable} leftHandOperand\n * @param {Iterable} rightHandOperand\n * @param {Object} [options] (Optional)\n * @return {Boolean} result\n */\n\nfunction generatorEqual(leftHandOperand, rightHandOperand, options) {\n  return iterableEqual(getGeneratorEntries(leftHandOperand), getGeneratorEntries(rightHandOperand), options);\n}\n\n/*!\n * Determine if the given object has an @@iterator function.\n *\n * @param {Object} target\n * @return {Boolean} `true` if the object has an @@iterator function.\n */\nfunction hasIteratorFunction(target) {\n  return typeof Symbol !== 'undefined' &&\n    typeof target === 'object' &&\n    typeof Symbol.iterator !== 'undefined' &&\n    typeof target[Symbol.iterator] === 'function';\n}\n\n/*!\n * Gets all iterator entries from the given Object. If the Object has no @@iterator function, returns an empty array.\n * This will consume the iterator - which could have side effects depending on the @@iterator implementation.\n *\n * @param {Object} target\n * @returns {Array} an array of entries from the @@iterator function\n */\nfunction getIteratorEntries(target) {\n  if (hasIteratorFunction(target)) {\n    try {\n      return getGeneratorEntries(target[Symbol.iterator]());\n    } catch (iteratorError) {\n      return [];\n    }\n  }\n  return [];\n}\n\n/*!\n * Gets all entries from a Generator. This will consume the generator - which could have side effects.\n *\n * @param {Generator} target\n * @returns {Array} an array of entries from the Generator.\n */\nfunction getGeneratorEntries(generator) {\n  var generatorResult = generator.next();\n  var accumulator = [ generatorResult.value ];\n  while (generatorResult.done === false) {\n    generatorResult = generator.next();\n    accumulator.push(generatorResult.value);\n  }\n  return accumulator;\n}\n\n/*!\n * Gets all own and inherited enumerable keys from a target.\n *\n * @param {Object} target\n * @returns {Array} an array of own and inherited enumerable keys from the target.\n */\nfunction getEnumerableKeys(target) {\n  var keys = [];\n  for (var key in target) {\n    keys.push(key);\n  }\n  return keys;\n}\n\n/*!\n * Determines if two objects have matching values, given a set of keys. Defers to deepEqual for the equality check of\n * each key. If any value of the given key is not equal, the function will return false (early).\n *\n * @param {Mixed} leftHandOperand\n * @param {Mixed} rightHandOperand\n * @param {Array} keys An array of keys to compare the values of leftHandOperand and rightHandOperand against\n * @param {Object} [options] (Optional)\n * @return {Boolean} result\n */\nfunction keysEqual(leftHandOperand, rightHandOperand, keys, options) {\n  var length = keys.length;\n  if (length === 0) {\n    return true;\n  }\n  for (var i = 0; i < length; i += 1) {\n    if (deepEqual(leftHandOperand[keys[i]], rightHandOperand[keys[i]], options) === false) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/*!\n * Recursively check the equality of two Objects. Once basic sameness has been established it will defer to `deepEqual`\n * for each enumerable key in the object.\n *\n * @param {Mixed} leftHandOperand\n * @param {Mixed} rightHandOperand\n * @param {Object} [options] (Optional)\n * @return {Boolean} result\n */\n\nfunction objectEqual(leftHandOperand, rightHandOperand, options) {\n  var leftHandKeys = getEnumerableKeys(leftHandOperand);\n  var rightHandKeys = getEnumerableKeys(rightHandOperand);\n  if (leftHandKeys.length && leftHandKeys.length === rightHandKeys.length) {\n    leftHandKeys.sort();\n    rightHandKeys.sort();\n    if (iterableEqual(leftHandKeys, rightHandKeys) === false) {\n      return false;\n    }\n    return keysEqual(leftHandOperand, rightHandOperand, leftHandKeys, options);\n  }\n\n  var leftHandEntries = getIteratorEntries(leftHandOperand);\n  var rightHandEntries = getIteratorEntries(rightHandOperand);\n  if (leftHandEntries.length && leftHandEntries.length === rightHandEntries.length) {\n    leftHandEntries.sort();\n    rightHandEntries.sort();\n    return iterableEqual(leftHandEntries, rightHandEntries, options);\n  }\n\n  if (leftHandKeys.length === 0 &&\n      leftHandEntries.length === 0 &&\n      rightHandKeys.length === 0 &&\n      rightHandEntries.length === 0) {\n    return true;\n  }\n\n  return false;\n}\n\n/*!\n * Returns true if the argument is a primitive.\n *\n * This intentionally returns true for all objects that can be compared by reference,\n * including functions and symbols.\n *\n * @param {Mixed} value\n * @return {Boolean} result\n */\nfunction isPrimitive(value) {\n  return value === null || typeof value !== 'object';\n}\n\n\n//# sourceURL=webpack:///../../node_modules/deep-eql/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/get-func-name/index.js":
  /*!*************************************************!*\
    !*** ../../node_modules/get-func-name/index.js ***!
    \*************************************************/
  /***/ ((module) => {
  
  "use strict";
  eval("\n\n/* !\n * Chai - getFuncName utility\n * Copyright(c) 2012-2016 Jake Luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\n\n/**\n * ### .getFuncName(constructorFn)\n *\n * Returns the name of a function.\n * When a non-function instance is passed, returns `null`.\n * This also includes a polyfill function if `aFunc.name` is not defined.\n *\n * @name getFuncName\n * @param {Function} funct\n * @namespace Utils\n * @api public\n */\n\nvar toString = Function.prototype.toString;\nvar functionNameMatch = /\\s*function(?:\\s|\\s*\\/\\*[^(?:*\\/)]+\\*\\/\\s*)*([^\\s\\(\\/]+)/;\nfunction getFuncName(aFunc) {\n  if (typeof aFunc !== 'function') {\n    return null;\n  }\n\n  var name = '';\n  if (typeof Function.prototype.name === 'undefined' && typeof aFunc.name === 'undefined') {\n    // Here we run a polyfill if Function does not support the `name` property and if aFunc.name is not defined\n    var match = toString.call(aFunc).match(functionNameMatch);\n    if (match) {\n      name = match[1];\n    }\n  } else {\n    // If we've got a `name` property we just use it\n    name = aFunc.name;\n  }\n\n  return name;\n}\n\nmodule.exports = getFuncName;\n\n\n//# sourceURL=webpack:///../../node_modules/get-func-name/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/isomorphic-fetch/fetch-npm-browserify.js":
  /*!*******************************************************************!*\
    !*** ../../node_modules/isomorphic-fetch/fetch-npm-browserify.js ***!
    \*******************************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("// the whatwg-fetch polyfill installs the fetch() function\n// on the global object (window or self)\n//\n// Return that as the export for use in Webpack, Browserify etc.\n__webpack_require__(/*! whatwg-fetch */ \"../../node_modules/whatwg-fetch/fetch.js\");\nmodule.exports = self.fetch.bind(self);\n\n\n//# sourceURL=webpack:///../../node_modules/isomorphic-fetch/fetch-npm-browserify.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/localforage/dist/localforage.js":
  /*!**********************************************************!*\
    !*** ../../node_modules/localforage/dist/localforage.js ***!
    \**********************************************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("/*!\n    localForage -- Offline Storage, Improved\n    Version 1.10.0\n    https://localforage.github.io/localForage\n    (c) 2013-2017 Mozilla, Apache License 2.0\n*/\n(function(f){if(true){module.exports=f()}else { var g; }})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=undefined;if(!u&&a)return require(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw (f.code=\"MODULE_NOT_FOUND\", f)}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=undefined;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){\n(function (global){\n'use strict';\nvar Mutation = global.MutationObserver || global.WebKitMutationObserver;\n\nvar scheduleDrain;\n\n{\n  if (Mutation) {\n    var called = 0;\n    var observer = new Mutation(nextTick);\n    var element = global.document.createTextNode('');\n    observer.observe(element, {\n      characterData: true\n    });\n    scheduleDrain = function () {\n      element.data = (called = ++called % 2);\n    };\n  } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {\n    var channel = new global.MessageChannel();\n    channel.port1.onmessage = nextTick;\n    scheduleDrain = function () {\n      channel.port2.postMessage(0);\n    };\n  } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {\n    scheduleDrain = function () {\n\n      // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted\n      // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.\n      var scriptEl = global.document.createElement('script');\n      scriptEl.onreadystatechange = function () {\n        nextTick();\n\n        scriptEl.onreadystatechange = null;\n        scriptEl.parentNode.removeChild(scriptEl);\n        scriptEl = null;\n      };\n      global.document.documentElement.appendChild(scriptEl);\n    };\n  } else {\n    scheduleDrain = function () {\n      setTimeout(nextTick, 0);\n    };\n  }\n}\n\nvar draining;\nvar queue = [];\n//named nextTick for less confusing stack traces\nfunction nextTick() {\n  draining = true;\n  var i, oldQueue;\n  var len = queue.length;\n  while (len) {\n    oldQueue = queue;\n    queue = [];\n    i = -1;\n    while (++i < len) {\n      oldQueue[i]();\n    }\n    len = queue.length;\n  }\n  draining = false;\n}\n\nmodule.exports = immediate;\nfunction immediate(task) {\n  if (queue.push(task) === 1 && !draining) {\n    scheduleDrain();\n  }\n}\n\n}).call(this,typeof __webpack_require__.g !== \"undefined\" ? __webpack_require__.g : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{}],2:[function(_dereq_,module,exports){\n'use strict';\nvar immediate = _dereq_(1);\n\n/* istanbul ignore next */\nfunction INTERNAL() {}\n\nvar handlers = {};\n\nvar REJECTED = ['REJECTED'];\nvar FULFILLED = ['FULFILLED'];\nvar PENDING = ['PENDING'];\n\nmodule.exports = Promise;\n\nfunction Promise(resolver) {\n  if (typeof resolver !== 'function') {\n    throw new TypeError('resolver must be a function');\n  }\n  this.state = PENDING;\n  this.queue = [];\n  this.outcome = void 0;\n  if (resolver !== INTERNAL) {\n    safelyResolveThenable(this, resolver);\n  }\n}\n\nPromise.prototype[\"catch\"] = function (onRejected) {\n  return this.then(null, onRejected);\n};\nPromise.prototype.then = function (onFulfilled, onRejected) {\n  if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||\n    typeof onRejected !== 'function' && this.state === REJECTED) {\n    return this;\n  }\n  var promise = new this.constructor(INTERNAL);\n  if (this.state !== PENDING) {\n    var resolver = this.state === FULFILLED ? onFulfilled : onRejected;\n    unwrap(promise, resolver, this.outcome);\n  } else {\n    this.queue.push(new QueueItem(promise, onFulfilled, onRejected));\n  }\n\n  return promise;\n};\nfunction QueueItem(promise, onFulfilled, onRejected) {\n  this.promise = promise;\n  if (typeof onFulfilled === 'function') {\n    this.onFulfilled = onFulfilled;\n    this.callFulfilled = this.otherCallFulfilled;\n  }\n  if (typeof onRejected === 'function') {\n    this.onRejected = onRejected;\n    this.callRejected = this.otherCallRejected;\n  }\n}\nQueueItem.prototype.callFulfilled = function (value) {\n  handlers.resolve(this.promise, value);\n};\nQueueItem.prototype.otherCallFulfilled = function (value) {\n  unwrap(this.promise, this.onFulfilled, value);\n};\nQueueItem.prototype.callRejected = function (value) {\n  handlers.reject(this.promise, value);\n};\nQueueItem.prototype.otherCallRejected = function (value) {\n  unwrap(this.promise, this.onRejected, value);\n};\n\nfunction unwrap(promise, func, value) {\n  immediate(function () {\n    var returnValue;\n    try {\n      returnValue = func(value);\n    } catch (e) {\n      return handlers.reject(promise, e);\n    }\n    if (returnValue === promise) {\n      handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));\n    } else {\n      handlers.resolve(promise, returnValue);\n    }\n  });\n}\n\nhandlers.resolve = function (self, value) {\n  var result = tryCatch(getThen, value);\n  if (result.status === 'error') {\n    return handlers.reject(self, result.value);\n  }\n  var thenable = result.value;\n\n  if (thenable) {\n    safelyResolveThenable(self, thenable);\n  } else {\n    self.state = FULFILLED;\n    self.outcome = value;\n    var i = -1;\n    var len = self.queue.length;\n    while (++i < len) {\n      self.queue[i].callFulfilled(value);\n    }\n  }\n  return self;\n};\nhandlers.reject = function (self, error) {\n  self.state = REJECTED;\n  self.outcome = error;\n  var i = -1;\n  var len = self.queue.length;\n  while (++i < len) {\n    self.queue[i].callRejected(error);\n  }\n  return self;\n};\n\nfunction getThen(obj) {\n  // Make sure we only access the accessor once as required by the spec\n  var then = obj && obj.then;\n  if (obj && (typeof obj === 'object' || typeof obj === 'function') && typeof then === 'function') {\n    return function appyThen() {\n      then.apply(obj, arguments);\n    };\n  }\n}\n\nfunction safelyResolveThenable(self, thenable) {\n  // Either fulfill, reject or reject with error\n  var called = false;\n  function onError(value) {\n    if (called) {\n      return;\n    }\n    called = true;\n    handlers.reject(self, value);\n  }\n\n  function onSuccess(value) {\n    if (called) {\n      return;\n    }\n    called = true;\n    handlers.resolve(self, value);\n  }\n\n  function tryToUnwrap() {\n    thenable(onSuccess, onError);\n  }\n\n  var result = tryCatch(tryToUnwrap);\n  if (result.status === 'error') {\n    onError(result.value);\n  }\n}\n\nfunction tryCatch(func, value) {\n  var out = {};\n  try {\n    out.value = func(value);\n    out.status = 'success';\n  } catch (e) {\n    out.status = 'error';\n    out.value = e;\n  }\n  return out;\n}\n\nPromise.resolve = resolve;\nfunction resolve(value) {\n  if (value instanceof this) {\n    return value;\n  }\n  return handlers.resolve(new this(INTERNAL), value);\n}\n\nPromise.reject = reject;\nfunction reject(reason) {\n  var promise = new this(INTERNAL);\n  return handlers.reject(promise, reason);\n}\n\nPromise.all = all;\nfunction all(iterable) {\n  var self = this;\n  if (Object.prototype.toString.call(iterable) !== '[object Array]') {\n    return this.reject(new TypeError('must be an array'));\n  }\n\n  var len = iterable.length;\n  var called = false;\n  if (!len) {\n    return this.resolve([]);\n  }\n\n  var values = new Array(len);\n  var resolved = 0;\n  var i = -1;\n  var promise = new this(INTERNAL);\n\n  while (++i < len) {\n    allResolver(iterable[i], i);\n  }\n  return promise;\n  function allResolver(value, i) {\n    self.resolve(value).then(resolveFromAll, function (error) {\n      if (!called) {\n        called = true;\n        handlers.reject(promise, error);\n      }\n    });\n    function resolveFromAll(outValue) {\n      values[i] = outValue;\n      if (++resolved === len && !called) {\n        called = true;\n        handlers.resolve(promise, values);\n      }\n    }\n  }\n}\n\nPromise.race = race;\nfunction race(iterable) {\n  var self = this;\n  if (Object.prototype.toString.call(iterable) !== '[object Array]') {\n    return this.reject(new TypeError('must be an array'));\n  }\n\n  var len = iterable.length;\n  var called = false;\n  if (!len) {\n    return this.resolve([]);\n  }\n\n  var i = -1;\n  var promise = new this(INTERNAL);\n\n  while (++i < len) {\n    resolver(iterable[i]);\n  }\n  return promise;\n  function resolver(value) {\n    self.resolve(value).then(function (response) {\n      if (!called) {\n        called = true;\n        handlers.resolve(promise, response);\n      }\n    }, function (error) {\n      if (!called) {\n        called = true;\n        handlers.reject(promise, error);\n      }\n    });\n  }\n}\n\n},{\"1\":1}],3:[function(_dereq_,module,exports){\n(function (global){\n'use strict';\nif (typeof global.Promise !== 'function') {\n  global.Promise = _dereq_(2);\n}\n\n}).call(this,typeof __webpack_require__.g !== \"undefined\" ? __webpack_require__.g : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"2\":2}],4:[function(_dereq_,module,exports){\n'use strict';\n\nvar _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; };\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction getIDB() {\n    /* global indexedDB,webkitIndexedDB,mozIndexedDB,OIndexedDB,msIndexedDB */\n    try {\n        if (typeof indexedDB !== 'undefined') {\n            return indexedDB;\n        }\n        if (typeof webkitIndexedDB !== 'undefined') {\n            return webkitIndexedDB;\n        }\n        if (typeof mozIndexedDB !== 'undefined') {\n            return mozIndexedDB;\n        }\n        if (typeof OIndexedDB !== 'undefined') {\n            return OIndexedDB;\n        }\n        if (typeof msIndexedDB !== 'undefined') {\n            return msIndexedDB;\n        }\n    } catch (e) {\n        return;\n    }\n}\n\nvar idb = getIDB();\n\nfunction isIndexedDBValid() {\n    try {\n        // Initialize IndexedDB; fall back to vendor-prefixed versions\n        // if needed.\n        if (!idb || !idb.open) {\n            return false;\n        }\n        // We mimic PouchDB here;\n        //\n        // We test for openDatabase because IE Mobile identifies itself\n        // as Safari. Oh the lulz...\n        var isSafari = typeof openDatabase !== 'undefined' && /(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent) && !/BlackBerry/.test(navigator.platform);\n\n        var hasFetch = typeof fetch === 'function' && fetch.toString().indexOf('[native code') !== -1;\n\n        // Safari <10.1 does not meet our requirements for IDB support\n        // (see: https://github.com/pouchdb/pouchdb/issues/5572).\n        // Safari 10.1 shipped with fetch, we can use that to detect it.\n        // Note: this creates issues with `window.fetch` polyfills and\n        // overrides; see:\n        // https://github.com/localForage/localForage/issues/856\n        return (!isSafari || hasFetch) && typeof indexedDB !== 'undefined' &&\n        // some outdated implementations of IDB that appear on Samsung\n        // and HTC Android devices <4.4 are missing IDBKeyRange\n        // See: https://github.com/mozilla/localForage/issues/128\n        // See: https://github.com/mozilla/localForage/issues/272\n        typeof IDBKeyRange !== 'undefined';\n    } catch (e) {\n        return false;\n    }\n}\n\n// Abstracts constructing a Blob object, so it also works in older\n// browsers that don't support the native Blob constructor. (i.e.\n// old QtWebKit versions, at least).\n// Abstracts constructing a Blob object, so it also works in older\n// browsers that don't support the native Blob constructor. (i.e.\n// old QtWebKit versions, at least).\nfunction createBlob(parts, properties) {\n    /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */\n    parts = parts || [];\n    properties = properties || {};\n    try {\n        return new Blob(parts, properties);\n    } catch (e) {\n        if (e.name !== 'TypeError') {\n            throw e;\n        }\n        var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : WebKitBlobBuilder;\n        var builder = new Builder();\n        for (var i = 0; i < parts.length; i += 1) {\n            builder.append(parts[i]);\n        }\n        return builder.getBlob(properties.type);\n    }\n}\n\n// This is CommonJS because lie is an external dependency, so Rollup\n// can just ignore it.\nif (typeof Promise === 'undefined') {\n    // In the \"nopromises\" build this will just throw if you don't have\n    // a global promise object, but it would throw anyway later.\n    _dereq_(3);\n}\nvar Promise$1 = Promise;\n\nfunction executeCallback(promise, callback) {\n    if (callback) {\n        promise.then(function (result) {\n            callback(null, result);\n        }, function (error) {\n            callback(error);\n        });\n    }\n}\n\nfunction executeTwoCallbacks(promise, callback, errorCallback) {\n    if (typeof callback === 'function') {\n        promise.then(callback);\n    }\n\n    if (typeof errorCallback === 'function') {\n        promise[\"catch\"](errorCallback);\n    }\n}\n\nfunction normalizeKey(key) {\n    // Cast the key to a string, as that's all we can set as a key.\n    if (typeof key !== 'string') {\n        console.warn(key + ' used as a key, but it is not a string.');\n        key = String(key);\n    }\n\n    return key;\n}\n\nfunction getCallback() {\n    if (arguments.length && typeof arguments[arguments.length - 1] === 'function') {\n        return arguments[arguments.length - 1];\n    }\n}\n\n// Some code originally from async_storage.js in\n// [Gaia](https://github.com/mozilla-b2g/gaia).\n\nvar DETECT_BLOB_SUPPORT_STORE = 'local-forage-detect-blob-support';\nvar supportsBlobs = void 0;\nvar dbContexts = {};\nvar toString = Object.prototype.toString;\n\n// Transaction Modes\nvar READ_ONLY = 'readonly';\nvar READ_WRITE = 'readwrite';\n\n// Transform a binary string to an array buffer, because otherwise\n// weird stuff happens when you try to work with the binary string directly.\n// It is known.\n// From http://stackoverflow.com/questions/14967647/ (continues on next line)\n// encode-decode-image-with-base64-breaks-image (2013-04-21)\nfunction _binStringToArrayBuffer(bin) {\n    var length = bin.length;\n    var buf = new ArrayBuffer(length);\n    var arr = new Uint8Array(buf);\n    for (var i = 0; i < length; i++) {\n        arr[i] = bin.charCodeAt(i);\n    }\n    return buf;\n}\n\n//\n// Blobs are not supported in all versions of IndexedDB, notably\n// Chrome <37 and Android <5. In those versions, storing a blob will throw.\n//\n// Various other blob bugs exist in Chrome v37-42 (inclusive).\n// Detecting them is expensive and confusing to users, and Chrome 37-42\n// is at very low usage worldwide, so we do a hacky userAgent check instead.\n//\n// content-type bug: https://code.google.com/p/chromium/issues/detail?id=408120\n// 404 bug: https://code.google.com/p/chromium/issues/detail?id=447916\n// FileReader bug: https://code.google.com/p/chromium/issues/detail?id=447836\n//\n// Code borrowed from PouchDB. See:\n// https://github.com/pouchdb/pouchdb/blob/master/packages/node_modules/pouchdb-adapter-idb/src/blobSupport.js\n//\nfunction _checkBlobSupportWithoutCaching(idb) {\n    return new Promise$1(function (resolve) {\n        var txn = idb.transaction(DETECT_BLOB_SUPPORT_STORE, READ_WRITE);\n        var blob = createBlob(['']);\n        txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key');\n\n        txn.onabort = function (e) {\n            // If the transaction aborts now its due to not being able to\n            // write to the database, likely due to the disk being full\n            e.preventDefault();\n            e.stopPropagation();\n            resolve(false);\n        };\n\n        txn.oncomplete = function () {\n            var matchedChrome = navigator.userAgent.match(/Chrome\\/(\\d+)/);\n            var matchedEdge = navigator.userAgent.match(/Edge\\//);\n            // MS Edge pretends to be Chrome 42:\n            // https://msdn.microsoft.com/en-us/library/hh869301%28v=vs.85%29.aspx\n            resolve(matchedEdge || !matchedChrome || parseInt(matchedChrome[1], 10) >= 43);\n        };\n    })[\"catch\"](function () {\n        return false; // error, so assume unsupported\n    });\n}\n\nfunction _checkBlobSupport(idb) {\n    if (typeof supportsBlobs === 'boolean') {\n        return Promise$1.resolve(supportsBlobs);\n    }\n    return _checkBlobSupportWithoutCaching(idb).then(function (value) {\n        supportsBlobs = value;\n        return supportsBlobs;\n    });\n}\n\nfunction _deferReadiness(dbInfo) {\n    var dbContext = dbContexts[dbInfo.name];\n\n    // Create a deferred object representing the current database operation.\n    var deferredOperation = {};\n\n    deferredOperation.promise = new Promise$1(function (resolve, reject) {\n        deferredOperation.resolve = resolve;\n        deferredOperation.reject = reject;\n    });\n\n    // Enqueue the deferred operation.\n    dbContext.deferredOperations.push(deferredOperation);\n\n    // Chain its promise to the database readiness.\n    if (!dbContext.dbReady) {\n        dbContext.dbReady = deferredOperation.promise;\n    } else {\n        dbContext.dbReady = dbContext.dbReady.then(function () {\n            return deferredOperation.promise;\n        });\n    }\n}\n\nfunction _advanceReadiness(dbInfo) {\n    var dbContext = dbContexts[dbInfo.name];\n\n    // Dequeue a deferred operation.\n    var deferredOperation = dbContext.deferredOperations.pop();\n\n    // Resolve its promise (which is part of the database readiness\n    // chain of promises).\n    if (deferredOperation) {\n        deferredOperation.resolve();\n        return deferredOperation.promise;\n    }\n}\n\nfunction _rejectReadiness(dbInfo, err) {\n    var dbContext = dbContexts[dbInfo.name];\n\n    // Dequeue a deferred operation.\n    var deferredOperation = dbContext.deferredOperations.pop();\n\n    // Reject its promise (which is part of the database readiness\n    // chain of promises).\n    if (deferredOperation) {\n        deferredOperation.reject(err);\n        return deferredOperation.promise;\n    }\n}\n\nfunction _getConnection(dbInfo, upgradeNeeded) {\n    return new Promise$1(function (resolve, reject) {\n        dbContexts[dbInfo.name] = dbContexts[dbInfo.name] || createDbContext();\n\n        if (dbInfo.db) {\n            if (upgradeNeeded) {\n                _deferReadiness(dbInfo);\n                dbInfo.db.close();\n            } else {\n                return resolve(dbInfo.db);\n            }\n        }\n\n        var dbArgs = [dbInfo.name];\n\n        if (upgradeNeeded) {\n            dbArgs.push(dbInfo.version);\n        }\n\n        var openreq = idb.open.apply(idb, dbArgs);\n\n        if (upgradeNeeded) {\n            openreq.onupgradeneeded = function (e) {\n                var db = openreq.result;\n                try {\n                    db.createObjectStore(dbInfo.storeName);\n                    if (e.oldVersion <= 1) {\n                        // Added when support for blob shims was added\n                        db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);\n                    }\n                } catch (ex) {\n                    if (ex.name === 'ConstraintError') {\n                        console.warn('The database \"' + dbInfo.name + '\"' + ' has been upgraded from version ' + e.oldVersion + ' to version ' + e.newVersion + ', but the storage \"' + dbInfo.storeName + '\" already exists.');\n                    } else {\n                        throw ex;\n                    }\n                }\n            };\n        }\n\n        openreq.onerror = function (e) {\n            e.preventDefault();\n            reject(openreq.error);\n        };\n\n        openreq.onsuccess = function () {\n            var db = openreq.result;\n            db.onversionchange = function (e) {\n                // Triggered when the database is modified (e.g. adding an objectStore) or\n                // deleted (even when initiated by other sessions in different tabs).\n                // Closing the connection here prevents those operations from being blocked.\n                // If the database is accessed again later by this instance, the connection\n                // will be reopened or the database recreated as needed.\n                e.target.close();\n            };\n            resolve(db);\n            _advanceReadiness(dbInfo);\n        };\n    });\n}\n\nfunction _getOriginalConnection(dbInfo) {\n    return _getConnection(dbInfo, false);\n}\n\nfunction _getUpgradedConnection(dbInfo) {\n    return _getConnection(dbInfo, true);\n}\n\nfunction _isUpgradeNeeded(dbInfo, defaultVersion) {\n    if (!dbInfo.db) {\n        return true;\n    }\n\n    var isNewStore = !dbInfo.db.objectStoreNames.contains(dbInfo.storeName);\n    var isDowngrade = dbInfo.version < dbInfo.db.version;\n    var isUpgrade = dbInfo.version > dbInfo.db.version;\n\n    if (isDowngrade) {\n        // If the version is not the default one\n        // then warn for impossible downgrade.\n        if (dbInfo.version !== defaultVersion) {\n            console.warn('The database \"' + dbInfo.name + '\"' + \" can't be downgraded from version \" + dbInfo.db.version + ' to version ' + dbInfo.version + '.');\n        }\n        // Align the versions to prevent errors.\n        dbInfo.version = dbInfo.db.version;\n    }\n\n    if (isUpgrade || isNewStore) {\n        // If the store is new then increment the version (if needed).\n        // This will trigger an \"upgradeneeded\" event which is required\n        // for creating a store.\n        if (isNewStore) {\n            var incVersion = dbInfo.db.version + 1;\n            if (incVersion > dbInfo.version) {\n                dbInfo.version = incVersion;\n            }\n        }\n\n        return true;\n    }\n\n    return false;\n}\n\n// encode a blob for indexeddb engines that don't support blobs\nfunction _encodeBlob(blob) {\n    return new Promise$1(function (resolve, reject) {\n        var reader = new FileReader();\n        reader.onerror = reject;\n        reader.onloadend = function (e) {\n            var base64 = btoa(e.target.result || '');\n            resolve({\n                __local_forage_encoded_blob: true,\n                data: base64,\n                type: blob.type\n            });\n        };\n        reader.readAsBinaryString(blob);\n    });\n}\n\n// decode an encoded blob\nfunction _decodeBlob(encodedBlob) {\n    var arrayBuff = _binStringToArrayBuffer(atob(encodedBlob.data));\n    return createBlob([arrayBuff], { type: encodedBlob.type });\n}\n\n// is this one of our fancy encoded blobs?\nfunction _isEncodedBlob(value) {\n    return value && value.__local_forage_encoded_blob;\n}\n\n// Specialize the default `ready()` function by making it dependent\n// on the current database operations. Thus, the driver will be actually\n// ready when it's been initialized (default) *and* there are no pending\n// operations on the database (initiated by some other instances).\nfunction _fullyReady(callback) {\n    var self = this;\n\n    var promise = self._initReady().then(function () {\n        var dbContext = dbContexts[self._dbInfo.name];\n\n        if (dbContext && dbContext.dbReady) {\n            return dbContext.dbReady;\n        }\n    });\n\n    executeTwoCallbacks(promise, callback, callback);\n    return promise;\n}\n\n// Try to establish a new db connection to replace the\n// current one which is broken (i.e. experiencing\n// InvalidStateError while creating a transaction).\nfunction _tryReconnect(dbInfo) {\n    _deferReadiness(dbInfo);\n\n    var dbContext = dbContexts[dbInfo.name];\n    var forages = dbContext.forages;\n\n    for (var i = 0; i < forages.length; i++) {\n        var forage = forages[i];\n        if (forage._dbInfo.db) {\n            forage._dbInfo.db.close();\n            forage._dbInfo.db = null;\n        }\n    }\n    dbInfo.db = null;\n\n    return _getOriginalConnection(dbInfo).then(function (db) {\n        dbInfo.db = db;\n        if (_isUpgradeNeeded(dbInfo)) {\n            // Reopen the database for upgrading.\n            return _getUpgradedConnection(dbInfo);\n        }\n        return db;\n    }).then(function (db) {\n        // store the latest db reference\n        // in case the db was upgraded\n        dbInfo.db = dbContext.db = db;\n        for (var i = 0; i < forages.length; i++) {\n            forages[i]._dbInfo.db = db;\n        }\n    })[\"catch\"](function (err) {\n        _rejectReadiness(dbInfo, err);\n        throw err;\n    });\n}\n\n// FF doesn't like Promises (micro-tasks) and IDDB store operations,\n// so we have to do it with callbacks\nfunction createTransaction(dbInfo, mode, callback, retries) {\n    if (retries === undefined) {\n        retries = 1;\n    }\n\n    try {\n        var tx = dbInfo.db.transaction(dbInfo.storeName, mode);\n        callback(null, tx);\n    } catch (err) {\n        if (retries > 0 && (!dbInfo.db || err.name === 'InvalidStateError' || err.name === 'NotFoundError')) {\n            return Promise$1.resolve().then(function () {\n                if (!dbInfo.db || err.name === 'NotFoundError' && !dbInfo.db.objectStoreNames.contains(dbInfo.storeName) && dbInfo.version <= dbInfo.db.version) {\n                    // increase the db version, to create the new ObjectStore\n                    if (dbInfo.db) {\n                        dbInfo.version = dbInfo.db.version + 1;\n                    }\n                    // Reopen the database for upgrading.\n                    return _getUpgradedConnection(dbInfo);\n                }\n            }).then(function () {\n                return _tryReconnect(dbInfo).then(function () {\n                    createTransaction(dbInfo, mode, callback, retries - 1);\n                });\n            })[\"catch\"](callback);\n        }\n\n        callback(err);\n    }\n}\n\nfunction createDbContext() {\n    return {\n        // Running localForages sharing a database.\n        forages: [],\n        // Shared database.\n        db: null,\n        // Database readiness (promise).\n        dbReady: null,\n        // Deferred operations on the database.\n        deferredOperations: []\n    };\n}\n\n// Open the IndexedDB database (automatically creates one if one didn't\n// previously exist), using any options set in the config.\nfunction _initStorage(options) {\n    var self = this;\n    var dbInfo = {\n        db: null\n    };\n\n    if (options) {\n        for (var i in options) {\n            dbInfo[i] = options[i];\n        }\n    }\n\n    // Get the current context of the database;\n    var dbContext = dbContexts[dbInfo.name];\n\n    // ...or create a new context.\n    if (!dbContext) {\n        dbContext = createDbContext();\n        // Register the new context in the global container.\n        dbContexts[dbInfo.name] = dbContext;\n    }\n\n    // Register itself as a running localForage in the current context.\n    dbContext.forages.push(self);\n\n    // Replace the default `ready()` function with the specialized one.\n    if (!self._initReady) {\n        self._initReady = self.ready;\n        self.ready = _fullyReady;\n    }\n\n    // Create an array of initialization states of the related localForages.\n    var initPromises = [];\n\n    function ignoreErrors() {\n        // Don't handle errors here,\n        // just makes sure related localForages aren't pending.\n        return Promise$1.resolve();\n    }\n\n    for (var j = 0; j < dbContext.forages.length; j++) {\n        var forage = dbContext.forages[j];\n        if (forage !== self) {\n            // Don't wait for itself...\n            initPromises.push(forage._initReady()[\"catch\"](ignoreErrors));\n        }\n    }\n\n    // Take a snapshot of the related localForages.\n    var forages = dbContext.forages.slice(0);\n\n    // Initialize the connection process only when\n    // all the related localForages aren't pending.\n    return Promise$1.all(initPromises).then(function () {\n        dbInfo.db = dbContext.db;\n        // Get the connection or open a new one without upgrade.\n        return _getOriginalConnection(dbInfo);\n    }).then(function (db) {\n        dbInfo.db = db;\n        if (_isUpgradeNeeded(dbInfo, self._defaultConfig.version)) {\n            // Reopen the database for upgrading.\n            return _getUpgradedConnection(dbInfo);\n        }\n        return db;\n    }).then(function (db) {\n        dbInfo.db = dbContext.db = db;\n        self._dbInfo = dbInfo;\n        // Share the final connection amongst related localForages.\n        for (var k = 0; k < forages.length; k++) {\n            var forage = forages[k];\n            if (forage !== self) {\n                // Self is already up-to-date.\n                forage._dbInfo.db = dbInfo.db;\n                forage._dbInfo.version = dbInfo.version;\n            }\n        }\n    });\n}\n\nfunction getItem(key, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n                    var req = store.get(key);\n\n                    req.onsuccess = function () {\n                        var value = req.result;\n                        if (value === undefined) {\n                            value = null;\n                        }\n                        if (_isEncodedBlob(value)) {\n                            value = _decodeBlob(value);\n                        }\n                        resolve(value);\n                    };\n\n                    req.onerror = function () {\n                        reject(req.error);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Iterate over all items stored in database.\nfunction iterate(iterator, callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n                    var req = store.openCursor();\n                    var iterationNumber = 1;\n\n                    req.onsuccess = function () {\n                        var cursor = req.result;\n\n                        if (cursor) {\n                            var value = cursor.value;\n                            if (_isEncodedBlob(value)) {\n                                value = _decodeBlob(value);\n                            }\n                            var result = iterator(value, cursor.key, iterationNumber++);\n\n                            // when the iterator callback returns any\n                            // (non-`undefined`) value, then we stop\n                            // the iteration immediately\n                            if (result !== void 0) {\n                                resolve(result);\n                            } else {\n                                cursor[\"continue\"]();\n                            }\n                        } else {\n                            resolve();\n                        }\n                    };\n\n                    req.onerror = function () {\n                        reject(req.error);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n\n    return promise;\n}\n\nfunction setItem(key, value, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = new Promise$1(function (resolve, reject) {\n        var dbInfo;\n        self.ready().then(function () {\n            dbInfo = self._dbInfo;\n            if (toString.call(value) === '[object Blob]') {\n                return _checkBlobSupport(dbInfo.db).then(function (blobSupport) {\n                    if (blobSupport) {\n                        return value;\n                    }\n                    return _encodeBlob(value);\n                });\n            }\n            return value;\n        }).then(function (value) {\n            createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n\n                    // The reason we don't _save_ null is because IE 10 does\n                    // not support saving the `null` type in IndexedDB. How\n                    // ironic, given the bug below!\n                    // See: https://github.com/mozilla/localForage/issues/161\n                    if (value === null) {\n                        value = undefined;\n                    }\n\n                    var req = store.put(value, key);\n\n                    transaction.oncomplete = function () {\n                        // Cast to undefined so the value passed to\n                        // callback/promise is the same as what one would get out\n                        // of `getItem()` later. This leads to some weirdness\n                        // (setItem('foo', undefined) will return `null`), but\n                        // it's not my fault localStorage is our baseline and that\n                        // it's weird.\n                        if (value === undefined) {\n                            value = null;\n                        }\n\n                        resolve(value);\n                    };\n                    transaction.onabort = transaction.onerror = function () {\n                        var err = req.error ? req.error : req.transaction.error;\n                        reject(err);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction removeItem(key, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n                    // We use a Grunt task to make this safe for IE and some\n                    // versions of Android (including those used by Cordova).\n                    // Normally IE won't like `.delete()` and will insist on\n                    // using `['delete']()`, but we have a build step that\n                    // fixes this for us now.\n                    var req = store[\"delete\"](key);\n                    transaction.oncomplete = function () {\n                        resolve();\n                    };\n\n                    transaction.onerror = function () {\n                        reject(req.error);\n                    };\n\n                    // The request will be also be aborted if we've exceeded our storage\n                    // space.\n                    transaction.onabort = function () {\n                        var err = req.error ? req.error : req.transaction.error;\n                        reject(err);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction clear(callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n                    var req = store.clear();\n\n                    transaction.oncomplete = function () {\n                        resolve();\n                    };\n\n                    transaction.onabort = transaction.onerror = function () {\n                        var err = req.error ? req.error : req.transaction.error;\n                        reject(err);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction length(callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n                    var req = store.count();\n\n                    req.onsuccess = function () {\n                        resolve(req.result);\n                    };\n\n                    req.onerror = function () {\n                        reject(req.error);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction key(n, callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        if (n < 0) {\n            resolve(null);\n\n            return;\n        }\n\n        self.ready().then(function () {\n            createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n                    var advanced = false;\n                    var req = store.openKeyCursor();\n\n                    req.onsuccess = function () {\n                        var cursor = req.result;\n                        if (!cursor) {\n                            // this means there weren't enough keys\n                            resolve(null);\n\n                            return;\n                        }\n\n                        if (n === 0) {\n                            // We have the first key, return it if that's what they\n                            // wanted.\n                            resolve(cursor.key);\n                        } else {\n                            if (!advanced) {\n                                // Otherwise, ask the cursor to skip ahead n\n                                // records.\n                                advanced = true;\n                                cursor.advance(n);\n                            } else {\n                                // When we get here, we've got the nth key.\n                                resolve(cursor.key);\n                            }\n                        }\n                    };\n\n                    req.onerror = function () {\n                        reject(req.error);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction keys(callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n                if (err) {\n                    return reject(err);\n                }\n\n                try {\n                    var store = transaction.objectStore(self._dbInfo.storeName);\n                    var req = store.openKeyCursor();\n                    var keys = [];\n\n                    req.onsuccess = function () {\n                        var cursor = req.result;\n\n                        if (!cursor) {\n                            resolve(keys);\n                            return;\n                        }\n\n                        keys.push(cursor.key);\n                        cursor[\"continue\"]();\n                    };\n\n                    req.onerror = function () {\n                        reject(req.error);\n                    };\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction dropInstance(options, callback) {\n    callback = getCallback.apply(this, arguments);\n\n    var currentConfig = this.config();\n    options = typeof options !== 'function' && options || {};\n    if (!options.name) {\n        options.name = options.name || currentConfig.name;\n        options.storeName = options.storeName || currentConfig.storeName;\n    }\n\n    var self = this;\n    var promise;\n    if (!options.name) {\n        promise = Promise$1.reject('Invalid arguments');\n    } else {\n        var isCurrentDb = options.name === currentConfig.name && self._dbInfo.db;\n\n        var dbPromise = isCurrentDb ? Promise$1.resolve(self._dbInfo.db) : _getOriginalConnection(options).then(function (db) {\n            var dbContext = dbContexts[options.name];\n            var forages = dbContext.forages;\n            dbContext.db = db;\n            for (var i = 0; i < forages.length; i++) {\n                forages[i]._dbInfo.db = db;\n            }\n            return db;\n        });\n\n        if (!options.storeName) {\n            promise = dbPromise.then(function (db) {\n                _deferReadiness(options);\n\n                var dbContext = dbContexts[options.name];\n                var forages = dbContext.forages;\n\n                db.close();\n                for (var i = 0; i < forages.length; i++) {\n                    var forage = forages[i];\n                    forage._dbInfo.db = null;\n                }\n\n                var dropDBPromise = new Promise$1(function (resolve, reject) {\n                    var req = idb.deleteDatabase(options.name);\n\n                    req.onerror = function () {\n                        var db = req.result;\n                        if (db) {\n                            db.close();\n                        }\n                        reject(req.error);\n                    };\n\n                    req.onblocked = function () {\n                        // Closing all open connections in onversionchange handler should prevent this situation, but if\n                        // we do get here, it just means the request remains pending - eventually it will succeed or error\n                        console.warn('dropInstance blocked for database \"' + options.name + '\" until all open connections are closed');\n                    };\n\n                    req.onsuccess = function () {\n                        var db = req.result;\n                        if (db) {\n                            db.close();\n                        }\n                        resolve(db);\n                    };\n                });\n\n                return dropDBPromise.then(function (db) {\n                    dbContext.db = db;\n                    for (var i = 0; i < forages.length; i++) {\n                        var _forage = forages[i];\n                        _advanceReadiness(_forage._dbInfo);\n                    }\n                })[\"catch\"](function (err) {\n                    (_rejectReadiness(options, err) || Promise$1.resolve())[\"catch\"](function () {});\n                    throw err;\n                });\n            });\n        } else {\n            promise = dbPromise.then(function (db) {\n                if (!db.objectStoreNames.contains(options.storeName)) {\n                    return;\n                }\n\n                var newVersion = db.version + 1;\n\n                _deferReadiness(options);\n\n                var dbContext = dbContexts[options.name];\n                var forages = dbContext.forages;\n\n                db.close();\n                for (var i = 0; i < forages.length; i++) {\n                    var forage = forages[i];\n                    forage._dbInfo.db = null;\n                    forage._dbInfo.version = newVersion;\n                }\n\n                var dropObjectPromise = new Promise$1(function (resolve, reject) {\n                    var req = idb.open(options.name, newVersion);\n\n                    req.onerror = function (err) {\n                        var db = req.result;\n                        db.close();\n                        reject(err);\n                    };\n\n                    req.onupgradeneeded = function () {\n                        var db = req.result;\n                        db.deleteObjectStore(options.storeName);\n                    };\n\n                    req.onsuccess = function () {\n                        var db = req.result;\n                        db.close();\n                        resolve(db);\n                    };\n                });\n\n                return dropObjectPromise.then(function (db) {\n                    dbContext.db = db;\n                    for (var j = 0; j < forages.length; j++) {\n                        var _forage2 = forages[j];\n                        _forage2._dbInfo.db = db;\n                        _advanceReadiness(_forage2._dbInfo);\n                    }\n                })[\"catch\"](function (err) {\n                    (_rejectReadiness(options, err) || Promise$1.resolve())[\"catch\"](function () {});\n                    throw err;\n                });\n            });\n        }\n    }\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nvar asyncStorage = {\n    _driver: 'asyncStorage',\n    _initStorage: _initStorage,\n    _support: isIndexedDBValid(),\n    iterate: iterate,\n    getItem: getItem,\n    setItem: setItem,\n    removeItem: removeItem,\n    clear: clear,\n    length: length,\n    key: key,\n    keys: keys,\n    dropInstance: dropInstance\n};\n\nfunction isWebSQLValid() {\n    return typeof openDatabase === 'function';\n}\n\n// Sadly, the best way to save binary data in WebSQL/localStorage is serializing\n// it to Base64, so this is how we store it to prevent very strange errors with less\n// verbose ways of binary <-> string data storage.\nvar BASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nvar BLOB_TYPE_PREFIX = '~~local_forage_type~';\nvar BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;\n\nvar SERIALIZED_MARKER = '__lfsc__:';\nvar SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;\n\n// OMG the serializations!\nvar TYPE_ARRAYBUFFER = 'arbf';\nvar TYPE_BLOB = 'blob';\nvar TYPE_INT8ARRAY = 'si08';\nvar TYPE_UINT8ARRAY = 'ui08';\nvar TYPE_UINT8CLAMPEDARRAY = 'uic8';\nvar TYPE_INT16ARRAY = 'si16';\nvar TYPE_INT32ARRAY = 'si32';\nvar TYPE_UINT16ARRAY = 'ur16';\nvar TYPE_UINT32ARRAY = 'ui32';\nvar TYPE_FLOAT32ARRAY = 'fl32';\nvar TYPE_FLOAT64ARRAY = 'fl64';\nvar TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;\n\nvar toString$1 = Object.prototype.toString;\n\nfunction stringToBuffer(serializedString) {\n    // Fill the string into a ArrayBuffer.\n    var bufferLength = serializedString.length * 0.75;\n    var len = serializedString.length;\n    var i;\n    var p = 0;\n    var encoded1, encoded2, encoded3, encoded4;\n\n    if (serializedString[serializedString.length - 1] === '=') {\n        bufferLength--;\n        if (serializedString[serializedString.length - 2] === '=') {\n            bufferLength--;\n        }\n    }\n\n    var buffer = new ArrayBuffer(bufferLength);\n    var bytes = new Uint8Array(buffer);\n\n    for (i = 0; i < len; i += 4) {\n        encoded1 = BASE_CHARS.indexOf(serializedString[i]);\n        encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);\n        encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);\n        encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);\n\n        /*jslint bitwise: true */\n        bytes[p++] = encoded1 << 2 | encoded2 >> 4;\n        bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\n        bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\n    }\n    return buffer;\n}\n\n// Converts a buffer to a string to store, serialized, in the backend\n// storage library.\nfunction bufferToString(buffer) {\n    // base64-arraybuffer\n    var bytes = new Uint8Array(buffer);\n    var base64String = '';\n    var i;\n\n    for (i = 0; i < bytes.length; i += 3) {\n        /*jslint bitwise: true */\n        base64String += BASE_CHARS[bytes[i] >> 2];\n        base64String += BASE_CHARS[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];\n        base64String += BASE_CHARS[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];\n        base64String += BASE_CHARS[bytes[i + 2] & 63];\n    }\n\n    if (bytes.length % 3 === 2) {\n        base64String = base64String.substring(0, base64String.length - 1) + '=';\n    } else if (bytes.length % 3 === 1) {\n        base64String = base64String.substring(0, base64String.length - 2) + '==';\n    }\n\n    return base64String;\n}\n\n// Serialize a value, afterwards executing a callback (which usually\n// instructs the `setItem()` callback/promise to be executed). This is how\n// we store binary data with localStorage.\nfunction serialize(value, callback) {\n    var valueType = '';\n    if (value) {\n        valueType = toString$1.call(value);\n    }\n\n    // Cannot use `value instanceof ArrayBuffer` or such here, as these\n    // checks fail when running the tests using casper.js...\n    //\n    // TODO: See why those tests fail and use a better solution.\n    if (value && (valueType === '[object ArrayBuffer]' || value.buffer && toString$1.call(value.buffer) === '[object ArrayBuffer]')) {\n        // Convert binary arrays to a string and prefix the string with\n        // a special marker.\n        var buffer;\n        var marker = SERIALIZED_MARKER;\n\n        if (value instanceof ArrayBuffer) {\n            buffer = value;\n            marker += TYPE_ARRAYBUFFER;\n        } else {\n            buffer = value.buffer;\n\n            if (valueType === '[object Int8Array]') {\n                marker += TYPE_INT8ARRAY;\n            } else if (valueType === '[object Uint8Array]') {\n                marker += TYPE_UINT8ARRAY;\n            } else if (valueType === '[object Uint8ClampedArray]') {\n                marker += TYPE_UINT8CLAMPEDARRAY;\n            } else if (valueType === '[object Int16Array]') {\n                marker += TYPE_INT16ARRAY;\n            } else if (valueType === '[object Uint16Array]') {\n                marker += TYPE_UINT16ARRAY;\n            } else if (valueType === '[object Int32Array]') {\n                marker += TYPE_INT32ARRAY;\n            } else if (valueType === '[object Uint32Array]') {\n                marker += TYPE_UINT32ARRAY;\n            } else if (valueType === '[object Float32Array]') {\n                marker += TYPE_FLOAT32ARRAY;\n            } else if (valueType === '[object Float64Array]') {\n                marker += TYPE_FLOAT64ARRAY;\n            } else {\n                callback(new Error('Failed to get type for BinaryArray'));\n            }\n        }\n\n        callback(marker + bufferToString(buffer));\n    } else if (valueType === '[object Blob]') {\n        // Conver the blob to a binaryArray and then to a string.\n        var fileReader = new FileReader();\n\n        fileReader.onload = function () {\n            // Backwards-compatible prefix for the blob type.\n            var str = BLOB_TYPE_PREFIX + value.type + '~' + bufferToString(this.result);\n\n            callback(SERIALIZED_MARKER + TYPE_BLOB + str);\n        };\n\n        fileReader.readAsArrayBuffer(value);\n    } else {\n        try {\n            callback(JSON.stringify(value));\n        } catch (e) {\n            console.error(\"Couldn't convert value into a JSON string: \", value);\n\n            callback(null, e);\n        }\n    }\n}\n\n// Deserialize data we've inserted into a value column/field. We place\n// special markers into our strings to mark them as encoded; this isn't\n// as nice as a meta field, but it's the only sane thing we can do whilst\n// keeping localStorage support intact.\n//\n// Oftentimes this will just deserialize JSON content, but if we have a\n// special marker (SERIALIZED_MARKER, defined above), we will extract\n// some kind of arraybuffer/binary data/typed array out of the string.\nfunction deserialize(value) {\n    // If we haven't marked this string as being specially serialized (i.e.\n    // something other than serialized JSON), we can just return it and be\n    // done with it.\n    if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {\n        return JSON.parse(value);\n    }\n\n    // The following code deals with deserializing some kind of Blob or\n    // TypedArray. First we separate out the type of data we're dealing\n    // with from the data itself.\n    var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);\n    var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);\n\n    var blobType;\n    // Backwards-compatible blob type serialization strategy.\n    // DBs created with older versions of localForage will simply not have the blob type.\n    if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {\n        var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);\n        blobType = matcher[1];\n        serializedString = serializedString.substring(matcher[0].length);\n    }\n    var buffer = stringToBuffer(serializedString);\n\n    // Return the right type based on the code/type set during\n    // serialization.\n    switch (type) {\n        case TYPE_ARRAYBUFFER:\n            return buffer;\n        case TYPE_BLOB:\n            return createBlob([buffer], { type: blobType });\n        case TYPE_INT8ARRAY:\n            return new Int8Array(buffer);\n        case TYPE_UINT8ARRAY:\n            return new Uint8Array(buffer);\n        case TYPE_UINT8CLAMPEDARRAY:\n            return new Uint8ClampedArray(buffer);\n        case TYPE_INT16ARRAY:\n            return new Int16Array(buffer);\n        case TYPE_UINT16ARRAY:\n            return new Uint16Array(buffer);\n        case TYPE_INT32ARRAY:\n            return new Int32Array(buffer);\n        case TYPE_UINT32ARRAY:\n            return new Uint32Array(buffer);\n        case TYPE_FLOAT32ARRAY:\n            return new Float32Array(buffer);\n        case TYPE_FLOAT64ARRAY:\n            return new Float64Array(buffer);\n        default:\n            throw new Error('Unkown type: ' + type);\n    }\n}\n\nvar localforageSerializer = {\n    serialize: serialize,\n    deserialize: deserialize,\n    stringToBuffer: stringToBuffer,\n    bufferToString: bufferToString\n};\n\n/*\n * Includes code from:\n *\n * base64-arraybuffer\n * https://github.com/niklasvh/base64-arraybuffer\n *\n * Copyright (c) 2012 Niklas von Hertzen\n * Licensed under the MIT license.\n */\n\nfunction createDbTable(t, dbInfo, callback, errorCallback) {\n    t.executeSql('CREATE TABLE IF NOT EXISTS ' + dbInfo.storeName + ' ' + '(id INTEGER PRIMARY KEY, key unique, value)', [], callback, errorCallback);\n}\n\n// Open the WebSQL database (automatically creates one if one didn't\n// previously exist), using any options set in the config.\nfunction _initStorage$1(options) {\n    var self = this;\n    var dbInfo = {\n        db: null\n    };\n\n    if (options) {\n        for (var i in options) {\n            dbInfo[i] = typeof options[i] !== 'string' ? options[i].toString() : options[i];\n        }\n    }\n\n    var dbInfoPromise = new Promise$1(function (resolve, reject) {\n        // Open the database; the openDatabase API will automatically\n        // create it for us if it doesn't exist.\n        try {\n            dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), dbInfo.description, dbInfo.size);\n        } catch (e) {\n            return reject(e);\n        }\n\n        // Create our key/value table if it doesn't exist.\n        dbInfo.db.transaction(function (t) {\n            createDbTable(t, dbInfo, function () {\n                self._dbInfo = dbInfo;\n                resolve();\n            }, function (t, error) {\n                reject(error);\n            });\n        }, reject);\n    });\n\n    dbInfo.serializer = localforageSerializer;\n    return dbInfoPromise;\n}\n\nfunction tryExecuteSql(t, dbInfo, sqlStatement, args, callback, errorCallback) {\n    t.executeSql(sqlStatement, args, callback, function (t, error) {\n        if (error.code === error.SYNTAX_ERR) {\n            t.executeSql('SELECT name FROM sqlite_master ' + \"WHERE type='table' AND name = ?\", [dbInfo.storeName], function (t, results) {\n                if (!results.rows.length) {\n                    // if the table is missing (was deleted)\n                    // re-create it table and retry\n                    createDbTable(t, dbInfo, function () {\n                        t.executeSql(sqlStatement, args, callback, errorCallback);\n                    }, errorCallback);\n                } else {\n                    errorCallback(t, error);\n                }\n            }, errorCallback);\n        } else {\n            errorCallback(t, error);\n        }\n    }, errorCallback);\n}\n\nfunction getItem$1(key, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            var dbInfo = self._dbInfo;\n            dbInfo.db.transaction(function (t) {\n                tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName + ' WHERE key = ? LIMIT 1', [key], function (t, results) {\n                    var result = results.rows.length ? results.rows.item(0).value : null;\n\n                    // Check to see if this is serialized content we need to\n                    // unpack.\n                    if (result) {\n                        result = dbInfo.serializer.deserialize(result);\n                    }\n\n                    resolve(result);\n                }, function (t, error) {\n                    reject(error);\n                });\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction iterate$1(iterator, callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            var dbInfo = self._dbInfo;\n\n            dbInfo.db.transaction(function (t) {\n                tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName, [], function (t, results) {\n                    var rows = results.rows;\n                    var length = rows.length;\n\n                    for (var i = 0; i < length; i++) {\n                        var item = rows.item(i);\n                        var result = item.value;\n\n                        // Check to see if this is serialized content\n                        // we need to unpack.\n                        if (result) {\n                            result = dbInfo.serializer.deserialize(result);\n                        }\n\n                        result = iterator(result, item.key, i + 1);\n\n                        // void(0) prevents problems with redefinition\n                        // of `undefined`.\n                        if (result !== void 0) {\n                            resolve(result);\n                            return;\n                        }\n                    }\n\n                    resolve();\n                }, function (t, error) {\n                    reject(error);\n                });\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction _setItem(key, value, callback, retriesLeft) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            // The localStorage API doesn't return undefined values in an\n            // \"expected\" way, so undefined is always cast to null in all\n            // drivers. See: https://github.com/mozilla/localForage/pull/42\n            if (value === undefined) {\n                value = null;\n            }\n\n            // Save the original value to pass to the callback.\n            var originalValue = value;\n\n            var dbInfo = self._dbInfo;\n            dbInfo.serializer.serialize(value, function (value, error) {\n                if (error) {\n                    reject(error);\n                } else {\n                    dbInfo.db.transaction(function (t) {\n                        tryExecuteSql(t, dbInfo, 'INSERT OR REPLACE INTO ' + dbInfo.storeName + ' ' + '(key, value) VALUES (?, ?)', [key, value], function () {\n                            resolve(originalValue);\n                        }, function (t, error) {\n                            reject(error);\n                        });\n                    }, function (sqlError) {\n                        // The transaction failed; check\n                        // to see if it's a quota error.\n                        if (sqlError.code === sqlError.QUOTA_ERR) {\n                            // We reject the callback outright for now, but\n                            // it's worth trying to re-run the transaction.\n                            // Even if the user accepts the prompt to use\n                            // more storage on Safari, this error will\n                            // be called.\n                            //\n                            // Try to re-run the transaction.\n                            if (retriesLeft > 0) {\n                                resolve(_setItem.apply(self, [key, originalValue, callback, retriesLeft - 1]));\n                                return;\n                            }\n                            reject(sqlError);\n                        }\n                    });\n                }\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction setItem$1(key, value, callback) {\n    return _setItem.apply(this, [key, value, callback, 1]);\n}\n\nfunction removeItem$1(key, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            var dbInfo = self._dbInfo;\n            dbInfo.db.transaction(function (t) {\n                tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName + ' WHERE key = ?', [key], function () {\n                    resolve();\n                }, function (t, error) {\n                    reject(error);\n                });\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Deletes every item in the table.\n// TODO: Find out if this resets the AUTO_INCREMENT number.\nfunction clear$1(callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            var dbInfo = self._dbInfo;\n            dbInfo.db.transaction(function (t) {\n                tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName, [], function () {\n                    resolve();\n                }, function (t, error) {\n                    reject(error);\n                });\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Does a simple `COUNT(key)` to get the number of items stored in\n// localForage.\nfunction length$1(callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            var dbInfo = self._dbInfo;\n            dbInfo.db.transaction(function (t) {\n                // Ahhh, SQL makes this one soooooo easy.\n                tryExecuteSql(t, dbInfo, 'SELECT COUNT(key) as c FROM ' + dbInfo.storeName, [], function (t, results) {\n                    var result = results.rows.item(0).c;\n                    resolve(result);\n                }, function (t, error) {\n                    reject(error);\n                });\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Return the key located at key index X; essentially gets the key from a\n// `WHERE id = ?`. This is the most efficient way I can think to implement\n// this rarely-used (in my experience) part of the API, but it can seem\n// inconsistent, because we do `INSERT OR REPLACE INTO` on `setItem()`, so\n// the ID of each key will change every time it's updated. Perhaps a stored\n// procedure for the `setItem()` SQL would solve this problem?\n// TODO: Don't change ID on `setItem()`.\nfunction key$1(n, callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            var dbInfo = self._dbInfo;\n            dbInfo.db.transaction(function (t) {\n                tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName + ' WHERE id = ? LIMIT 1', [n + 1], function (t, results) {\n                    var result = results.rows.length ? results.rows.item(0).key : null;\n                    resolve(result);\n                }, function (t, error) {\n                    reject(error);\n                });\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction keys$1(callback) {\n    var self = this;\n\n    var promise = new Promise$1(function (resolve, reject) {\n        self.ready().then(function () {\n            var dbInfo = self._dbInfo;\n            dbInfo.db.transaction(function (t) {\n                tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName, [], function (t, results) {\n                    var keys = [];\n\n                    for (var i = 0; i < results.rows.length; i++) {\n                        keys.push(results.rows.item(i).key);\n                    }\n\n                    resolve(keys);\n                }, function (t, error) {\n                    reject(error);\n                });\n            });\n        })[\"catch\"](reject);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// https://www.w3.org/TR/webdatabase/#databases\n// > There is no way to enumerate or delete the databases available for an origin from this API.\nfunction getAllStoreNames(db) {\n    return new Promise$1(function (resolve, reject) {\n        db.transaction(function (t) {\n            t.executeSql('SELECT name FROM sqlite_master ' + \"WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'\", [], function (t, results) {\n                var storeNames = [];\n\n                for (var i = 0; i < results.rows.length; i++) {\n                    storeNames.push(results.rows.item(i).name);\n                }\n\n                resolve({\n                    db: db,\n                    storeNames: storeNames\n                });\n            }, function (t, error) {\n                reject(error);\n            });\n        }, function (sqlError) {\n            reject(sqlError);\n        });\n    });\n}\n\nfunction dropInstance$1(options, callback) {\n    callback = getCallback.apply(this, arguments);\n\n    var currentConfig = this.config();\n    options = typeof options !== 'function' && options || {};\n    if (!options.name) {\n        options.name = options.name || currentConfig.name;\n        options.storeName = options.storeName || currentConfig.storeName;\n    }\n\n    var self = this;\n    var promise;\n    if (!options.name) {\n        promise = Promise$1.reject('Invalid arguments');\n    } else {\n        promise = new Promise$1(function (resolve) {\n            var db;\n            if (options.name === currentConfig.name) {\n                // use the db reference of the current instance\n                db = self._dbInfo.db;\n            } else {\n                db = openDatabase(options.name, '', '', 0);\n            }\n\n            if (!options.storeName) {\n                // drop all database tables\n                resolve(getAllStoreNames(db));\n            } else {\n                resolve({\n                    db: db,\n                    storeNames: [options.storeName]\n                });\n            }\n        }).then(function (operationInfo) {\n            return new Promise$1(function (resolve, reject) {\n                operationInfo.db.transaction(function (t) {\n                    function dropTable(storeName) {\n                        return new Promise$1(function (resolve, reject) {\n                            t.executeSql('DROP TABLE IF EXISTS ' + storeName, [], function () {\n                                resolve();\n                            }, function (t, error) {\n                                reject(error);\n                            });\n                        });\n                    }\n\n                    var operations = [];\n                    for (var i = 0, len = operationInfo.storeNames.length; i < len; i++) {\n                        operations.push(dropTable(operationInfo.storeNames[i]));\n                    }\n\n                    Promise$1.all(operations).then(function () {\n                        resolve();\n                    })[\"catch\"](function (e) {\n                        reject(e);\n                    });\n                }, function (sqlError) {\n                    reject(sqlError);\n                });\n            });\n        });\n    }\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nvar webSQLStorage = {\n    _driver: 'webSQLStorage',\n    _initStorage: _initStorage$1,\n    _support: isWebSQLValid(),\n    iterate: iterate$1,\n    getItem: getItem$1,\n    setItem: setItem$1,\n    removeItem: removeItem$1,\n    clear: clear$1,\n    length: length$1,\n    key: key$1,\n    keys: keys$1,\n    dropInstance: dropInstance$1\n};\n\nfunction isLocalStorageValid() {\n    try {\n        return typeof localStorage !== 'undefined' && 'setItem' in localStorage &&\n        // in IE8 typeof localStorage.setItem === 'object'\n        !!localStorage.setItem;\n    } catch (e) {\n        return false;\n    }\n}\n\nfunction _getKeyPrefix(options, defaultConfig) {\n    var keyPrefix = options.name + '/';\n\n    if (options.storeName !== defaultConfig.storeName) {\n        keyPrefix += options.storeName + '/';\n    }\n    return keyPrefix;\n}\n\n// Check if localStorage throws when saving an item\nfunction checkIfLocalStorageThrows() {\n    var localStorageTestKey = '_localforage_support_test';\n\n    try {\n        localStorage.setItem(localStorageTestKey, true);\n        localStorage.removeItem(localStorageTestKey);\n\n        return false;\n    } catch (e) {\n        return true;\n    }\n}\n\n// Check if localStorage is usable and allows to save an item\n// This method checks if localStorage is usable in Safari Private Browsing\n// mode, or in any other case where the available quota for localStorage\n// is 0 and there wasn't any saved items yet.\nfunction _isLocalStorageUsable() {\n    return !checkIfLocalStorageThrows() || localStorage.length > 0;\n}\n\n// Config the localStorage backend, using options set in the config.\nfunction _initStorage$2(options) {\n    var self = this;\n    var dbInfo = {};\n    if (options) {\n        for (var i in options) {\n            dbInfo[i] = options[i];\n        }\n    }\n\n    dbInfo.keyPrefix = _getKeyPrefix(options, self._defaultConfig);\n\n    if (!_isLocalStorageUsable()) {\n        return Promise$1.reject();\n    }\n\n    self._dbInfo = dbInfo;\n    dbInfo.serializer = localforageSerializer;\n\n    return Promise$1.resolve();\n}\n\n// Remove all keys from the datastore, effectively destroying all data in\n// the app's key/value store!\nfunction clear$2(callback) {\n    var self = this;\n    var promise = self.ready().then(function () {\n        var keyPrefix = self._dbInfo.keyPrefix;\n\n        for (var i = localStorage.length - 1; i >= 0; i--) {\n            var key = localStorage.key(i);\n\n            if (key.indexOf(keyPrefix) === 0) {\n                localStorage.removeItem(key);\n            }\n        }\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Retrieve an item from the store. Unlike the original async_storage\n// library in Gaia, we don't modify return values at all. If a key's value\n// is `undefined`, we pass that value to the callback function.\nfunction getItem$2(key, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = self.ready().then(function () {\n        var dbInfo = self._dbInfo;\n        var result = localStorage.getItem(dbInfo.keyPrefix + key);\n\n        // If a result was found, parse it from the serialized\n        // string into a JS object. If result isn't truthy, the key\n        // is likely undefined and we'll pass it straight to the\n        // callback.\n        if (result) {\n            result = dbInfo.serializer.deserialize(result);\n        }\n\n        return result;\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Iterate over all items in the store.\nfunction iterate$2(iterator, callback) {\n    var self = this;\n\n    var promise = self.ready().then(function () {\n        var dbInfo = self._dbInfo;\n        var keyPrefix = dbInfo.keyPrefix;\n        var keyPrefixLength = keyPrefix.length;\n        var length = localStorage.length;\n\n        // We use a dedicated iterator instead of the `i` variable below\n        // so other keys we fetch in localStorage aren't counted in\n        // the `iterationNumber` argument passed to the `iterate()`\n        // callback.\n        //\n        // See: github.com/mozilla/localForage/pull/435#discussion_r38061530\n        var iterationNumber = 1;\n\n        for (var i = 0; i < length; i++) {\n            var key = localStorage.key(i);\n            if (key.indexOf(keyPrefix) !== 0) {\n                continue;\n            }\n            var value = localStorage.getItem(key);\n\n            // If a result was found, parse it from the serialized\n            // string into a JS object. If result isn't truthy, the\n            // key is likely undefined and we'll pass it straight\n            // to the iterator.\n            if (value) {\n                value = dbInfo.serializer.deserialize(value);\n            }\n\n            value = iterator(value, key.substring(keyPrefixLength), iterationNumber++);\n\n            if (value !== void 0) {\n                return value;\n            }\n        }\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Same as localStorage's key() method, except takes a callback.\nfunction key$2(n, callback) {\n    var self = this;\n    var promise = self.ready().then(function () {\n        var dbInfo = self._dbInfo;\n        var result;\n        try {\n            result = localStorage.key(n);\n        } catch (error) {\n            result = null;\n        }\n\n        // Remove the prefix from the key, if a key is found.\n        if (result) {\n            result = result.substring(dbInfo.keyPrefix.length);\n        }\n\n        return result;\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction keys$2(callback) {\n    var self = this;\n    var promise = self.ready().then(function () {\n        var dbInfo = self._dbInfo;\n        var length = localStorage.length;\n        var keys = [];\n\n        for (var i = 0; i < length; i++) {\n            var itemKey = localStorage.key(i);\n            if (itemKey.indexOf(dbInfo.keyPrefix) === 0) {\n                keys.push(itemKey.substring(dbInfo.keyPrefix.length));\n            }\n        }\n\n        return keys;\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Supply the number of keys in the datastore to the callback function.\nfunction length$2(callback) {\n    var self = this;\n    var promise = self.keys().then(function (keys) {\n        return keys.length;\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Remove an item from the store, nice and simple.\nfunction removeItem$2(key, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = self.ready().then(function () {\n        var dbInfo = self._dbInfo;\n        localStorage.removeItem(dbInfo.keyPrefix + key);\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\n// Set a key's value and run an optional callback once the value is set.\n// Unlike Gaia's implementation, the callback function is passed the value,\n// in case you want to operate on that value only after you're sure it\n// saved, or something like that.\nfunction setItem$2(key, value, callback) {\n    var self = this;\n\n    key = normalizeKey(key);\n\n    var promise = self.ready().then(function () {\n        // Convert undefined values to null.\n        // https://github.com/mozilla/localForage/pull/42\n        if (value === undefined) {\n            value = null;\n        }\n\n        // Save the original value to pass to the callback.\n        var originalValue = value;\n\n        return new Promise$1(function (resolve, reject) {\n            var dbInfo = self._dbInfo;\n            dbInfo.serializer.serialize(value, function (value, error) {\n                if (error) {\n                    reject(error);\n                } else {\n                    try {\n                        localStorage.setItem(dbInfo.keyPrefix + key, value);\n                        resolve(originalValue);\n                    } catch (e) {\n                        // localStorage capacity exceeded.\n                        // TODO: Make this a specific error/event.\n                        if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {\n                            reject(e);\n                        }\n                        reject(e);\n                    }\n                }\n            });\n        });\n    });\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nfunction dropInstance$2(options, callback) {\n    callback = getCallback.apply(this, arguments);\n\n    options = typeof options !== 'function' && options || {};\n    if (!options.name) {\n        var currentConfig = this.config();\n        options.name = options.name || currentConfig.name;\n        options.storeName = options.storeName || currentConfig.storeName;\n    }\n\n    var self = this;\n    var promise;\n    if (!options.name) {\n        promise = Promise$1.reject('Invalid arguments');\n    } else {\n        promise = new Promise$1(function (resolve) {\n            if (!options.storeName) {\n                resolve(options.name + '/');\n            } else {\n                resolve(_getKeyPrefix(options, self._defaultConfig));\n            }\n        }).then(function (keyPrefix) {\n            for (var i = localStorage.length - 1; i >= 0; i--) {\n                var key = localStorage.key(i);\n\n                if (key.indexOf(keyPrefix) === 0) {\n                    localStorage.removeItem(key);\n                }\n            }\n        });\n    }\n\n    executeCallback(promise, callback);\n    return promise;\n}\n\nvar localStorageWrapper = {\n    _driver: 'localStorageWrapper',\n    _initStorage: _initStorage$2,\n    _support: isLocalStorageValid(),\n    iterate: iterate$2,\n    getItem: getItem$2,\n    setItem: setItem$2,\n    removeItem: removeItem$2,\n    clear: clear$2,\n    length: length$2,\n    key: key$2,\n    keys: keys$2,\n    dropInstance: dropInstance$2\n};\n\nvar sameValue = function sameValue(x, y) {\n    return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);\n};\n\nvar includes = function includes(array, searchElement) {\n    var len = array.length;\n    var i = 0;\n    while (i < len) {\n        if (sameValue(array[i], searchElement)) {\n            return true;\n        }\n        i++;\n    }\n\n    return false;\n};\n\nvar isArray = Array.isArray || function (arg) {\n    return Object.prototype.toString.call(arg) === '[object Array]';\n};\n\n// Drivers are stored here when `defineDriver()` is called.\n// They are shared across all instances of localForage.\nvar DefinedDrivers = {};\n\nvar DriverSupport = {};\n\nvar DefaultDrivers = {\n    INDEXEDDB: asyncStorage,\n    WEBSQL: webSQLStorage,\n    LOCALSTORAGE: localStorageWrapper\n};\n\nvar DefaultDriverOrder = [DefaultDrivers.INDEXEDDB._driver, DefaultDrivers.WEBSQL._driver, DefaultDrivers.LOCALSTORAGE._driver];\n\nvar OptionalDriverMethods = ['dropInstance'];\n\nvar LibraryMethods = ['clear', 'getItem', 'iterate', 'key', 'keys', 'length', 'removeItem', 'setItem'].concat(OptionalDriverMethods);\n\nvar DefaultConfig = {\n    description: '',\n    driver: DefaultDriverOrder.slice(),\n    name: 'localforage',\n    // Default DB size is _JUST UNDER_ 5MB, as it's the highest size\n    // we can use without a prompt.\n    size: 4980736,\n    storeName: 'keyvaluepairs',\n    version: 1.0\n};\n\nfunction callWhenReady(localForageInstance, libraryMethod) {\n    localForageInstance[libraryMethod] = function () {\n        var _args = arguments;\n        return localForageInstance.ready().then(function () {\n            return localForageInstance[libraryMethod].apply(localForageInstance, _args);\n        });\n    };\n}\n\nfunction extend() {\n    for (var i = 1; i < arguments.length; i++) {\n        var arg = arguments[i];\n\n        if (arg) {\n            for (var _key in arg) {\n                if (arg.hasOwnProperty(_key)) {\n                    if (isArray(arg[_key])) {\n                        arguments[0][_key] = arg[_key].slice();\n                    } else {\n                        arguments[0][_key] = arg[_key];\n                    }\n                }\n            }\n        }\n    }\n\n    return arguments[0];\n}\n\nvar LocalForage = function () {\n    function LocalForage(options) {\n        _classCallCheck(this, LocalForage);\n\n        for (var driverTypeKey in DefaultDrivers) {\n            if (DefaultDrivers.hasOwnProperty(driverTypeKey)) {\n                var driver = DefaultDrivers[driverTypeKey];\n                var driverName = driver._driver;\n                this[driverTypeKey] = driverName;\n\n                if (!DefinedDrivers[driverName]) {\n                    // we don't need to wait for the promise,\n                    // since the default drivers can be defined\n                    // in a blocking manner\n                    this.defineDriver(driver);\n                }\n            }\n        }\n\n        this._defaultConfig = extend({}, DefaultConfig);\n        this._config = extend({}, this._defaultConfig, options);\n        this._driverSet = null;\n        this._initDriver = null;\n        this._ready = false;\n        this._dbInfo = null;\n\n        this._wrapLibraryMethodsWithReady();\n        this.setDriver(this._config.driver)[\"catch\"](function () {});\n    }\n\n    // Set any config values for localForage; can be called anytime before\n    // the first API call (e.g. `getItem`, `setItem`).\n    // We loop through options so we don't overwrite existing config\n    // values.\n\n\n    LocalForage.prototype.config = function config(options) {\n        // If the options argument is an object, we use it to set values.\n        // Otherwise, we return either a specified config value or all\n        // config values.\n        if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {\n            // If localforage is ready and fully initialized, we can't set\n            // any new configuration values. Instead, we return an error.\n            if (this._ready) {\n                return new Error(\"Can't call config() after localforage \" + 'has been used.');\n            }\n\n            for (var i in options) {\n                if (i === 'storeName') {\n                    options[i] = options[i].replace(/\\W/g, '_');\n                }\n\n                if (i === 'version' && typeof options[i] !== 'number') {\n                    return new Error('Database version must be a number.');\n                }\n\n                this._config[i] = options[i];\n            }\n\n            // after all config options are set and\n            // the driver option is used, try setting it\n            if ('driver' in options && options.driver) {\n                return this.setDriver(this._config.driver);\n            }\n\n            return true;\n        } else if (typeof options === 'string') {\n            return this._config[options];\n        } else {\n            return this._config;\n        }\n    };\n\n    // Used to define a custom driver, shared across all instances of\n    // localForage.\n\n\n    LocalForage.prototype.defineDriver = function defineDriver(driverObject, callback, errorCallback) {\n        var promise = new Promise$1(function (resolve, reject) {\n            try {\n                var driverName = driverObject._driver;\n                var complianceError = new Error('Custom driver not compliant; see ' + 'https://mozilla.github.io/localForage/#definedriver');\n\n                // A driver name should be defined and not overlap with the\n                // library-defined, default drivers.\n                if (!driverObject._driver) {\n                    reject(complianceError);\n                    return;\n                }\n\n                var driverMethods = LibraryMethods.concat('_initStorage');\n                for (var i = 0, len = driverMethods.length; i < len; i++) {\n                    var driverMethodName = driverMethods[i];\n\n                    // when the property is there,\n                    // it should be a method even when optional\n                    var isRequired = !includes(OptionalDriverMethods, driverMethodName);\n                    if ((isRequired || driverObject[driverMethodName]) && typeof driverObject[driverMethodName] !== 'function') {\n                        reject(complianceError);\n                        return;\n                    }\n                }\n\n                var configureMissingMethods = function configureMissingMethods() {\n                    var methodNotImplementedFactory = function methodNotImplementedFactory(methodName) {\n                        return function () {\n                            var error = new Error('Method ' + methodName + ' is not implemented by the current driver');\n                            var promise = Promise$1.reject(error);\n                            executeCallback(promise, arguments[arguments.length - 1]);\n                            return promise;\n                        };\n                    };\n\n                    for (var _i = 0, _len = OptionalDriverMethods.length; _i < _len; _i++) {\n                        var optionalDriverMethod = OptionalDriverMethods[_i];\n                        if (!driverObject[optionalDriverMethod]) {\n                            driverObject[optionalDriverMethod] = methodNotImplementedFactory(optionalDriverMethod);\n                        }\n                    }\n                };\n\n                configureMissingMethods();\n\n                var setDriverSupport = function setDriverSupport(support) {\n                    if (DefinedDrivers[driverName]) {\n                        console.info('Redefining LocalForage driver: ' + driverName);\n                    }\n                    DefinedDrivers[driverName] = driverObject;\n                    DriverSupport[driverName] = support;\n                    // don't use a then, so that we can define\n                    // drivers that have simple _support methods\n                    // in a blocking manner\n                    resolve();\n                };\n\n                if ('_support' in driverObject) {\n                    if (driverObject._support && typeof driverObject._support === 'function') {\n                        driverObject._support().then(setDriverSupport, reject);\n                    } else {\n                        setDriverSupport(!!driverObject._support);\n                    }\n                } else {\n                    setDriverSupport(true);\n                }\n            } catch (e) {\n                reject(e);\n            }\n        });\n\n        executeTwoCallbacks(promise, callback, errorCallback);\n        return promise;\n    };\n\n    LocalForage.prototype.driver = function driver() {\n        return this._driver || null;\n    };\n\n    LocalForage.prototype.getDriver = function getDriver(driverName, callback, errorCallback) {\n        var getDriverPromise = DefinedDrivers[driverName] ? Promise$1.resolve(DefinedDrivers[driverName]) : Promise$1.reject(new Error('Driver not found.'));\n\n        executeTwoCallbacks(getDriverPromise, callback, errorCallback);\n        return getDriverPromise;\n    };\n\n    LocalForage.prototype.getSerializer = function getSerializer(callback) {\n        var serializerPromise = Promise$1.resolve(localforageSerializer);\n        executeTwoCallbacks(serializerPromise, callback);\n        return serializerPromise;\n    };\n\n    LocalForage.prototype.ready = function ready(callback) {\n        var self = this;\n\n        var promise = self._driverSet.then(function () {\n            if (self._ready === null) {\n                self._ready = self._initDriver();\n            }\n\n            return self._ready;\n        });\n\n        executeTwoCallbacks(promise, callback, callback);\n        return promise;\n    };\n\n    LocalForage.prototype.setDriver = function setDriver(drivers, callback, errorCallback) {\n        var self = this;\n\n        if (!isArray(drivers)) {\n            drivers = [drivers];\n        }\n\n        var supportedDrivers = this._getSupportedDrivers(drivers);\n\n        function setDriverToConfig() {\n            self._config.driver = self.driver();\n        }\n\n        function extendSelfWithDriver(driver) {\n            self._extend(driver);\n            setDriverToConfig();\n\n            self._ready = self._initStorage(self._config);\n            return self._ready;\n        }\n\n        function initDriver(supportedDrivers) {\n            return function () {\n                var currentDriverIndex = 0;\n\n                function driverPromiseLoop() {\n                    while (currentDriverIndex < supportedDrivers.length) {\n                        var driverName = supportedDrivers[currentDriverIndex];\n                        currentDriverIndex++;\n\n                        self._dbInfo = null;\n                        self._ready = null;\n\n                        return self.getDriver(driverName).then(extendSelfWithDriver)[\"catch\"](driverPromiseLoop);\n                    }\n\n                    setDriverToConfig();\n                    var error = new Error('No available storage method found.');\n                    self._driverSet = Promise$1.reject(error);\n                    return self._driverSet;\n                }\n\n                return driverPromiseLoop();\n            };\n        }\n\n        // There might be a driver initialization in progress\n        // so wait for it to finish in order to avoid a possible\n        // race condition to set _dbInfo\n        var oldDriverSetDone = this._driverSet !== null ? this._driverSet[\"catch\"](function () {\n            return Promise$1.resolve();\n        }) : Promise$1.resolve();\n\n        this._driverSet = oldDriverSetDone.then(function () {\n            var driverName = supportedDrivers[0];\n            self._dbInfo = null;\n            self._ready = null;\n\n            return self.getDriver(driverName).then(function (driver) {\n                self._driver = driver._driver;\n                setDriverToConfig();\n                self._wrapLibraryMethodsWithReady();\n                self._initDriver = initDriver(supportedDrivers);\n            });\n        })[\"catch\"](function () {\n            setDriverToConfig();\n            var error = new Error('No available storage method found.');\n            self._driverSet = Promise$1.reject(error);\n            return self._driverSet;\n        });\n\n        executeTwoCallbacks(this._driverSet, callback, errorCallback);\n        return this._driverSet;\n    };\n\n    LocalForage.prototype.supports = function supports(driverName) {\n        return !!DriverSupport[driverName];\n    };\n\n    LocalForage.prototype._extend = function _extend(libraryMethodsAndProperties) {\n        extend(this, libraryMethodsAndProperties);\n    };\n\n    LocalForage.prototype._getSupportedDrivers = function _getSupportedDrivers(drivers) {\n        var supportedDrivers = [];\n        for (var i = 0, len = drivers.length; i < len; i++) {\n            var driverName = drivers[i];\n            if (this.supports(driverName)) {\n                supportedDrivers.push(driverName);\n            }\n        }\n        return supportedDrivers;\n    };\n\n    LocalForage.prototype._wrapLibraryMethodsWithReady = function _wrapLibraryMethodsWithReady() {\n        // Add a stub for each driver API method that delays the call to the\n        // corresponding driver method until localForage is ready. These stubs\n        // will be replaced by the driver methods as soon as the driver is\n        // loaded, so there is no performance impact.\n        for (var i = 0, len = LibraryMethods.length; i < len; i++) {\n            callWhenReady(this, LibraryMethods[i]);\n        }\n    };\n\n    LocalForage.prototype.createInstance = function createInstance(options) {\n        return new LocalForage(options);\n    };\n\n    return LocalForage;\n}();\n\n// The actual localForage object that we expose as a module or via a\n// global. It's extended by pulling in one of our other libraries.\n\n\nvar localforage_js = new LocalForage();\n\nmodule.exports = localforage_js;\n\n},{\"3\":3}]},{},[4])(4)\n});\n\n\n//# sourceURL=webpack:///../../node_modules/localforage/dist/localforage.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/loupe/loupe.js":
  /*!*****************************************!*\
    !*** ../../node_modules/loupe/loupe.js ***!
    \*****************************************/
  /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
  
  eval("(function (global, factory) {\n   true ? factory(exports) :\n  0;\n}(this, (function (exports) { 'use strict';\n\n  function _typeof(obj) {\n    \"@babel/helpers - typeof\";\n\n    if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n      _typeof = function (obj) {\n        return typeof obj;\n      };\n    } else {\n      _typeof = function (obj) {\n        return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n      };\n    }\n\n    return _typeof(obj);\n  }\n\n  function _slicedToArray(arr, i) {\n    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();\n  }\n\n  function _arrayWithHoles(arr) {\n    if (Array.isArray(arr)) return arr;\n  }\n\n  function _iterableToArrayLimit(arr, i) {\n    if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return;\n    var _arr = [];\n    var _n = true;\n    var _d = false;\n    var _e = undefined;\n\n    try {\n      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n        _arr.push(_s.value);\n\n        if (i && _arr.length === i) break;\n      }\n    } catch (err) {\n      _d = true;\n      _e = err;\n    } finally {\n      try {\n        if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n      } finally {\n        if (_d) throw _e;\n      }\n    }\n\n    return _arr;\n  }\n\n  function _unsupportedIterableToArray(o, minLen) {\n    if (!o) return;\n    if (typeof o === \"string\") return _arrayLikeToArray(o, minLen);\n    var n = Object.prototype.toString.call(o).slice(8, -1);\n    if (n === \"Object\" && o.constructor) n = o.constructor.name;\n    if (n === \"Map\" || n === \"Set\") return Array.from(o);\n    if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);\n  }\n\n  function _arrayLikeToArray(arr, len) {\n    if (len == null || len > arr.length) len = arr.length;\n\n    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];\n\n    return arr2;\n  }\n\n  function _nonIterableRest() {\n    throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n  }\n\n  var ansiColors = {\n    bold: ['1', '22'],\n    dim: ['2', '22'],\n    italic: ['3', '23'],\n    underline: ['4', '24'],\n    // 5 & 6 are blinking\n    inverse: ['7', '27'],\n    hidden: ['8', '28'],\n    strike: ['9', '29'],\n    // 10-20 are fonts\n    // 21-29 are resets for 1-9\n    black: ['30', '39'],\n    red: ['31', '39'],\n    green: ['32', '39'],\n    yellow: ['33', '39'],\n    blue: ['34', '39'],\n    magenta: ['35', '39'],\n    cyan: ['36', '39'],\n    white: ['37', '39'],\n    brightblack: ['30;1', '39'],\n    brightred: ['31;1', '39'],\n    brightgreen: ['32;1', '39'],\n    brightyellow: ['33;1', '39'],\n    brightblue: ['34;1', '39'],\n    brightmagenta: ['35;1', '39'],\n    brightcyan: ['36;1', '39'],\n    brightwhite: ['37;1', '39'],\n    grey: ['90', '39']\n  };\n  var styles = {\n    special: 'cyan',\n    number: 'yellow',\n    bigint: 'yellow',\n    boolean: 'yellow',\n    undefined: 'grey',\n    null: 'bold',\n    string: 'green',\n    symbol: 'green',\n    date: 'magenta',\n    regexp: 'red'\n  };\n  var truncator = '…';\n\n  function colorise(value, styleType) {\n    var color = ansiColors[styles[styleType]] || ansiColors[styleType];\n\n    if (!color) {\n      return String(value);\n    }\n\n    return \"\\x1B[\".concat(color[0], \"m\").concat(String(value), \"\\x1B[\").concat(color[1], \"m\");\n  }\n\n  function normaliseOptions() {\n    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},\n        _ref$showHidden = _ref.showHidden,\n        showHidden = _ref$showHidden === void 0 ? false : _ref$showHidden,\n        _ref$depth = _ref.depth,\n        depth = _ref$depth === void 0 ? 2 : _ref$depth,\n        _ref$colors = _ref.colors,\n        colors = _ref$colors === void 0 ? false : _ref$colors,\n        _ref$customInspect = _ref.customInspect,\n        customInspect = _ref$customInspect === void 0 ? true : _ref$customInspect,\n        _ref$showProxy = _ref.showProxy,\n        showProxy = _ref$showProxy === void 0 ? false : _ref$showProxy,\n        _ref$maxArrayLength = _ref.maxArrayLength,\n        maxArrayLength = _ref$maxArrayLength === void 0 ? Infinity : _ref$maxArrayLength,\n        _ref$breakLength = _ref.breakLength,\n        breakLength = _ref$breakLength === void 0 ? Infinity : _ref$breakLength,\n        _ref$seen = _ref.seen,\n        seen = _ref$seen === void 0 ? [] : _ref$seen,\n        _ref$truncate = _ref.truncate,\n        truncate = _ref$truncate === void 0 ? Infinity : _ref$truncate,\n        _ref$stylize = _ref.stylize,\n        stylize = _ref$stylize === void 0 ? String : _ref$stylize;\n\n    var options = {\n      showHidden: Boolean(showHidden),\n      depth: Number(depth),\n      colors: Boolean(colors),\n      customInspect: Boolean(customInspect),\n      showProxy: Boolean(showProxy),\n      maxArrayLength: Number(maxArrayLength),\n      breakLength: Number(breakLength),\n      truncate: Number(truncate),\n      seen: seen,\n      stylize: stylize\n    };\n\n    if (options.colors) {\n      options.stylize = colorise;\n    }\n\n    return options;\n  }\n  function truncate(string, length) {\n    var tail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : truncator;\n    string = String(string);\n    var tailLength = tail.length;\n    var stringLength = string.length;\n\n    if (tailLength > length && stringLength > tailLength) {\n      return tail;\n    }\n\n    if (stringLength > length && stringLength > tailLength) {\n      return \"\".concat(string.slice(0, length - tailLength)).concat(tail);\n    }\n\n    return string;\n  } // eslint-disable-next-line complexity\n\n  function inspectList(list, options, inspectItem) {\n    var separator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ', ';\n    inspectItem = inspectItem || options.inspect;\n    var size = list.length;\n    if (size === 0) return '';\n    var originalLength = options.truncate;\n    var output = '';\n    var peek = '';\n    var truncated = '';\n\n    for (var i = 0; i < size; i += 1) {\n      var last = i + 1 === list.length;\n      var secondToLast = i + 2 === list.length;\n      truncated = \"\".concat(truncator, \"(\").concat(list.length - i, \")\");\n      var value = list[i]; // If there is more than one remaining we need to account for a separator of `, `\n\n      options.truncate = originalLength - output.length - (last ? 0 : separator.length);\n      var string = peek || inspectItem(value, options) + (last ? '' : separator);\n      var nextLength = output.length + string.length;\n      var truncatedLength = nextLength + truncated.length; // If this is the last element, and adding it would\n      // take us over length, but adding the truncator wouldn't - then break now\n\n      if (last && nextLength > originalLength && output.length + truncated.length <= originalLength) {\n        break;\n      } // If this isn't the last or second to last element to scan,\n      // but the string is already over length then break here\n\n\n      if (!last && !secondToLast && truncatedLength > originalLength) {\n        break;\n      } // Peek at the next string to determine if we should\n      // break early before adding this item to the output\n\n\n      peek = last ? '' : inspectItem(list[i + 1], options) + (secondToLast ? '' : separator); // If we have one element left, but this element and\n      // the next takes over length, the break early\n\n      if (!last && secondToLast && truncatedLength > originalLength && nextLength + peek.length > originalLength) {\n        break;\n      }\n\n      output += string; // If the next element takes us to length -\n      // but there are more after that, then we should truncate now\n\n      if (!last && !secondToLast && nextLength + peek.length >= originalLength) {\n        truncated = \"\".concat(truncator, \"(\").concat(list.length - i - 1, \")\");\n        break;\n      }\n\n      truncated = '';\n    }\n\n    return \"\".concat(output).concat(truncated);\n  }\n\n  function quoteComplexKey(key) {\n    if (key.match(/^[a-zA-Z_][a-zA-Z_0-9]*$/)) {\n      return key;\n    }\n\n    return JSON.stringify(key).replace(/'/g, \"\\\\'\").replace(/\\\\\"/g, '\"').replace(/(^\"|\"$)/g, \"'\");\n  }\n\n  function inspectProperty(_ref2, options) {\n    var _ref3 = _slicedToArray(_ref2, 2),\n        key = _ref3[0],\n        value = _ref3[1];\n\n    options.truncate -= 2;\n\n    if (typeof key === 'string') {\n      key = quoteComplexKey(key);\n    } else if (typeof key !== 'number') {\n      key = \"[\".concat(options.inspect(key, options), \"]\");\n    }\n\n    options.truncate -= key.length;\n    value = options.inspect(value, options);\n    return \"\".concat(key, \": \").concat(value);\n  }\n\n  function inspectArray(array, options) {\n    // Object.keys will always output the Array indices first, so we can slice by\n    // `array.length` to get non-index properties\n    var nonIndexProperties = Object.keys(array).slice(array.length);\n    if (!array.length && !nonIndexProperties.length) return '[]';\n    options.truncate -= 4;\n    var listContents = inspectList(array, options);\n    options.truncate -= listContents.length;\n    var propertyContents = '';\n\n    if (nonIndexProperties.length) {\n      propertyContents = inspectList(nonIndexProperties.map(function (key) {\n        return [key, array[key]];\n      }), options, inspectProperty);\n    }\n\n    return \"[ \".concat(listContents).concat(propertyContents ? \", \".concat(propertyContents) : '', \" ]\");\n  }\n\n  /* !\n   * Chai - getFuncName utility\n   * Copyright(c) 2012-2016 Jake Luer <jake@alogicalparadox.com>\n   * MIT Licensed\n   */\n\n  /**\n   * ### .getFuncName(constructorFn)\n   *\n   * Returns the name of a function.\n   * When a non-function instance is passed, returns `null`.\n   * This also includes a polyfill function if `aFunc.name` is not defined.\n   *\n   * @name getFuncName\n   * @param {Function} funct\n   * @namespace Utils\n   * @api public\n   */\n\n  var toString = Function.prototype.toString;\n  var functionNameMatch = /\\s*function(?:\\s|\\s*\\/\\*[^(?:*\\/)]+\\*\\/\\s*)*([^\\s\\(\\/]+)/;\n  function getFuncName(aFunc) {\n    if (typeof aFunc !== 'function') {\n      return null;\n    }\n\n    var name = '';\n    if (typeof Function.prototype.name === 'undefined' && typeof aFunc.name === 'undefined') {\n      // Here we run a polyfill if Function does not support the `name` property and if aFunc.name is not defined\n      var match = toString.call(aFunc).match(functionNameMatch);\n      if (match) {\n        name = match[1];\n      }\n    } else {\n      // If we've got a `name` property we just use it\n      name = aFunc.name;\n    }\n\n    return name;\n  }\n\n  var getFuncName_1 = getFuncName;\n\n  var getArrayName = function getArrayName(array) {\n    // We need to special case Node.js' Buffers, which report to be Uint8Array\n    if (typeof Buffer === 'function' && array instanceof Buffer) {\n      return 'Buffer';\n    }\n\n    if (array[Symbol.toStringTag]) {\n      return array[Symbol.toStringTag];\n    }\n\n    return getFuncName_1(array.constructor);\n  };\n\n  function inspectTypedArray(array, options) {\n    var name = getArrayName(array);\n    options.truncate -= name.length + 4; // Object.keys will always output the Array indices first, so we can slice by\n    // `array.length` to get non-index properties\n\n    var nonIndexProperties = Object.keys(array).slice(array.length);\n    if (!array.length && !nonIndexProperties.length) return \"\".concat(name, \"[]\"); // As we know TypedArrays only contain Unsigned Integers, we can skip inspecting each one and simply\n    // stylise the toString() value of them\n\n    var output = '';\n\n    for (var i = 0; i < array.length; i++) {\n      var string = \"\".concat(options.stylize(truncate(array[i], options.truncate), 'number')).concat(i === array.length - 1 ? '' : ', ');\n      options.truncate -= string.length;\n\n      if (array[i] !== array.length && options.truncate <= 3) {\n        output += \"\".concat(truncator, \"(\").concat(array.length - array[i] + 1, \")\");\n        break;\n      }\n\n      output += string;\n    }\n\n    var propertyContents = '';\n\n    if (nonIndexProperties.length) {\n      propertyContents = inspectList(nonIndexProperties.map(function (key) {\n        return [key, array[key]];\n      }), options, inspectProperty);\n    }\n\n    return \"\".concat(name, \"[ \").concat(output).concat(propertyContents ? \", \".concat(propertyContents) : '', \" ]\");\n  }\n\n  function inspectDate(dateObject, options) {\n    // If we need to - truncate the time portion, but never the date\n    var split = dateObject.toJSON().split('T');\n    var date = split[0];\n    return options.stylize(\"\".concat(date, \"T\").concat(truncate(split[1], options.truncate - date.length - 1)), 'date');\n  }\n\n  function inspectFunction(func, options) {\n    var name = getFuncName_1(func);\n\n    if (!name) {\n      return options.stylize('[Function]', 'special');\n    }\n\n    return options.stylize(\"[Function \".concat(truncate(name, options.truncate - 11), \"]\"), 'special');\n  }\n\n  function inspectMapEntry(_ref, options) {\n    var _ref2 = _slicedToArray(_ref, 2),\n        key = _ref2[0],\n        value = _ref2[1];\n\n    options.truncate -= 4;\n    key = options.inspect(key, options);\n    options.truncate -= key.length;\n    value = options.inspect(value, options);\n    return \"\".concat(key, \" => \").concat(value);\n  } // IE11 doesn't support `map.entries()`\n\n\n  function mapToEntries(map) {\n    var entries = [];\n    map.forEach(function (value, key) {\n      entries.push([key, value]);\n    });\n    return entries;\n  }\n\n  function inspectMap(map, options) {\n    var size = map.size - 1;\n\n    if (size <= 0) {\n      return 'Map{}';\n    }\n\n    options.truncate -= 7;\n    return \"Map{ \".concat(inspectList(mapToEntries(map), options, inspectMapEntry), \" }\");\n  }\n\n  var isNaN = Number.isNaN || function (i) {\n    return i !== i;\n  }; // eslint-disable-line no-self-compare\n\n\n  function inspectNumber(number, options) {\n    if (isNaN(number)) {\n      return options.stylize('NaN', 'number');\n    }\n\n    if (number === Infinity) {\n      return options.stylize('Infinity', 'number');\n    }\n\n    if (number === -Infinity) {\n      return options.stylize('-Infinity', 'number');\n    }\n\n    if (number === 0) {\n      return options.stylize(1 / number === Infinity ? '+0' : '-0', 'number');\n    }\n\n    return options.stylize(truncate(number, options.truncate), 'number');\n  }\n\n  function inspectBigInt(number, options) {\n    var nums = truncate(number.toString(), options.truncate - 1);\n    if (nums !== truncator) nums += 'n';\n    return options.stylize(nums, 'bigint');\n  }\n\n  function inspectRegExp(value, options) {\n    var flags = value.toString().split('/')[2];\n    var sourceLength = options.truncate - (2 + flags.length);\n    var source = value.source;\n    return options.stylize(\"/\".concat(truncate(source, sourceLength), \"/\").concat(flags), 'regexp');\n  }\n\n  function arrayFromSet(set) {\n    var values = [];\n    set.forEach(function (value) {\n      values.push(value);\n    });\n    return values;\n  }\n\n  function inspectSet(set, options) {\n    if (set.size === 0) return 'Set{}';\n    options.truncate -= 7;\n    return \"Set{ \".concat(inspectList(arrayFromSet(set), options), \" }\");\n  }\n\n  var stringEscapeChars = new RegExp(\"['\\\\u0000-\\\\u001f\\\\u007f-\\\\u009f\\\\u00ad\\\\u0600-\\\\u0604\\\\u070f\\\\u17b4\\\\u17b5\" + \"\\\\u200c-\\\\u200f\\\\u2028-\\\\u202f\\\\u2060-\\\\u206f\\\\ufeff\\\\ufff0-\\\\uffff]\", 'g');\n  var escapeCharacters = {\n    '\\b': '\\\\b',\n    '\\t': '\\\\t',\n    '\\n': '\\\\n',\n    '\\f': '\\\\f',\n    '\\r': '\\\\r',\n    \"'\": \"\\\\'\",\n    '\\\\': '\\\\\\\\'\n  };\n  var hex = 16;\n  var unicodeLength = 4;\n\n  function escape(char) {\n    return escapeCharacters[char] || \"\\\\u\".concat(\"0000\".concat(char.charCodeAt(0).toString(hex)).slice(-unicodeLength));\n  }\n\n  function inspectString(string, options) {\n    if (stringEscapeChars.test(string)) {\n      string = string.replace(stringEscapeChars, escape);\n    }\n\n    return options.stylize(\"'\".concat(truncate(string, options.truncate - 2), \"'\"), 'string');\n  }\n\n  function inspectSymbol(value) {\n    if ('description' in Symbol.prototype) {\n      return value.description ? \"Symbol(\".concat(value.description, \")\") : 'Symbol()';\n    }\n\n    return value.toString();\n  }\n\n  var getPromiseValue = function getPromiseValue() {\n    return 'Promise{…}';\n  };\n\n  try {\n    var _process$binding = process.binding('util'),\n        getPromiseDetails = _process$binding.getPromiseDetails,\n        kPending = _process$binding.kPending,\n        kRejected = _process$binding.kRejected;\n\n    if (Array.isArray(getPromiseDetails(Promise.resolve()))) {\n      getPromiseValue = function getPromiseValue(value, options) {\n        var _getPromiseDetails = getPromiseDetails(value),\n            _getPromiseDetails2 = _slicedToArray(_getPromiseDetails, 2),\n            state = _getPromiseDetails2[0],\n            innerValue = _getPromiseDetails2[1];\n\n        if (state === kPending) {\n          return 'Promise{<pending>}';\n        }\n\n        return \"Promise\".concat(state === kRejected ? '!' : '', \"{\").concat(options.inspect(innerValue, options), \"}\");\n      };\n    }\n  } catch (notNode) {\n    /* ignore */\n  }\n\n  var inspectPromise = getPromiseValue;\n\n  function inspectObject(object, options) {\n    var properties = Object.getOwnPropertyNames(object);\n    var symbols = Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : [];\n\n    if (properties.length === 0 && symbols.length === 0) {\n      return '{}';\n    }\n\n    options.truncate -= 4;\n    options.seen = options.seen || [];\n\n    if (options.seen.indexOf(object) >= 0) {\n      return '[Circular]';\n    }\n\n    options.seen.push(object);\n    var propertyContents = inspectList(properties.map(function (key) {\n      return [key, object[key]];\n    }), options, inspectProperty);\n    var symbolContents = inspectList(symbols.map(function (key) {\n      return [key, object[key]];\n    }), options, inspectProperty);\n    options.seen.pop();\n    var sep = '';\n\n    if (propertyContents && symbolContents) {\n      sep = ', ';\n    }\n\n    return \"{ \".concat(propertyContents).concat(sep).concat(symbolContents, \" }\");\n  }\n\n  var toStringTag = typeof Symbol !== 'undefined' && Symbol.toStringTag ? Symbol.toStringTag : false;\n  function inspectClass(value, options) {\n    var name = '';\n\n    if (toStringTag && toStringTag in value) {\n      name = value[toStringTag];\n    }\n\n    name = name || getFuncName_1(value.constructor); // Babel transforms anonymous classes to the name `_class`\n\n    if (!name || name === '_class') {\n      name = '<Anonymous Class>';\n    }\n\n    options.truncate -= name.length;\n    return \"\".concat(name).concat(inspectObject(value, options));\n  }\n\n  function inspectArguments(args, options) {\n    if (args.length === 0) return 'Arguments[]';\n    options.truncate -= 13;\n    return \"Arguments[ \".concat(inspectList(args, options), \" ]\");\n  }\n\n  var errorKeys = ['stack', 'line', 'column', 'name', 'message', 'fileName', 'lineNumber', 'columnNumber', 'number', 'description'];\n  function inspectObject$1(error, options) {\n    var properties = Object.getOwnPropertyNames(error).filter(function (key) {\n      return errorKeys.indexOf(key) === -1;\n    });\n    var name = error.name;\n    options.truncate -= name.length;\n    var message = '';\n\n    if (typeof error.message === 'string') {\n      message = truncate(error.message, options.truncate);\n    } else {\n      properties.unshift('message');\n    }\n\n    message = message ? \": \".concat(message) : '';\n    options.truncate -= message.length + 5;\n    var propertyContents = inspectList(properties.map(function (key) {\n      return [key, error[key]];\n    }), options, inspectProperty);\n    return \"\".concat(name).concat(message).concat(propertyContents ? \" { \".concat(propertyContents, \" }\") : '');\n  }\n\n  function inspectAttribute(_ref, options) {\n    var _ref2 = _slicedToArray(_ref, 2),\n        key = _ref2[0],\n        value = _ref2[1];\n\n    options.truncate -= 3;\n\n    if (!value) {\n      return \"\".concat(options.stylize(key, 'yellow'));\n    }\n\n    return \"\".concat(options.stylize(key, 'yellow'), \"=\").concat(options.stylize(\"\\\"\".concat(value, \"\\\"\"), 'string'));\n  }\n  function inspectHTMLCollection(collection, options) {\n    // eslint-disable-next-line no-use-before-define\n    return inspectList(collection, options, inspectHTML, '\\n');\n  }\n  function inspectHTML(element, options) {\n    var properties = element.getAttributeNames();\n    var name = element.tagName.toLowerCase();\n    var head = options.stylize(\"<\".concat(name), 'special');\n    var headClose = options.stylize(\">\", 'special');\n    var tail = options.stylize(\"</\".concat(name, \">\"), 'special');\n    options.truncate -= name.length * 2 + 5;\n    var propertyContents = '';\n\n    if (properties.length > 0) {\n      propertyContents += ' ';\n      propertyContents += inspectList(properties.map(function (key) {\n        return [key, element.getAttribute(key)];\n      }), options, inspectAttribute, ' ');\n    }\n\n    options.truncate -= propertyContents.length;\n    var truncate = options.truncate;\n    var children = inspectHTMLCollection(element.children, options);\n\n    if (children && children.length > truncate) {\n      children = \"\".concat(truncator, \"(\").concat(element.children.length, \")\");\n    }\n\n    return \"\".concat(head).concat(propertyContents).concat(headClose).concat(children).concat(tail);\n  }\n\n  var symbolsSupported = typeof Symbol === 'function' && typeof Symbol.for === 'function';\n  var chaiInspect = symbolsSupported ? Symbol.for('chai/inspect') : '@@chai/inspect';\n  var nodeInspect = false;\n\n  try {\n    // eslint-disable-next-line global-require\n    var nodeUtil = __webpack_require__(/*! util */ \"?7779\");\n\n    nodeInspect = nodeUtil.inspect ? nodeUtil.inspect.custom : false;\n  } catch (noNodeInspect) {\n    nodeInspect = false;\n  }\n\n  var constructorMap = new WeakMap();\n  var stringTagMap = {};\n  var baseTypesMap = {\n    undefined: function undefined$1(value, options) {\n      return options.stylize('undefined', 'undefined');\n    },\n    null: function _null(value, options) {\n      return options.stylize(null, 'null');\n    },\n    boolean: function boolean(value, options) {\n      return options.stylize(value, 'boolean');\n    },\n    Boolean: function Boolean(value, options) {\n      return options.stylize(value, 'boolean');\n    },\n    number: inspectNumber,\n    Number: inspectNumber,\n    bigint: inspectBigInt,\n    BigInt: inspectBigInt,\n    string: inspectString,\n    String: inspectString,\n    function: inspectFunction,\n    Function: inspectFunction,\n    symbol: inspectSymbol,\n    // A Symbol polyfill will return `Symbol` not `symbol` from typedetect\n    Symbol: inspectSymbol,\n    Array: inspectArray,\n    Date: inspectDate,\n    Map: inspectMap,\n    Set: inspectSet,\n    RegExp: inspectRegExp,\n    Promise: inspectPromise,\n    // WeakSet, WeakMap are totally opaque to us\n    WeakSet: function WeakSet(value, options) {\n      return options.stylize('WeakSet{…}', 'special');\n    },\n    WeakMap: function WeakMap(value, options) {\n      return options.stylize('WeakMap{…}', 'special');\n    },\n    Arguments: inspectArguments,\n    Int8Array: inspectTypedArray,\n    Uint8Array: inspectTypedArray,\n    Uint8ClampedArray: inspectTypedArray,\n    Int16Array: inspectTypedArray,\n    Uint16Array: inspectTypedArray,\n    Int32Array: inspectTypedArray,\n    Uint32Array: inspectTypedArray,\n    Float32Array: inspectTypedArray,\n    Float64Array: inspectTypedArray,\n    Generator: function Generator() {\n      return '';\n    },\n    DataView: function DataView() {\n      return '';\n    },\n    ArrayBuffer: function ArrayBuffer() {\n      return '';\n    },\n    Error: inspectObject$1,\n    HTMLCollection: inspectHTMLCollection,\n    NodeList: inspectHTMLCollection\n  }; // eslint-disable-next-line complexity\n\n  var inspectCustom = function inspectCustom(value, options, type) {\n    if (chaiInspect in value && typeof value[chaiInspect] === 'function') {\n      return value[chaiInspect](options);\n    }\n\n    if (nodeInspect && nodeInspect in value && typeof value[nodeInspect] === 'function') {\n      return value[nodeInspect](options.depth, options);\n    }\n\n    if ('inspect' in value && typeof value.inspect === 'function') {\n      return value.inspect(options.depth, options);\n    }\n\n    if ('constructor' in value && constructorMap.has(value.constructor)) {\n      return constructorMap.get(value.constructor)(value, options);\n    }\n\n    if (stringTagMap[type]) {\n      return stringTagMap[type](value, options);\n    }\n\n    return '';\n  };\n\n  var toString$1 = Object.prototype.toString; // eslint-disable-next-line complexity\n\n  function inspect(value, options) {\n    options = normaliseOptions(options);\n    options.inspect = inspect;\n    var _options = options,\n        customInspect = _options.customInspect;\n    var type = value === null ? 'null' : _typeof(value);\n\n    if (type === 'object') {\n      type = toString$1.call(value).slice(8, -1);\n    } // If it is a base value that we already support, then use Loupe's inspector\n\n\n    if (baseTypesMap[type]) {\n      return baseTypesMap[type](value, options);\n    } // If `options.customInspect` is set to true then try to use the custom inspector\n\n\n    if (customInspect && value) {\n      var output = inspectCustom(value, options, type);\n\n      if (output) {\n        if (typeof output === 'string') return output;\n        return inspect(output, options);\n      }\n    }\n\n    var proto = value ? Object.getPrototypeOf(value) : false; // If it's a plain Object then use Loupe's inspector\n\n    if (proto === Object.prototype || proto === null) {\n      return inspectObject(value, options);\n    } // Specifically account for HTMLElements\n    // eslint-disable-next-line no-undef\n\n\n    if (value && typeof HTMLElement === 'function' && value instanceof HTMLElement) {\n      return inspectHTML(value, options);\n    }\n\n    if ('constructor' in value) {\n      // If it is a class, inspect it like an object but add the constructor name\n      if (value.constructor !== Object) {\n        return inspectClass(value, options);\n      } // If it is an object with an anonymous prototype, display it as an object.\n\n\n      return inspectObject(value, options);\n    } // last chance to check if it's an object\n\n\n    if (value === Object(value)) {\n      return inspectObject(value, options);\n    } // We have run out of options! Just stringify the value\n\n\n    return options.stylize(String(value), type);\n  }\n  function registerConstructor(constructor, inspector) {\n    if (constructorMap.has(constructor)) {\n      return false;\n    }\n\n    constructorMap.add(constructor, inspector);\n    return true;\n  }\n  function registerStringTag(stringTag, inspector) {\n    if (stringTag in stringTagMap) {\n      return false;\n    }\n\n    stringTagMap[stringTag] = inspector;\n    return true;\n  }\n  var custom = chaiInspect;\n\n  exports.custom = custom;\n  exports.default = inspect;\n  exports.inspect = inspect;\n  exports.registerConstructor = registerConstructor;\n  exports.registerStringTag = registerStringTag;\n\n  Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n\n\n//# sourceURL=webpack:///../../node_modules/loupe/loupe.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/path-browserify/index.js":
  /*!***************************************************!*\
    !*** ../../node_modules/path-browserify/index.js ***!
    \***************************************************/
  /***/ ((module) => {
  
  "use strict";
  eval("// 'path' module extracted from Node.js v8.11.1 (only the posix part)\n// transplited with Babel\n\n// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n\nfunction assertPath(path) {\n  if (typeof path !== 'string') {\n    throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));\n  }\n}\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeStringPosix(path, allowAboveRoot) {\n  var res = '';\n  var lastSegmentLength = 0;\n  var lastSlash = -1;\n  var dots = 0;\n  var code;\n  for (var i = 0; i <= path.length; ++i) {\n    if (i < path.length)\n      code = path.charCodeAt(i);\n    else if (code === 47 /*/*/)\n      break;\n    else\n      code = 47 /*/*/;\n    if (code === 47 /*/*/) {\n      if (lastSlash === i - 1 || dots === 1) {\n        // NOOP\n      } else if (lastSlash !== i - 1 && dots === 2) {\n        if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {\n          if (res.length > 2) {\n            var lastSlashIndex = res.lastIndexOf('/');\n            if (lastSlashIndex !== res.length - 1) {\n              if (lastSlashIndex === -1) {\n                res = '';\n                lastSegmentLength = 0;\n              } else {\n                res = res.slice(0, lastSlashIndex);\n                lastSegmentLength = res.length - 1 - res.lastIndexOf('/');\n              }\n              lastSlash = i;\n              dots = 0;\n              continue;\n            }\n          } else if (res.length === 2 || res.length === 1) {\n            res = '';\n            lastSegmentLength = 0;\n            lastSlash = i;\n            dots = 0;\n            continue;\n          }\n        }\n        if (allowAboveRoot) {\n          if (res.length > 0)\n            res += '/..';\n          else\n            res = '..';\n          lastSegmentLength = 2;\n        }\n      } else {\n        if (res.length > 0)\n          res += '/' + path.slice(lastSlash + 1, i);\n        else\n          res = path.slice(lastSlash + 1, i);\n        lastSegmentLength = i - lastSlash - 1;\n      }\n      lastSlash = i;\n      dots = 0;\n    } else if (code === 46 /*.*/ && dots !== -1) {\n      ++dots;\n    } else {\n      dots = -1;\n    }\n  }\n  return res;\n}\n\nfunction _format(sep, pathObject) {\n  var dir = pathObject.dir || pathObject.root;\n  var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');\n  if (!dir) {\n    return base;\n  }\n  if (dir === pathObject.root) {\n    return dir + base;\n  }\n  return dir + sep + base;\n}\n\nvar posix = {\n  // path.resolve([from ...], to)\n  resolve: function resolve() {\n    var resolvedPath = '';\n    var resolvedAbsolute = false;\n    var cwd;\n\n    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {\n      var path;\n      if (i >= 0)\n        path = arguments[i];\n      else {\n        if (cwd === undefined)\n          cwd = process.cwd();\n        path = cwd;\n      }\n\n      assertPath(path);\n\n      // Skip empty entries\n      if (path.length === 0) {\n        continue;\n      }\n\n      resolvedPath = path + '/' + resolvedPath;\n      resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    }\n\n    // At this point the path should be resolved to a full absolute path, but\n    // handle relative paths to be safe (might happen when process.cwd() fails)\n\n    // Normalize the path\n    resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);\n\n    if (resolvedAbsolute) {\n      if (resolvedPath.length > 0)\n        return '/' + resolvedPath;\n      else\n        return '/';\n    } else if (resolvedPath.length > 0) {\n      return resolvedPath;\n    } else {\n      return '.';\n    }\n  },\n\n  normalize: function normalize(path) {\n    assertPath(path);\n\n    if (path.length === 0) return '.';\n\n    var isAbsolute = path.charCodeAt(0) === 47 /*/*/;\n    var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;\n\n    // Normalize the path\n    path = normalizeStringPosix(path, !isAbsolute);\n\n    if (path.length === 0 && !isAbsolute) path = '.';\n    if (path.length > 0 && trailingSeparator) path += '/';\n\n    if (isAbsolute) return '/' + path;\n    return path;\n  },\n\n  isAbsolute: function isAbsolute(path) {\n    assertPath(path);\n    return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;\n  },\n\n  join: function join() {\n    if (arguments.length === 0)\n      return '.';\n    var joined;\n    for (var i = 0; i < arguments.length; ++i) {\n      var arg = arguments[i];\n      assertPath(arg);\n      if (arg.length > 0) {\n        if (joined === undefined)\n          joined = arg;\n        else\n          joined += '/' + arg;\n      }\n    }\n    if (joined === undefined)\n      return '.';\n    return posix.normalize(joined);\n  },\n\n  relative: function relative(from, to) {\n    assertPath(from);\n    assertPath(to);\n\n    if (from === to) return '';\n\n    from = posix.resolve(from);\n    to = posix.resolve(to);\n\n    if (from === to) return '';\n\n    // Trim any leading backslashes\n    var fromStart = 1;\n    for (; fromStart < from.length; ++fromStart) {\n      if (from.charCodeAt(fromStart) !== 47 /*/*/)\n        break;\n    }\n    var fromEnd = from.length;\n    var fromLen = fromEnd - fromStart;\n\n    // Trim any leading backslashes\n    var toStart = 1;\n    for (; toStart < to.length; ++toStart) {\n      if (to.charCodeAt(toStart) !== 47 /*/*/)\n        break;\n    }\n    var toEnd = to.length;\n    var toLen = toEnd - toStart;\n\n    // Compare paths to find the longest common path from root\n    var length = fromLen < toLen ? fromLen : toLen;\n    var lastCommonSep = -1;\n    var i = 0;\n    for (; i <= length; ++i) {\n      if (i === length) {\n        if (toLen > length) {\n          if (to.charCodeAt(toStart + i) === 47 /*/*/) {\n            // We get here if `from` is the exact base path for `to`.\n            // For example: from='/foo/bar'; to='/foo/bar/baz'\n            return to.slice(toStart + i + 1);\n          } else if (i === 0) {\n            // We get here if `from` is the root\n            // For example: from='/'; to='/foo'\n            return to.slice(toStart + i);\n          }\n        } else if (fromLen > length) {\n          if (from.charCodeAt(fromStart + i) === 47 /*/*/) {\n            // We get here if `to` is the exact base path for `from`.\n            // For example: from='/foo/bar/baz'; to='/foo/bar'\n            lastCommonSep = i;\n          } else if (i === 0) {\n            // We get here if `to` is the root.\n            // For example: from='/foo'; to='/'\n            lastCommonSep = 0;\n          }\n        }\n        break;\n      }\n      var fromCode = from.charCodeAt(fromStart + i);\n      var toCode = to.charCodeAt(toStart + i);\n      if (fromCode !== toCode)\n        break;\n      else if (fromCode === 47 /*/*/)\n        lastCommonSep = i;\n    }\n\n    var out = '';\n    // Generate the relative path based on the path difference between `to`\n    // and `from`\n    for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {\n      if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {\n        if (out.length === 0)\n          out += '..';\n        else\n          out += '/..';\n      }\n    }\n\n    // Lastly, append the rest of the destination (`to`) path that comes after\n    // the common path parts\n    if (out.length > 0)\n      return out + to.slice(toStart + lastCommonSep);\n    else {\n      toStart += lastCommonSep;\n      if (to.charCodeAt(toStart) === 47 /*/*/)\n        ++toStart;\n      return to.slice(toStart);\n    }\n  },\n\n  _makeLong: function _makeLong(path) {\n    return path;\n  },\n\n  dirname: function dirname(path) {\n    assertPath(path);\n    if (path.length === 0) return '.';\n    var code = path.charCodeAt(0);\n    var hasRoot = code === 47 /*/*/;\n    var end = -1;\n    var matchedSlash = true;\n    for (var i = path.length - 1; i >= 1; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          if (!matchedSlash) {\n            end = i;\n            break;\n          }\n        } else {\n        // We saw the first non-path separator\n        matchedSlash = false;\n      }\n    }\n\n    if (end === -1) return hasRoot ? '/' : '.';\n    if (hasRoot && end === 1) return '//';\n    return path.slice(0, end);\n  },\n\n  basename: function basename(path, ext) {\n    if (ext !== undefined && typeof ext !== 'string') throw new TypeError('\"ext\" argument must be a string');\n    assertPath(path);\n\n    var start = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i;\n\n    if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n      if (ext.length === path.length && ext === path) return '';\n      var extIdx = ext.length - 1;\n      var firstNonSlashEnd = -1;\n      for (i = path.length - 1; i >= 0; --i) {\n        var code = path.charCodeAt(i);\n        if (code === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else {\n          if (firstNonSlashEnd === -1) {\n            // We saw the first non-path separator, remember this index in case\n            // we need it if the extension ends up not matching\n            matchedSlash = false;\n            firstNonSlashEnd = i + 1;\n          }\n          if (extIdx >= 0) {\n            // Try to match the explicit extension\n            if (code === ext.charCodeAt(extIdx)) {\n              if (--extIdx === -1) {\n                // We matched the extension, so mark this as the end of our path\n                // component\n                end = i;\n              }\n            } else {\n              // Extension does not match, so our result is the entire path\n              // component\n              extIdx = -1;\n              end = firstNonSlashEnd;\n            }\n          }\n        }\n      }\n\n      if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;\n      return path.slice(start, end);\n    } else {\n      for (i = path.length - 1; i >= 0; --i) {\n        if (path.charCodeAt(i) === 47 /*/*/) {\n            // If we reached a path separator that was not part of a set of path\n            // separators at the end of the string, stop now\n            if (!matchedSlash) {\n              start = i + 1;\n              break;\n            }\n          } else if (end === -1) {\n          // We saw the first non-path separator, mark this as the end of our\n          // path component\n          matchedSlash = false;\n          end = i + 1;\n        }\n      }\n\n      if (end === -1) return '';\n      return path.slice(start, end);\n    }\n  },\n\n  extname: function extname(path) {\n    assertPath(path);\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n    for (var i = path.length - 1; i >= 0; --i) {\n      var code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1)\n            startDot = i;\n          else if (preDotState !== 1)\n            preDotState = 1;\n      } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n        // We saw a non-dot character immediately before the dot\n        preDotState === 0 ||\n        // The (right-most) trimmed path component is exactly '..'\n        preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      return '';\n    }\n    return path.slice(startDot, end);\n  },\n\n  format: function format(pathObject) {\n    if (pathObject === null || typeof pathObject !== 'object') {\n      throw new TypeError('The \"pathObject\" argument must be of type Object. Received type ' + typeof pathObject);\n    }\n    return _format('/', pathObject);\n  },\n\n  parse: function parse(path) {\n    assertPath(path);\n\n    var ret = { root: '', dir: '', base: '', ext: '', name: '' };\n    if (path.length === 0) return ret;\n    var code = path.charCodeAt(0);\n    var isAbsolute = code === 47 /*/*/;\n    var start;\n    if (isAbsolute) {\n      ret.root = '/';\n      start = 1;\n    } else {\n      start = 0;\n    }\n    var startDot = -1;\n    var startPart = 0;\n    var end = -1;\n    var matchedSlash = true;\n    var i = path.length - 1;\n\n    // Track the state of characters (if any) we see before our first dot and\n    // after any path separator we find\n    var preDotState = 0;\n\n    // Get non-dir info\n    for (; i >= start; --i) {\n      code = path.charCodeAt(i);\n      if (code === 47 /*/*/) {\n          // If we reached a path separator that was not part of a set of path\n          // separators at the end of the string, stop now\n          if (!matchedSlash) {\n            startPart = i + 1;\n            break;\n          }\n          continue;\n        }\n      if (end === -1) {\n        // We saw the first non-path separator, mark this as the end of our\n        // extension\n        matchedSlash = false;\n        end = i + 1;\n      }\n      if (code === 46 /*.*/) {\n          // If this is our first dot, mark it as the start of our extension\n          if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;\n        } else if (startDot !== -1) {\n        // We saw a non-dot and non-path separator before our dot, so we should\n        // have a good chance at having a non-empty extension\n        preDotState = -1;\n      }\n    }\n\n    if (startDot === -1 || end === -1 ||\n    // We saw a non-dot character immediately before the dot\n    preDotState === 0 ||\n    // The (right-most) trimmed path component is exactly '..'\n    preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {\n      if (end !== -1) {\n        if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);\n      }\n    } else {\n      if (startPart === 0 && isAbsolute) {\n        ret.name = path.slice(1, startDot);\n        ret.base = path.slice(1, end);\n      } else {\n        ret.name = path.slice(startPart, startDot);\n        ret.base = path.slice(startPart, end);\n      }\n      ret.ext = path.slice(startDot, end);\n    }\n\n    if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';\n\n    return ret;\n  },\n\n  sep: '/',\n  delimiter: ':',\n  win32: null,\n  posix: null\n};\n\nposix.posix = posix;\n\nmodule.exports = posix;\n\n\n//# sourceURL=webpack:///../../node_modules/path-browserify/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/pathval/index.js":
  /*!*******************************************!*\
    !*** ../../node_modules/pathval/index.js ***!
    \*******************************************/
  /***/ ((module) => {
  
  "use strict";
  eval("\n\n/* !\n * Chai - pathval utility\n * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>\n * @see https://github.com/logicalparadox/filtr\n * MIT Licensed\n */\n\n/**\n * ### .hasProperty(object, name)\n *\n * This allows checking whether an object has own\n * or inherited from prototype chain named property.\n *\n * Basically does the same thing as the `in`\n * operator but works properly with null/undefined values\n * and other primitives.\n *\n *     var obj = {\n *         arr: ['a', 'b', 'c']\n *       , str: 'Hello'\n *     }\n *\n * The following would be the results.\n *\n *     hasProperty(obj, 'str');  // true\n *     hasProperty(obj, 'constructor');  // true\n *     hasProperty(obj, 'bar');  // false\n *\n *     hasProperty(obj.str, 'length'); // true\n *     hasProperty(obj.str, 1);  // true\n *     hasProperty(obj.str, 5);  // false\n *\n *     hasProperty(obj.arr, 'length');  // true\n *     hasProperty(obj.arr, 2);  // true\n *     hasProperty(obj.arr, 3);  // false\n *\n * @param {Object} object\n * @param {String|Symbol} name\n * @returns {Boolean} whether it exists\n * @namespace Utils\n * @name hasProperty\n * @api public\n */\n\nfunction hasProperty(obj, name) {\n  if (typeof obj === 'undefined' || obj === null) {\n    return false;\n  }\n\n  // The `in` operator does not work with primitives.\n  return name in Object(obj);\n}\n\n/* !\n * ## parsePath(path)\n *\n * Helper function used to parse string object\n * paths. Use in conjunction with `internalGetPathValue`.\n *\n *      var parsed = parsePath('myobject.property.subprop');\n *\n * ### Paths:\n *\n * * Can be infinitely deep and nested.\n * * Arrays are also valid using the formal `myobject.document[3].property`.\n * * Literal dots and brackets (not delimiter) must be backslash-escaped.\n *\n * @param {String} path\n * @returns {Object} parsed\n * @api private\n */\n\nfunction parsePath(path) {\n  var str = path.replace(/([^\\\\])\\[/g, '$1.[');\n  var parts = str.match(/(\\\\\\.|[^.]+?)+/g);\n  return parts.map(function mapMatches(value) {\n    if (\n      value === 'constructor' ||\n      value === '__proto__' ||\n      value === 'prototype'\n    ) {\n      return {};\n    }\n    var regexp = /^\\[(\\d+)\\]$/;\n    var mArr = regexp.exec(value);\n    var parsed = null;\n    if (mArr) {\n      parsed = { i: parseFloat(mArr[1]) };\n    } else {\n      parsed = { p: value.replace(/\\\\([.[\\]])/g, '$1') };\n    }\n\n    return parsed;\n  });\n}\n\n/* !\n * ## internalGetPathValue(obj, parsed[, pathDepth])\n *\n * Helper companion function for `.parsePath` that returns\n * the value located at the parsed address.\n *\n *      var value = getPathValue(obj, parsed);\n *\n * @param {Object} object to search against\n * @param {Object} parsed definition from `parsePath`.\n * @param {Number} depth (nesting level) of the property we want to retrieve\n * @returns {Object|Undefined} value\n * @api private\n */\n\nfunction internalGetPathValue(obj, parsed, pathDepth) {\n  var temporaryValue = obj;\n  var res = null;\n  pathDepth = typeof pathDepth === 'undefined' ? parsed.length : pathDepth;\n\n  for (var i = 0; i < pathDepth; i++) {\n    var part = parsed[i];\n    if (temporaryValue) {\n      if (typeof part.p === 'undefined') {\n        temporaryValue = temporaryValue[part.i];\n      } else {\n        temporaryValue = temporaryValue[part.p];\n      }\n\n      if (i === pathDepth - 1) {\n        res = temporaryValue;\n      }\n    }\n  }\n\n  return res;\n}\n\n/* !\n * ## internalSetPathValue(obj, value, parsed)\n *\n * Companion function for `parsePath` that sets\n * the value located at a parsed address.\n *\n *  internalSetPathValue(obj, 'value', parsed);\n *\n * @param {Object} object to search and define on\n * @param {*} value to use upon set\n * @param {Object} parsed definition from `parsePath`\n * @api private\n */\n\nfunction internalSetPathValue(obj, val, parsed) {\n  var tempObj = obj;\n  var pathDepth = parsed.length;\n  var part = null;\n  // Here we iterate through every part of the path\n  for (var i = 0; i < pathDepth; i++) {\n    var propName = null;\n    var propVal = null;\n    part = parsed[i];\n\n    // If it's the last part of the path, we set the 'propName' value with the property name\n    if (i === pathDepth - 1) {\n      propName = typeof part.p === 'undefined' ? part.i : part.p;\n      // Now we set the property with the name held by 'propName' on object with the desired val\n      tempObj[propName] = val;\n    } else if (typeof part.p !== 'undefined' && tempObj[part.p]) {\n      tempObj = tempObj[part.p];\n    } else if (typeof part.i !== 'undefined' && tempObj[part.i]) {\n      tempObj = tempObj[part.i];\n    } else {\n      // If the obj doesn't have the property we create one with that name to define it\n      var next = parsed[i + 1];\n      // Here we set the name of the property which will be defined\n      propName = typeof part.p === 'undefined' ? part.i : part.p;\n      // Here we decide if this property will be an array or a new object\n      propVal = typeof next.p === 'undefined' ? [] : {};\n      tempObj[propName] = propVal;\n      tempObj = tempObj[propName];\n    }\n  }\n}\n\n/**\n * ### .getPathInfo(object, path)\n *\n * This allows the retrieval of property info in an\n * object given a string path.\n *\n * The path info consists of an object with the\n * following properties:\n *\n * * parent - The parent object of the property referenced by `path`\n * * name - The name of the final property, a number if it was an array indexer\n * * value - The value of the property, if it exists, otherwise `undefined`\n * * exists - Whether the property exists or not\n *\n * @param {Object} object\n * @param {String} path\n * @returns {Object} info\n * @namespace Utils\n * @name getPathInfo\n * @api public\n */\n\nfunction getPathInfo(obj, path) {\n  var parsed = parsePath(path);\n  var last = parsed[parsed.length - 1];\n  var info = {\n    parent:\n      parsed.length > 1 ?\n        internalGetPathValue(obj, parsed, parsed.length - 1) :\n        obj,\n    name: last.p || last.i,\n    value: internalGetPathValue(obj, parsed),\n  };\n  info.exists = hasProperty(info.parent, info.name);\n\n  return info;\n}\n\n/**\n * ### .getPathValue(object, path)\n *\n * This allows the retrieval of values in an\n * object given a string path.\n *\n *     var obj = {\n *         prop1: {\n *             arr: ['a', 'b', 'c']\n *           , str: 'Hello'\n *         }\n *       , prop2: {\n *             arr: [ { nested: 'Universe' } ]\n *           , str: 'Hello again!'\n *         }\n *     }\n *\n * The following would be the results.\n *\n *     getPathValue(obj, 'prop1.str'); // Hello\n *     getPathValue(obj, 'prop1.att[2]'); // b\n *     getPathValue(obj, 'prop2.arr[0].nested'); // Universe\n *\n * @param {Object} object\n * @param {String} path\n * @returns {Object} value or `undefined`\n * @namespace Utils\n * @name getPathValue\n * @api public\n */\n\nfunction getPathValue(obj, path) {\n  var info = getPathInfo(obj, path);\n  return info.value;\n}\n\n/**\n * ### .setPathValue(object, path, value)\n *\n * Define the value in an object at a given string path.\n *\n * ```js\n * var obj = {\n *     prop1: {\n *         arr: ['a', 'b', 'c']\n *       , str: 'Hello'\n *     }\n *   , prop2: {\n *         arr: [ { nested: 'Universe' } ]\n *       , str: 'Hello again!'\n *     }\n * };\n * ```\n *\n * The following would be acceptable.\n *\n * ```js\n * var properties = require('tea-properties');\n * properties.set(obj, 'prop1.str', 'Hello Universe!');\n * properties.set(obj, 'prop1.arr[2]', 'B');\n * properties.set(obj, 'prop2.arr[0].nested.value', { hello: 'universe' });\n * ```\n *\n * @param {Object} object\n * @param {String} path\n * @param {Mixed} value\n * @api private\n */\n\nfunction setPathValue(obj, path, val) {\n  var parsed = parsePath(path);\n  internalSetPathValue(obj, val, parsed);\n  return obj;\n}\n\nmodule.exports = {\n  hasProperty: hasProperty,\n  getPathInfo: getPathInfo,\n  getPathValue: getPathValue,\n  setPathValue: setPathValue,\n};\n\n\n//# sourceURL=webpack:///../../node_modules/pathval/index.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/type-detect/type-detect.js":
  /*!*****************************************************!*\
    !*** ../../node_modules/type-detect/type-detect.js ***!
    \*****************************************************/
  /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
  
  eval("(function (global, factory) {\n\t true ? module.exports = factory() :\n\t0;\n}(this, (function () { 'use strict';\n\n/* !\n * type-detect\n * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>\n * MIT Licensed\n */\nvar promiseExists = typeof Promise === 'function';\n\n/* eslint-disable no-undef */\nvar globalObject = typeof self === 'object' ? self : __webpack_require__.g; // eslint-disable-line id-blacklist\n\nvar symbolExists = typeof Symbol !== 'undefined';\nvar mapExists = typeof Map !== 'undefined';\nvar setExists = typeof Set !== 'undefined';\nvar weakMapExists = typeof WeakMap !== 'undefined';\nvar weakSetExists = typeof WeakSet !== 'undefined';\nvar dataViewExists = typeof DataView !== 'undefined';\nvar symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined';\nvar symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined';\nvar setEntriesExists = setExists && typeof Set.prototype.entries === 'function';\nvar mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function';\nvar setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries());\nvar mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries());\nvar arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function';\nvar arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]());\nvar stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function';\nvar stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]());\nvar toStringLeftSliceLength = 8;\nvar toStringRightSliceLength = -1;\n/**\n * ### typeOf (obj)\n *\n * Uses `Object.prototype.toString` to determine the type of an object,\n * normalising behaviour across engine versions & well optimised.\n *\n * @param {Mixed} object\n * @return {String} object type\n * @api public\n */\nfunction typeDetect(obj) {\n  /* ! Speed optimisation\n   * Pre:\n   *   string literal     x 3,039,035 ops/sec ±1.62% (78 runs sampled)\n   *   boolean literal    x 1,424,138 ops/sec ±4.54% (75 runs sampled)\n   *   number literal     x 1,653,153 ops/sec ±1.91% (82 runs sampled)\n   *   undefined          x 9,978,660 ops/sec ±1.92% (75 runs sampled)\n   *   function           x 2,556,769 ops/sec ±1.73% (77 runs sampled)\n   * Post:\n   *   string literal     x 38,564,796 ops/sec ±1.15% (79 runs sampled)\n   *   boolean literal    x 31,148,940 ops/sec ±1.10% (79 runs sampled)\n   *   number literal     x 32,679,330 ops/sec ±1.90% (78 runs sampled)\n   *   undefined          x 32,363,368 ops/sec ±1.07% (82 runs sampled)\n   *   function           x 31,296,870 ops/sec ±0.96% (83 runs sampled)\n   */\n  var typeofObj = typeof obj;\n  if (typeofObj !== 'object') {\n    return typeofObj;\n  }\n\n  /* ! Speed optimisation\n   * Pre:\n   *   null               x 28,645,765 ops/sec ±1.17% (82 runs sampled)\n   * Post:\n   *   null               x 36,428,962 ops/sec ±1.37% (84 runs sampled)\n   */\n  if (obj === null) {\n    return 'null';\n  }\n\n  /* ! Spec Conformance\n   * Test: `Object.prototype.toString.call(window)``\n   *  - Node === \"[object global]\"\n   *  - Chrome === \"[object global]\"\n   *  - Firefox === \"[object Window]\"\n   *  - PhantomJS === \"[object Window]\"\n   *  - Safari === \"[object Window]\"\n   *  - IE 11 === \"[object Window]\"\n   *  - IE Edge === \"[object Window]\"\n   * Test: `Object.prototype.toString.call(this)``\n   *  - Chrome Worker === \"[object global]\"\n   *  - Firefox Worker === \"[object DedicatedWorkerGlobalScope]\"\n   *  - Safari Worker === \"[object DedicatedWorkerGlobalScope]\"\n   *  - IE 11 Worker === \"[object WorkerGlobalScope]\"\n   *  - IE Edge Worker === \"[object WorkerGlobalScope]\"\n   */\n  if (obj === globalObject) {\n    return 'global';\n  }\n\n  /* ! Speed optimisation\n   * Pre:\n   *   array literal      x 2,888,352 ops/sec ±0.67% (82 runs sampled)\n   * Post:\n   *   array literal      x 22,479,650 ops/sec ±0.96% (81 runs sampled)\n   */\n  if (\n    Array.isArray(obj) &&\n    (symbolToStringTagExists === false || !(Symbol.toStringTag in obj))\n  ) {\n    return 'Array';\n  }\n\n  // Not caching existence of `window` and related properties due to potential\n  // for `window` to be unset before tests in quasi-browser environments.\n  if (typeof window === 'object' && window !== null) {\n    /* ! Spec Conformance\n     * (https://html.spec.whatwg.org/multipage/browsers.html#location)\n     * WhatWG HTML$7.7.3 - The `Location` interface\n     * Test: `Object.prototype.toString.call(window.location)``\n     *  - IE <=11 === \"[object Object]\"\n     *  - IE Edge <=13 === \"[object Object]\"\n     */\n    if (typeof window.location === 'object' && obj === window.location) {\n      return 'Location';\n    }\n\n    /* ! Spec Conformance\n     * (https://html.spec.whatwg.org/#document)\n     * WhatWG HTML$3.1.1 - The `Document` object\n     * Note: Most browsers currently adher to the W3C DOM Level 2 spec\n     *       (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268)\n     *       which suggests that browsers should use HTMLTableCellElement for\n     *       both TD and TH elements. WhatWG separates these.\n     *       WhatWG HTML states:\n     *         > For historical reasons, Window objects must also have a\n     *         > writable, configurable, non-enumerable property named\n     *         > HTMLDocument whose value is the Document interface object.\n     * Test: `Object.prototype.toString.call(document)``\n     *  - Chrome === \"[object HTMLDocument]\"\n     *  - Firefox === \"[object HTMLDocument]\"\n     *  - Safari === \"[object HTMLDocument]\"\n     *  - IE <=10 === \"[object Document]\"\n     *  - IE 11 === \"[object HTMLDocument]\"\n     *  - IE Edge <=13 === \"[object HTMLDocument]\"\n     */\n    if (typeof window.document === 'object' && obj === window.document) {\n      return 'Document';\n    }\n\n    if (typeof window.navigator === 'object') {\n      /* ! Spec Conformance\n       * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray)\n       * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray\n       * Test: `Object.prototype.toString.call(navigator.mimeTypes)``\n       *  - IE <=10 === \"[object MSMimeTypesCollection]\"\n       */\n      if (typeof window.navigator.mimeTypes === 'object' &&\n          obj === window.navigator.mimeTypes) {\n        return 'MimeTypeArray';\n      }\n\n      /* ! Spec Conformance\n       * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray)\n       * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray\n       * Test: `Object.prototype.toString.call(navigator.plugins)``\n       *  - IE <=10 === \"[object MSPluginsCollection]\"\n       */\n      if (typeof window.navigator.plugins === 'object' &&\n          obj === window.navigator.plugins) {\n        return 'PluginArray';\n      }\n    }\n\n    if ((typeof window.HTMLElement === 'function' ||\n        typeof window.HTMLElement === 'object') &&\n        obj instanceof window.HTMLElement) {\n      /* ! Spec Conformance\n      * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray)\n      * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement`\n      * Test: `Object.prototype.toString.call(document.createElement('blockquote'))``\n      *  - IE <=10 === \"[object HTMLBlockElement]\"\n      */\n      if (obj.tagName === 'BLOCKQUOTE') {\n        return 'HTMLQuoteElement';\n      }\n\n      /* ! Spec Conformance\n       * (https://html.spec.whatwg.org/#htmltabledatacellelement)\n       * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement`\n       * Note: Most browsers currently adher to the W3C DOM Level 2 spec\n       *       (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075)\n       *       which suggests that browsers should use HTMLTableCellElement for\n       *       both TD and TH elements. WhatWG separates these.\n       * Test: Object.prototype.toString.call(document.createElement('td'))\n       *  - Chrome === \"[object HTMLTableCellElement]\"\n       *  - Firefox === \"[object HTMLTableCellElement]\"\n       *  - Safari === \"[object HTMLTableCellElement]\"\n       */\n      if (obj.tagName === 'TD') {\n        return 'HTMLTableDataCellElement';\n      }\n\n      /* ! Spec Conformance\n       * (https://html.spec.whatwg.org/#htmltableheadercellelement)\n       * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement`\n       * Note: Most browsers currently adher to the W3C DOM Level 2 spec\n       *       (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075)\n       *       which suggests that browsers should use HTMLTableCellElement for\n       *       both TD and TH elements. WhatWG separates these.\n       * Test: Object.prototype.toString.call(document.createElement('th'))\n       *  - Chrome === \"[object HTMLTableCellElement]\"\n       *  - Firefox === \"[object HTMLTableCellElement]\"\n       *  - Safari === \"[object HTMLTableCellElement]\"\n       */\n      if (obj.tagName === 'TH') {\n        return 'HTMLTableHeaderCellElement';\n      }\n    }\n  }\n\n  /* ! Speed optimisation\n  * Pre:\n  *   Float64Array       x 625,644 ops/sec ±1.58% (80 runs sampled)\n  *   Float32Array       x 1,279,852 ops/sec ±2.91% (77 runs sampled)\n  *   Uint32Array        x 1,178,185 ops/sec ±1.95% (83 runs sampled)\n  *   Uint16Array        x 1,008,380 ops/sec ±2.25% (80 runs sampled)\n  *   Uint8Array         x 1,128,040 ops/sec ±2.11% (81 runs sampled)\n  *   Int32Array         x 1,170,119 ops/sec ±2.88% (80 runs sampled)\n  *   Int16Array         x 1,176,348 ops/sec ±5.79% (86 runs sampled)\n  *   Int8Array          x 1,058,707 ops/sec ±4.94% (77 runs sampled)\n  *   Uint8ClampedArray  x 1,110,633 ops/sec ±4.20% (80 runs sampled)\n  * Post:\n  *   Float64Array       x 7,105,671 ops/sec ±13.47% (64 runs sampled)\n  *   Float32Array       x 5,887,912 ops/sec ±1.46% (82 runs sampled)\n  *   Uint32Array        x 6,491,661 ops/sec ±1.76% (79 runs sampled)\n  *   Uint16Array        x 6,559,795 ops/sec ±1.67% (82 runs sampled)\n  *   Uint8Array         x 6,463,966 ops/sec ±1.43% (85 runs sampled)\n  *   Int32Array         x 5,641,841 ops/sec ±3.49% (81 runs sampled)\n  *   Int16Array         x 6,583,511 ops/sec ±1.98% (80 runs sampled)\n  *   Int8Array          x 6,606,078 ops/sec ±1.74% (81 runs sampled)\n  *   Uint8ClampedArray  x 6,602,224 ops/sec ±1.77% (83 runs sampled)\n  */\n  var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]);\n  if (typeof stringTag === 'string') {\n    return stringTag;\n  }\n\n  var objPrototype = Object.getPrototypeOf(obj);\n  /* ! Speed optimisation\n  * Pre:\n  *   regex literal      x 1,772,385 ops/sec ±1.85% (77 runs sampled)\n  *   regex constructor  x 2,143,634 ops/sec ±2.46% (78 runs sampled)\n  * Post:\n  *   regex literal      x 3,928,009 ops/sec ±0.65% (78 runs sampled)\n  *   regex constructor  x 3,931,108 ops/sec ±0.58% (84 runs sampled)\n  */\n  if (objPrototype === RegExp.prototype) {\n    return 'RegExp';\n  }\n\n  /* ! Speed optimisation\n  * Pre:\n  *   date               x 2,130,074 ops/sec ±4.42% (68 runs sampled)\n  * Post:\n  *   date               x 3,953,779 ops/sec ±1.35% (77 runs sampled)\n  */\n  if (objPrototype === Date.prototype) {\n    return 'Date';\n  }\n\n  /* ! Spec Conformance\n   * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag)\n   * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be \"Promise\":\n   * Test: `Object.prototype.toString.call(Promise.resolve())``\n   *  - Chrome <=47 === \"[object Object]\"\n   *  - Edge <=20 === \"[object Object]\"\n   *  - Firefox 29-Latest === \"[object Promise]\"\n   *  - Safari 7.1-Latest === \"[object Promise]\"\n   */\n  if (promiseExists && objPrototype === Promise.prototype) {\n    return 'Promise';\n  }\n\n  /* ! Speed optimisation\n  * Pre:\n  *   set                x 2,222,186 ops/sec ±1.31% (82 runs sampled)\n  * Post:\n  *   set                x 4,545,879 ops/sec ±1.13% (83 runs sampled)\n  */\n  if (setExists && objPrototype === Set.prototype) {\n    return 'Set';\n  }\n\n  /* ! Speed optimisation\n  * Pre:\n  *   map                x 2,396,842 ops/sec ±1.59% (81 runs sampled)\n  * Post:\n  *   map                x 4,183,945 ops/sec ±6.59% (82 runs sampled)\n  */\n  if (mapExists && objPrototype === Map.prototype) {\n    return 'Map';\n  }\n\n  /* ! Speed optimisation\n  * Pre:\n  *   weakset            x 1,323,220 ops/sec ±2.17% (76 runs sampled)\n  * Post:\n  *   weakset            x 4,237,510 ops/sec ±2.01% (77 runs sampled)\n  */\n  if (weakSetExists && objPrototype === WeakSet.prototype) {\n    return 'WeakSet';\n  }\n\n  /* ! Speed optimisation\n  * Pre:\n  *   weakmap            x 1,500,260 ops/sec ±2.02% (78 runs sampled)\n  * Post:\n  *   weakmap            x 3,881,384 ops/sec ±1.45% (82 runs sampled)\n  */\n  if (weakMapExists && objPrototype === WeakMap.prototype) {\n    return 'WeakMap';\n  }\n\n  /* ! Spec Conformance\n   * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag)\n   * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be \"DataView\":\n   * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))``\n   *  - Edge <=13 === \"[object Object]\"\n   */\n  if (dataViewExists && objPrototype === DataView.prototype) {\n    return 'DataView';\n  }\n\n  /* ! Spec Conformance\n   * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag)\n   * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be \"Map Iterator\":\n   * Test: `Object.prototype.toString.call(new Map().entries())``\n   *  - Edge <=13 === \"[object Object]\"\n   */\n  if (mapExists && objPrototype === mapIteratorPrototype) {\n    return 'Map Iterator';\n  }\n\n  /* ! Spec Conformance\n   * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag)\n   * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be \"Set Iterator\":\n   * Test: `Object.prototype.toString.call(new Set().entries())``\n   *  - Edge <=13 === \"[object Object]\"\n   */\n  if (setExists && objPrototype === setIteratorPrototype) {\n    return 'Set Iterator';\n  }\n\n  /* ! Spec Conformance\n   * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag)\n   * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be \"Array Iterator\":\n   * Test: `Object.prototype.toString.call([][Symbol.iterator]())``\n   *  - Edge <=13 === \"[object Object]\"\n   */\n  if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) {\n    return 'Array Iterator';\n  }\n\n  /* ! Spec Conformance\n   * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag)\n   * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be \"String Iterator\":\n   * Test: `Object.prototype.toString.call(''[Symbol.iterator]())``\n   *  - Edge <=13 === \"[object Object]\"\n   */\n  if (stringIteratorExists && objPrototype === stringIteratorPrototype) {\n    return 'String Iterator';\n  }\n\n  /* ! Speed optimisation\n  * Pre:\n  *   object from null   x 2,424,320 ops/sec ±1.67% (76 runs sampled)\n  * Post:\n  *   object from null   x 5,838,000 ops/sec ±0.99% (84 runs sampled)\n  */\n  if (objPrototype === null) {\n    return 'Object';\n  }\n\n  return Object\n    .prototype\n    .toString\n    .call(obj)\n    .slice(toStringLeftSliceLength, toStringRightSliceLength);\n}\n\nreturn typeDetect;\n\n})));\n\n\n//# sourceURL=webpack:///../../node_modules/type-detect/type-detect.js?");
  
  /***/ }),
  
  /***/ "../../node_modules/whatwg-fetch/fetch.js":
  /*!************************************************!*\
    !*** ../../node_modules/whatwg-fetch/fetch.js ***!
    \************************************************/
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  
  "use strict";
  eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"DOMException\": () => (/* binding */ DOMException),\n/* harmony export */   \"Headers\": () => (/* binding */ Headers),\n/* harmony export */   \"Request\": () => (/* binding */ Request),\n/* harmony export */   \"Response\": () => (/* binding */ Response),\n/* harmony export */   \"fetch\": () => (/* binding */ fetch)\n/* harmony export */ });\nvar global =\n  (typeof globalThis !== 'undefined' && globalThis) ||\n  (typeof self !== 'undefined' && self) ||\n  (typeof global !== 'undefined' && global)\n\nvar support = {\n  searchParams: 'URLSearchParams' in global,\n  iterable: 'Symbol' in global && 'iterator' in Symbol,\n  blob:\n    'FileReader' in global &&\n    'Blob' in global &&\n    (function() {\n      try {\n        new Blob()\n        return true\n      } catch (e) {\n        return false\n      }\n    })(),\n  formData: 'FormData' in global,\n  arrayBuffer: 'ArrayBuffer' in global\n}\n\nfunction isDataView(obj) {\n  return obj && DataView.prototype.isPrototypeOf(obj)\n}\n\nif (support.arrayBuffer) {\n  var viewClasses = [\n    '[object Int8Array]',\n    '[object Uint8Array]',\n    '[object Uint8ClampedArray]',\n    '[object Int16Array]',\n    '[object Uint16Array]',\n    '[object Int32Array]',\n    '[object Uint32Array]',\n    '[object Float32Array]',\n    '[object Float64Array]'\n  ]\n\n  var isArrayBufferView =\n    ArrayBuffer.isView ||\n    function(obj) {\n      return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1\n    }\n}\n\nfunction normalizeName(name) {\n  if (typeof name !== 'string') {\n    name = String(name)\n  }\n  if (/[^a-z0-9\\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {\n    throw new TypeError('Invalid character in header field name: \"' + name + '\"')\n  }\n  return name.toLowerCase()\n}\n\nfunction normalizeValue(value) {\n  if (typeof value !== 'string') {\n    value = String(value)\n  }\n  return value\n}\n\n// Build a destructive iterator for the value list\nfunction iteratorFor(items) {\n  var iterator = {\n    next: function() {\n      var value = items.shift()\n      return {done: value === undefined, value: value}\n    }\n  }\n\n  if (support.iterable) {\n    iterator[Symbol.iterator] = function() {\n      return iterator\n    }\n  }\n\n  return iterator\n}\n\nfunction Headers(headers) {\n  this.map = {}\n\n  if (headers instanceof Headers) {\n    headers.forEach(function(value, name) {\n      this.append(name, value)\n    }, this)\n  } else if (Array.isArray(headers)) {\n    headers.forEach(function(header) {\n      this.append(header[0], header[1])\n    }, this)\n  } else if (headers) {\n    Object.getOwnPropertyNames(headers).forEach(function(name) {\n      this.append(name, headers[name])\n    }, this)\n  }\n}\n\nHeaders.prototype.append = function(name, value) {\n  name = normalizeName(name)\n  value = normalizeValue(value)\n  var oldValue = this.map[name]\n  this.map[name] = oldValue ? oldValue + ', ' + value : value\n}\n\nHeaders.prototype['delete'] = function(name) {\n  delete this.map[normalizeName(name)]\n}\n\nHeaders.prototype.get = function(name) {\n  name = normalizeName(name)\n  return this.has(name) ? this.map[name] : null\n}\n\nHeaders.prototype.has = function(name) {\n  return this.map.hasOwnProperty(normalizeName(name))\n}\n\nHeaders.prototype.set = function(name, value) {\n  this.map[normalizeName(name)] = normalizeValue(value)\n}\n\nHeaders.prototype.forEach = function(callback, thisArg) {\n  for (var name in this.map) {\n    if (this.map.hasOwnProperty(name)) {\n      callback.call(thisArg, this.map[name], name, this)\n    }\n  }\n}\n\nHeaders.prototype.keys = function() {\n  var items = []\n  this.forEach(function(value, name) {\n    items.push(name)\n  })\n  return iteratorFor(items)\n}\n\nHeaders.prototype.values = function() {\n  var items = []\n  this.forEach(function(value) {\n    items.push(value)\n  })\n  return iteratorFor(items)\n}\n\nHeaders.prototype.entries = function() {\n  var items = []\n  this.forEach(function(value, name) {\n    items.push([name, value])\n  })\n  return iteratorFor(items)\n}\n\nif (support.iterable) {\n  Headers.prototype[Symbol.iterator] = Headers.prototype.entries\n}\n\nfunction consumed(body) {\n  if (body.bodyUsed) {\n    return Promise.reject(new TypeError('Already read'))\n  }\n  body.bodyUsed = true\n}\n\nfunction fileReaderReady(reader) {\n  return new Promise(function(resolve, reject) {\n    reader.onload = function() {\n      resolve(reader.result)\n    }\n    reader.onerror = function() {\n      reject(reader.error)\n    }\n  })\n}\n\nfunction readBlobAsArrayBuffer(blob) {\n  var reader = new FileReader()\n  var promise = fileReaderReady(reader)\n  reader.readAsArrayBuffer(blob)\n  return promise\n}\n\nfunction readBlobAsText(blob) {\n  var reader = new FileReader()\n  var promise = fileReaderReady(reader)\n  reader.readAsText(blob)\n  return promise\n}\n\nfunction readArrayBufferAsText(buf) {\n  var view = new Uint8Array(buf)\n  var chars = new Array(view.length)\n\n  for (var i = 0; i < view.length; i++) {\n    chars[i] = String.fromCharCode(view[i])\n  }\n  return chars.join('')\n}\n\nfunction bufferClone(buf) {\n  if (buf.slice) {\n    return buf.slice(0)\n  } else {\n    var view = new Uint8Array(buf.byteLength)\n    view.set(new Uint8Array(buf))\n    return view.buffer\n  }\n}\n\nfunction Body() {\n  this.bodyUsed = false\n\n  this._initBody = function(body) {\n    /*\n      fetch-mock wraps the Response object in an ES6 Proxy to\n      provide useful test harness features such as flush. However, on\n      ES5 browsers without fetch or Proxy support pollyfills must be used;\n      the proxy-pollyfill is unable to proxy an attribute unless it exists\n      on the object before the Proxy is created. This change ensures\n      Response.bodyUsed exists on the instance, while maintaining the\n      semantic of setting Request.bodyUsed in the constructor before\n      _initBody is called.\n    */\n    this.bodyUsed = this.bodyUsed\n    this._bodyInit = body\n    if (!body) {\n      this._bodyText = ''\n    } else if (typeof body === 'string') {\n      this._bodyText = body\n    } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {\n      this._bodyBlob = body\n    } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {\n      this._bodyFormData = body\n    } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n      this._bodyText = body.toString()\n    } else if (support.arrayBuffer && support.blob && isDataView(body)) {\n      this._bodyArrayBuffer = bufferClone(body.buffer)\n      // IE 10-11 can't handle a DataView body.\n      this._bodyInit = new Blob([this._bodyArrayBuffer])\n    } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {\n      this._bodyArrayBuffer = bufferClone(body)\n    } else {\n      this._bodyText = body = Object.prototype.toString.call(body)\n    }\n\n    if (!this.headers.get('content-type')) {\n      if (typeof body === 'string') {\n        this.headers.set('content-type', 'text/plain;charset=UTF-8')\n      } else if (this._bodyBlob && this._bodyBlob.type) {\n        this.headers.set('content-type', this._bodyBlob.type)\n      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n        this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')\n      }\n    }\n  }\n\n  if (support.blob) {\n    this.blob = function() {\n      var rejected = consumed(this)\n      if (rejected) {\n        return rejected\n      }\n\n      if (this._bodyBlob) {\n        return Promise.resolve(this._bodyBlob)\n      } else if (this._bodyArrayBuffer) {\n        return Promise.resolve(new Blob([this._bodyArrayBuffer]))\n      } else if (this._bodyFormData) {\n        throw new Error('could not read FormData body as blob')\n      } else {\n        return Promise.resolve(new Blob([this._bodyText]))\n      }\n    }\n\n    this.arrayBuffer = function() {\n      if (this._bodyArrayBuffer) {\n        var isConsumed = consumed(this)\n        if (isConsumed) {\n          return isConsumed\n        }\n        if (ArrayBuffer.isView(this._bodyArrayBuffer)) {\n          return Promise.resolve(\n            this._bodyArrayBuffer.buffer.slice(\n              this._bodyArrayBuffer.byteOffset,\n              this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength\n            )\n          )\n        } else {\n          return Promise.resolve(this._bodyArrayBuffer)\n        }\n      } else {\n        return this.blob().then(readBlobAsArrayBuffer)\n      }\n    }\n  }\n\n  this.text = function() {\n    var rejected = consumed(this)\n    if (rejected) {\n      return rejected\n    }\n\n    if (this._bodyBlob) {\n      return readBlobAsText(this._bodyBlob)\n    } else if (this._bodyArrayBuffer) {\n      return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))\n    } else if (this._bodyFormData) {\n      throw new Error('could not read FormData body as text')\n    } else {\n      return Promise.resolve(this._bodyText)\n    }\n  }\n\n  if (support.formData) {\n    this.formData = function() {\n      return this.text().then(decode)\n    }\n  }\n\n  this.json = function() {\n    return this.text().then(JSON.parse)\n  }\n\n  return this\n}\n\n// HTTP methods whose capitalization should be normalized\nvar methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']\n\nfunction normalizeMethod(method) {\n  var upcased = method.toUpperCase()\n  return methods.indexOf(upcased) > -1 ? upcased : method\n}\n\nfunction Request(input, options) {\n  if (!(this instanceof Request)) {\n    throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\n  }\n\n  options = options || {}\n  var body = options.body\n\n  if (input instanceof Request) {\n    if (input.bodyUsed) {\n      throw new TypeError('Already read')\n    }\n    this.url = input.url\n    this.credentials = input.credentials\n    if (!options.headers) {\n      this.headers = new Headers(input.headers)\n    }\n    this.method = input.method\n    this.mode = input.mode\n    this.signal = input.signal\n    if (!body && input._bodyInit != null) {\n      body = input._bodyInit\n      input.bodyUsed = true\n    }\n  } else {\n    this.url = String(input)\n  }\n\n  this.credentials = options.credentials || this.credentials || 'same-origin'\n  if (options.headers || !this.headers) {\n    this.headers = new Headers(options.headers)\n  }\n  this.method = normalizeMethod(options.method || this.method || 'GET')\n  this.mode = options.mode || this.mode || null\n  this.signal = options.signal || this.signal\n  this.referrer = null\n\n  if ((this.method === 'GET' || this.method === 'HEAD') && body) {\n    throw new TypeError('Body not allowed for GET or HEAD requests')\n  }\n  this._initBody(body)\n\n  if (this.method === 'GET' || this.method === 'HEAD') {\n    if (options.cache === 'no-store' || options.cache === 'no-cache') {\n      // Search for a '_' parameter in the query string\n      var reParamSearch = /([?&])_=[^&]*/\n      if (reParamSearch.test(this.url)) {\n        // If it already exists then set the value with the current time\n        this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime())\n      } else {\n        // Otherwise add a new '_' parameter to the end with the current time\n        var reQueryString = /\\?/\n        this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime()\n      }\n    }\n  }\n}\n\nRequest.prototype.clone = function() {\n  return new Request(this, {body: this._bodyInit})\n}\n\nfunction decode(body) {\n  var form = new FormData()\n  body\n    .trim()\n    .split('&')\n    .forEach(function(bytes) {\n      if (bytes) {\n        var split = bytes.split('=')\n        var name = split.shift().replace(/\\+/g, ' ')\n        var value = split.join('=').replace(/\\+/g, ' ')\n        form.append(decodeURIComponent(name), decodeURIComponent(value))\n      }\n    })\n  return form\n}\n\nfunction parseHeaders(rawHeaders) {\n  var headers = new Headers()\n  // Replace instances of \\r\\n and \\n followed by at least one space or horizontal tab with a space\n  // https://tools.ietf.org/html/rfc7230#section-3.2\n  var preProcessedHeaders = rawHeaders.replace(/\\r?\\n[\\t ]+/g, ' ')\n  // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill\n  // https://github.com/github/fetch/issues/748\n  // https://github.com/zloirock/core-js/issues/751\n  preProcessedHeaders\n    .split('\\r')\n    .map(function(header) {\n      return header.indexOf('\\n') === 0 ? header.substr(1, header.length) : header\n    })\n    .forEach(function(line) {\n      var parts = line.split(':')\n      var key = parts.shift().trim()\n      if (key) {\n        var value = parts.join(':').trim()\n        headers.append(key, value)\n      }\n    })\n  return headers\n}\n\nBody.call(Request.prototype)\n\nfunction Response(bodyInit, options) {\n  if (!(this instanceof Response)) {\n    throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\n  }\n  if (!options) {\n    options = {}\n  }\n\n  this.type = 'default'\n  this.status = options.status === undefined ? 200 : options.status\n  this.ok = this.status >= 200 && this.status < 300\n  this.statusText = options.statusText === undefined ? '' : '' + options.statusText\n  this.headers = new Headers(options.headers)\n  this.url = options.url || ''\n  this._initBody(bodyInit)\n}\n\nBody.call(Response.prototype)\n\nResponse.prototype.clone = function() {\n  return new Response(this._bodyInit, {\n    status: this.status,\n    statusText: this.statusText,\n    headers: new Headers(this.headers),\n    url: this.url\n  })\n}\n\nResponse.error = function() {\n  var response = new Response(null, {status: 0, statusText: ''})\n  response.type = 'error'\n  return response\n}\n\nvar redirectStatuses = [301, 302, 303, 307, 308]\n\nResponse.redirect = function(url, status) {\n  if (redirectStatuses.indexOf(status) === -1) {\n    throw new RangeError('Invalid status code')\n  }\n\n  return new Response(null, {status: status, headers: {location: url}})\n}\n\nvar DOMException = global.DOMException\ntry {\n  new DOMException()\n} catch (err) {\n  DOMException = function(message, name) {\n    this.message = message\n    this.name = name\n    var error = Error(message)\n    this.stack = error.stack\n  }\n  DOMException.prototype = Object.create(Error.prototype)\n  DOMException.prototype.constructor = DOMException\n}\n\nfunction fetch(input, init) {\n  return new Promise(function(resolve, reject) {\n    var request = new Request(input, init)\n\n    if (request.signal && request.signal.aborted) {\n      return reject(new DOMException('Aborted', 'AbortError'))\n    }\n\n    var xhr = new XMLHttpRequest()\n\n    function abortXhr() {\n      xhr.abort()\n    }\n\n    xhr.onload = function() {\n      var options = {\n        status: xhr.status,\n        statusText: xhr.statusText,\n        headers: parseHeaders(xhr.getAllResponseHeaders() || '')\n      }\n      options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')\n      var body = 'response' in xhr ? xhr.response : xhr.responseText\n      setTimeout(function() {\n        resolve(new Response(body, options))\n      }, 0)\n    }\n\n    xhr.onerror = function() {\n      setTimeout(function() {\n        reject(new TypeError('Network request failed'))\n      }, 0)\n    }\n\n    xhr.ontimeout = function() {\n      setTimeout(function() {\n        reject(new TypeError('Network request failed'))\n      }, 0)\n    }\n\n    xhr.onabort = function() {\n      setTimeout(function() {\n        reject(new DOMException('Aborted', 'AbortError'))\n      }, 0)\n    }\n\n    function fixUrl(url) {\n      try {\n        return url === '' && global.location.href ? global.location.href : url\n      } catch (e) {\n        return url\n      }\n    }\n\n    xhr.open(request.method, fixUrl(request.url), true)\n\n    if (request.credentials === 'include') {\n      xhr.withCredentials = true\n    } else if (request.credentials === 'omit') {\n      xhr.withCredentials = false\n    }\n\n    if ('responseType' in xhr) {\n      if (support.blob) {\n        xhr.responseType = 'blob'\n      } else if (\n        support.arrayBuffer &&\n        request.headers.get('Content-Type') &&\n        request.headers.get('Content-Type').indexOf('application/octet-stream') !== -1\n      ) {\n        xhr.responseType = 'arraybuffer'\n      }\n    }\n\n    if (init && typeof init.headers === 'object' && !(init.headers instanceof Headers)) {\n      Object.getOwnPropertyNames(init.headers).forEach(function(name) {\n        xhr.setRequestHeader(name, normalizeValue(init.headers[name]))\n      })\n    } else {\n      request.headers.forEach(function(value, name) {\n        xhr.setRequestHeader(name, value)\n      })\n    }\n\n    if (request.signal) {\n      request.signal.addEventListener('abort', abortXhr)\n\n      xhr.onreadystatechange = function() {\n        // DONE (success or failure)\n        if (xhr.readyState === 4) {\n          request.signal.removeEventListener('abort', abortXhr)\n        }\n      }\n    }\n\n    xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)\n  })\n}\n\nfetch.polyfill = true\n\nif (!global.fetch) {\n  global.fetch = fetch\n  global.Headers = Headers\n  global.Request = Request\n  global.Response = Response\n}\n\n\n//# sourceURL=webpack:///../../node_modules/whatwg-fetch/fetch.js?");
  
  /***/ }),
  
  /***/ "../../src/browser-store.js":
  /*!**********************************!*\
    !*** ../../src/browser-store.js ***!
    \**********************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const Store = __webpack_require__(/*! ../lib/store */ \"../../lib/store.js\");\nconst localForage = __webpack_require__(/*! localforage */ \"../../node_modules/localforage/dist/localforage.js\");\n\n\n/**\n *  <!--<% __render__ = require 'markdown' %>-->\n *\n *  BrowserStore\n *  ============================================================================\n *  This is a [Store](./store.md) object backed by the browser permanent storage\n *  ([IndexDB] or [localStorage]).\n *\n *  ```js\n *  fileStore = new BrowserStore(storeId)\n *  ```\n *\n *  - `storeId` is a name that uniquely identifies your store in the browser\n *    storage.\n *  \n *  > BrowserStore inherits from the [Store](./store.md) class and overrides the\n *  > methods described below.\n */\nclass BrowserStore extends Store {\n\n    constructor (storeId) {\n        super();\n        this.id = storeId;\n        this._backend = localForage.createInstance({\n            name: storeId,\n            version: 0.1\n        });\n    }\n\n\n    /**\n     *  async browserStore.read: String path -> String source\n     *  ----------------------------------------------------------------------------\n     *  Retrieves a document from the browser storage.\n     *\n     *  ```js\n     *  source = await browserStore.read(\"/path/to/doc\");\n     *  ```\n     *\n     *  The document path gets normalized, therefore `path/to/doc`,\n     *  `/path/to/./doc`, `/path/to/doc`, etc. refer to the same document.\n     *  \n     *  If the passed path doesn't exist, it returns an empty string.\n     */\n    async read (path) {\n        const key = this.normalizePath(path);\n        const value = await this._backend.getItem(key);\n        return value === null ? \"\" : String(value);\n    }\n\n\n\n\n    /**\n     *  async browserStore.write: (String path, String source) -> undefined\n     *  ------------------------------------------------------------------------\n     *  Maps a document path to a source, in the browser storage.\n     *\n     *  ```js\n     *  await browserStore.write(\"/path/to/doc\", source);\n     *  ```\n     *\n     *  The document path gets normalized, therefore `path/to/doc`,\n     *  `/path/to/./doc`, `/path/to/doc`, etc. refer to the same document.\n     *  \n     *  If the passed path doesn't exist, it will be created.\n     */\n    async write (path, source) {\n        const key = this.normalizePath(path);\n        const value = String(source);\n        await this._backend.setItem(key, value);\n    }\n\n\n    /**\n     *  async browserStore.delete: String path -> undefined\n     *  ------------------------------------------------------------------------\n     *  Erases the doc source mapped in the browser storage to the given path.\n     *\n     *  ```js\n     *  await browserStore.delete(\"/path/to/doc\");\n     *  ```\n     *  \n     *  The document path gets normalized, therefore `path/to/doc`,\n     *  `/path/to/./doc`, `/path/to/doc`, etc. refer to the same document.\n     *  \n     *  If the passed path doesn't exist, the methods returns silently.\n     */\n    async delete (path) {\n        const key = this.normalizePath(path);\n        await this._backend.removeItem(key);\n    }\n}\n\nmodule.exports = BrowserStore;\n\n\n/**\n *  [IndexDB]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\n *  [localStorage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage\n */\n\n\n//# sourceURL=webpack:///../../src/browser-store.js?");
  
  /***/ }),
  
  /***/ "../browser-store.js":
  /*!***************************!*\
    !*** ../browser-store.js ***!
    \***************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const describeStore = __webpack_require__(/*! ./describe-store */ \"../describe-store.js\");\nconst BrowserStore = __webpack_require__(/*! ../src/browser-store */ \"../../src/browser-store.js\");\n\ndescribeStore('BrowserStore', {\n    create: async (content) => {\n        const pathlib = __webpack_require__(/*! path */ \"../../node_modules/path-browserify/index.js\");\n        const store = new BrowserStore('testStore');\n        await store._backend.clear();\n        for (let path in content) {\n            await store._backend.setItem(pathlib.normalize(`/${path}`), String(content[path]));\n        }\n        return store;\n    }\n});\n\n\n//# sourceURL=webpack:///../browser-store.js?");
  
  /***/ }),
  
  /***/ "./index.js":
  /*!******************!*\
    !*** ./index.js ***!
    \******************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = (__webpack_require__(/*! chai */ \"../../node_modules/chai/index.js\").expect);\nconst olo = __webpack_require__(/*! ../../browser */ \"../../browser.js\");\n\nconst pathlib = __webpack_require__(/*! path */ \"../../node_modules/path-browserify/index.js\");\nconsole.log(pathlib);\n\ndescribe(\"olojs\", () => {\n        \n    __webpack_require__(/*! ../expression */ \"../expression.js\");\n    __webpack_require__(/*! ../document */ \"../document.js\");\n    __webpack_require__(/*! ../store */ \"../store.js\");\n    __webpack_require__(/*! ../memory-store */ \"../memory-store.js\");\n    __webpack_require__(/*! ../browser-store */ \"../browser-store.js\");\n    // require(\"./http-store\");\n    __webpack_require__(/*! ../router */ \"../router.js\");\n    \n    \n    describe(\"index\", () => {\n\n        it(\"should export the `expression` module\", () => {\n            expect(olo.expression).to.equal(__webpack_require__(/*! ../../lib/expression */ \"../../lib/expression.js\"));\n        });\n\n        it(\"should export the `document` module\", () => {\n            expect(olo.document).to.equal(__webpack_require__(/*! ../../lib/document */ \"../../lib/document.js\"));\n        });\n\n        it(\"should export the `Store` class\", () => {\n            expect(olo.Store).to.equal(__webpack_require__(/*! ../../lib/store */ \"../../lib/store.js\"));\n        });\n\n        it(\"should export the `MemoryStore` class\", () => {\n            expect(olo.MemoryStore).to.equal(__webpack_require__(/*! ../../lib/memory-store */ \"../../lib/memory-store.js\"));\n        });\n\n        it(\"should export the `BrowserStore` class\", () => {\n            expect(olo.BrowserStore).to.equal(__webpack_require__(/*! ../../src/browser-store */ \"../../src/browser-store.js\"));\n        });\n\n        it(\"should export the `HTTPStore` class\", () => {\n            expect(olo.HTTPStore).to.equal(__webpack_require__(/*! ../../lib/http-store */ \"../../lib/http-store.js\"));\n        });\n\n        it(\"should export the `Router` class\", () => {\n            expect(olo.Router).to.equal(__webpack_require__(/*! ../../lib/router */ \"../../lib/router.js\"));\n        });    \n    });    \n});\n\n\n//# sourceURL=webpack:///./index.js?");
  
  /***/ }),
  
  /***/ "../describe-store.js":
  /*!****************************!*\
    !*** ../describe-store.js ***!
    \****************************/
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const expect = (__webpack_require__(/*! chai */ \"../../node_modules/chai/index.js\").expect);\nconst document = __webpack_require__(/*! ../lib/document */ \"../../lib/document.js\");\nconst Store = __webpack_require__(/*! ../lib/store */ \"../../lib/store.js\");\n\n\nmodule.exports = (description, options={}) => describe(description, () => {\n    var store;\n\n    before(async () => {\n        store = await options.create({\n            \"/doc1\": \"doc @ /doc1\",\n            \"/doc2\": \"doc @ /doc2\",\n            \"/doc3\": \"doc @ /doc3\",\n            \"/path/to/\": \"doc @ /path/to/\",\n            \"/path/to/doc1\": \"doc @ /path/to/doc1\",\n            \"/path/to/doc2\": \"doc @ /path/to/doc2\",\n            \"/path/to/doc3\": \"doc @ /path/to/doc3\",\n            \"/path/to/doc7\": \"doc @ <% path : '/path/to/doc7' %>\",\n            \"/path/to/dir/doc1\": \"doc @ /path/to/dir/doc1\",\n            \"/path/to/dir/doc2\": \"doc @ /path/to/dir/doc2\",\n            \"/path/to/dir/doc3\": \"doc @ /path/to/dir/doc3\",\n        });\n    })\n\n    describe(\"source = await store.read(path)\", () => {\n\n        if (options.readAccessDenied) {\n\n            it(\"should always throw a `ReadPermissionDenied` error\", async () => {\n                try {\n                    await store.read(\"/path/to/doc1\");\n                    throw new Error(\"Id didn't throw\");\n                } catch (error) {\n                    expect(error).to.be.instanceof(Store.ReadPermissionDeniedError);\n                    expect(error.message).to.equal(\"Permission denied: READ /path/to/doc1\");\n                }\n            });\n        }\n\n        else if (options.voidStore) {\n\n            it(\"Should always return an empty document\", async () => {\n                // file path\n                var doc = await store.read(`/path/to/doc1`);\n                expect(doc).to.equal(\"\");\n\n                // directory path\n                var doc = await store.read(`/path/to/`);\n                expect(doc).to.equal(\"\")\n\n                // non-existing path\n                var doc = await store.read(`path/to/../to/doc2`);\n                expect(doc).to.equal(\"\")\n\n                // non-existing path\n                var doc = await store.read(`/non/existing/doc`);\n                expect(doc).to.equal(\"\");\n            });\n\n        } else {\n\n            it(\"should return the document stored at the normalized given path\", async () => {\n\n                // file path\n                var doc = await store.read(`/path/to/doc1`);\n                expect(doc).to.equal(\"doc @ /path/to/doc1\");\n\n                // directory path\n                var doc = await store.read(`/path/to/`);\n                expect(doc).to.equal(\"doc @ /path/to/\")\n\n                // non-normalized path\n                var doc = await store.read(`path/to/../to/doc2`);\n                expect(doc).to.equal(\"doc @ /path/to/doc2\")\n            });\n\n            it(\"should return an empty string if the path doesn't exist\", async () => {\n                var doc = await store.read(`/non/existing/doc`);\n                expect(doc).to.equal(\"\");\n            });\n        }\n    });\n\n    describe(\"await store.write(path, source)\", () => {\n\n        if (options.writeAccessDenied) {\n\n            it(\"should always throw a `ReadPermissionDenied` error\", async () => {\n                try {\n                    await store.write(\"/path/to/doc1\", \"...\");\n                    throw new Error(\"Id didn't throw\");\n                } catch (error) {\n                    expect(error).to.be.instanceof(Store.WritePermissionDeniedError);\n                    expect(error.message).to.equal(\"Permission denied: WRITE /path/to/doc1\");\n                }\n            });\n        }\n\n        else if (options.voidStore || options.readOnly) {\n\n            it(\"should always throw a `WriteOperationNotAllowed` error\", async () => {\n                try {\n                    await store.write(\"/path/to/doc1\", \"source of doc 1\");\n                    throw new Error(\"Id didn't throw\");\n                } catch (error) {\n                    expect(error).to.be.instanceof(Store.WriteOperationNotAllowedError);\n                    expect(error.message).to.equal(\"Operation not allowed: WRITE /path/to/doc1\");\n                }\n            });\n\n        } else {\n\n            it(\"should change the source of the document maped to the given path\", async () => {\n\n                // file-like path\n                expect(await store.read(`/path/to/doc1`)).to.equal(\"doc @ /path/to/doc1\");\n                await store.write(`/path/to/doc1`, \"new doc @ /path/to/doc1\");\n                expect(await store.read(`/path/to/doc1`)).to.equal(\"new doc @ /path/to/doc1\");\n\n                //directory-like path\n                expect(await store.read(`/path/to/`)).to.equal(\"doc @ /path/to/\");\n                await store.write(`/path/to/`, \"new doc @ /path/to/\");\n                expect(await store.read(`/path/to/`)).to.equal(\"new doc @ /path/to/\");\n            });\n\n            it(\"should create the document if it doesn't exist\", async () => {\n                expect(await store.read(`/path/to/doc4`)).to.equal(\"\");\n                await store.write(`/path/to/doc4`, \"doc @ /path/to/doc4\");\n                expect(await store.read(`/path/to/doc4`)).to.equal(\"doc @ /path/to/doc4\");\n            });\n        }\n    });\n\n    describe(\"await store.delete(path)\", () => {\n\n        if (options.writeAccessDenied) {\n\n            it(\"should always throw a `ReadPermissionDenied` error\", async () => {\n                try {\n                    await store.delete(\"/path/to/doc1\");\n                    throw new Error(\"Id didn't throw\");\n                } catch (error) {\n                    expect(error).to.be.instanceof(Store.WritePermissionDeniedError);\n                    expect(error.message).to.equal(\"Permission denied: WRITE /path/to/doc1\");\n                }\n            });\n        }\n\n        else if (options.voidStore || options.readOnly) {\n\n            it(\"should always throw a `WriteOperationNotAllowed` error\", async () => {\n                try {\n                    await store.delete(\"/path/to/doc1\");\n                    throw new Error(\"Id didn't throw\");\n                } catch (error) {\n                    expect(error).to.be.instanceof(Store.WriteOperationNotAllowedError);\n                    expect(error.message).to.equal(\"Operation not allowed: WRITE /path/to/doc1\");\n                }\n            });\n\n        } else {\n\n            it(\"should remove the file at path\", async () => {\n                expect(await store.read(`/path/to/doc1`)).to.not.equal(\"\");\n                await store.delete(`/path/to/doc1`);\n                expect(await store.read(`/path/to/doc1`)).to.equal(\"\");\n            });\n\n            it(\"should return silentrly if the file already doesn't exist\", async () => {\n                expect(await store.read(`/path/to/doc1`)).to.equal(\"\");\n                await store.delete(`/path/to/doc1`);\n                expect(await store.read(`/path/to/doc1`)).to.equal(\"\");\n            });\n        }\n    });\n\n    describe(\"evaluate = store.parse(source)\", () => {\n\n        it(\"should return a function\", () => {\n            const evaluate = store.parse(`<%a=10%><%b=a+10%>a + b = <%a+b%>`);\n            expect(evaluate).to.be.a(\"function\");\n        });\n\n        describe(\"(await evaluate(context)).data\", () => {\n\n            it(\"should be an object\", async () => {\n                const evaluate = store.parse(\"\");\n                const context = document.createContext();\n                const {data} = await evaluate(context);\n                expect(data).to.be.an(\"object\");\n            });\n\n            it(\"should contain all the names defined in the swan expressions\", async () => {\n                const evaluate = store.parse(`<%a=10%><%b=a+10%>`);\n                const context = document.createContext({});\n                const {data} = await evaluate(context);\n                expect(data.a).to.equal(10);\n                expect(data.b).to.equal(20);\n            });\n        });\n\n        describe(\"(await evaluate(context)).text\", () => {\n\n            it(\"should be string obtained replacing the swan expressions with their stringified return value\", async () => {\n                const evaluate = store.parse(`<%a=10%><%b=a+10%>a + b = <%a+b%>`);\n                const context = document.createContext();\n                const {text} = await evaluate(context);\n                expect(text).to.equal(\"a + b = 30\");\n            });\n\n            it(\"should decorate the rendered text with the `__render__` function if it exists\", async () => {\n                var evaluate = store.parse(`<% __render__ = text -> text + \"!\" %>Hello World`);\n                var context = document.createContext();\n                var {text} = await evaluate(context);\n                expect(text).to.equal(\"Hello World!\");\n\n                var evaluate = store.parse(`<% __render__ = text -> {__str__: this -> text + \"!!\"} %>Hello World`);\n                var {text} = await evaluate(context);\n                expect(text).to.equal(\"Hello World!!\");\n            });\n        });\n    });\n\n    describe(\"context = store.createContext(docPath, ...namespaces)\", () => {\n\n        it(\"should be a document context\", () => {\n            const document_context = document.createContext();\n            const context = store.createContext('/path/to/doc1');\n            for (let key in document_context) {\n                expect(context[key]).to.equal(document_context[key]);\n            }\n        })\n\n        it(\"should contain the document path as '__path__'\", () => {\n            const context = store.createContext('/path/to/doc1');\n            expect(context.__path__).to.equal('/path/to/doc1');\n        });\n\n        it(\"should contain the document directory path as '__dirpath__'\", () => {\n            const context = store.createContext('/path/to/doc1');\n            expect(context.__dirpath__).to.equal('/path/to');\n        });\n\n        it(\"should contain the passed namespaces properties\", () => {\n            const context = store.createContext('/path/to/doc1', {x:10, y:20}, {y:30, z:40});\n            expect(context.x).to.equal(10);\n            expect(context.y).to.equal(30);\n            expect(context.z).to.equal(40);\n        });\n\n        it(\"should contain an 'import' function\", () => {\n            const context = store.createContext('/path/to/doc1');\n            expect(context.import).to.be.a(\"function\");\n        });\n\n        if (!(options.readAccessDenied || options.writeAccessDenied || options.voidStore || options.readOnly)) {\n            describe(\"context.import\", () => {\n\n                it(\"should return the namespace of the passed document\", async () => {\n                    await store.write('/path/to/doc1', \"<% docnum = 1 %>doc1\");\n                    await store.write('/path/to/doc2', \"<% docnum = 2 %>doc2\");\n\n                    const ctx1 = store.createContext('/path/to/doc1');\n                    const doc2_ns = await ctx1.import('/path/to/doc2');\n                    expect(doc2_ns.docnum).to.equal(2);\n                    expect(await ctx1.str(doc2_ns)).to.equal(\"doc2\");\n\n                    const eval3 = store.parse(\"<% doc1 = import './doc1' %>\");\n                    const ctx3 = store.createContext('/path/to/doc3');\n                    const data3 = (await eval3(ctx3)).data;\n                    expect(data3.doc1.docnum).to.equal(1);\n                });\n\n                it(\"should resolve relative ids\", async () => {\n                    await store.write('/path/to/doc1', \"<% docnum = 1 %>\");\n                    await store.write('/path/to/doc2', \"<% docnum = 2 %>\");\n                    await store.write('/path/to/doc3', \"<% docnum = 3 %>\");\n\n                    const ctx1 = store.createContext('/path/to/doc1');\n\n                    const doc2_ns = await ctx1.import('doc2');\n                    expect(doc2_ns.docnum).to.equal(2);\n\n                    const doc3_ns = await ctx1.import('./doc3');\n                    expect(doc3_ns.docnum).to.equal(3);\n                });\n\n                it(\"should cache the documents\", async () => {\n                    var count;\n                    store.read = path => {\n                        count += 1;\n                        return `doc @ ${path}<% p = __path__ %>`;\n                    }\n\n                    const ctx = store.createContext('/path/to/doc');\n                    count = 0;\n\n                    var ns = await ctx.import(\"/path/to/doc1\");\n                    expect(count).to.equal(1);\n                    expect(ns.p).to.equal(\"/path/to/doc1\");\n\n                    var ns = await ctx.import(\"/path/to/doc1\");\n                    expect(count).to.equal(1);\n                    expect(ns.p).to.equal(\"/path/to/doc1\");\n\n                    var ns = await ctx.import(\"/path/to/doc2\");\n                    expect(count).to.equal(2);\n                    expect(ns.p).to.equal(\"/path/to/doc2\");\n\n                    var ns = await ctx.import(\"/path/to/doc2\");\n                    expect(count).to.equal(2);\n                    expect(ns.p).to.equal(\"/path/to/doc2\");\n\n                    store.read = path => {\n                        count += 1;\n                        return `doc @ ${path}<% p = __path__ %><% doc2 = import '/path/to/doc2' %>`;\n                    }\n\n                    var ns = await ctx.import(\"/path/to/doc3\");\n                    expect(count).to.equal(3);\n                    expect(ns.p).to.equal(\"/path/to/doc3\");\n                    expect(ns.doc2.__path__).to.equal(\"/path/to/doc2\");\n\n                    delete store.read;\n                });\n            });\n        }\n    });\n    \n    describe(\"await store.load(docPath, ...namespaces)\", () => {\n\n        if (options.readAccessDenied) {\n\n            it(\"should always throw a `ReadPermissionDenied` error\", async () => {\n                try {\n                    await store.load(\"/path/to/doc1\");\n                    throw new Error(\"Id didn't throw\");\n                } catch (error) {\n                    expect(error).to.be.instanceof(Store.ReadPermissionDeniedError);\n                    expect(error.message).to.equal(\"Permission denied: READ /path/to/doc1\");\n                }\n            });\n        }\n\n        else if (options.voidStore) {\n\n            it(\"Should always return an empty document\", async () => {\n                var doc = await store.load(`/path/to/doc7`);\n                expect(doc.source).to.equal(\"\");\n                expect(doc.text).to.equal(\"\");\n            });\n\n        } else {\n\n            it(\"should return an object containing the document source as 'source' property\", async () => {\n                var doc = await store.load(`/path/to/doc7`);\n                expect(doc.source).to.equal(\"doc @ <% path : '/path/to/doc7' %>\");\n            });\n\n            it(\"should return an object containing the document context as 'context' property\", async () => {\n                var doc = await store.load(`/path/to/doc7`);\n                const document_context = document.createContext();\n                for (let key in document_context) {\n                    expect(doc.context[key]).to.equal(document_context[key]);\n                }\n                expect(doc.context.__path__).to.equal(`/path/to/doc7`)\n            });\n            \n            it(\"should return an object containing the document namespace as 'data' property\", async () => {\n                var doc = await store.load(`/path/to/doc7`);\n                expect(doc.data.path).to.equal('/path/to/doc7');\n            });\n\n            it(\"should return an object containing the rendered document as 'text' property\", async () => {\n                var doc = await store.load(`/path/to/doc7`);\n                expect(doc.text).to.equal('doc @ /path/to/doc7');                \n            });\n            \n            it(\"should return an object containing the document evaluator as 'evaluate' property\", async () => {\n                var doc = await store.load(`/path/to/doc7`);\n                var {data, text} = await doc.evaluate(doc.context);\n                expect(text).to.equal(doc.text);                \n                expect(data).to.deep.equal(doc.data);                \n            });\n        }        \n    });\n\n    after(async () => {\n        if (typeof options.destroy === 'function') {\n            await options.destroy(store);\n        }\n    });\n});\n\n\n//# sourceURL=webpack:///../describe-store.js?");
  
  /***/ }),
  
  /***/ "../document.js":
  /*!**********************!*\
    !*** ../document.js ***!
    \**********************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("\nvar expect = (__webpack_require__(/*! chai */ \"../../node_modules/chai/index.js\").expect);\nvar swan = __webpack_require__(/*! @onlabsorg/swan-js */ \"../../node_modules/@onlabsorg/swan-js/index.js\");\n\nvar document = __webpack_require__(/*! ../lib/document */ \"../../lib/document.js\");\n\n\ndescribe(\"document\", () => {\n    \n    describe(\"context = document.createContext(namespace)\", () => {\n        \n        it(\"should be an expression context\", () => {\n            var expContext = swan.createContext();\n            var docContext = document.createContext();\n            for (let name in expContext) {\n                expect(docContext[name]).to.equal(expContext[name]);\n            }\n        });\n        \n        it(\"should contain the passed namespace properties as own properties\", () => {\n            var namespace = {a:1,b:2};\n            var docContext = document.createContext(namespace);\n            var ownProps = Object.assign({}, docContext);\n            expect(ownProps).to.deep.equal(namespace);\n        });\n    });    \n    \n    describe(\"evaluateDocument = document.parse(source)\", () => {\n        \n        it(\"should be a function\", () => {\n            var source = `<%a=10%><%b=a+10%>a + b = <%a+b%>`;\n            var evaluate = document.parse(source);\n            expect(evaluate).to.be.a(\"function\");            \n        });\n        \n        describe(\"doc = await evaluateDocument(context)\", () => {\n            \n            describe(\"doc.data\", () => {\n                \n                it(\"should be an object\", async () => {\n                    var evaluate = document.parse(\"document source ...\");\n                    var context = swan.createContext();\n                    var {data} = await evaluate(context);\n                    expect(data).to.be.an(\"object\");                \n                });\n                \n                it(\"should contain all the names defined in the swan expressions\", async () => {\n                    var source = `<%a=10%><%b=a+10%>`;\n                    var evaluate = document.parse(source);\n                    var context = document.createContext({});\n                    var {data} = await evaluate(context);\n                    expect(data.a).to.equal(10);\n                    expect(data.b).to.equal(20);\n                });\n            });\n            \n            describe(\"doc.text\", () => {\n                \n                it(\"should be string obtained replacing the swan expressions with their stringified return value\", async () => {\n                    var source = `<%a=10%><%b=a+10%>a + b = <%a+b%>`;\n                    var evaluate = document.parse(source);\n                    var context = document.createContext();\n                    var {text} = await evaluate(context);\n                    expect(text).to.equal(\"a + b = 30\");\n                });\n\n                it(\"should decorate the rendered text with the `__render__` function if it exists\", async () => {\n                    var source = `<% __render__ = text -> text + \"!\" %>Hello World`;\n                    var evaluate = document.parse(source);\n                    var context = document.createContext();\n                    var {text} = await evaluate(context);\n                    expect(text).to.equal(\"Hello World!\");\n\n                    var source = `<% __render__ = text -> {__str__: this -> text + \"!!\"} %>Hello World`;\n                    var evaluate = document.parse(source);\n                    var context = document.createContext();\n                    var {text} = await evaluate(context);\n                    expect(text).to.equal(\"Hello World!!\");\n                });\n                \n                it(\"should render [[Undefined Syntax]] for expression with syntax error\", async () => {\n                    var source = `<% $x = 10 %>!`;\n                    var evaluate = document.parse(source);\n                    expect(evaluate).to.be.a(\"function\");\n                    var context = document.createContext();\n                    var {text} = await evaluate(context);\n                    expect(text).to.equal(\"[[Undefined Syntax]]!\");\n                });\n            });\n        });        \n    });\n});\n\n\n//# sourceURL=webpack:///../document.js?");
  
  /***/ }),
  
  /***/ "../expression.js":
  /*!************************!*\
    !*** ../expression.js ***!
    \************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("var expect = (__webpack_require__(/*! chai */ \"../../node_modules/chai/index.js\").expect);\nvar expression = __webpack_require__(/*! ../lib/expression */ \"../../lib/expression.js\");\n\n__webpack_require__(/*! @onlabsorg/swan-js/test/index */ \"../../node_modules/@onlabsorg/swan-js/test/index.js\");\n\ndescribe(\"olojs expression stdlib\", () => {\n\n    describe(\"markdown module\", () => {\n\n        it(\"should expose a function that converts markdown to HTML\", async () => {\n            var evaluate = expression.parse(`{\n                markdown = require 'markdown',\n                html = markdown '*bold*'\n            }.html`);\n            console.log(await evaluate(expression.createContext()))\n            var html = await evaluate(expression.createContext());\n            expect(html).to.equal(\"<p><em>bold</em></p>\\n\");\n        });\n    });\n});\n\n\n//# sourceURL=webpack:///../expression.js?");
  
  /***/ }),
  
  /***/ "../memory-store.js":
  /*!**************************!*\
    !*** ../memory-store.js ***!
    \**************************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const describeStore = __webpack_require__(/*! ./describe-store */ \"../describe-store.js\");\nconst MemoryStore = __webpack_require__(/*! ../lib/memory-store */ \"../../lib/memory-store.js\");\n\ndescribeStore('MemoryStore', {\n    create: content => new MemoryStore(content)\n});\n\n\n//# sourceURL=webpack:///../memory-store.js?");
  
  /***/ }),
  
  /***/ "../router.js":
  /*!********************!*\
    !*** ../router.js ***!
    \********************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("var expect = (__webpack_require__(/*! chai */ \"../../node_modules/chai/index.js\").expect);\nvar document = __webpack_require__(/*! ../lib/document */ \"../../lib/document.js\");\nvar Store = __webpack_require__(/*! ../lib/store */ \"../../lib/store.js\");\nvar MemoryStore = __webpack_require__(/*! ../lib/memory-store */ \"../../lib/memory-store.js\");\nvar Router = __webpack_require__(/*! ../lib/router */ \"../../lib/router.js\");\n\n\n\ndescribe(\"Router\", () => {\n\n    describe(\"iterator = router._iterRoutes()\", () => {\n\n        it(\"should return an iterator yielding all the [routeId, store] pairs in analphabetic order\", () => {\n            var routes = {\n                \"path/to\": new MemoryStore(),\n                \"/path/to/store2\": new MemoryStore(),\n                \"/\": new MemoryStore()\n            }\n            var router = new Router(routes);\n            expect(router._iterRoutes()[Symbol.iterator]).to.be.a(\"function\");\n            expect(Array.from(router._iterRoutes())).to.deep.equal([\n                ['/path/to/store2/', routes[\"/path/to/store2\"]],\n                ['/path/to/', routes[\"path/to\"]],\n                ['/', routes[\"/\"]],\n            ]);\n        });\n    });\n\n    describe(\"router.mount(path, store)\", () => {\n\n        it(\"should add a new store to the router\", () => {\n            var routes = {\n                \"path/to\": new MemoryStore(),\n                \"/path/to/store2\": new MemoryStore(),\n                \"/\": new MemoryStore()\n            }\n            var router = new Router(routes);\n            expect(Array.from(router._iterRoutes())).to.deep.equal([\n                ['/path/to/store2/', routes[\"/path/to/store2\"]],\n                ['/path/to/', routes[\"path/to\"]],\n                ['/', routes[\"/\"]],\n            ]);\n\n            var store3 = new MemoryStore();\n            router.mount('/path/to/new/store', store3);\n            expect(Array.from(router._iterRoutes())).to.deep.equal([\n                ['/path/to/store2/', routes[\"/path/to/store2\"]],\n                ['/path/to/new/store/', store3],\n                ['/path/to/', routes[\"path/to\"]],\n                ['/', routes[\"/\"]],\n            ]);\n        });\n\n        it(\"should fail silently is store is not a valid store\", () => {\n            var routes = {\n                \"path/to\": new MemoryStore(),\n                \"/path/to/store2\": new MemoryStore(),\n                \"/\": new MemoryStore()\n            }\n            var router = new Router(routes);\n            expect(Array.from(router._iterRoutes())).to.deep.equal([\n                ['/path/to/store2/', routes[\"/path/to/store2\"]],\n                ['/path/to/', routes[\"path/to\"]],\n                ['/', routes[\"/\"]],\n            ]);\n\n            router.mount('/path/to/new/store', {});\n            expect(Array.from(router._iterRoutes())).to.deep.equal([\n                ['/path/to/store2/', routes[\"/path/to/store2\"]],\n                ['/path/to/', routes[\"path/to\"]],\n                ['/', routes[\"/\"]],\n            ]);\n        });\n    });\n\n    describe(\"router.unmount(routeId)\", () => {\n\n        it(\"should remove the store mapped to the given Id from the router\", () => {\n            var routes = {\n                \"path/to\": new MemoryStore(),\n                \"/path/to/store2\": new MemoryStore(),\n                \"/\": new MemoryStore()\n            }\n            var router = new Router(routes);\n            expect(Array.from(router._iterRoutes())).to.deep.equal([\n                ['/path/to/store2/', routes[\"/path/to/store2\"]],\n                ['/path/to/', routes[\"path/to\"]],\n                ['/', routes[\"/\"]],\n            ]);\n\n            router.unmount('path/to/store2');\n            expect(Array.from(router._iterRoutes())).to.deep.equal([\n                ['/path/to/', routes[\"path/to\"]],\n                ['/', routes[\"/\"]],\n            ]);\n        });\n    });\n\n    describe(\"[store, subPath] = router._match(path)\", () => {\n\n        it(\"should return store mounted at the route matching the path and the subPath relative to that route\", () => {\n            var routes = {\n                \"path/to\": new MemoryStore(),\n                \"/path/to/store2\": new MemoryStore(),\n                \"/\": new MemoryStore()\n            }\n            var router = new Router(routes);\n            expect(router._match('/path/to/')).to.deep.equal([routes['path/to'], \"/\"]);\n            expect(router._match('/path/to/doc')).to.deep.equal([routes['path/to'], \"/doc\"]);\n            expect(router._match('/path/to/store2/path/to/doc')).to.deep.equal([routes['/path/to/store2'], \"/path/to/doc\"]);\n            expect(router._match('/path/to/store2/')).to.deep.equal([routes['/path/to/store2'], \"/\"]);\n            expect(router._match('/path_to/doc')).to.deep.equal([routes['/'], \"/path_to/doc\"]);\n        });\n\n        it(\"should treat `scheme:/path/to/doc` routes as shortcut for `/.protocolos/scheme/path/to/doc`\", async () => {\n            var routes = {\n                \"http:/\": new MemoryStore(),\n                \"/.schemes/https\": new MemoryStore(),\n                \"/\": new MemoryStore()\n            }\n            var router = new Router(routes);\n            expect(router._match('https:/path/to/doc')).to.deep.equal([routes['/.schemes/https'], \"/path/to/doc\"]);\n            expect(router._match('/.schemes/https/path/to/doc')).to.deep.equal([routes['/.schemes/https'], \"/path/to/doc\"]);\n            expect(router._match('http:/path/to/doc')).to.deep.equal([routes['http:/'], \"/path/to/doc\"]);\n            expect(router._match('/.schemes/http/path/to/doc')).to.deep.equal([routes['http:/'], \"/path/to/doc\"]);\n        });\n\n        it(\"should return [null, path] if no match is found\", () => {\n            var routes = {\n                \"/path/to/s1\": new MemoryStore(),\n                \"/path/to/s2\": new MemoryStore(),\n            }\n            var router = new Router(routes);\n            expect(router._match('/path/to/s3/doc')).to.deep.equal([null, \"/path/to/s3/doc\"]);\n        });\n    });\n\n    describe(`source = router.read(path)`, () => {\n\n        it(\"should delegate to the matching mounted store\", async () => {\n            var router = new Router({\n                \"path/to\": new MemoryStore({\n                    \"/\"    : \"doc @ store1:/\",\n                    \"doc\"  : \"doc @ store1:/path/to/doc\"\n                }),\n                \"/path/to/store2\": new MemoryStore({\n                    \"/\"             : \"doc @ store2:/\",\n                    \"/path/to/doc\"  : \"doc @ store2:/path/to/doc\"\n                }),\n                \"/\": new MemoryStore({\n                    \"/path/to/doc\"  : \"doc @ root:/path/to/doc\",\n                    \"/path_to/doc\"  : \"doc @ root:/path_to/doc\"\n                }),\n            });\n            expect(await router.read('/path/to/')).to.equal(\"doc @ store1:/\");\n            expect(await router.read('/path/to/doc')).to.equal(\"doc @ store1:/path/to/doc\");\n            expect(await router.read('/path/to/store2/path/to/doc')).to.equal(\"doc @ store2:/path/to/doc\");\n            expect(await router.read('/path/to/store2/')).to.equal(\"doc @ store2:/\");\n            expect(await router.read('/path_to/doc')).to.equal(\"doc @ root:/path_to/doc\");\n        });\n\n        it(\"should return an empty document if no match is found\", async () => {\n            var router = new Router({\n                \"path/to\": new MemoryStore({\n                    \"/\"    : \"doc @ store1:/\",\n                    \"doc\"  : \"doc @ store1:/path/to/doc\"\n                }),\n                \"/path/to/store2\": new MemoryStore({\n                    \"/\"             : \"doc @ store2:/\",\n                    \"/path/to/doc\"  : \"doc @ store2:/path/to/doc\"\n                }),\n            });\n            expect(await router.read('/path_to/doc')).to.equal(\"\");\n        })\n    });\n\n    describe(`router.write(path, source)`, () => {\n\n        it(\"should delegate to the matching mounted store\", async () => {\n            var store1 = new MemoryStore();\n            var store2 = new MemoryStore();\n            var router = new Router({\n                s1: store1,\n                s2: store2,\n            });\n            await router.write('/s1/path/to/doc', \"doc @ store1\");\n            await router.write('s2/path/to/doc', \"doc @ store2\");\n            expect(await store1.read('/path/to/doc')).to.equal(\"doc @ store1\");\n            expect(await store2.read('/path/to/doc')).to.equal(\"doc @ store2\");\n        });\n\n        it(\"should throw an error if no match is found\", async () => {\n            var router = new Router();\n            try {\n                await router.write('/s1/path/to/doc', \"...\");\n                throw new Error(\"Id did not throw\");\n            } catch (error) {\n                expect(error).to.be.instanceof(Router.WriteOperationNotAllowedError);\n                expect(error.message).to.equal('Operation not allowed: WRITE /s1/path/to/doc')\n            }\n        });\n    });\n\n    describe(`router.delete(path)`, () => {\n\n        it(\"should delegate to the matching mounted store\", async () => {\n            var store1 = new MemoryStore();\n            var store2 = new MemoryStore();\n            var router = new Router({\n                s1: store1,\n                s2: store2,\n            });\n\n            await store1.write('/path/to/doc', \"doc @ store1\");\n            await router.delete('/s1/path/to/doc');\n            expect(store1.read('/path/to/doc')).to.equal(\"\");\n        });\n\n        it(\"should throw an error if no match is found\", async () => {\n            var router = new Router();\n            try {\n                await router.delete('/s1/path/to/doc');\n                throw new Error(\"Id did not throw\");\n            } catch (error) {\n                expect(error).to.be.instanceof(Router.WriteOperationNotAllowedError);\n                expect(error.message).to.equal('Operation not allowed: WRITE /s1/path/to/doc')\n            }\n        })\n    });\n\n    describe(\"evaluate = router.parse(source)\", () => {\n\n        it(\"should return a function\", () => {\n            var store1 = new MemoryStore();\n            var store2 = new MemoryStore();\n            var router = new Router({\n                s1: store1,\n                s2: store2,\n            });\n            const evaluate = router.parse(`<%a=10%><%b=a+10%>a + b = <%a+b%>`);\n            expect(evaluate).to.be.a(\"function\");\n        });\n\n        describe(\"(await evaluate(context)).data\", () => {\n\n            it(\"should be an object\", async () => {\n                var store1 = new MemoryStore();\n                var store2 = new MemoryStore();\n                var router = new Router({\n                    s1: store1,\n                    s2: store2,\n                });\n                const evaluate = router.parse(\"\");\n                const context = document.createContext();\n                const {data} = await evaluate(context);\n                expect(data).to.be.an(\"object\");\n            });\n\n            it(\"should contain all the names defined in the swan expressions\", async () => {\n                var store1 = new MemoryStore();\n                var store2 = new MemoryStore();\n                var router = new Router({\n                    s1: store1,\n                    s2: store2,\n                });\n                const evaluate = router.parse(`<%a=10%><%b=a+10%>`);\n                const context = document.createContext({});\n                const {data} = await evaluate(context);\n                expect(data.a).to.equal(10);\n                expect(data.b).to.equal(20);\n            });\n        });\n\n        describe(\"(await evaluate(context)).text\", () => {\n\n            it(\"should be string obtained replacing the swan expressions with their stringified return value\", async () => {\n                var store1 = new MemoryStore();\n                var store2 = new MemoryStore();\n                var router = new Router({\n                    s1: store1,\n                    s2: store2,\n                });\n                const evaluate = router.parse(`<%a=10%><%b=a+10%>a + b = <%a+b%>`);\n                const context = document.createContext();\n                const {text} = await evaluate(context);\n                expect(text).to.equal(\"a + b = 30\");\n            });\n\n            it(\"should decorate the rendered text with the `__render__` function if it exists\", async () => {\n                var store1 = new MemoryStore();\n                var store2 = new MemoryStore();\n                var router = new Router({\n                    s1: store1,\n                    s2: store2,\n                });\n\n                var evaluate = router.parse(`<% __render__ = text -> text + \"!\" %>Hello World`);\n                var context = document.createContext();\n                var {text} = await evaluate(context);\n                expect(text).to.equal(\"Hello World!\");\n\n                var evaluate = router.parse(`<% __render__ = text -> {__str__: this -> text + \"!!\"} %>Hello World`);\n                var {text} = await evaluate(context);\n                expect(text).to.equal(\"Hello World!!\");\n            });\n        });\n    });\n\n    describe(\"context = router.createContext(docPath, ...namespaces)\", () => {\n\n        it(\"should be a document context\", () => {\n            var router = new Router({\n                s1: new MemoryStore(),\n                s2: new MemoryStore()\n            });\n            const document_context = document.createContext();\n            const context = router.createContext('/path/to/doc1');\n            for (let key in document_context) {\n                expect(context[key]).to.equal(document_context[key]);\n            }\n        })\n\n        it(\"should contain the document path as '__path__'\", () => {\n            var router = new Router({\n                '/path/to/s1': new MemoryStore(),\n                '/path/to/s2': new MemoryStore()\n            });\n            const context = router.createContext('/path/to/s1/dir1/doc1');\n            expect(context.__path__).to.equal('/path/to/s1/dir1/doc1');\n        });\n\n        it(\"should contain the document directory path as '__dirpath__'\", () => {\n            var router = new Router({\n                '/path/to/s1': new MemoryStore(),\n                '/path/to/s2': new MemoryStore()\n            });\n            const context = router.createContext('/path/to/s1/dir1/doc1');\n            expect(context.__dirpath__).to.equal('/path/to/s1/dir1');\n        });\n\n        it(\"should contain the passed namespaces properties\", () => {\n            var router = new Router({\n                '/path/to/s1': new MemoryStore(),\n                '/path/to/s2': new MemoryStore()\n            });\n            const context = router.createContext('/path/to/doc1', {x:10, y:20}, {y:30, z:40});\n            expect(context.x).to.equal(10);\n            expect(context.y).to.equal(30);\n            expect(context.z).to.equal(40);\n        });\n\n        it(\"should contain an 'import' function\", () => {\n            var router = new Router({\n                '/path/to/s1': new MemoryStore(),\n                '/path/to/s2': new MemoryStore()\n            });\n            const context = router.createContext('/path/to/doc1');\n            expect(context.import).to.be.a(\"function\");\n        });\n\n        describe(\"context.import function\", () => {\n\n            it(\"should resolve paths relative to the router, not to the context store\", async () => {\n                const router = new Router({\n                    '/store1': new MemoryStore({\n                        '/path/to/doc1': \"<% docnum = 1 %>\",\n                        '/path/to/doc2': \"<% docnum = 2 %>\",\n                        '/path/to/doc3': \"<% docnum = 3 %>\",\n                    })\n                });\n\n                const ctx1 = await router.createContext('/store1/path/to/doc1');\n\n                const doc2_ns = await ctx1.import('doc2');\n                expect(doc2_ns.docnum).to.equal(2);\n                expect(doc2_ns.__path__).to.equal('/store1/path/to/doc2')\n\n                const doc3_ns = await ctx1.import('/store1/path/to/doc3');\n                expect(doc3_ns.docnum).to.equal(3);\n                expect(doc3_ns.__path__).to.equal('/store1/path/to/doc3')\n            });\n\n            it(\"should correctly resolve url-like path\", async () => {\n\n                const router = new Router({\n                    '/store1': new MemoryStore({\n                        '/path/to/doc1': \"<% docnum = 11 %>\",\n                        '/path/to/doc2': \"<% docnum = 12 %>\",\n                        '/path/to/doc3': \"<% docnum = 13 %>\",\n                    }),\n\n                    'xxx:/': new MemoryStore({\n                        '/path/to/doc1': \"<% docnum = 21 %>\",\n                        '/path/to/doc2': \"<% docnum = 22 %>\",\n                        '/path/to/doc3': \"<% docnum = 23 %>\",\n                    })\n                });\n\n                const ctx1 = await router.createContext('/store1/path/to/doc1');\n\n                const doc2_ns = await ctx1.import('doc2');\n                expect(doc2_ns.docnum).to.equal(12);\n                expect(doc2_ns.__path__).to.equal('/store1/path/to/doc2')\n\n                const doc3_ns = await ctx1.import('xxx:/path/to/doc3');\n                expect(doc3_ns.docnum).to.equal(23);\n                expect(doc3_ns.__path__).to.equal('/.schemes/xxx/path/to/doc3')\n            });\n        });\n    });\n});\n\n\n//# sourceURL=webpack:///../router.js?");
  
  /***/ }),
  
  /***/ "../store.js":
  /*!*******************!*\
    !*** ../store.js ***!
    \*******************/
  /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
  
  eval("const describeStore = __webpack_require__(/*! ./describe-store */ \"../describe-store.js\");\nconst Store = __webpack_require__(/*! ../lib/store */ \"../../lib/store.js\");\n\ndescribeStore('VoidStore', {\n    create: documents => new Store(), \n    voidStore: true\n});\n\n\n//# sourceURL=webpack:///../store.js?");
  
  /***/ }),
  
  /***/ "?7779":
  /*!**********************!*\
    !*** util (ignored) ***!
    \**********************/
  /***/ (() => {
  
  eval("/* (ignored) */\n\n//# sourceURL=webpack:///util_(ignored)?");
  
  /***/ })
  
  /******/ 	});
  /************************************************************************/
  /******/ 	// The module cache
  /******/ 	var __webpack_module_cache__ = {};
  /******/ 	
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  /******/ 		// Check if module is in cache
  /******/ 		var cachedModule = __webpack_module_cache__[moduleId];
  /******/ 		if (cachedModule !== undefined) {
  /******/ 			return cachedModule.exports;
  /******/ 		}
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = __webpack_module_cache__[moduleId] = {
  /******/ 			// no module.id needed
  /******/ 			// no module.loaded needed
  /******/ 			exports: {}
  /******/ 		};
  /******/ 	
  /******/ 		// Execute the module function
  /******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  /******/ 	
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  /******/ 	
  /******/ 	// expose the modules object (__webpack_modules__)
  /******/ 	__webpack_require__.m = __webpack_modules__;
  /******/ 	
  /************************************************************************/
  /******/ 	/* webpack/runtime/create fake namespace object */
  /******/ 	(() => {
  /******/ 		var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
  /******/ 		var leafPrototypes;
  /******/ 		// create a fake namespace object
  /******/ 		// mode & 1: value is a module id, require it
  /******/ 		// mode & 2: merge all properties of value into the ns
  /******/ 		// mode & 4: return value when already ns object
  /******/ 		// mode & 16: return value when it's Promise-like
  /******/ 		// mode & 8|1: behave like require
  /******/ 		__webpack_require__.t = function(value, mode) {
  /******/ 			if(mode & 1) value = this(value);
  /******/ 			if(mode & 8) return value;
  /******/ 			if(typeof value === 'object' && value) {
  /******/ 				if((mode & 4) && value.__esModule) return value;
  /******/ 				if((mode & 16) && typeof value.then === 'function') return value;
  /******/ 			}
  /******/ 			var ns = Object.create(null);
  /******/ 			__webpack_require__.r(ns);
  /******/ 			var def = {};
  /******/ 			leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
  /******/ 			for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {
  /******/ 				Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
  /******/ 			}
  /******/ 			def['default'] = () => (value);
  /******/ 			__webpack_require__.d(ns, def);
  /******/ 			return ns;
  /******/ 		};
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/define property getters */
  /******/ 	(() => {
  /******/ 		// define getter functions for harmony exports
  /******/ 		__webpack_require__.d = (exports, definition) => {
  /******/ 			for(var key in definition) {
  /******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  /******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  /******/ 				}
  /******/ 			}
  /******/ 		};
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/ensure chunk */
  /******/ 	(() => {
  /******/ 		__webpack_require__.f = {};
  /******/ 		// This file contains only the entry chunk.
  /******/ 		// The chunk loading function for additional chunks
  /******/ 		__webpack_require__.e = (chunkId) => {
  /******/ 			return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
  /******/ 				__webpack_require__.f[key](chunkId, promises);
  /******/ 				return promises;
  /******/ 			}, []));
  /******/ 		};
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/get javascript chunk filename */
  /******/ 	(() => {
  /******/ 		// This function allow to reference async chunks
  /******/ 		__webpack_require__.u = (chunkId) => {
  /******/ 			// return url for filenames based on template
  /******/ 			return "" + chunkId + ".bundle.js";
  /******/ 		};
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/global */
  /******/ 	(() => {
  /******/ 		__webpack_require__.g = (function() {
  /******/ 			if (typeof globalThis === 'object') return globalThis;
  /******/ 			try {
  /******/ 				return this || new Function('return this')();
  /******/ 			} catch (e) {
  /******/ 				if (typeof window === 'object') return window;
  /******/ 			}
  /******/ 		})();
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/hasOwnProperty shorthand */
  /******/ 	(() => {
  /******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/load script */
  /******/ 	(() => {
  /******/ 		var inProgress = {};
  /******/ 		// data-webpack is not used as build has no uniqueName
  /******/ 		// loadScript function to load a script via script tag
  /******/ 		__webpack_require__.l = (url, done, key, chunkId) => {
  /******/ 			if(inProgress[url]) { inProgress[url].push(done); return; }
  /******/ 			var script, needAttach;
  /******/ 			if(key !== undefined) {
  /******/ 				var scripts = document.getElementsByTagName("script");
  /******/ 				for(var i = 0; i < scripts.length; i++) {
  /******/ 					var s = scripts[i];
  /******/ 					if(s.getAttribute("src") == url) { script = s; break; }
  /******/ 				}
  /******/ 			}
  /******/ 			if(!script) {
  /******/ 				needAttach = true;
  /******/ 				script = document.createElement('script');
  /******/ 		
  /******/ 				script.charset = 'utf-8';
  /******/ 				script.timeout = 120;
  /******/ 				if (__webpack_require__.nc) {
  /******/ 					script.setAttribute("nonce", __webpack_require__.nc);
  /******/ 				}
  /******/ 		
  /******/ 				script.src = url;
  /******/ 			}
  /******/ 			inProgress[url] = [done];
  /******/ 			var onScriptComplete = (prev, event) => {
  /******/ 				// avoid mem leaks in IE.
  /******/ 				script.onerror = script.onload = null;
  /******/ 				clearTimeout(timeout);
  /******/ 				var doneFns = inProgress[url];
  /******/ 				delete inProgress[url];
  /******/ 				script.parentNode && script.parentNode.removeChild(script);
  /******/ 				doneFns && doneFns.forEach((fn) => (fn(event)));
  /******/ 				if(prev) return prev(event);
  /******/ 			}
  /******/ 			;
  /******/ 			var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
  /******/ 			script.onerror = onScriptComplete.bind(null, script.onerror);
  /******/ 			script.onload = onScriptComplete.bind(null, script.onload);
  /******/ 			needAttach && document.head.appendChild(script);
  /******/ 		};
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/make namespace object */
  /******/ 	(() => {
  /******/ 		// define __esModule on exports
  /******/ 		__webpack_require__.r = (exports) => {
  /******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  /******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  /******/ 			}
  /******/ 			Object.defineProperty(exports, '__esModule', { value: true });
  /******/ 		};
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/publicPath */
  /******/ 	(() => {
  /******/ 		var scriptUrl;
  /******/ 		if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
  /******/ 		var document = __webpack_require__.g.document;
  /******/ 		if (!scriptUrl && document) {
  /******/ 			if (document.currentScript)
  /******/ 				scriptUrl = document.currentScript.src
  /******/ 			if (!scriptUrl) {
  /******/ 				var scripts = document.getElementsByTagName("script");
  /******/ 				if(scripts.length) scriptUrl = scripts[scripts.length - 1].src
  /******/ 			}
  /******/ 		}
  /******/ 		// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
  /******/ 		// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
  /******/ 		if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");
  /******/ 		scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
  /******/ 		__webpack_require__.p = scriptUrl;
  /******/ 	})();
  /******/ 	
  /******/ 	/* webpack/runtime/jsonp chunk loading */
  /******/ 	(() => {
  /******/ 		// no baseURI
  /******/ 		
  /******/ 		// object to store loaded and loading chunks
  /******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
  /******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
  /******/ 		var installedChunks = {
  /******/ 			"main": 0
  /******/ 		};
  /******/ 		
  /******/ 		__webpack_require__.f.j = (chunkId, promises) => {
  /******/ 				// JSONP chunk loading for javascript
  /******/ 				var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
  /******/ 				if(installedChunkData !== 0) { // 0 means "already installed".
  /******/ 		
  /******/ 					// a Promise means "currently loading".
  /******/ 					if(installedChunkData) {
  /******/ 						promises.push(installedChunkData[2]);
  /******/ 					} else {
  /******/ 						if(true) { // all chunks have JS
  /******/ 							// setup Promise in chunk cache
  /******/ 							var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
  /******/ 							promises.push(installedChunkData[2] = promise);
  /******/ 		
  /******/ 							// start chunk loading
  /******/ 							var url = __webpack_require__.p + __webpack_require__.u(chunkId);
  /******/ 							// create error before stack unwound to get useful stacktrace later
  /******/ 							var error = new Error();
  /******/ 							var loadingEnded = (event) => {
  /******/ 								if(__webpack_require__.o(installedChunks, chunkId)) {
  /******/ 									installedChunkData = installedChunks[chunkId];
  /******/ 									if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
  /******/ 									if(installedChunkData) {
  /******/ 										var errorType = event && (event.type === 'load' ? 'missing' : event.type);
  /******/ 										var realSrc = event && event.target && event.target.src;
  /******/ 										error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
  /******/ 										error.name = 'ChunkLoadError';
  /******/ 										error.type = errorType;
  /******/ 										error.request = realSrc;
  /******/ 										installedChunkData[1](error);
  /******/ 									}
  /******/ 								}
  /******/ 							};
  /******/ 							__webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);
  /******/ 						} else installedChunks[chunkId] = 0;
  /******/ 					}
  /******/ 				}
  /******/ 		};
  /******/ 		
  /******/ 		// no prefetching
  /******/ 		
  /******/ 		// no preloaded
  /******/ 		
  /******/ 		// no HMR
  /******/ 		
  /******/ 		// no HMR manifest
  /******/ 		
  /******/ 		// no on chunks loaded
  /******/ 		
  /******/ 		// install a JSONP callback for chunk loading
  /******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
  /******/ 			var [chunkIds, moreModules, runtime] = data;
  /******/ 			// add "moreModules" to the modules object,
  /******/ 			// then flag all "chunkIds" as loaded and fire callback
  /******/ 			var moduleId, chunkId, i = 0;
  /******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
  /******/ 				for(moduleId in moreModules) {
  /******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
  /******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
  /******/ 					}
  /******/ 				}
  /******/ 				if(runtime) var result = runtime(__webpack_require__);
  /******/ 			}
  /******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
  /******/ 			for(;i < chunkIds.length; i++) {
  /******/ 				chunkId = chunkIds[i];
  /******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
  /******/ 					installedChunks[chunkId][0]();
  /******/ 				}
  /******/ 				installedChunks[chunkId] = 0;
  /******/ 			}
  /******/ 		
  /******/ 		}
  /******/ 		
  /******/ 		var chunkLoadingGlobal = self["webpackChunk"] = self["webpackChunk"] || [];
  /******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
  /******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
  /******/ 	})();
  /******/ 	
  /************************************************************************/
  /******/ 	
  /******/ 	// startup
  /******/ 	// Load entry module and return exports
  /******/ 	// This entry module can't be inlined because the eval devtool is used.
  /******/ 	var __webpack_exports__ = __webpack_require__("./index.js");
  /******/ 	
  /******/ })()
  ;