Index: frontend/node_modules/static-eval/.travis.yml
===================================================================
--- frontend/node_modules/static-eval/.travis.yml	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/.travis.yml	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,18 @@
+language: node_js
+os: linux
+dist: bionic
+before_install:
+  - "nvm install-latest-npm"
+node_js:
+  - "0.8"
+  - "0.10"
+  - "0.12"
+  - "4"
+  - "6"
+  - "8"
+  - "9"
+  - "10"
+  - "11"
+  - "12"
+  - "13"
+  - "14"
Index: frontend/node_modules/static-eval/CHANGELOG.md
===================================================================
--- frontend/node_modules/static-eval/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/CHANGELOG.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,21 @@
+# static-eval Change Log
+All notable changes to this project will be documented in this file.
+This project adheres to [Semantic Versioning](http://semver.org/).
+
+## 2.1.1
+* Update `escodegen`. [@FabianWarnecke](https://github.com/FabianWarnecke) in [#43](https://github.com/browserify/static-eval/pull/43)
+
+  escodegen doesn't officially support all the Node.js versions that `static-eval` supports, but so far it still works on them.
+  This has been the case for both v1.x and v2.1.0 of escodegen, so the upgrade doesn't change that situation.
+
+## 2.1.0
+* Add `allowAccessToMethodsOnFunctions` option to restore 1.x behaviour so that [cwise](https://github.com/scijs/cwise) can upgrade. ([@archmoj](https://github.com/archmoj) in [#31](https://github.com/browserify/static-eval/pull/31))
+
+  Do not use this option if you are not sure that you need it, as it had previously been removed for security reasons. There is a known exploit to execute arbitrary code. Only use it on trusted inputs, like the developer's JS files in a build system.
+
+## 2.0.5
+* Fix function bodies being invoked during declaration. ([@RoboPhred](https://github.com/RoboPhred) in [#30](https://github.com/browserify/static-eval/pull/30))
+
+## 2.0.4
+* Short-circuit evaluation in `&&` and `||` expressions. ([@RoboPhred](https://github.com/RoboPhred) in [#28](https://github.com/browserify/static-eval/pull/28))
+* Start tracking changes.
Index: frontend/node_modules/static-eval/LICENSE
===================================================================
--- frontend/node_modules/static-eval/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/LICENSE	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,20 @@
+MIT License
+
+Copyright (c) 2013 James Halliday
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: frontend/node_modules/static-eval/example/eval.js
===================================================================
--- frontend/node_modules/static-eval/example/eval.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/example/eval.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,7 @@
+var evaluate = require('static-eval');
+var parse = require('esprima').parse;
+
+var src = process.argv.slice(2).join(' ');
+var ast = parse(src).body[0].expression;
+
+console.log(evaluate(ast));
Index: frontend/node_modules/static-eval/example/vars.js
===================================================================
--- frontend/node_modules/static-eval/example/vars.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/example/vars.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,11 @@
+var evaluate = require('../');
+var parse = require('esprima').parse;
+
+var src = '[1,2,3+4*10+n,foo(3+5),obj[""+"x"].y]';
+var ast = parse(src).body[0].expression;
+
+console.log(evaluate(ast, {
+    n: 6,
+    foo: function (x) { return x * 100 },
+    obj: { x: { y: 555 } }
+}));
Index: frontend/node_modules/static-eval/index.js
===================================================================
--- frontend/node_modules/static-eval/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/index.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,209 @@
+var unparse = require('escodegen').generate;
+
+module.exports = function (ast, vars, opts) {
+    if(!opts) opts = {};
+    var rejectAccessToMethodsOnFunctions = !opts.allowAccessToMethodsOnFunctions;
+
+    if (!vars) vars = {};
+    var FAIL = {};
+
+    var result = (function walk (node, noExecute) {
+        if (node.type === 'Literal') {
+            return node.value;
+        }
+        else if (node.type === 'UnaryExpression'){
+            var val = walk(node.argument, noExecute)
+            if (node.operator === '+') return +val
+            if (node.operator === '-') return -val
+            if (node.operator === '~') return ~val
+            if (node.operator === '!') return !val
+            return FAIL
+        }
+        else if (node.type === 'ArrayExpression') {
+            var xs = [];
+            for (var i = 0, l = node.elements.length; i < l; i++) {
+                var x = walk(node.elements[i], noExecute);
+                if (x === FAIL) return FAIL;
+                xs.push(x);
+            }
+            return xs;
+        }
+        else if (node.type === 'ObjectExpression') {
+            var obj = {};
+            for (var i = 0; i < node.properties.length; i++) {
+                var prop = node.properties[i];
+                var value = prop.value === null
+                    ? prop.value
+                    : walk(prop.value, noExecute)
+                ;
+                if (value === FAIL) return FAIL;
+                obj[prop.key.value || prop.key.name] = value;
+            }
+            return obj;
+        }
+        else if (node.type === 'BinaryExpression' ||
+                 node.type === 'LogicalExpression') {
+            var op = node.operator;
+
+            if (op === '&&') {
+                var l = walk(node.left);
+                if (l === FAIL) return FAIL;
+                if (!l) return l;
+                var r = walk(node.right);
+                if (r === FAIL) return FAIL;
+                return r;
+            }
+            else if (op === '||') {
+                var l = walk(node.left);
+                if (l === FAIL) return FAIL;
+                if (l) return l;
+                var r = walk(node.right);
+                if (r === FAIL) return FAIL;
+                return r;
+            }
+
+            var l = walk(node.left, noExecute);
+            if (l === FAIL) return FAIL;
+            var r = walk(node.right, noExecute);
+            if (r === FAIL) return FAIL;
+
+            if (op === '==') return l == r;
+            if (op === '===') return l === r;
+            if (op === '!=') return l != r;
+            if (op === '!==') return l !== r;
+            if (op === '+') return l + r;
+            if (op === '-') return l - r;
+            if (op === '*') return l * r;
+            if (op === '/') return l / r;
+            if (op === '%') return l % r;
+            if (op === '<') return l < r;
+            if (op === '<=') return l <= r;
+            if (op === '>') return l > r;
+            if (op === '>=') return l >= r;
+            if (op === '|') return l | r;
+            if (op === '&') return l & r;
+            if (op === '^') return l ^ r;
+
+            return FAIL;
+        }
+        else if (node.type === 'Identifier') {
+            if ({}.hasOwnProperty.call(vars, node.name)) {
+                return vars[node.name];
+            }
+            else return FAIL;
+        }
+        else if (node.type === 'ThisExpression') {
+            if ({}.hasOwnProperty.call(vars, 'this')) {
+                return vars['this'];
+            }
+            else return FAIL;
+        }
+        else if (node.type === 'CallExpression') {
+            var callee = walk(node.callee, noExecute);
+            if (callee === FAIL) return FAIL;
+            if (typeof callee !== 'function') return FAIL;
+
+
+            var ctx = node.callee.object ? walk(node.callee.object, noExecute) : FAIL;
+            if (ctx === FAIL) ctx = null;
+
+            var args = [];
+            for (var i = 0, l = node.arguments.length; i < l; i++) {
+                var x = walk(node.arguments[i], noExecute);
+                if (x === FAIL) return FAIL;
+                args.push(x);
+            }
+
+            if (noExecute) {
+                return undefined;
+            }
+
+            return callee.apply(ctx, args);
+        }
+        else if (node.type === 'MemberExpression') {
+            var obj = walk(node.object, noExecute);
+            if((obj === FAIL) || (
+                (typeof obj == 'function') && rejectAccessToMethodsOnFunctions
+            )){
+                return FAIL;
+            }
+            if (node.property.type === 'Identifier' && !node.computed) {
+                if (isUnsafeProperty(node.property.name)) return FAIL;
+                return obj[node.property.name];
+            }
+            var prop = walk(node.property, noExecute);
+            if (prop === null || prop === FAIL) return FAIL;
+            if (isUnsafeProperty(prop)) return FAIL;
+            return obj[prop];
+        }
+        else if (node.type === 'ConditionalExpression') {
+            var val = walk(node.test, noExecute)
+            if (val === FAIL) return FAIL;
+            return val ? walk(node.consequent) : walk(node.alternate, noExecute)
+        }
+        else if (node.type === 'ExpressionStatement') {
+            var val = walk(node.expression, noExecute)
+            if (val === FAIL) return FAIL;
+            return val;
+        }
+        else if (node.type === 'ReturnStatement') {
+            return walk(node.argument, noExecute)
+        }
+        else if (node.type === 'FunctionExpression') {
+            var bodies = node.body.body;
+
+            // Create a "scope" for our arguments
+            var oldVars = {};
+            Object.keys(vars).forEach(function(element){
+                oldVars[element] = vars[element];
+            })
+
+            for(var i=0; i<node.params.length; i++){
+                var key = node.params[i];
+                if(key.type == 'Identifier'){
+                  vars[key.name] = null;
+                }
+                else return FAIL;
+            }
+            for(var i in bodies){
+                if(walk(bodies[i], true) === FAIL){
+                    return FAIL;
+                }
+            }
+            // restore the vars and scope after we walk
+            vars = oldVars;
+
+            var keys = Object.keys(vars);
+            var vals = keys.map(function(key) {
+                return vars[key];
+            });
+            return Function(keys.join(', '), 'return ' + unparse(node)).apply(null, vals);
+        }
+        else if (node.type === 'TemplateLiteral') {
+            var str = '';
+            for (var i = 0; i < node.expressions.length; i++) {
+                str += walk(node.quasis[i], noExecute);
+                str += walk(node.expressions[i], noExecute);
+            }
+            str += walk(node.quasis[i], noExecute);
+            return str;
+        }
+        else if (node.type === 'TaggedTemplateExpression') {
+            var tag = walk(node.tag, noExecute);
+            var quasi = node.quasi;
+            var strings = quasi.quasis.map(walk);
+            var values = quasi.expressions.map(walk);
+            return tag.apply(null, [strings].concat(values));
+        }
+        else if (node.type === 'TemplateElement') {
+            return node.value.cooked;
+        }
+        else return FAIL;
+    })(ast);
+
+    return result === FAIL ? undefined : result;
+};
+
+function isUnsafeProperty(name) {
+    return name === 'constructor' || name === '__proto__';
+}
Index: frontend/node_modules/static-eval/package.json
===================================================================
--- frontend/node_modules/static-eval/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,54 @@
+{
+  "name": "static-eval",
+  "description": "evaluate statically-analyzable expressions",
+  "version": "2.1.1",
+  "author": {
+    "name": "James Halliday",
+    "email": "mail@substack.net",
+    "url": "http://substack.net"
+  },
+  "contributors": [
+    {
+      "name": "Renée Kooi",
+      "email": "renee@kooi.me"
+    }
+  ],
+  "dependencies": {
+    "escodegen": "^2.1.0"
+  },
+  "devDependencies": {
+    "esprima": "^3.1.3",
+    "tape": "^4.10.1"
+  },
+  "homepage": "https://github.com/browserify/static-eval",
+  "keywords": [
+    "abstract",
+    "analysis",
+    "ast",
+    "esprima",
+    "eval",
+    "expression",
+    "static",
+    "syntax",
+    "tree"
+  ],
+  "license": "MIT",
+  "main": "index.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/browserify/static-eval.git"
+  },
+  "scripts": {
+    "test": "tape test/*.js"
+  },
+  "testling": {
+    "files": "test/*.js",
+    "browsers": [
+      "ie/8..latest",
+      "ff/latest",
+      "chrome/latest",
+      "opera/latest",
+      "safari/latest"
+    ]
+  }
+}
Index: frontend/node_modules/static-eval/readme.markdown
===================================================================
--- frontend/node_modules/static-eval/readme.markdown	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/readme.markdown	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,87 @@
+# static-eval
+
+evaluate statically-analyzable expressions
+
+[![testling badge](https://ci.testling.com/substack/static-eval.png)](https://ci.testling.com/substack/static-eval)
+
+[![build status](https://secure.travis-ci.org/browserify/static-eval.png)](http://travis-ci.org/browserify/static-eval)
+
+# security
+
+static-eval is like `eval`. It is intended for use in build scripts and code transformations, doing some evaluation at build time—it is **NOT** suitable for handling arbitrary untrusted user input. Malicious user input _can_ execute arbitrary code.
+
+# example
+
+``` js
+var evaluate = require('static-eval');
+var parse = require('esprima').parse;
+
+var src = process.argv[2];
+var ast = parse(src).body[0].expression;
+
+console.log(evaluate(ast));
+```
+
+If you stick to simple expressions, the result is statically analyzable:
+
+```
+$ node '7*8+9'
+65
+$ node eval.js '[1,2,3+4*5-(5*11)]'
+[ 1, 2, -32 ]
+```
+
+but if you use statements, undeclared identifiers, or syntax, the result is no
+longer statically analyzable and `evaluate()` returns `undefined`:
+
+```
+$ node eval.js '1+2+3*n'
+undefined
+$ node eval.js 'x=5; x*2'
+undefined
+$ node eval.js '5-4*3'
+-7
+```
+
+You can also declare variables and functions to use in the static evaluation:
+
+``` js
+var evaluate = require('static-eval');
+var parse = require('esprima').parse;
+
+var src = '[1,2,3+4*10+n,foo(3+5),obj[""+"x"].y]';
+var ast = parse(src).body[0].expression;
+
+console.log(evaluate(ast, {
+    n: 6,
+    foo: function (x) { return x * 100 },
+    obj: { x: { y: 555 } }
+}));
+```
+
+# methods
+
+``` js
+var evaluate = require('static-eval');
+```
+
+## evaluate(ast, vars={})
+
+Evaluate the [esprima](https://npmjs.org/package/esprima)-parsed abstract syntax
+tree object `ast` with an optional collection of variables `vars` to use in the
+static expression resolution.
+
+If the expression contained in `ast` can't be statically resolved, `evaluate()`
+returns undefined.
+
+# install
+
+With [npm](https://npmjs.org) do:
+
+```
+npm install static-eval
+```
+
+# license
+
+MIT
Index: frontend/node_modules/static-eval/security.md
===================================================================
--- frontend/node_modules/static-eval/security.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/security.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,15 @@
+# Security Policy
+
+## Supported Versions
+Only the latest major version is supported at any given time.
+
+## Reporting a Vulnerability
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.
+
+Note that this package is intended for use in build-time
+transformations. It is only intended to handle trusted code. If a
+vulnerability requires a fix that would prevent important use cases, we
+may decide not to address it.
Index: frontend/node_modules/static-eval/test/eval.js
===================================================================
--- frontend/node_modules/static-eval/test/eval.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/test/eval.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,177 @@
+var test = require('tape');
+var evaluate = require('../');
+var parse = require('esprima').parse;
+
+test('resolved', function (t) {
+    t.plan(1);
+    
+    var src = '[1,2,3+4*10+(n||6),foo(3+5),obj[""+"x"].y]';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {
+        n: false,
+        foo: function (x) { return x * 100 },
+        obj: { x: { y: 555 } }
+    });
+    t.deepEqual(res, [ 1, 2, 49, 800, 555 ]);
+});
+
+test('unresolved', function (t) {
+    t.plan(1);
+    
+    var src = '[1,2,3+4*10*z+n,foo(3+5),obj[""+"x"].y]';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {
+        n: 6,
+        foo: function (x) { return x * 100 },
+        obj: { x: { y: 555 } }
+    });
+    t.equal(res, undefined);
+});
+
+test('boolean', function (t) {
+    t.plan(1);
+    
+    var src = '[ 1===2+3-16/4, [2]==2, [2]!==2, [2]!==[2] ]';
+    var ast = parse(src).body[0].expression;
+    t.deepEqual(evaluate(ast), [ true, true, true, true ]);
+});
+
+test('array methods', function(t) {
+    t.plan(1);
+
+    var src = '[1, 2, 3].map(function(n) { return n * 2 })';
+    var ast = parse(src).body[0].expression;
+    t.deepEqual(evaluate(ast), [2, 4, 6]);
+});
+
+test('array methods invocation count', function(t) {
+    t.plan(2);
+
+    var variables = {
+        values: [1, 2, 3],
+        receiver: []
+    };
+    var src = 'values.forEach(function(x) { receiver.push(x); })'
+    var ast = parse(src).body[0].expression;
+    evaluate(ast, variables);
+    t.equal(variables.receiver.length, 3);
+    t.deepEqual(variables.receiver, [1, 2, 3]);
+})
+
+test('array methods with vars', function(t) {
+    t.plan(1);
+
+    var src = '[1, 2, 3].map(function(n) { return n * x })';
+    var ast = parse(src).body[0].expression;
+    t.deepEqual(evaluate(ast, {x: 2}), [2, 4, 6]);
+});
+
+test('evaluate this', function(t) {
+    t.plan(1);
+
+    var src = 'this.x + this.y.z';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {
+        'this': { x: 1, y: { z: 100 } }
+    });
+    t.equal(res, 101);
+});
+
+test('FunctionExpression unresolved', function(t) {
+    t.plan(1);
+
+    var src = '(function(){console.log("Not Good")})';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {});
+    t.equal(res, undefined);
+});
+
+test('MemberExpressions from Functions unresolved', function(t) {
+    t.plan(1);
+
+    var src = '(function () {}).constructor';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {});
+    t.equal(res, undefined);
+});
+
+test('disallow accessing constructor or __proto__', function (t) {
+    t.plan(4)
+
+    var someValue = {};
+
+    var src = 'object.constructor';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, { vars: { object: someValue } });
+    t.equal(res, undefined);
+
+    var src = 'object["constructor"]';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, { vars: { object: someValue } });
+    t.equal(res, undefined);
+
+    var src = 'object.__proto__';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, { vars: { object: someValue } });
+    t.equal(res, undefined);
+
+    var src = 'object["__pro"+"t\x6f__"]';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, { vars: { object: someValue } });
+    t.equal(res, undefined);
+});
+
+
+test('constructor at runtime only', function(t) {
+    t.plan(2)
+
+    var src = '(function myTag(y){return ""[!y?"__proto__":"constructor"][y]})("constructor")("console.log(process.env)")()'
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast);
+    t.equal(res, undefined);
+
+    var src = '(function(prop) { return {}[prop ? "benign" : "constructor"][prop] })("constructor")("alert(1)")()'
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast);
+    t.equal(res, undefined);
+});
+
+test('short circuit evaluation AND', function(t) {
+    t.plan(1);
+
+    var variables = {
+        value: null
+    };
+    var src = 'value && value.func()';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, variables);
+    t.equals(res, null);
+})
+
+test('short circuit evaluation OR', function(t) {
+    t.plan(1);
+
+    var fnInvoked = false;
+    var variables = {
+        value: true,
+        fn: function() { fnInvoked = true}
+    };
+    var src = 'value || fn()';
+    var ast = parse(src).body[0].expression;
+    evaluate(ast, variables);
+    t.equals(fnInvoked, false);
+})
+
+test('function declaration does not invoke CallExpressions', function(t) {
+    t.plan(1);
+
+    var invoked = false;
+    var variables = {
+        noop: function(){},
+        onInvoke: function() {invoked = true}
+    };
+    var src = 'noop(function(){ onInvoke(); })';
+    var ast = parse(src).body[0].expression;
+    evaluate(ast, variables);
+    t.equal(invoked, false);
+});
Index: frontend/node_modules/static-eval/test/prop.js
===================================================================
--- frontend/node_modules/static-eval/test/prop.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/test/prop.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,16 @@
+var test = require('tape');
+var evaluate = require('../');
+var parse = require('esprima').parse;
+
+test('function property', function (t) {
+    t.plan(1);
+    
+    var src = '[1,2,3+4*10+n,beep.boop(3+5),obj[""+"x"].y]';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {
+        n: 6,
+        beep: { boop: function (x) { return x * 100 } },
+        obj: { x: { y: 555 } }
+    });
+    t.deepEqual(res, [ 1, 2, 49, 800, 555 ]);
+});
Index: frontend/node_modules/static-eval/test/template-strings.js
===================================================================
--- frontend/node_modules/static-eval/test/template-strings.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/static-eval/test/template-strings.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,33 @@
+var test = require('tape');
+var evaluate = require('../');
+var parse = require('esprima').parse;
+
+test('untagged template strings', function (t) {
+    t.plan(1);
+    
+    var src = '`${1},${2 + n},${`4,5`}`';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {
+        n: 6
+    });
+    t.deepEqual(res, '1,8,4,5');
+});
+
+test('tagged template strings', function (t) {
+    t.plan(3);
+
+    var src = 'template`${1},${2 + n},${`4,5`}`';
+    var ast = parse(src).body[0].expression;
+    var res = evaluate(ast, {
+        template: function (strings) {
+            t.deepEqual(strings, ['', ',', ',', '']);
+
+            var values = [].slice.call(arguments, 1);
+            t.deepEqual(values, [1, 8, '4,5']);
+
+            return 'foo';
+        },
+        n: 6
+    });
+    t.deepEqual(res, 'foo');
+})
