From 83f22432d80768c09707d07fc88356f46a9ffcfc Mon Sep 17 00:00:00 2001 From: Recursive Lambda God Date: Sat, 29 Apr 2017 13:49:13 -0400 Subject: [PATCH] "Recursive Lambda Refactor V1" --- runtime/Zumo.Node.js | 7750 +++++++++-------- runtime/consolelogwriter.js | 7 +- runtime/core.js | 89 +- runtime/encryptor.js | 4 +- runtime/filehelpers.js | 21 +- runtime/filewatcher.js | 15 +- runtime/jsonwebtoken.js | 27 +- runtime/logger.js | 37 +- runtime/logwriter.js | 46 +- runtime/metrics.js | 16 +- runtime/newrelicadapter.js | 26 +- runtime/push/nhregistrationhandler.js | 95 +- runtime/push/nhregistrationhelpers/apns.js | 6 +- runtime/push/nhregistrationhelpers/gcm.js | 6 +- runtime/push/nhregistrationhelpers/mpns.js | 18 +- runtime/push/nhregistrationhelpers/wns.js | 18 +- runtime/push/pushadapter.js | 37 +- .../scripthelpers/apnconnectionfactory.js | 21 +- runtime/push/scripthelpers/notify-apns.js | 37 +- runtime/push/scripthelpers/notify-gcm.js | 13 +- runtime/push/scripthelpers/notify-mpns.js | 9 +- runtime/push/scripthelpers/notify-wns.js | 14 +- runtime/push/scripthelpers/notify.js | 35 +- runtime/query/expressions.js | 20 +- runtime/query/expressionvisitor.js | 26 +- runtime/query/queryparser.js | 104 +- runtime/request/authentication/aad.js | 75 +- runtime/request/authentication/aadcert.js | 10 +- .../request/authentication/certcachehelper.js | 15 +- runtime/request/authentication/facebook.js | 21 +- runtime/request/authentication/google.js | 75 +- runtime/request/authentication/googlecert.js | 7 +- .../authentication/microsoftaccount.js | 50 +- runtime/request/authentication/twitter.js | 33 +- runtime/request/dataoperation.js | 39 +- runtime/request/datapipeline.js | 53 +- runtime/request/diagnosticshandler.js | 38 +- runtime/request/errorhelper.js | 17 +- runtime/request/etaghelper.js | 15 +- runtime/request/html/corshelper.js | 43 +- runtime/request/html/crossdomainhandler.js | 21 +- runtime/request/html/templating.js | 22 +- runtime/request/loginhandler.js | 156 +- runtime/request/middleware/allowhandler.js | 11 +- runtime/request/middleware/authenticate.js | 29 +- runtime/request/middleware/authorize.js | 19 +- runtime/request/middleware/bodyparser.js | 6 +- runtime/request/middleware/errorhandler.js | 21 +- runtime/request/middleware/requestlimit.js | 19 +- runtime/request/middleware/requirehttps.js | 16 +- runtime/request/middleware/versioncheck.js | 36 +- runtime/request/request.js | 11 +- runtime/request/requesthandler.js | 126 +- runtime/request/schedulerhandler.js | 15 +- runtime/request/statushandler.js | 6 +- runtime/request/tablehandler.js | 43 +- runtime/request/user.js | 27 +- runtime/resources.js | 4 +- runtime/script/apibuilder.js | 68 +- runtime/script/extensionmanager.js | 33 +- runtime/script/metadata.js | 29 +- runtime/script/scriptcache.js | 6 +- runtime/script/scripterror.js | 9 +- runtime/script/scriptloader.js | 89 +- runtime/script/scriptmanager.js | 64 +- runtime/script/scriptstate.js | 21 +- runtime/script/sqladapter.js | 37 +- runtime/script/table.js | 73 +- runtime/script/zumocallback.js | 42 +- runtime/server.js | 97 +- runtime/statuscodes.js | 4 +- runtime/storage/sqlbooleanizer.js | 10 +- runtime/storage/sqlformatter.js | 79 +- runtime/storage/sqlhelpers.js | 42 +- runtime/storage/storage.js | 248 +- runtime/storage/tablemetadata.js | 15 +- runtime/storage/typeconverter.js | 18 +- runtime/users/userproperties.js | 11 +- runtime/users/userservice.js | 61 +- runtime/users/userstore.js | 40 +- 80 files changed, 5515 insertions(+), 5157 deletions(-) diff --git a/runtime/Zumo.Node.js b/runtime/Zumo.Node.js index 99e4a80..5b50c7d 100644 --- a/runtime/Zumo.Node.js +++ b/runtime/Zumo.Node.js @@ -9,7 +9,7 @@ // lost the next time it is regenerated. -(function (global) { +((global => { /// /// Map module names to either their cached exports or a function which /// will define the module's exports when invoked. @@ -47,7 +47,7 @@ } } - $__modules__.NodeExports = function (exports) { + $__modules__.NodeExports = exports => { // ---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- @@ -68,63 +68,66 @@ * ---------------------------------------------------------------------------- */ - (function() { - var JS, JavaScript, JavaScriptToQueryVisitor, PartialEvaluator, esprima; - - esprima = require('esprima'); - - JS = require('./JavaScriptNodes'); - - PartialEvaluator = require('./PartialEvaluator').PartialEvaluator; - - JavaScriptToQueryVisitor = require('./JavaScriptToQueryVisitor').JavaScriptToQueryVisitor; - - - /* - * Define operations on JavaScript - */ - - exports.JavaScript = JavaScript = (function() { - function JavaScript() {} - - + ((() => { + var JS; + var JavaScript; + var JavaScriptToQueryVisitor; + var PartialEvaluator; + var esprima; + + esprima = require('esprima'); + + JS = require('./JavaScriptNodes'); + + PartialEvaluator = require('./PartialEvaluator').PartialEvaluator; + + JavaScriptToQueryVisitor = require('./JavaScriptToQueryVisitor').JavaScriptToQueryVisitor; + + /* - * Static method to transform a constraint specified as a function into - * a QueryExpression tree. + * Define operations on JavaScript */ - - JavaScript.transformConstraint = function(func, env) { - + + exports.JavaScript = JavaScript = ((() => { + function JavaScript() {} + + /* - * Parse the body of the function into a JavaScriptExpression tree - * (into a context that also contains its source and manually reified - * environment) + * Static method to transform a constraint specified as a function into + * a QueryExpression tree. */ - var context, translator; - context = JavaScript.getExpression(func, env); - + + JavaScript.transformConstraint = (func, env) => { + /* + * Parse the body of the function into a JavaScriptExpression tree + * (into a context that also contains its source and manually reified + * environment) + */ + var context; + + var translator; + context = JavaScript.getExpression(func, env); + + /* + * Evaluate any independent subexpressions and turn them into + * literals. + */ + context.expression = PartialEvaluator.evaluate(context); + + /* + * Convert the JavaScriptExpression tree into a QueryExpression tree + */ + translator = new JavaScriptToQueryVisitor(context); + return translator.visit(context.expression); + }; + + /* - * Evaluate any independent subexpressions and turn them into - * literals. + * Static method to walk a projection specified as a function and + * determine which fields it uses. */ - context.expression = PartialEvaluator.evaluate(context); - - /* - * Convert the JavaScriptExpression tree into a QueryExpression tree - */ - translator = new JavaScriptToQueryVisitor(context); - return translator.visit(context.expression); - }; - - - /* - * Static method to walk a projection specified as a function and - * determine which fields it uses. - */ - - JavaScript.getProjectedFields = function(func) { - - /* + + JavaScript.getProjectedFields = func => /* * This currently returns an empty array which indicates all fields. * At some point we'll need to go through and walk the expression * tree for func and see exactly which fields it uses. This is @@ -134,73 +137,91 @@ * probably just default to [] rather than trying to do alias * analysis across function calls, etc.) */ - return []; - }; - - - /* - * Turn a function and its explicitly passed environment into an - * expression tree - */ - - JavaScript.getExpression = function(func, env) { - + []; + + /* - * An anonymous function isn't considered a valid program, so we'll wrap - * it in an assignment statement to keep the parser happy + * Turn a function and its explicitly passed environment into an + * expression tree */ - var environment, expr, i, name, names, program, source, _i, _len, _ref, _ref1, _ref10, _ref11, _ref12, _ref13, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; - source = "var _$$_stmt_$$_ = " + func + ";"; - - /* - * Use esprima to parse the source of the function body (and have it - * return source locations in character ranges ) - */ - program = esprima.parse(source, { - range: true - }); - - /* - * Get the expression from return statement of the function body to use - * as our lambda expression - */ - expr = (program != null ? program.type : void 0) === 'Program' && (program != null ? (_ref = program.body) != null ? _ref.length : void 0 : void 0) === 1 && ((_ref1 = program.body[0]) != null ? _ref1.type : void 0) === 'VariableDeclaration' && ((_ref2 = program.body[0]) != null ? (_ref3 = _ref2.declarations) != null ? _ref3.length : void 0 : void 0) === 1 && ((_ref4 = program.body[0].declarations[0]) != null ? _ref4.type : void 0) === 'VariableDeclarator' && ((_ref5 = program.body[0].declarations[0]) != null ? (_ref6 = _ref5.init) != null ? _ref6.type : void 0 : void 0) === 'FunctionExpression' && ((_ref7 = program.body[0].declarations[0].init) != null ? (_ref8 = _ref7.body) != null ? _ref8.type : void 0 : void 0) === 'BlockStatement' && ((_ref9 = program.body[0].declarations[0].init.body) != null ? (_ref10 = _ref9.body) != null ? _ref10.length : void 0 : void 0) === 1 && ((_ref11 = program.body[0].declarations[0].init.body.body[0]) != null ? _ref11.type : void 0) === 'ReturnStatement' && ((_ref12 = program.body[0].declarations[0].init.body.body[0]) != null ? _ref12.argument : void 0); - if (!expr) { - throw "Expected a predicate with a single return statement, not " + func; - } - - /* - * Create the environment mqpping parameters to values - */ - names = (_ref13 = program.body[0].declarations[0].init.params) != null ? _ref13.map(function(p) { - return p.name; - }) : void 0; - if (names.length > env.length) { - throw "Expected value(s) for parameter(s) " + names.slice(env.length); - } else if (env.length > names.length) { - throw "Expected parameter(s) for value(s) " + env.slice(names.length); - } - environment = {}; - for (i = _i = 0, _len = names.length; _i < _len; i = ++_i) { - name = names[i]; - environment[name] = env[i]; - } - return { - - /* - * Return the environment context - */ - source: source, - expression: expr, - environment: environment + + JavaScript.getExpression = (func, env) => { + /* + * An anonymous function isn't considered a valid program, so we'll wrap + * it in an assignment statement to keep the parser happy + */ + var environment; + + var expr; + var i; + var name; + var names; + var program; + var source; + var _i; + var _len; + var _ref; + var _ref1; + var _ref10; + var _ref11; + var _ref12; + var _ref13; + var _ref2; + var _ref3; + var _ref4; + var _ref5; + var _ref6; + var _ref7; + var _ref8; + var _ref9; + source = "var _$$_stmt_$$_ = " + func + ";"; + + /* + * Use esprima to parse the source of the function body (and have it + * return source locations in character ranges ) + */ + program = esprima.parse(source, { + range: true + }); + + /* + * Get the expression from return statement of the function body to use + * as our lambda expression + */ + expr = (program != null ? program.type : void 0) === 'Program' && (program != null ? (_ref = program.body) != null ? _ref.length : void 0 : void 0) === 1 && ((_ref1 = program.body[0]) != null ? _ref1.type : void 0) === 'VariableDeclaration' && ((_ref2 = program.body[0]) != null ? (_ref3 = _ref2.declarations) != null ? _ref3.length : void 0 : void 0) === 1 && ((_ref4 = program.body[0].declarations[0]) != null ? _ref4.type : void 0) === 'VariableDeclarator' && ((_ref5 = program.body[0].declarations[0]) != null ? (_ref6 = _ref5.init) != null ? _ref6.type : void 0 : void 0) === 'FunctionExpression' && ((_ref7 = program.body[0].declarations[0].init) != null ? (_ref8 = _ref7.body) != null ? _ref8.type : void 0 : void 0) === 'BlockStatement' && ((_ref9 = program.body[0].declarations[0].init.body) != null ? (_ref10 = _ref9.body) != null ? _ref10.length : void 0 : void 0) === 1 && ((_ref11 = program.body[0].declarations[0].init.body.body[0]) != null ? _ref11.type : void 0) === 'ReturnStatement' && ((_ref12 = program.body[0].declarations[0].init.body.body[0]) != null ? _ref12.argument : void 0); + if (!expr) { + throw "Expected a predicate with a single return statement, not " + func; + } + + /* + * Create the environment mqpping parameters to values + */ + names = (_ref13 = program.body[0].declarations[0].init.params) != null ? _ref13.map(p => p.name) : void 0; + if (names.length > env.length) { + throw "Expected value(s) for parameter(s) " + names.slice(env.length); + } else if (env.length > names.length) { + throw "Expected parameter(s) for value(s) " + env.slice(names.length); + } + environment = {}; + for (i = _i = 0, _len = names.length; _i < _len; i = ++_i) { + name = names[i]; + environment[name] = env[i]; + } + return { + + /* + * Return the environment context + */ + source, + expression: expr, + environment + }; }; - }; - - return JavaScript; - - })(); - - }).call(this); + + return JavaScript; + + }))(); + })).call(this); }; $__modules__.JavaScriptNodes = function (exports) { @@ -228,1434 +249,1487 @@ /* Get the base Node and Visitor classes. */ - (function() { - var ArrayExpression, ArrayPattern, AssignmentExpression, BinaryExpression, BlockStatement, BreakStatement, CallExpression, CatchClause, ConditionalExpression, ContinueStatement, DebuggerStatement, Declaration, DoWhileStatement, EmptyStatement, Expression, ExpressionStatement, ForInStatement, ForStatement, Function, FunctionDeclaration, FunctionExpression, Identifier, IfStatement, JavaScriptNode, JavaScriptVisitor, LabeledStatement, Literal, LogicalExpression, MemberExpression, NewExpression, Node, ObjectExpression, ObjectPattern, Pattern, Program, ReturnStatement, SequenceExpression, Statement, SwitchCase, SwitchStatement, ThisExpression, ThrowStatement, TryStatement, UnaryExpression, UpdateExpression, VariableDeclaration, VariableDeclarator, Visitor, WhileStatement, WithStatement, _ref, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - _ref = require('./Node'), Node = _ref.Node, Visitor = _ref.Visitor; - - - /* - * Base node for all JavaScript nodes. - */ - - exports.JavaScriptNode = JavaScriptNode = (function(_super) { - __extends(JavaScriptNode, _super); - - function JavaScriptNode() { - JavaScriptNode.__super__.constructor.call(this); - } - - return JavaScriptNode; - - })(Node); - - - /* - * Base visitor for all JavaScript nodes. - */ - - exports.JavaScriptVisitor = JavaScriptVisitor = (function(_super) { - __extends(JavaScriptVisitor, _super); - - function JavaScriptVisitor() { - JavaScriptVisitor.__super__.constructor.call(this); - } - - JavaScriptVisitor.prototype.JavaScriptNode = function(node) { + ((() => { + var ArrayExpression; + var ArrayPattern; + var AssignmentExpression; + var BinaryExpression; + var BlockStatement; + var BreakStatement; + var CallExpression; + var CatchClause; + var ConditionalExpression; + var ContinueStatement; + var DebuggerStatement; + var Declaration; + var DoWhileStatement; + var EmptyStatement; + var Expression; + var ExpressionStatement; + var ForInStatement; + var ForStatement; + var Function; + var FunctionDeclaration; + var FunctionExpression; + var Identifier; + var IfStatement; + var JavaScriptNode; + var JavaScriptVisitor; + var LabeledStatement; + var Literal; + var LogicalExpression; + var MemberExpression; + var NewExpression; + var Node; + var ObjectExpression; + var ObjectPattern; + var Pattern; + var Program; + var ReturnStatement; + var SequenceExpression; + var Statement; + var SwitchCase; + var SwitchStatement; + var ThisExpression; + var ThrowStatement; + var TryStatement; + var UnaryExpression; + var UpdateExpression; + var VariableDeclaration; + var VariableDeclarator; + var Visitor; + var WhileStatement; + var WithStatement; + var _ref; + var __hasProp = {}.hasOwnProperty; + var __extends = (child, parent) => { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + _ref = require('./Node'), Node = _ref.Node, Visitor = _ref.Visitor; + + + /* + * Base node for all JavaScript nodes. + */ + + exports.JavaScriptNode = JavaScriptNode = ((_super => { + __extends(JavaScriptNode, _super); + + function JavaScriptNode() { + JavaScriptNode.__super__.constructor.call(this); + } + + return JavaScriptNode; + + }))(Node); + + + /* + * Base visitor for all JavaScript nodes. + */ + + exports.JavaScriptVisitor = JavaScriptVisitor = ((_super => { + __extends(JavaScriptVisitor, _super); + + function JavaScriptVisitor() { + JavaScriptVisitor.__super__.constructor.call(this); + } + + JavaScriptVisitor.prototype.JavaScriptNode = node => node; + + return JavaScriptVisitor; + + }))(Visitor); + + + /* + * A complete program source tree. + */ + + exports.Program = Program = ((_super => { + __extends(Program, _super); + + + /* + * @elements: [Statement] + */ + + function Program(elements) { + this.elements = elements; + Program.__super__.constructor.call(this); + } + + return Program; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.Program = function(node) { + node = this.JavaScriptNode(node); + node.elements = this.visit(node.elements); return node; }; - - return JavaScriptVisitor; - - })(Visitor); - - - /* - * A complete program source tree. - */ - - exports.Program = Program = (function(_super) { - __extends(Program, _super); - - + + /* - * @elements: [Statement] + * A function declaration or expression. The body of the function is a block + * statement. */ - - function Program(elements) { - this.elements = elements; - Program.__super__.constructor.call(this); - } - - return Program; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.Program = function(node) { - node = this.JavaScriptNode(node); - node.elements = this.visit(node.elements); - return node; - }; - - - /* - * A function declaration or expression. The body of the function is a block - * statement. - */ - - exports.Function = Function = (function(_super) { - __extends(Function, _super); - - - /* - * @id: Identifier | null - * @params: [Pattern] - * @body: BlockStatement - */ - - function Function(id, params, body) { - this.id = id; - this.params = params; - this.body = body; - Function.__super__.constructor.call(this); - } - - return Function; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.Function = function(node) { - node = this.JavaScriptNode(node); - node.id = this.visit(node.id); - node.params = this.visit(node.params); - node.body = this.visit(node.body); - return node; - }; - - - /* - * Any statement. - */ - - exports.Statement = Statement = (function(_super) { - __extends(Statement, _super); - - function Statement() { - Statement.__super__.constructor.call(this); - } - - return Statement; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.Statement = function(node) { - node = this.JavaScriptNode(node); - return node; - }; - - - /* - * An empty statement, i.e., a solitary semicolon. - */ - - exports.EmptyStatement = EmptyStatement = (function(_super) { - __extends(EmptyStatement, _super); - - function EmptyStatement() { - EmptyStatement.__super__.constructor.call(this); - } - - return EmptyStatement; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.EmptyStatement = function(node) { - node = this.JavaScriptNode(node); - return node; - }; - - - /* - * A block statement, i.e., a sequence of statements surrounded by braces. - */ - - exports.BlockStatement = BlockStatement = (function(_super) { - __extends(BlockStatement, _super); - - - /* - * @body: [Statement] - */ - - function BlockStatement(body) { - this.body = body; - BlockStatement.__super__.constructor.call(this); - } - - return BlockStatement; - - })(Statement); - - JavaScriptVisitor.prototype.BlockStatement = function(node) { - node = this.Statement(node); - node.body = this.visit(node.body); - return node; - }; - - - /* - * An expression statement, i.e., a statement consisting of a single expression. - */ - - exports.ExpressionStatement = ExpressionStatement = (function(_super) { - __extends(ExpressionStatement, _super); - - function ExpressionStatement() { - ExpressionStatement.__super__.constructor.call(this); - } - - return ExpressionStatement; - - })(Statement); - - JavaScriptVisitor.prototype.ExpressionStatement = function(node) { - node = this.Statement(node); - return node; - }; - - - /* - * An if statement. - */ - - exports.IfStatement = IfStatement = (function(_super) { - __extends(IfStatement, _super); - - - /* - * @test: Expression - * @consequent: Statement - * @alternate: Statement | null - */ - - function IfStatement(test, consequent, alternate) { - this.test = test; - this.consequent = consequent; - this.alternate = alternate; - IfStatement.__super__.constructor.call(this); - } - - return IfStatement; - - })(Statement); - - JavaScriptVisitor.prototype.IfStatement = function(node) { - node = this.Statement(node); - node.test = this.visit(node.test); - node.consequent = this.visit(node.consequent); - node.alternate = this.visit(node.alternate); - return node; - }; - - - /* - * A labeled statement, i.e., a statement prefixed by a break/continue label. - */ - - exports.LabeledStatement = LabeledStatement = (function(_super) { - __extends(LabeledStatement, _super); - - - /* - * @label: Identifier - * @body: Statement - */ - - function LabeledStatement(label, body) { - this.label = label; - this.body = body; - LabeledStatement.__super__.constructor.call(this); - } - - return LabeledStatement; - - })(Statement); - - JavaScriptVisitor.prototype.LabeledStatement = function(node) { - node = this.Statement(node); - node.label = this.visit(node.label); - node.body = this.visit(node.body); - return node; - }; - - - /* - * A break statement. - */ - - exports.BreakStatement = BreakStatement = (function(_super) { - __extends(BreakStatement, _super); - - - /* - * @label: Identifier | null - */ - - function BreakStatement(label) { - this.label = label; - BreakStatement.__super__.constructor.call(this); - } - - return BreakStatement; - - })(Statement); - - JavaScriptVisitor.prototype.BreakStatement = function(node) { - node = this.Statement(node); - node.label = this.visit(node.label); - return node; - }; - - - /* - A continue statement. - */ - - exports.ContinueStatement = ContinueStatement = (function(_super) { - __extends(ContinueStatement, _super); - - - /* - @label: Identifier | null - */ - - function ContinueStatement(label) { - this.label = label; - ContinueStatement.__super__.constructor.call(this); - } - - return ContinueStatement; - - })(Statement); - - JavaScriptVisitor.prototype.ContinueStatement = function(node) { - node = this.Statement(node); - node.label = this.visit(node.label); - return node; - }; - - - /* - * A with statement. - */ - - exports.WithStatement = WithStatement = (function(_super) { - __extends(WithStatement, _super); - - - /* - * @object: Expression - * @body: Statement - */ - - function WithStatement(object, body) { - this.object = object; - this.body = body; - WithStatement.__super__.constructor.call(this); - } - - return WithStatement; - - })(Statement); - - JavaScriptVisitor.prototype.WithStatement = function(node) { - node = this.Statement(node); - node.object = this.visit(node.object); - node.body = this.visit(node.body); - return node; - }; - - - /* - * A switch statement. - */ - - exports.SwitchStatement = SwitchStatement = (function(_super) { - __extends(SwitchStatement, _super); - - - /* - * @discriminant: Expression - * @cases: [SwitchCase] - */ - - function SwitchStatement(discriminant, cases) { - this.discriminant = discriminant; - this.cases = cases; - SwitchStatement.__super__.constructor.call(this); - } - - return SwitchStatement; - - })(Statement); - - JavaScriptVisitor.prototype.SwitchStatement = function(node) { - node = this.Statement(node); - node.discriminant = this.visit(node.discriminant); - node.cases = this.visit(node.cases); - return node; - }; - - - /* - * A return statement. - */ - - exports.ReturnStatement = ReturnStatement = (function(_super) { - __extends(ReturnStatement, _super); - - - /* - * @argument: Expression | null - */ - - function ReturnStatement(argument) { - this.argument = argument; - ReturnStatement.__super__.constructor.call(this); - } - - return ReturnStatement; - - })(Statement); - - JavaScriptVisitor.prototype.ReturnStatement = function(node) { - node = this.Statement(node); - node.argument = this.visit(node.argument); - return node; - }; - - - /* - * A throw statement. - */ - - exports.ThrowStatement = ThrowStatement = (function(_super) { - __extends(ThrowStatement, _super); - - - /* - * @argument: Expression - */ - - function ThrowStatement(argument) { - this.argument = argument; - ThrowStatement.__super__.constructor.call(this); - } - - return ThrowStatement; - - })(Statement); - - JavaScriptVisitor.prototype.ThrowStatement = function(node) { - node = this.Statement(node); - node.argument = this.visit(node.argument); - return node; - }; - - - /* - * A try statement. - */ - - exports.TryStatement = TryStatement = (function(_super) { - __extends(TryStatement, _super); - - - /* - * @block: BlockStatement - * @handlers: [CatchClause] - * @finalizer: BlockStatement | null - */ - - function TryStatement(block, handlers, finalizer) { - this.block = block; - this.handlers = handlers; - this.finalizer = finalizer; - TryStatement.__super__.constructor.call(this); - } - - return TryStatement; - - })(Statement); - - JavaScriptVisitor.prototype.TryStatement = function(node) { - node = this.Statement(node); - node.block = this.visit(node.block); - node.handlers = this.visit(node.handlers); - node.finalizer = this.visit(node.finalizer); - return node; - }; - - - /* - * A while statement. - */ - - exports.WhileStatement = WhileStatement = (function(_super) { - __extends(WhileStatement, _super); - - - /* - * @test: Expression - * @body: Statement - */ - - function WhileStatement(test, body) { - this.test = test; - this.body = body; - WhileStatement.__super__.constructor.call(this); - } - - return WhileStatement; - - })(Statement); - - JavaScriptVisitor.prototype.WhileStatement = function(node) { - node = this.Statement(node); - node.test = this.visit(node.test); - node.body = this.visit(node.body); - return node; - }; - - - /* - * A do/while statement. - */ - - exports.DoWhileStatement = DoWhileStatement = (function(_super) { - __extends(DoWhileStatement, _super); - - - /* - * @body: Statement - * @test: Expression - */ - - function DoWhileStatement(body, test) { - this.body = body; - this.test = test; - DoWhileStatement.__super__.constructor.call(this); - } - - return DoWhileStatement; - - })(Statement); - - JavaScriptVisitor.prototype.DoWhileStatement = function(node) { - node = this.Statement(node); - node.body = this.visit(node.body); - node.test = this.visit(node.test); - return node; - }; - - - /* - * A for statement. - */ - - exports.ForStatement = ForStatement = (function(_super) { - __extends(ForStatement, _super); - - - /* - * @init: VariableDeclaration | Expression | null - * @test: Expression | null - * @update: Expression | null - * @body: Statement - */ - - function ForStatement(init, test, update, body) { - this.init = init; - this.test = test; - this.update = update; - this.body = body; - ForStatement.__super__.constructor.call(this); - } - - return ForStatement; - - })(Statement); - - JavaScriptVisitor.prototype.ForStatement = function(node) { - node = this.Statement(node); - node.init = this.visit(node.init); - node.test = this.visit(node.test); - node.update = this.visit(node.update); - node.body = this.visit(node.body); - return node; - }; - - - /* - * A for/in statement, or, if each is true, a for each/in statement. - */ - - exports.ForInStatement = ForInStatement = (function(_super) { - __extends(ForInStatement, _super); - - - /* - * @left: VariableDeclaration | Expression - * @right: Expression - * @body: Statement - */ - - function ForInStatement(left, right, body) { - this.left = left; - this.right = right; - this.body = body; - ForInStatement.__super__.constructor.call(this); - } - - return ForInStatement; - - })(Statement); - - JavaScriptVisitor.prototype.ForInStatement = function(node) { - node = this.Statement(node); - node.left = this.visit(node.left); - node.right = this.visit(node.right); - node.body = this.visit(node.body); - return node; - }; - - - /* - * A debugger statement. - */ - - exports.DebuggerStatement = DebuggerStatement = (function(_super) { - __extends(DebuggerStatement, _super); - - function DebuggerStatement() { - DebuggerStatement.__super__.constructor.call(this); - } - - return DebuggerStatement; - - })(Statement); - - JavaScriptVisitor.prototype.DebuggerStatement = function(node) { - node = this.Statement(node); - return node; - }; - - - /* - * Any declaration node. Note that declarations are considered statements; this - * is because declarations can appear in any statement context in the language. - */ - - exports.Declaration = Declaration = (function(_super) { - __extends(Declaration, _super); - - function Declaration() { - Declaration.__super__.constructor.call(this); - } - - return Declaration; - - })(Statement); - - JavaScriptVisitor.prototype.Declaration = function(node) { - node = this.Statement(node); - return node; - }; - - - /* - * A function declaration. Note: The id field cannot be null. - */ - - exports.FunctionDeclaration = FunctionDeclaration = (function(_super) { - __extends(FunctionDeclaration, _super); - - - /* - * @id: Identifier - * @params: [ Pattern ] - * @body: BlockStatement | Expression - */ - - function FunctionDeclaration(id, params, body) { - this.id = id; - this.params = params; - this.body = body; - FunctionDeclaration.__super__.constructor.call(this); - } - - return FunctionDeclaration; - - })(Declaration); - - JavaScriptVisitor.prototype.FunctionDeclaration = function(node) { - node = this.Declaration(node); - node.id = this.visit(node.id); - node.params = this.visit(node.params); - node.body = this.visit(node.body); - return node; - }; - - - /* - * A variable declaration, via one of var, let, or const. - */ - - exports.VariableDeclaration = VariableDeclaration = (function(_super) { - __extends(VariableDeclaration, _super); - - - /* - * @declarations: [ VariableDeclarator ] - * @kind: "var" - */ - - function VariableDeclaration(declarations, kind) { - this.declarations = declarations; - this.kind = kind; - VariableDeclaration.__super__.constructor.call(this); - } - - return VariableDeclaration; - - })(Declaration); - - JavaScriptVisitor.prototype.VariableDeclaration = function(node) { - node = this.Declaration(node); - node.declarations = this.visit(node.declarations); - return node; - }; - - - /* - * A variable declarator. Note: The id field cannot be null. - */ - - exports.VariableDeclarator = VariableDeclarator = (function(_super) { - __extends(VariableDeclarator, _super); - - - /* - * @id: Pattern - * @init: Expression | null - */ - - function VariableDeclarator(id, init) { - this.id = id; - this.init = init; - VariableDeclarator.__super__.constructor.call(this); - } - - return VariableDeclarator; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.VariableDeclarator = function(node) { - node = this.JavaScriptNode(node); - node.id = this.visit(node.id); - node.init = this.visit(node.init); - return node; - }; - - - /* - * Any expression node. Since the left-hand side of an assignment may be any - * expression in general, an expression can also be a pattern. - */ - - exports.Expression = Expression = (function(_super) { - __extends(Expression, _super); - - function Expression() { - return Expression.__super__.constructor.apply(this, arguments); - } - - Expression.prototype.constuctor = function() { - return Expression.__super__.constuctor.call(this); + + exports.Function = Function = ((_super => { + __extends(Function, _super); + + + /* + * @id: Identifier | null + * @params: [Pattern] + * @body: BlockStatement + */ + + function Function(id, params, body) { + this.id = id; + this.params = params; + this.body = body; + Function.__super__.constructor.call(this); + } + + return Function; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.Function = function(node) { + node = this.JavaScriptNode(node); + node.id = this.visit(node.id); + node.params = this.visit(node.params); + node.body = this.visit(node.body); + return node; }; - - return Expression; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.Expression = function(node) { - node = this.JavaScriptNode(node); - return node; - }; - - - /* - * A this expression. - */ - - exports.ThisExpression = ThisExpression = (function(_super) { - __extends(ThisExpression, _super); - - function ThisExpression() { - ThisExpression.__super__.constructor.call(this); - } - - return ThisExpression; - - })(Expression); - - JavaScriptVisitor.prototype.ThisExpression = function(node) { - node = this.Expression(node); - return node; - }; - - - /* - * An array expression. - */ - - exports.ArrayExpression = ArrayExpression = (function(_super) { - __extends(ArrayExpression, _super); - - + + /* - * @elements: [ Expression | null ] + * Any statement. */ - - function ArrayExpression(elements) { - this.elements = elements; - ArrayExpression.__super__.constructor.call(this); - } - - return ArrayExpression; - - })(Expression); - - JavaScriptVisitor.prototype.ArrayExpression = function(node) { - node = this.Expression(node); - node.elements = this.visit(node.elements); - return node; - }; - - - /* - * An object expression. A literal property in an object expression can have - * either a string or number as its value. Ordinary property initializers have a - * kind value "init"; getters and setters have the kind values "get" and "set", - * respectively. - */ - - exports.ObjectExpression = ObjectExpression = (function(_super) { - __extends(ObjectExpression, _super); - - + + exports.Statement = Statement = ((_super => { + __extends(Statement, _super); + + function Statement() { + Statement.__super__.constructor.call(this); + } + + return Statement; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.Statement = function(node) { + node = this.JavaScriptNode(node); + return node; + }; + + /* - * @properties: [ { key: Literal | Identifier, - * value: Expression, - * kind: "init" | "get" | "set" } ]; + * An empty statement, i.e., a solitary semicolon. */ - - function ObjectExpression(properties) { - this.properties = properties; - ObjectExpression.__super__.constructor.call(this); - } - - return ObjectExpression; - - })(Expression); - - JavaScriptVisitor.prototype.ObjectExpression = function(node) { - var setter, _i, _len, _ref1; - node = this.Expression(node); - _ref1 = node.properties; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - setter = _ref1[_i]; - setter.key = this.visit(setter.key); - setter.value = this.visit(setter.value); - } - return node; - }; - - - /* - * A function expression. - */ - - exports.FunctionExpression = FunctionExpression = (function(_super) { - __extends(FunctionExpression, _super); - - + + exports.EmptyStatement = EmptyStatement = ((_super => { + __extends(EmptyStatement, _super); + + function EmptyStatement() { + EmptyStatement.__super__.constructor.call(this); + } + + return EmptyStatement; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.EmptyStatement = function(node) { + node = this.JavaScriptNode(node); + return node; + }; + + /* - * @id: Identifier | null - * @params: [ Pattern ] - * @body: BlockStatement | Expression + * A block statement, i.e., a sequence of statements surrounded by braces. */ - - function FunctionExpression(id, params, body) { - this.id = id; - this.params = params; - this.body = body; - FunctionExpression.__super__.constructor.call(this); - } - - return FunctionExpression; - - })(Expression); - - JavaScriptVisitor.prototype.FunctionExpression = function(node) { - node = this.Expression(node); - node.id = this.visit(node.id); - node.params = this.visit(node.params); - node.body = this.visit(node.body); - return node; - }; - - - /* - * A sequence expression, i.e., a comma-separated sequence of expressions. - */ - - exports.SequenceExpression = SequenceExpression = (function(_super) { - __extends(SequenceExpression, _super); - - + + exports.BlockStatement = BlockStatement = ((_super => { + __extends(BlockStatement, _super); + + + /* + * @body: [Statement] + */ + + function BlockStatement(body) { + this.body = body; + BlockStatement.__super__.constructor.call(this); + } + + return BlockStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.BlockStatement = function(node) { + node = this.Statement(node); + node.body = this.visit(node.body); + return node; + }; + + /* - * @expressions: [ Expression ] + * An expression statement, i.e., a statement consisting of a single expression. */ - - function SequenceExpression(expressions) { - this.expressions = expressions; - SequenceExpression.__super__.constructor.call(this); - } - - return SequenceExpression; - - })(Expression); - - JavaScriptVisitor.prototype.SequenceExpression = function(node) { - node = this.Expression(node); - node.expressions = this.visit(node.expressions); - return node; - }; - - - /* - * A unary operator expression. - */ - - exports.UnaryExpression = UnaryExpression = (function(_super) { - __extends(UnaryExpression, _super); - - + + exports.ExpressionStatement = ExpressionStatement = ((_super => { + __extends(ExpressionStatement, _super); + + function ExpressionStatement() { + ExpressionStatement.__super__.constructor.call(this); + } + + return ExpressionStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.ExpressionStatement = function(node) { + node = this.Statement(node); + return node; + }; + + /* - * @operator: "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" - * @prefix: boolean - * @argument: Expression + * An if statement. */ - - function UnaryExpression(operator, prefix, argument) { - this.operator = operator; - this.prefix = prefix; - this.argument = argument; - UnaryExpression.__super__.constructor.call(this); - } - - return UnaryExpression; - - })(Expression); - - JavaScriptVisitor.prototype.UnaryExpression = function(node) { - node = this.Expression(node); - node.argument = this.visit(node.argument); - return node; - }; - - - /* - * A binary operator expression. - */ - - exports.BinaryExpression = BinaryExpression = (function(_super) { - __extends(BinaryExpression, _super); - - + + exports.IfStatement = IfStatement = ((_super => { + __extends(IfStatement, _super); + + + /* + * @test: Expression + * @consequent: Statement + * @alternate: Statement | null + */ + + function IfStatement(test, consequent, alternate) { + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + IfStatement.__super__.constructor.call(this); + } + + return IfStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.IfStatement = function(node) { + node = this.Statement(node); + node.test = this.visit(node.test); + node.consequent = this.visit(node.consequent); + node.alternate = this.visit(node.alternate); + return node; + }; + + /* - * @operator: "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" - * | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" - * | "|" | "&" | "^" | "in" | "instanceof" | ".." - * @left: Expression - * @right: Expression + * A labeled statement, i.e., a statement prefixed by a break/continue label. */ - - function BinaryExpression(operator, left, right) { - this.operator = operator; - this.left = left; - this.right = right; - BinaryExpression.__super__.constructor.call(this); - } - - return BinaryExpression; - - })(Expression); - - JavaScriptVisitor.prototype.BinaryExpression = function(node) { - node = this.Expression(node); - node.left = this.visit(node.left); - node.right = this.visit(node.right); - return node; - }; - - - /* - * An assignment operator expression. - */ - - exports.AssignmentExpression = AssignmentExpression = (function(_super) { - __extends(AssignmentExpression, _super); - - + + exports.LabeledStatement = LabeledStatement = ((_super => { + __extends(LabeledStatement, _super); + + + /* + * @label: Identifier + * @body: Statement + */ + + function LabeledStatement(label, body) { + this.label = label; + this.body = body; + LabeledStatement.__super__.constructor.call(this); + } + + return LabeledStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.LabeledStatement = function(node) { + node = this.Statement(node); + node.label = this.visit(node.label); + node.body = this.visit(node.body); + return node; + }; + + /* - * @operator: "=" | "+=" | "-=" | "*=" | "/=" | "%=" - * | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&="; - * @left: Expression - * @right: Expression + * A break statement. */ - - function AssignmentExpression(operator, left, right) { - this.operator = operator; - this.left = left; - this.right = right; - AssignmentExpression.__super__.constructor.call(this); - } - - return AssignmentExpression; - - })(Expression); - - JavaScriptVisitor.prototype.AssignmentExpression = function(node) { - node = this.Expression(node); - node.left = this.visit(node.left); - node.right = this.visit(node.right); - return node; - }; - - - /* - * An update (increment or decrement) operator expression. - */ - - exports.UpdateExpression = UpdateExpression = (function(_super) { - __extends(UpdateExpression, _super); - - + + exports.BreakStatement = BreakStatement = ((_super => { + __extends(BreakStatement, _super); + + + /* + * @label: Identifier | null + */ + + function BreakStatement(label) { + this.label = label; + BreakStatement.__super__.constructor.call(this); + } + + return BreakStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.BreakStatement = function(node) { + node = this.Statement(node); + node.label = this.visit(node.label); + return node; + }; + + /* - * @operator: "++" | "--" - * @argument: Expression - * @prefix: boolean + A continue statement. */ - - function UpdateExpression(operator, argument, prefix) { - this.operator = operator; - this.argument = argument; - this.prefix = prefix; - UpdateExpression.__super__.constructor.call(this); - } - - return UpdateExpression; - - })(Expression); - - JavaScriptVisitor.prototype.UpdateExpression = function(node) { - node = this.Expression(node); - node.argument = this.visit(node.argument); - return node; - }; - - - /* - * A logical operator expression. - */ - - exports.LogicalExpression = LogicalExpression = (function(_super) { - __extends(LogicalExpression, _super); - - + + exports.ContinueStatement = ContinueStatement = ((_super => { + __extends(ContinueStatement, _super); + + + /* + @label: Identifier | null + */ + + function ContinueStatement(label) { + this.label = label; + ContinueStatement.__super__.constructor.call(this); + } + + return ContinueStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.ContinueStatement = function(node) { + node = this.Statement(node); + node.label = this.visit(node.label); + return node; + }; + + /* - * @operator: "||" | "&&" - * @left: Expression - * @right: Expression + * A with statement. */ - - function LogicalExpression(operator, left, right) { - this.operator = operator; - this.left = left; - this.right = right; - LogicalExpression.__super__.constructor.call(this); - } - - return LogicalExpression; - - })(Expression); - - JavaScriptVisitor.prototype.LogicalExpression = function(node) { - node = this.Expression(node); - node.left = this.visit(node.left); - node.right = this.visit(node.right); - return node; - }; - - - /* - * A conditional expression, i.e., a ternary ?/: expression. - */ - - exports.ConditionalExpression = ConditionalExpression = (function(_super) { - __extends(ConditionalExpression, _super); - - + + exports.WithStatement = WithStatement = ((_super => { + __extends(WithStatement, _super); + + + /* + * @object: Expression + * @body: Statement + */ + + function WithStatement(object, body) { + this.object = object; + this.body = body; + WithStatement.__super__.constructor.call(this); + } + + return WithStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.WithStatement = function(node) { + node = this.Statement(node); + node.object = this.visit(node.object); + node.body = this.visit(node.body); + return node; + }; + + /* - * @test: Expression - * @alternate: Expression - * @consequent: Expression + * A switch statement. */ - - function ConditionalExpression(test, alternate, consequent) { - this.test = test; - this.alternate = alternate; - this.consequent = consequent; - ConditionalExpression.__super__.constructor.call(this); - } - - return ConditionalExpression; - - })(Expression); - - JavaScriptVisitor.prototype.ConditionalExpression = function(node) { - node = this.Expression(node); - node.test = this.visit(node.test); - node.alternate = this.visit(node.alternate); - node.consequent = this.visit(node.consequent); - return node; - }; - - - /* - * A new expression. - */ - - exports.NewExpression = NewExpression = (function(_super) { - __extends(NewExpression, _super); - - + + exports.SwitchStatement = SwitchStatement = ((_super => { + __extends(SwitchStatement, _super); + + + /* + * @discriminant: Expression + * @cases: [SwitchCase] + */ + + function SwitchStatement(discriminant, cases) { + this.discriminant = discriminant; + this.cases = cases; + SwitchStatement.__super__.constructor.call(this); + } + + return SwitchStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.SwitchStatement = function(node) { + node = this.Statement(node); + node.discriminant = this.visit(node.discriminant); + node.cases = this.visit(node.cases); + return node; + }; + + /* - * @callee: Expression - * @arguments: [ Expression ] | null + * A return statement. */ - - function NewExpression(callee, _arguments) { - this.callee = callee; - this["arguments"] = _arguments; - NewExpression.__super__.constructor.call(this); - } - - return NewExpression; - - })(Expression); - - JavaScriptVisitor.prototype.NewExpression = function(node) { - node = this.Expression(node); - node.callee = this.visit(node.callee); - node["arguments"] = this.visit(node["arguments"]); - return node; - }; - - - /* - * A function or method call expression. - */ - - exports.CallExpression = CallExpression = (function(_super) { - __extends(CallExpression, _super); - - + + exports.ReturnStatement = ReturnStatement = ((_super => { + __extends(ReturnStatement, _super); + + + /* + * @argument: Expression | null + */ + + function ReturnStatement(argument) { + this.argument = argument; + ReturnStatement.__super__.constructor.call(this); + } + + return ReturnStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.ReturnStatement = function(node) { + node = this.Statement(node); + node.argument = this.visit(node.argument); + return node; + }; + + /* - * @callee: Expression - * @arguments: [ Expression ] + * A throw statement. */ - - function CallExpression(callee, _arguments) { - this.callee = callee; - this["arguments"] = _arguments; - CallExpression.__super__.constructor.call(this); - } - - return CallExpression; - - })(Expression); - - JavaScriptVisitor.prototype.CallExpression = function(node) { - node = this.Expression(node); - node.callee = this.visit(node.callee); - node["arguments"] = this.visit(node["arguments"]); - return node; - }; - - - /* - * A member expression. If computed === true, the node corresponds to a computed - * e1[e2] expression and property is an Expression. If computed === false, the - * node corresponds to a static e1.x expression and property is an Identifier. - */ - - exports.MemberExpression = MemberExpression = (function(_super) { - __extends(MemberExpression, _super); - - + + exports.ThrowStatement = ThrowStatement = ((_super => { + __extends(ThrowStatement, _super); + + + /* + * @argument: Expression + */ + + function ThrowStatement(argument) { + this.argument = argument; + ThrowStatement.__super__.constructor.call(this); + } + + return ThrowStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.ThrowStatement = function(node) { + node = this.Statement(node); + node.argument = this.visit(node.argument); + return node; + }; + + /* - * @object: Expression - * @property: Identifier | Expression - * @computed : boolean + * A try statement. */ - - function MemberExpression(object, property, computed) { - this.object = object; - this.property = property; - this.computed = computed; - MemberExpression.__super__.constructor.call(this); - } - - return MemberExpression; - - })(Expression); - - JavaScriptVisitor.prototype.MemberExpression = function(node) { - node = this.Expression(node); - node.object = this.visit(node.object); - node.property = this.visit(node.property); - return node; - }; - - - /* - * JavaScript 1.7 introduced destructuring assignment and binding forms. All - * binding forms (such as function parameters, variable declarations, and catch - * block headers), accept array and object destructuring patterns in addition to - * plain identifiers. The left-hand sides of assignment expressions can be - * arbitrary expressions, but in the case where the expression is an object or - * array literal, it is interpreted by SpiderMonkey as a destructuring pattern. - * - * Since the left-hand side of an assignment can in general be any expression, in - * an assignment context, a pattern can be any expression. In binding positions - * (such as function parameters, variable declarations, and catch headers), - * patterns can only be identifiers in the base case, not arbitrary expressions. - */ - - exports.Pattern = Pattern = (function(_super) { - __extends(Pattern, _super); - - function Pattern() { - Pattern.__super__.constructor.call(this); - } - - return Pattern; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.Pattern = function(node) { - node = this.JavaScriptNode(node); - return node; - }; - - - /* - * An object-destructuring pattern. A literal property in an object pattern can - * have either a string or number as its value. - */ - - exports.ObjectPattern = ObjectPattern = (function(_super) { - __extends(ObjectPattern, _super); - - + + exports.TryStatement = TryStatement = ((_super => { + __extends(TryStatement, _super); + + + /* + * @block: BlockStatement + * @handlers: [CatchClause] + * @finalizer: BlockStatement | null + */ + + function TryStatement(block, handlers, finalizer) { + this.block = block; + this.handlers = handlers; + this.finalizer = finalizer; + TryStatement.__super__.constructor.call(this); + } + + return TryStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.TryStatement = function(node) { + node = this.Statement(node); + node.block = this.visit(node.block); + node.handlers = this.visit(node.handlers); + node.finalizer = this.visit(node.finalizer); + return node; + }; + + /* - * @properties: [ { key: Literal | Identifier, value: Pattern } ] + * A while statement. */ - - function ObjectPattern(properties) { - this.properties = properties; - ObjectPattern.__super__.constructor.call(this); - } - - return ObjectPattern; - - })(Pattern); - - JavaScriptVisitor.prototype.ObjectPattern = function(node) { - var setter, _i, _len, _ref1; - node = this.Pattern(node); - _ref1 = node.properties; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - setter = _ref1[_i]; - setter.key = this.visit(setter.key); - setter.value = this.visit(setter.value); - } - return node; - }; - - - /* - * An array-destructuring pattern. - */ - - exports.ArrayPattern = ArrayPattern = (function(_super) { - __extends(ArrayPattern, _super); - - + + exports.WhileStatement = WhileStatement = ((_super => { + __extends(WhileStatement, _super); + + + /* + * @test: Expression + * @body: Statement + */ + + function WhileStatement(test, body) { + this.test = test; + this.body = body; + WhileStatement.__super__.constructor.call(this); + } + + return WhileStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.WhileStatement = function(node) { + node = this.Statement(node); + node.test = this.visit(node.test); + node.body = this.visit(node.body); + return node; + }; + + /* - * @elements: [ Pattern | null ] + * A do/while statement. */ - - function ArrayPattern(elements) { - this.elements = elements; - ArrayPattern.__super__.constructor.call(this); - } - - return ArrayPattern; - - })(Pattern); - - JavaScriptVisitor.prototype.ArrayPattern = function(node) { - node = this.Pattern(node); - node.elements = this.visit(node.elements); - return node; - }; - - - /* - * A case (if test is an Expression) or default (if test === null) clause in the - * body of a switch statement. - */ - - exports.SwitchCase = SwitchCase = (function(_super) { - __extends(SwitchCase, _super); - - + + exports.DoWhileStatement = DoWhileStatement = ((_super => { + __extends(DoWhileStatement, _super); + + + /* + * @body: Statement + * @test: Expression + */ + + function DoWhileStatement(body, test) { + this.body = body; + this.test = test; + DoWhileStatement.__super__.constructor.call(this); + } + + return DoWhileStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.DoWhileStatement = function(node) { + node = this.Statement(node); + node.body = this.visit(node.body); + node.test = this.visit(node.test); + return node; + }; + + /* - * @test: Expression | null - * @consequent: [ Statement ] + * A for statement. */ - - function SwitchCase(test, consequent) { - this.test = test; - this.consequent = consequent; - SwitchCase.__super__.constructor.call(this); - } - - return SwitchCase; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.SwitchCase = function(node) { - node = this.JavaScriptNode(node); - node.test = this.visit(node.test); - node.consequent = this.visit(node.consequent); - return node; - }; - - - /* - * A catch clause following a try block. The optional guard property corresponds - * to the optional expression guard on the bound variable. - */ - - exports.CatchClause = CatchClause = (function(_super) { - __extends(CatchClause, _super); - - + + exports.ForStatement = ForStatement = ((_super => { + __extends(ForStatement, _super); + + + /* + * @init: VariableDeclaration | Expression | null + * @test: Expression | null + * @update: Expression | null + * @body: Statement + */ + + function ForStatement(init, test, update, body) { + this.init = init; + this.test = test; + this.update = update; + this.body = body; + ForStatement.__super__.constructor.call(this); + } + + return ForStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.ForStatement = function(node) { + node = this.Statement(node); + node.init = this.visit(node.init); + node.test = this.visit(node.test); + node.update = this.visit(node.update); + node.body = this.visit(node.body); + return node; + }; + + /* - * @param: Pattern - * @body: BlockStatement + * A for/in statement, or, if each is true, a for each/in statement. */ - - function CatchClause(param, body) { - this.param = param; - this.body = body; - CatchClause.__super__.constructor.call(this); - } - - return CatchClause; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.CatchClause = function(node) { - node = this.JavaScriptNode(node); - node.param = this.visit(node.param); - node.body = this.visit(node.body); - return node; - }; - - - /* - * An identifier. Note that an identifier may be an expression or a destructuring - * pattern. - */ - - exports.Identifier = Identifier = (function(_super) { - __extends(Identifier, _super); - - + + exports.ForInStatement = ForInStatement = ((_super => { + __extends(ForInStatement, _super); + + + /* + * @left: VariableDeclaration | Expression + * @right: Expression + * @body: Statement + */ + + function ForInStatement(left, right, body) { + this.left = left; + this.right = right; + this.body = body; + ForInStatement.__super__.constructor.call(this); + } + + return ForInStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.ForInStatement = function(node) { + node = this.Statement(node); + node.left = this.visit(node.left); + node.right = this.visit(node.right); + node.body = this.visit(node.body); + return node; + }; + + /* - * @name: string + * A debugger statement. */ - - function Identifier(name) { - this.name = name; - Identifier.__super__.constructor.call(this); - } - - return Identifier; - - })(JavaScriptNode); - - JavaScriptVisitor.prototype.Identifier = function(node) { - node = this.JavaScriptNode(node); - return node; - }; - - - /* - * A literal token. Note that a literal can be an expression. - */ - - exports.Literal = Literal = (function(_super) { - __extends(Literal, _super); - - + + exports.DebuggerStatement = DebuggerStatement = ((_super => { + __extends(DebuggerStatement, _super); + + function DebuggerStatement() { + DebuggerStatement.__super__.constructor.call(this); + } + + return DebuggerStatement; + + }))(Statement); + + JavaScriptVisitor.prototype.DebuggerStatement = function(node) { + node = this.Statement(node); + return node; + }; + + /* - * @value: string | boolean | null | number | RegExp + * Any declaration node. Note that declarations are considered statements; this + * is because declarations can appear in any statement context in the language. */ - - function Literal(value) { - this.value = value; - Literal.__super__.constructor.call(this); - } - - return Literal; - - })(Expression); - - JavaScriptVisitor.prototype.Literal = function(node) { - node = this.Expression(node); - return node; - }; - - }).call(this); + + exports.Declaration = Declaration = ((_super => { + __extends(Declaration, _super); + + function Declaration() { + Declaration.__super__.constructor.call(this); + } + + return Declaration; + + }))(Statement); + + JavaScriptVisitor.prototype.Declaration = function(node) { + node = this.Statement(node); + return node; + }; + + + /* + * A function declaration. Note: The id field cannot be null. + */ + + exports.FunctionDeclaration = FunctionDeclaration = ((_super => { + __extends(FunctionDeclaration, _super); + + + /* + * @id: Identifier + * @params: [ Pattern ] + * @body: BlockStatement | Expression + */ + + function FunctionDeclaration(id, params, body) { + this.id = id; + this.params = params; + this.body = body; + FunctionDeclaration.__super__.constructor.call(this); + } + + return FunctionDeclaration; + + }))(Declaration); + + JavaScriptVisitor.prototype.FunctionDeclaration = function(node) { + node = this.Declaration(node); + node.id = this.visit(node.id); + node.params = this.visit(node.params); + node.body = this.visit(node.body); + return node; + }; + + + /* + * A variable declaration, via one of var, let, or const. + */ + + exports.VariableDeclaration = VariableDeclaration = ((_super => { + __extends(VariableDeclaration, _super); + + + /* + * @declarations: [ VariableDeclarator ] + * @kind: "var" + */ + + function VariableDeclaration(declarations, kind) { + this.declarations = declarations; + this.kind = kind; + VariableDeclaration.__super__.constructor.call(this); + } + + return VariableDeclaration; + + }))(Declaration); + + JavaScriptVisitor.prototype.VariableDeclaration = function(node) { + node = this.Declaration(node); + node.declarations = this.visit(node.declarations); + return node; + }; + + + /* + * A variable declarator. Note: The id field cannot be null. + */ + + exports.VariableDeclarator = VariableDeclarator = ((_super => { + __extends(VariableDeclarator, _super); + + + /* + * @id: Pattern + * @init: Expression | null + */ + + function VariableDeclarator(id, init) { + this.id = id; + this.init = init; + VariableDeclarator.__super__.constructor.call(this); + } + + return VariableDeclarator; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.VariableDeclarator = function(node) { + node = this.JavaScriptNode(node); + node.id = this.visit(node.id); + node.init = this.visit(node.init); + return node; + }; + + + /* + * Any expression node. Since the left-hand side of an assignment may be any + * expression in general, an expression can also be a pattern. + */ + + exports.Expression = Expression = ((_super => { + __extends(Expression, _super); + + function Expression(...args) { + return Expression.__super__.constructor.apply(this, args); + } + + Expression.prototype.constuctor = function() { + return Expression.__super__.constuctor.call(this); + }; + + return Expression; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.Expression = function(node) { + node = this.JavaScriptNode(node); + return node; + }; + + + /* + * A this expression. + */ + + exports.ThisExpression = ThisExpression = ((_super => { + __extends(ThisExpression, _super); + + function ThisExpression() { + ThisExpression.__super__.constructor.call(this); + } + + return ThisExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.ThisExpression = function(node) { + node = this.Expression(node); + return node; + }; + + + /* + * An array expression. + */ + + exports.ArrayExpression = ArrayExpression = ((_super => { + __extends(ArrayExpression, _super); + + + /* + * @elements: [ Expression | null ] + */ + + function ArrayExpression(elements) { + this.elements = elements; + ArrayExpression.__super__.constructor.call(this); + } + + return ArrayExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.ArrayExpression = function(node) { + node = this.Expression(node); + node.elements = this.visit(node.elements); + return node; + }; + + + /* + * An object expression. A literal property in an object expression can have + * either a string or number as its value. Ordinary property initializers have a + * kind value "init"; getters and setters have the kind values "get" and "set", + * respectively. + */ + + exports.ObjectExpression = ObjectExpression = ((_super => { + __extends(ObjectExpression, _super); + + + /* + * @properties: [ { key: Literal | Identifier, + * value: Expression, + * kind: "init" | "get" | "set" } ]; + */ + + function ObjectExpression(properties) { + this.properties = properties; + ObjectExpression.__super__.constructor.call(this); + } + + return ObjectExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.ObjectExpression = function(node) { + var setter; + var _i; + var _len; + var _ref1; + node = this.Expression(node); + _ref1 = node.properties; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + setter = _ref1[_i]; + setter.key = this.visit(setter.key); + setter.value = this.visit(setter.value); + } + return node; + }; + + + /* + * A function expression. + */ + + exports.FunctionExpression = FunctionExpression = ((_super => { + __extends(FunctionExpression, _super); + + + /* + * @id: Identifier | null + * @params: [ Pattern ] + * @body: BlockStatement | Expression + */ + + function FunctionExpression(id, params, body) { + this.id = id; + this.params = params; + this.body = body; + FunctionExpression.__super__.constructor.call(this); + } + + return FunctionExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.FunctionExpression = function(node) { + node = this.Expression(node); + node.id = this.visit(node.id); + node.params = this.visit(node.params); + node.body = this.visit(node.body); + return node; + }; + + + /* + * A sequence expression, i.e., a comma-separated sequence of expressions. + */ + + exports.SequenceExpression = SequenceExpression = ((_super => { + __extends(SequenceExpression, _super); + + + /* + * @expressions: [ Expression ] + */ + + function SequenceExpression(expressions) { + this.expressions = expressions; + SequenceExpression.__super__.constructor.call(this); + } + + return SequenceExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.SequenceExpression = function(node) { + node = this.Expression(node); + node.expressions = this.visit(node.expressions); + return node; + }; + + + /* + * A unary operator expression. + */ + + exports.UnaryExpression = UnaryExpression = ((_super => { + __extends(UnaryExpression, _super); + + + /* + * @operator: "-" | "+" | "!" | "~" | "typeof" | "void" | "delete" + * @prefix: boolean + * @argument: Expression + */ + + function UnaryExpression(operator, prefix, argument) { + this.operator = operator; + this.prefix = prefix; + this.argument = argument; + UnaryExpression.__super__.constructor.call(this); + } + + return UnaryExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.UnaryExpression = function(node) { + node = this.Expression(node); + node.argument = this.visit(node.argument); + return node; + }; + + + /* + * A binary operator expression. + */ + + exports.BinaryExpression = BinaryExpression = ((_super => { + __extends(BinaryExpression, _super); + + + /* + * @operator: "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" + * | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" + * | "|" | "&" | "^" | "in" | "instanceof" | ".." + * @left: Expression + * @right: Expression + */ + + function BinaryExpression(operator, left, right) { + this.operator = operator; + this.left = left; + this.right = right; + BinaryExpression.__super__.constructor.call(this); + } + + return BinaryExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.BinaryExpression = function(node) { + node = this.Expression(node); + node.left = this.visit(node.left); + node.right = this.visit(node.right); + return node; + }; + + + /* + * An assignment operator expression. + */ + + exports.AssignmentExpression = AssignmentExpression = ((_super => { + __extends(AssignmentExpression, _super); + + + /* + * @operator: "=" | "+=" | "-=" | "*=" | "/=" | "%=" + * | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&="; + * @left: Expression + * @right: Expression + */ + + function AssignmentExpression(operator, left, right) { + this.operator = operator; + this.left = left; + this.right = right; + AssignmentExpression.__super__.constructor.call(this); + } + + return AssignmentExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.AssignmentExpression = function(node) { + node = this.Expression(node); + node.left = this.visit(node.left); + node.right = this.visit(node.right); + return node; + }; + + + /* + * An update (increment or decrement) operator expression. + */ + + exports.UpdateExpression = UpdateExpression = ((_super => { + __extends(UpdateExpression, _super); + + + /* + * @operator: "++" | "--" + * @argument: Expression + * @prefix: boolean + */ + + function UpdateExpression(operator, argument, prefix) { + this.operator = operator; + this.argument = argument; + this.prefix = prefix; + UpdateExpression.__super__.constructor.call(this); + } + + return UpdateExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.UpdateExpression = function(node) { + node = this.Expression(node); + node.argument = this.visit(node.argument); + return node; + }; + + + /* + * A logical operator expression. + */ + + exports.LogicalExpression = LogicalExpression = ((_super => { + __extends(LogicalExpression, _super); + + + /* + * @operator: "||" | "&&" + * @left: Expression + * @right: Expression + */ + + function LogicalExpression(operator, left, right) { + this.operator = operator; + this.left = left; + this.right = right; + LogicalExpression.__super__.constructor.call(this); + } + + return LogicalExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.LogicalExpression = function(node) { + node = this.Expression(node); + node.left = this.visit(node.left); + node.right = this.visit(node.right); + return node; + }; + + + /* + * A conditional expression, i.e., a ternary ?/: expression. + */ + + exports.ConditionalExpression = ConditionalExpression = ((_super => { + __extends(ConditionalExpression, _super); + + + /* + * @test: Expression + * @alternate: Expression + * @consequent: Expression + */ + + function ConditionalExpression(test, alternate, consequent) { + this.test = test; + this.alternate = alternate; + this.consequent = consequent; + ConditionalExpression.__super__.constructor.call(this); + } + + return ConditionalExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.ConditionalExpression = function(node) { + node = this.Expression(node); + node.test = this.visit(node.test); + node.alternate = this.visit(node.alternate); + node.consequent = this.visit(node.consequent); + return node; + }; + + + /* + * A new expression. + */ + + exports.NewExpression = NewExpression = ((_super => { + __extends(NewExpression, _super); + + + /* + * @callee: Expression + * @arguments: [ Expression ] | null + */ + + function NewExpression(callee, _arguments) { + this.callee = callee; + this["arguments"] = _arguments; + NewExpression.__super__.constructor.call(this); + } + + return NewExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.NewExpression = function(node) { + node = this.Expression(node); + node.callee = this.visit(node.callee); + node["arguments"] = this.visit(node["arguments"]); + return node; + }; + + + /* + * A function or method call expression. + */ + + exports.CallExpression = CallExpression = ((_super => { + __extends(CallExpression, _super); + + + /* + * @callee: Expression + * @arguments: [ Expression ] + */ + + function CallExpression(callee, _arguments) { + this.callee = callee; + this["arguments"] = _arguments; + CallExpression.__super__.constructor.call(this); + } + + return CallExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.CallExpression = function(node) { + node = this.Expression(node); + node.callee = this.visit(node.callee); + node["arguments"] = this.visit(node["arguments"]); + return node; + }; + + + /* + * A member expression. If computed === true, the node corresponds to a computed + * e1[e2] expression and property is an Expression. If computed === false, the + * node corresponds to a static e1.x expression and property is an Identifier. + */ + + exports.MemberExpression = MemberExpression = ((_super => { + __extends(MemberExpression, _super); + + + /* + * @object: Expression + * @property: Identifier | Expression + * @computed : boolean + */ + + function MemberExpression(object, property, computed) { + this.object = object; + this.property = property; + this.computed = computed; + MemberExpression.__super__.constructor.call(this); + } + + return MemberExpression; + + }))(Expression); + + JavaScriptVisitor.prototype.MemberExpression = function(node) { + node = this.Expression(node); + node.object = this.visit(node.object); + node.property = this.visit(node.property); + return node; + }; + + + /* + * JavaScript 1.7 introduced destructuring assignment and binding forms. All + * binding forms (such as function parameters, variable declarations, and catch + * block headers), accept array and object destructuring patterns in addition to + * plain identifiers. The left-hand sides of assignment expressions can be + * arbitrary expressions, but in the case where the expression is an object or + * array literal, it is interpreted by SpiderMonkey as a destructuring pattern. + * + * Since the left-hand side of an assignment can in general be any expression, in + * an assignment context, a pattern can be any expression. In binding positions + * (such as function parameters, variable declarations, and catch headers), + * patterns can only be identifiers in the base case, not arbitrary expressions. + */ + + exports.Pattern = Pattern = ((_super => { + __extends(Pattern, _super); + + function Pattern() { + Pattern.__super__.constructor.call(this); + } + + return Pattern; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.Pattern = function(node) { + node = this.JavaScriptNode(node); + return node; + }; + + + /* + * An object-destructuring pattern. A literal property in an object pattern can + * have either a string or number as its value. + */ + + exports.ObjectPattern = ObjectPattern = ((_super => { + __extends(ObjectPattern, _super); + + + /* + * @properties: [ { key: Literal | Identifier, value: Pattern } ] + */ + + function ObjectPattern(properties) { + this.properties = properties; + ObjectPattern.__super__.constructor.call(this); + } + + return ObjectPattern; + + }))(Pattern); + + JavaScriptVisitor.prototype.ObjectPattern = function(node) { + var setter; + var _i; + var _len; + var _ref1; + node = this.Pattern(node); + _ref1 = node.properties; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + setter = _ref1[_i]; + setter.key = this.visit(setter.key); + setter.value = this.visit(setter.value); + } + return node; + }; + + + /* + * An array-destructuring pattern. + */ + + exports.ArrayPattern = ArrayPattern = ((_super => { + __extends(ArrayPattern, _super); + + + /* + * @elements: [ Pattern | null ] + */ + + function ArrayPattern(elements) { + this.elements = elements; + ArrayPattern.__super__.constructor.call(this); + } + + return ArrayPattern; + + }))(Pattern); + + JavaScriptVisitor.prototype.ArrayPattern = function(node) { + node = this.Pattern(node); + node.elements = this.visit(node.elements); + return node; + }; + + + /* + * A case (if test is an Expression) or default (if test === null) clause in the + * body of a switch statement. + */ + + exports.SwitchCase = SwitchCase = ((_super => { + __extends(SwitchCase, _super); + + + /* + * @test: Expression | null + * @consequent: [ Statement ] + */ + + function SwitchCase(test, consequent) { + this.test = test; + this.consequent = consequent; + SwitchCase.__super__.constructor.call(this); + } + + return SwitchCase; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.SwitchCase = function(node) { + node = this.JavaScriptNode(node); + node.test = this.visit(node.test); + node.consequent = this.visit(node.consequent); + return node; + }; + + + /* + * A catch clause following a try block. The optional guard property corresponds + * to the optional expression guard on the bound variable. + */ + + exports.CatchClause = CatchClause = ((_super => { + __extends(CatchClause, _super); + + + /* + * @param: Pattern + * @body: BlockStatement + */ + + function CatchClause(param, body) { + this.param = param; + this.body = body; + CatchClause.__super__.constructor.call(this); + } + + return CatchClause; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.CatchClause = function(node) { + node = this.JavaScriptNode(node); + node.param = this.visit(node.param); + node.body = this.visit(node.body); + return node; + }; + + + /* + * An identifier. Note that an identifier may be an expression or a destructuring + * pattern. + */ + + exports.Identifier = Identifier = ((_super => { + __extends(Identifier, _super); + + + /* + * @name: string + */ + + function Identifier(name) { + this.name = name; + Identifier.__super__.constructor.call(this); + } + + return Identifier; + + }))(JavaScriptNode); + + JavaScriptVisitor.prototype.Identifier = function(node) { + node = this.JavaScriptNode(node); + return node; + }; + + + /* + * A literal token. Note that a literal can be an expression. + */ + + exports.Literal = Literal = ((_super => { + __extends(Literal, _super); + + + /* + * @value: string | boolean | null | number | RegExp + */ + + function Literal(value) { + this.value = value; + Literal.__super__.constructor.call(this); + } + + return Literal; + + }))(Expression); + + JavaScriptVisitor.prototype.Literal = function(node) { + node = this.Expression(node); + return node; + }; + })).call(this); }; $__modules__.JavaScriptToQueryVisitor = function (exports) { @@ -1667,303 +1741,331 @@ * ---------------------------------------------------------------------------- */ - (function() { - var JS, JavaScriptToQueryVisitor, Q, _, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - _ = require('./Utilities'); - - JS = require('./JavaScriptNodes'); - - Q = require('./QueryNodes'); - - - /* - * Walk the JavaScriptExpression tree and convert its nodes into QueryExpression - * trees - */ - - exports.JavaScriptToQueryVisitor = JavaScriptToQueryVisitor = (function(_super) { - __extends(JavaScriptToQueryVisitor, _super); - - function JavaScriptToQueryVisitor(context) { - this.context = context; - } - - - /* Get the source code for a given node */ - - JavaScriptToQueryVisitor.prototype.getSource = function(node) { - var _ref, _ref1; - return this.context.source.slice(node != null ? (_ref = node.range) != null ? _ref[0] : void 0 : void 0, +((node != null ? (_ref1 = node.range) != null ? _ref1[1] : void 0 : void 0) - 1) + 1 || 9e9); - }; - - - /* Throw an exception for an invalid node. */ - - JavaScriptToQueryVisitor.prototype.invalid = function(node) { - throw "The expression '" + (this.getSource(node)) + "'' is not supported."; - }; - - - /* Unary expressions just map operators */ - - JavaScriptToQueryVisitor.prototype.translateUnary = function(node, mapping) { - var op, value; - op = mapping[node.operator]; - if (op) { - value = this.visit(node.argument); - return new Q.UnaryExpression(op, value); - } else { - return null; - } - }; - - - /* Binary expressions just map operators */ - - JavaScriptToQueryVisitor.prototype.translateBinary = function(node, mapping) { - var left, op, right; - op = mapping[node.operator]; - if (op) { - left = this.visit(node.left); - right = this.visit(node.right); - return new Q.BinaryExpression(op, left, right); - } else { - return null; - } - }; - - + ((() => { + var JS; + var JavaScriptToQueryVisitor; + var Q; + var _; + var __hasProp = {}.hasOwnProperty; + var __extends = (child, parent) => { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + _ = require('./Utilities'); + + JS = require('./JavaScriptNodes'); + + Q = require('./QueryNodes'); + + /* - * The base visit method will throw exceptions for any nodes that remain - * untransformed (which allows us to only bother defining meaningful - * translations) + * Walk the JavaScriptExpression tree and convert its nodes into QueryExpression + * trees */ - - JavaScriptToQueryVisitor.prototype.visit = function(node) { - var visited; - visited = JavaScriptToQueryVisitor.__super__.visit.call(this, node); - if (node === visited) { - this.invalid(node); + + exports.JavaScriptToQueryVisitor = JavaScriptToQueryVisitor = ((_super => { + __extends(JavaScriptToQueryVisitor, _super); + + function JavaScriptToQueryVisitor(context) { + this.context = context; } - return visited; - }; - - JavaScriptToQueryVisitor.prototype.MemberExpression = function(node) { - var expr; - expr = (function() { - var _ref, _ref1, _ref2, _ref3; - if ((node != null ? (_ref = node.object) != null ? _ref.type : void 0 : void 0) === 'ThisExpression' && (node != null ? (_ref1 = node.property) != null ? _ref1.type : void 0 : void 0) === 'Identifier') { - - /* Simple member access */ - return new Q.MemberExpression(node.property.name); - } else if ((node != null ? (_ref2 = node.object) != null ? _ref2.type : void 0 : void 0) === 'MemberExpression' && ((_ref3 = node.object.object) != null ? _ref3.type : void 0) === 'ThisExpression' && node.property.type === 'Identifier') { - - /* Methods that look like properties */ - if (node.property.name === 'length') { - return new Q.InvocationExpression(Q.Methods.Length, new Q.MemberExpression(node.object.property.name)); - } - } - })(); - return expr != null ? expr : JavaScriptToQueryVisitor.__super__.MemberExpression.call(this, node); - }; - - JavaScriptToQueryVisitor.prototype.Literal = function(node) { - return new Q.ConstantExpression(node.value); - }; - - JavaScriptToQueryVisitor.prototype.UnaryExpression = function(node) { - var mapping, _ref; - if (node.operator === '+') { - - /* Ignore the + in '+52' */ - return this.visit(node.argument); - } else { - mapping = { - '!': Q.UnaryOperators.Not, - '-': Q.UnaryOperators.Negate - }; - return (_ref = this.translateUnary(node, mapping)) != null ? _ref : JavaScriptToQueryVisitor.__super__.UnaryExpression.call(this, node); - } - }; - - JavaScriptToQueryVisitor.prototype.UpdateExpression = function(node) { - var mapping, _ref; - mapping = { - '++': Q.UnaryOperators.Increment, - '--': Q.UnaryOperators.Decrement + + + /* Get the source code for a given node */ + + JavaScriptToQueryVisitor.prototype.getSource = function(node) { + var _ref; + var _ref1; + return this.context.source.slice(node != null ? (_ref = node.range) != null ? _ref[0] : void 0 : void 0, +((node != null ? (_ref1 = node.range) != null ? _ref1[1] : void 0 : void 0) - 1) + 1 || 9e9); }; - return (_ref = this.translateUnary(node, mapping)) != null ? _ref : JavaScriptToQueryVisitor.__super__.UpdateExpression.call(this, node); - }; - - JavaScriptToQueryVisitor.prototype.LogicalExpression = function(node) { - var mapping, _ref; - mapping = { - '&&': Q.BinaryOperators.And, - '||': Q.BinaryOperators.Or + + + /* Throw an exception for an invalid node. */ + + JavaScriptToQueryVisitor.prototype.invalid = function(node) { + throw "The expression '" + (this.getSource(node)) + "'' is not supported."; }; - return (_ref = this.translateBinary(node, mapping)) != null ? _ref : JavaScriptToQueryVisitor.__super__.LogicalExpression.call(this, node); - }; - - JavaScriptToQueryVisitor.prototype.BinaryExpression = function(node) { - var k, left, mapping, properties, v, value, _ref; - mapping = { - '+': Q.BinaryOperators.Add, - '-': Q.BinaryOperators.Subtract, - '*': Q.BinaryOperators.Multiply, - '/': Q.BinaryOperators.Divide, - '%': Q.BinaryOperators.Modulo, - '>': Q.BinaryOperators.GreaterThan, - '>=': Q.BinaryOperators.GreaterThanOrEqual, - '<': Q.BinaryOperators.LessThan, - '<=': Q.BinaryOperators.LessThanOrEqual, - '!=': Q.BinaryOperators.NotEqual, - '!==': Q.BinaryOperators.NotEqual, - '==': Q.BinaryOperators.Equal, - '===': Q.BinaryOperators.Equal - }; - return (function() { - var _ref1, _ref2; - if ((_ref = this.translateBinary(node, mapping)) != null) { - return _ref; - } else if (node.operator === 'in' && ((_ref1 = node.right) != null ? _ref1.type : void 0) === 'Literal' && _.isArray((_ref2 = node.right) != null ? _ref2.value : void 0)) { - - /* - * Transform the 'varName in [x, y, z]' operator into a series of - * comparisons like varName == x || varName == y || varName == z. - */ - if (node.right.value.length > 0) { - left = this.visit(node.left); - return Q.QueryExpression.groupClauses(Q.BinaryOperators.Or, (function() { - var _i, _len, _ref3, _results; - _ref3 = node.right.value; - _results = []; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - value = _ref3[_i]; - - /* - * If we've got an array of objects who each have - * a single property, we'll use the value of that - * property. Otherwise we'll throw an exception. - */ - if (_.isObject(value)) { - properties = (function() { - var _results1; - _results1 = []; - for (k in value) { - v = value[k]; - _results1.push(v); - } - return _results1; - })(); - if ((properties != null ? properties.length : void 0) !== 1) { - throw "in operator requires comparison objects with a single field, not " + value + " (" + (JSON.stringify(value)) + "), for expression '" + (this.getSource(node)) + "'"; - } - value = properties[0]; - } - _results.push(new Q.BinaryExpression(Q.BinaryOperators.Equal, left, new Q.ConstantExpression(value))); - } - return _results; - }).call(this)); + + + /* Unary expressions just map operators */ + + JavaScriptToQueryVisitor.prototype.translateUnary = function(node, mapping) { + var op; + var value; + op = mapping[node.operator]; + if (op) { + value = this.visit(node.argument); + return new Q.UnaryExpression(op, value); } else { - - /* - * If the array of values is empty, change the query to - * true == false since it can't be satisfied. - */ - return new Q.BinaryExpression(Q.BinaryOperators.Equal, new Q.ConstantExpression(true), new Q.ConstantExpression(false)); + return null; } - } else { - return JavaScriptToQueryVisitor.__super__.BinaryExpression.call(this, node); - } - }).call(this); - }; - - JavaScriptToQueryVisitor.prototype.CallExpression = function(node) { - var expr, func, getSingleArg, getTwoArgs, member, method, _ref; - getSingleArg = (function(_this) { - return function(name) { - var _ref; - if (((_ref = node["arguments"]) != null ? _ref.length : void 0) !== 1) { - throw "Function " + name + " expects one argument in expression '" + (_this.getSource(node)) + "'"; + }; + + + /* Binary expressions just map operators */ + + JavaScriptToQueryVisitor.prototype.translateBinary = function(node, mapping) { + var left; + var op; + var right; + op = mapping[node.operator]; + if (op) { + left = this.visit(node.left); + right = this.visit(node.right); + return new Q.BinaryExpression(op, left, right); + } else { + return null; } - return _this.visit(node["arguments"][0]); - }; - })(this); - getTwoArgs = (function(_this) { - return function(member, name) { - var _ref; - if (((_ref = node["arguments"]) != null ? _ref.length : void 0) !== 2) { - throw "Function " + name + " expects two arguments in expression '" + (_this.getSource(node)) + "'"; - } - return [member, _this.visit(node["arguments"][0]), _this.visit(node["arguments"][1])]; - }; - })(this); - + }; + + /* - * Translate known method calls that aren't attached to an instance. - * Note that we can compare against the actual method because the - * partial evaluator will have converted it into a literal for us. + * The base visit method will throw exceptions for any nodes that remain + * untransformed (which allows us to only bother defining meaningful + * translations) */ - func = node != null ? (_ref = node.callee) != null ? _ref.value : void 0 : void 0; - expr = (function() { - var _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; - if (func === Math.floor) { - return new Q.InvocationExpression(Q.Methods.Floor, [getSingleArg('floor')]); - } else if (func === Math.ceil) { - return new Q.InvocationExpression(Q.Methods.Ceiling, [getSingleArg('ceil')]); - } else if (func === Math.round) { - return new Q.InvocationExpression(Q.Methods.Round, [getSingleArg('round')]); - } else { - - /* - * Translate methods dangling off an instance - */ - if (node.callee.type === 'MemberExpression' && ((_ref1 = node.callee.object) != null ? _ref1.__hasThisExp : void 0) === true) { - if ((node != null ? (_ref2 = node.callee) != null ? (_ref3 = _ref2.object) != null ? _ref3.type : void 0 : void 0 : void 0) === 'CallExpression') { - member = this.visit(node.callee.object); - } else { - member = new Q.MemberExpression((_ref4 = node.callee.object) != null ? (_ref5 = _ref4.property) != null ? _ref5.name : void 0 : void 0); - } - method = (_ref6 = node.callee) != null ? (_ref7 = _ref6.property) != null ? _ref7.name : void 0 : void 0; - if (method === 'toUpperCase') { - return new Q.InvocationExpression(Q.Methods.ToUpperCase, [member]); - } else if (method === 'toLowerCase') { - return new Q.InvocationExpression(Q.Methods.ToLowerCase, [member]); - } else if (method === 'trim') { - return new Q.InvocationExpression(Q.Methods.Trim, [member]); - } else if (method === 'indexOf') { - return new Q.InvocationExpression(Q.Methods.IndexOf, [member, getSingleArg('indexOf')]); - } else if (method === 'concat') { - return new Q.InvocationExpression(Q.Methods.Concat, [member, getSingleArg('concat')]); - } else if (method === 'substring' || method === 'substr') { - return new Q.InvocationExpression(Q.Methods.Substring, getTwoArgs(member, 'substring')); - } else if (method === 'replace') { - return new Q.InvocationExpression(Q.Methods.Replace, getTwoArgs(member, 'replace')); - } else if (method === 'getFullYear' || method === 'getUTCFullYear') { - return new Q.InvocationExpression(Q.Methods.Year, [member]); - } else if (method === 'getYear') { - return new Q.BinaryExpression(Q.BinaryOperators.Subtract, new Q.InvocationExpression(Q.Methods.Year, [member]), new Q.ConstantExpression(1900)); - } else if (method === 'getMonth' || method === 'getUTCMonth') { - - /* getMonth is 0 indexed in JavaScript */ - return new Q.BinaryExpression(Q.BinaryOperators.Subtract, new Q.InvocationExpression(Q.Methods.Month, [member]), new Q.ConstantExpression(1)); - } else if (method === 'getDate' || method === 'getUTCDate') { - return new Q.InvocationExpression(Q.Methods.Day, [member]); - } - } + + JavaScriptToQueryVisitor.prototype.visit = function(node) { + var visited; + visited = JavaScriptToQueryVisitor.__super__.visit.call(this, node); + if (node === visited) { + this.invalid(node); } - }).call(this); - return expr != null ? expr : JavaScriptToQueryVisitor.__super__.CallExpression.call(this, node); - }; - - return JavaScriptToQueryVisitor; - - })(JS.JavaScriptVisitor); - - }).call(this); + return visited; + }; + + JavaScriptToQueryVisitor.prototype.MemberExpression = function(node) { + var expr; + expr = ((() => { + var _ref; + var _ref1; + var _ref2; + var _ref3; + if ((node != null ? (_ref = node.object) != null ? _ref.type : void 0 : void 0) === 'ThisExpression' && (node != null ? (_ref1 = node.property) != null ? _ref1.type : void 0 : void 0) === 'Identifier') { + + /* Simple member access */ + return new Q.MemberExpression(node.property.name); + } else if ((node != null ? (_ref2 = node.object) != null ? _ref2.type : void 0 : void 0) === 'MemberExpression' && ((_ref3 = node.object.object) != null ? _ref3.type : void 0) === 'ThisExpression' && node.property.type === 'Identifier') { + + /* Methods that look like properties */ + if (node.property.name === 'length') { + return new Q.InvocationExpression(Q.Methods.Length, new Q.MemberExpression(node.object.property.name)); + } + } + }))(); + return expr != null ? expr : JavaScriptToQueryVisitor.__super__.MemberExpression.call(this, node); + }; + + JavaScriptToQueryVisitor.prototype.Literal = node => new Q.ConstantExpression(node.value); + + JavaScriptToQueryVisitor.prototype.UnaryExpression = function(node) { + var mapping; + var _ref; + if (node.operator === '+') { + + /* Ignore the + in '+52' */ + return this.visit(node.argument); + } else { + mapping = { + '!': Q.UnaryOperators.Not, + '-': Q.UnaryOperators.Negate + }; + return (_ref = this.translateUnary(node, mapping)) != null ? _ref : JavaScriptToQueryVisitor.__super__.UnaryExpression.call(this, node); + } + }; + + JavaScriptToQueryVisitor.prototype.UpdateExpression = function(node) { + var mapping; + var _ref; + mapping = { + '++': Q.UnaryOperators.Increment, + '--': Q.UnaryOperators.Decrement + }; + return (_ref = this.translateUnary(node, mapping)) != null ? _ref : JavaScriptToQueryVisitor.__super__.UpdateExpression.call(this, node); + }; + + JavaScriptToQueryVisitor.prototype.LogicalExpression = function(node) { + var mapping; + var _ref; + mapping = { + '&&': Q.BinaryOperators.And, + '||': Q.BinaryOperators.Or + }; + return (_ref = this.translateBinary(node, mapping)) != null ? _ref : JavaScriptToQueryVisitor.__super__.LogicalExpression.call(this, node); + }; + + JavaScriptToQueryVisitor.prototype.BinaryExpression = function(node) { + var k; + var left; + var mapping; + var properties; + var v; + var value; + var _ref; + mapping = { + '+': Q.BinaryOperators.Add, + '-': Q.BinaryOperators.Subtract, + '*': Q.BinaryOperators.Multiply, + '/': Q.BinaryOperators.Divide, + '%': Q.BinaryOperators.Modulo, + '>': Q.BinaryOperators.GreaterThan, + '>=': Q.BinaryOperators.GreaterThanOrEqual, + '<': Q.BinaryOperators.LessThan, + '<=': Q.BinaryOperators.LessThanOrEqual, + '!=': Q.BinaryOperators.NotEqual, + '!==': Q.BinaryOperators.NotEqual, + '==': Q.BinaryOperators.Equal, + '===': Q.BinaryOperators.Equal + }; + return (function() { + var _ref1; + var _ref2; + if ((_ref = this.translateBinary(node, mapping)) != null) { + return _ref; + } else if (node.operator === 'in' && ((_ref1 = node.right) != null ? _ref1.type : void 0) === 'Literal' && _.isArray((_ref2 = node.right) != null ? _ref2.value : void 0)) { + + /* + * Transform the 'varName in [x, y, z]' operator into a series of + * comparisons like varName == x || varName == y || varName == z. + */ + if (node.right.value.length > 0) { + left = this.visit(node.left); + return Q.QueryExpression.groupClauses(Q.BinaryOperators.Or, (function() { + var _i; + var _len; + var _ref3; + var _results; + _ref3 = node.right.value; + _results = []; + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + value = _ref3[_i]; + + /* + * If we've got an array of objects who each have + * a single property, we'll use the value of that + * property. Otherwise we'll throw an exception. + */ + if (_.isObject(value)) { + properties = ((() => { + var _results1; + _results1 = []; + for (k in value) { + v = value[k]; + _results1.push(v); + } + return _results1; + }))(); + if ((properties != null ? properties.length : void 0) !== 1) { + throw "in operator requires comparison objects with a single field, not " + value + " (" + (JSON.stringify(value)) + "), for expression '" + (this.getSource(node)) + "'"; + } + value = properties[0]; + } + _results.push(new Q.BinaryExpression(Q.BinaryOperators.Equal, left, new Q.ConstantExpression(value))); + } + return _results; + }).call(this)); + } else { + + /* + * If the array of values is empty, change the query to + * true == false since it can't be satisfied. + */ + return new Q.BinaryExpression(Q.BinaryOperators.Equal, new Q.ConstantExpression(true), new Q.ConstantExpression(false)); + } + } else { + return JavaScriptToQueryVisitor.__super__.BinaryExpression.call(this, node); + } + }).call(this); + }; + + JavaScriptToQueryVisitor.prototype.CallExpression = function(node) { + var expr; + var func; + var getSingleArg; + var getTwoArgs; + var member; + var method; + var _ref; + getSingleArg = ((_this => name => { + var _ref; + if (((_ref = node["arguments"]) != null ? _ref.length : void 0) !== 1) { + throw "Function " + name + " expects one argument in expression '" + (_this.getSource(node)) + "'"; + } + return _this.visit(node["arguments"][0]); + }))(this); + getTwoArgs = ((_this => (member, name) => { + var _ref; + if (((_ref = node["arguments"]) != null ? _ref.length : void 0) !== 2) { + throw "Function " + name + " expects two arguments in expression '" + (_this.getSource(node)) + "'"; + } + return [member, _this.visit(node["arguments"][0]), _this.visit(node["arguments"][1])]; + }))(this); + + /* + * Translate known method calls that aren't attached to an instance. + * Note that we can compare against the actual method because the + * partial evaluator will have converted it into a literal for us. + */ + func = node != null ? (_ref = node.callee) != null ? _ref.value : void 0 : void 0; + expr = (function() { + var _ref1; + var _ref2; + var _ref3; + var _ref4; + var _ref5; + var _ref6; + var _ref7; + if (func === Math.floor) { + return new Q.InvocationExpression(Q.Methods.Floor, [getSingleArg('floor')]); + } else if (func === Math.ceil) { + return new Q.InvocationExpression(Q.Methods.Ceiling, [getSingleArg('ceil')]); + } else if (func === Math.round) { + return new Q.InvocationExpression(Q.Methods.Round, [getSingleArg('round')]); + } else { + + /* + * Translate methods dangling off an instance + */ + if (node.callee.type === 'MemberExpression' && ((_ref1 = node.callee.object) != null ? _ref1.__hasThisExp : void 0) === true) { + if ((node != null ? (_ref2 = node.callee) != null ? (_ref3 = _ref2.object) != null ? _ref3.type : void 0 : void 0 : void 0) === 'CallExpression') { + member = this.visit(node.callee.object); + } else { + member = new Q.MemberExpression((_ref4 = node.callee.object) != null ? (_ref5 = _ref4.property) != null ? _ref5.name : void 0 : void 0); + } + method = (_ref6 = node.callee) != null ? (_ref7 = _ref6.property) != null ? _ref7.name : void 0 : void 0; + if (method === 'toUpperCase') { + return new Q.InvocationExpression(Q.Methods.ToUpperCase, [member]); + } else if (method === 'toLowerCase') { + return new Q.InvocationExpression(Q.Methods.ToLowerCase, [member]); + } else if (method === 'trim') { + return new Q.InvocationExpression(Q.Methods.Trim, [member]); + } else if (method === 'indexOf') { + return new Q.InvocationExpression(Q.Methods.IndexOf, [member, getSingleArg('indexOf')]); + } else if (method === 'concat') { + return new Q.InvocationExpression(Q.Methods.Concat, [member, getSingleArg('concat')]); + } else if (method === 'substring' || method === 'substr') { + return new Q.InvocationExpression(Q.Methods.Substring, getTwoArgs(member, 'substring')); + } else if (method === 'replace') { + return new Q.InvocationExpression(Q.Methods.Replace, getTwoArgs(member, 'replace')); + } else if (method === 'getFullYear' || method === 'getUTCFullYear') { + return new Q.InvocationExpression(Q.Methods.Year, [member]); + } else if (method === 'getYear') { + return new Q.BinaryExpression(Q.BinaryOperators.Subtract, new Q.InvocationExpression(Q.Methods.Year, [member]), new Q.ConstantExpression(1900)); + } else if (method === 'getMonth' || method === 'getUTCMonth') { + + /* getMonth is 0 indexed in JavaScript */ + return new Q.BinaryExpression(Q.BinaryOperators.Subtract, new Q.InvocationExpression(Q.Methods.Month, [member]), new Q.ConstantExpression(1)); + } else if (method === 'getDate' || method === 'getUTCDate') { + return new Q.InvocationExpression(Q.Methods.Day, [member]); + } + } + } + }).call(this); + return expr != null ? expr : JavaScriptToQueryVisitor.__super__.CallExpression.call(this, node); + }; + + return JavaScriptToQueryVisitor; + + }))(JS.JavaScriptVisitor); + })).call(this); }; $__modules__.Node = function (exports) { @@ -1975,87 +2077,88 @@ * ---------------------------------------------------------------------------- */ - (function() { - var Node, Visitor, _; - - _ = require('./Utilities'); - - - /* - * The base Node class for all expressions used for analysis and translation by - * visitors. It's designed to interop with other modules that create expression - * trees using object literals with a type tag. - */ - - exports.Node = Node = (function() { - + ((() => { + var Node; + var Visitor; + var _; + + _ = require('./Utilities'); + + /* - * Type tag of the node that allows for eash dispatch in visitors. This is - * automatically set in the constructor (so it's important to call super() in - * derived Node classes). + * The base Node class for all expressions used for analysis and translation by + * visitors. It's designed to interop with other modules that create expression + * trees using object literals with a type tag. */ - Node.prototype.type = 'Node'; - - - /* - * Initializes a new instance of the Node class and sets its type tag. - */ - - function Node() { - this.type = _.functionName(this.constructor); - } - - return Node; - - })(); - - - /* - * Base class for all visitors - */ - - exports.Visitor = Visitor = (function() { - function Visitor() {} - - - /* - * Visit a node. - */ - - Visitor.prototype.visit = function(node) { - var element, _i, _len, _results; - if (_.isArray(node)) { - _results = []; - for (_i = 0, _len = node.length; _i < _len; _i++) { - element = node[_i]; - _results.push(this.visit(element)); - } - return _results; - } else if (!(node != null ? node.type : void 0)) { - return node; - } else if (!_.isFunction(this[node.type])) { - throw "Unsupported expression " + (this.getSource(node)); - } else { - return this[node.type](node); + + exports.Node = Node = ((() => { + + /* + * Type tag of the node that allows for eash dispatch in visitors. This is + * automatically set in the constructor (so it's important to call super() in + * derived Node classes). + */ + Node.prototype.type = 'Node'; + + + /* + * Initializes a new instance of the Node class and sets its type tag. + */ + + function Node() { + this.type = _.functionName(this.constructor); } - }; - - + + return Node; + + }))(); + + /* - * Get the source code corresponding to a node. + * Base class for all visitors */ - - Visitor.prototype.getSource = function(node) { - - /* It is expected this will be overridden in derived visitors. */ - return null; - }; - - return Visitor; - - })(); - - }).call(this); + + exports.Visitor = Visitor = ((() => { + function Visitor() {} + + + /* + * Visit a node. + */ + + Visitor.prototype.visit = function(node) { + var element; + var _i; + var _len; + var _results; + if (_.isArray(node)) { + _results = []; + for (_i = 0, _len = node.length; _i < _len; _i++) { + element = node[_i]; + _results.push(this.visit(element)); + } + return _results; + } else if (!(node != null ? node.type : void 0)) { + return node; + } else if (!_.isFunction(this[node.type])) { + throw "Unsupported expression " + (this.getSource(node)); + } else { + return this[node.type](node); + } + }; + + + /* + * Get the source code corresponding to a node. + */ + + Visitor.prototype.getSource = node => /* It is expected this will be overridden in derived visitors. */ + null; + + return Visitor; + + }))(); + })).call(this); }; $__modules__.ODataProvider = function (exports) { @@ -2067,309 +2170,343 @@ * ---------------------------------------------------------------------------- */ - (function() { - var ODataFilterQueryVisitor, ODataProvider, Q, Query, _, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - _ = require('./Utilities'); - - Q = require('./QueryNodes'); - - Query = require('./Query').Query; - - exports.ODataProvider = ODataProvider = (function() { - function ODataProvider() {} - - - /* - * Convert a query into an OData URI. - */ - - ODataProvider.prototype.toQuery = function(query) { - var odata, s, url; - odata = this.toOData(query, true); - url = "/" + odata.table; - s = '?'; - if (odata.filters) { - url += "" + s + "$filter=" + odata.filters; - s = '&'; - } - if (odata.ordering) { - url += "" + s + "$orderby=" + odata.ordering; - s = '&'; - } - if (odata.skip) { - url += "" + s + "$skip=" + odata.skip; - s = '&'; - } - if (odata.take || odata.take === 0) { - url += "" + s + "$top=" + odata.take; - s = '&'; - } - if (odata.selections) { - url += "" + s + "$select=" + odata.selections; - s = '&'; - } - if (odata.includeTotalCount) { - url += "" + s + "$inlinecount=allpages"; - } - return url; - }; - - - /* - * Translate the query components into OData strings - */ - - ODataProvider.prototype.toOData = function(query, encodeForUri) { - var asc, components, name, odata, ordering, _ref, _ref1; - if (encodeForUri == null) { - encodeForUri = false; - } - components = (_ref = query != null ? query.getComponents() : void 0) != null ? _ref : {}; - ordering = (function() { - var _ref1, _results; - _ref1 = components != null ? components.ordering : void 0; - _results = []; - for (name in _ref1) { - asc = _ref1[name]; - _results.push(asc ? name : "" + name + " desc"); - } - return _results; - })(); - return odata = { - table: components != null ? components.table : void 0, - filters: ODataFilterQueryVisitor.convert(components.filters, encodeForUri), - ordering: ordering != null ? ordering.toString() : void 0, - skip: components != null ? components.skip : void 0, - take: components != null ? components.take : void 0, - selections: components != null ? (_ref1 = components.selections) != null ? _ref1.toString() : void 0 : void 0, - includeTotalCount: components != null ? components.includeTotalCount : void 0 - }; - }; - - - /* - * Convert OData components into a query object - */ - - ODataProvider.prototype.fromOData = function(table, filters, ordering, skip, take, selections, includeTotalCount) { - var direction, field, item, query, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3; - query = new Query(table); - if (filters) { - query.where(filters); - } - if (skip || skip === 0) { - query.skip(skip); - } - if (take || take === 0) { - query.take(take); - } - if (includeTotalCount) { - query.includeTotalCount(); - } - _ref1 = (_ref = selections != null ? selections.split(',') : void 0) != null ? _ref : []; - for (_i = 0, _len = _ref1.length; _i < _len; _i++) { - field = _ref1[_i]; - query.select(field.trim()); - } - _ref2 = (function() { - var _k, _len1, _ref2, _ref3, _results; - _ref3 = (_ref2 = ordering != null ? ordering.split(',') : void 0) != null ? _ref2 : []; - _results = []; - for (_k = 0, _len1 = _ref3.length; _k < _len1; _k++) { - item = _ref3[_k]; - _results.push(item.trim().split(' ')); - } - return _results; - })(); - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - _ref3 = _ref2[_j], field = _ref3[0], direction = _ref3[1]; - if ((direction != null ? direction.toUpperCase() : void 0) !== 'DESC') { - query.orderBy(field); - } else { - query.orderByDescending(field); - } - } - return query; - }; - - return ODataProvider; - - })(); - - - /* - * Visitor that converts query expression trees into OData filter statements. - */ - - ODataFilterQueryVisitor = (function(_super) { - __extends(ODataFilterQueryVisitor, _super); - - function ODataFilterQueryVisitor(encodeForUri) { - this.encodeForUri = encodeForUri; - } - - ODataFilterQueryVisitor.convert = function(filters, encodeForUri) { - var visitor, _ref; - visitor = new ODataFilterQueryVisitor(encodeForUri); - return (_ref = (filters ? visitor.visit(filters) : void 0)) != null ? _ref : null; - }; - - ODataFilterQueryVisitor.prototype.toOData = function(value) { - var text; - if ((_.isNumber(value)) || (_.isBoolean(value))) { - return value.toString(); - } else if (_.isString(value)) { - value = value.replace(/'/g, "''"); - if ((this.encodeForUri != null) && this.encodeForUri === true) { - value = encodeURIComponent(value); - } - return "'" + value + "'"; - } else if (_.isDate(value)) { - - /* - * Dates are expected in the format - * "datetime'yyyy-mm-ddThh:mm[:ss[.fffffff]]'" - * which JSON.stringify gives us by default - */ - text = JSON.stringify(value); - if (text.length > 2) { - text = text.slice(1, +(text.length - 2) + 1 || 9e9); - } - text = text.replace(/(T\d{2}:\d{2}:\d{2})Z$/, function(all, time) { - var msec; - msec = String(value.getMilliseconds() + 1000).substring(1); - return "" + time + "." + msec + "Z"; - }); - return "datetime'" + text + "'"; - } else if (!value) { - return "null"; - } else { - throw "Unsupported literal value " + value; - } - }; - - ODataFilterQueryVisitor.prototype.ConstantExpression = function(node) { - return this.toOData(node.value); - }; - - ODataFilterQueryVisitor.prototype.MemberExpression = function(node) { - return node.member; - }; - - ODataFilterQueryVisitor.prototype.UnaryExpression = function(node) { - if (node.operator === Q.UnaryOperators.Not) { - return "not " + (this.visit(node.operand)); - } else if (node.operator === Q.UnaryOperators.Negate) { - return "(0 sub " + (this.visit(node.operand)) + ")"; - } else { - throw "Unsupported operator " + node.operator; - } - }; - - ODataFilterQueryVisitor.prototype.BinaryExpression = function(node) { - var mapping, op; - mapping = { - And: 'and', - Or: 'or', - Add: 'add', - Subtract: 'sub', - Multiply: 'mul', - Divide: 'div', - Modulo: 'mod', - GreaterThan: 'gt', - GreaterThanOrEqual: 'ge', - LessThan: 'lt', - LessThanOrEqual: 'le', - NotEqual: 'ne', - Equal: 'eq' - }; - op = mapping[node.operator]; - if (op) { - return "(" + (this.visit(node.left)) + " " + op + " " + (this.visit(node.right)) + ")"; - } else { - throw "Unsupported operator " + node.operator; - } - }; - - ODataFilterQueryVisitor.prototype.InvocationExpression = function(node) { - var mapping, method; - mapping = { - Length: 'length', - ToUpperCase: 'toupper', - ToLowerCase: 'tolower', - Trim: 'trim', - IndexOf: 'indexof', - Replace: 'replace', - Substring: 'substring', - Concat: 'concat', - Day: 'day', - Month: 'month', - Year: 'year', - Floor: 'floor', - Ceiling: 'ceiling', - Round: 'round' - }; - method = mapping[node.method]; - if (method) { - return "" + method + "(" + (this.visit(node.args)) + ")"; - } else { - throw "Invocation of unsupported method " + node.method; - } - }; - - ODataFilterQueryVisitor.prototype.LiteralExpression = function (node) { - var ch, inString, literal, parenBalance, _i, _len, _ref; - literal = ''; - parenBalance = 0; - inString = false; - _ref = node.queryString; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - ch = _ref[_i]; - if (parenBalance < 0) { - break; - } else if (inString) { - literal += ch; - inString = ch !== "'"; - } else if (ch === '?') { - if ((!node.args) || (node.args.length <= 0)) { - throw "Too few arguments for " + node.queryString + "."; - } - literal += this.toOData(node.args.shift()); - } else if (ch === "'") { - literal += ch; - inString = true; - } else if (ch === '(') { - parenBalance += 1; - literal += ch; - } else if (ch === ')') { - parenBalance -= 1; - literal += ch; - } else { - literal += ch; - } - } - if (node.args && node.args.length > 0) { - throw "Too many arguments for " + node.queryString; - } - if (parenBalance !== 0) { - throw "Unbalanced parentheses in " + node.queryString; - } - if (literal.trim().length > 0) { - return "(" + literal + ")"; - } else { - return literal; - } - }; + ((() => { + var ODataFilterQueryVisitor; + var ODataProvider; + var Q; + var Query; + var _; + var __hasProp = {}.hasOwnProperty; + var __extends = (child, parent) => { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - return ODataFilterQueryVisitor; - - })(Q.QueryExpressionVisitor); - - }).call(this); + _ = require('./Utilities'); + + Q = require('./QueryNodes'); + + Query = require('./Query').Query; + + exports.ODataProvider = ODataProvider = ((() => { + function ODataProvider() {} + + + /* + * Convert a query into an OData URI. + */ + + ODataProvider.prototype.toQuery = function(query) { + var odata; + var s; + var url; + odata = this.toOData(query, true); + url = "/" + odata.table; + s = '?'; + if (odata.filters) { + url += "" + s + "$filter=" + odata.filters; + s = '&'; + } + if (odata.ordering) { + url += "" + s + "$orderby=" + odata.ordering; + s = '&'; + } + if (odata.skip) { + url += "" + s + "$skip=" + odata.skip; + s = '&'; + } + if (odata.take || odata.take === 0) { + url += "" + s + "$top=" + odata.take; + s = '&'; + } + if (odata.selections) { + url += "" + s + "$select=" + odata.selections; + s = '&'; + } + if (odata.includeTotalCount) { + url += "" + s + "$inlinecount=allpages"; + } + return url; + }; + + + /* + * Translate the query components into OData strings + */ + + ODataProvider.prototype.toOData = (query, encodeForUri) => { + var asc; + var components; + var name; + var odata; + var ordering; + var _ref; + var _ref1; + if (encodeForUri == null) { + encodeForUri = false; + } + components = (_ref = query != null ? query.getComponents() : void 0) != null ? _ref : {}; + ordering = ((() => { + var _ref1; + var _results; + _ref1 = components != null ? components.ordering : void 0; + _results = []; + for (name in _ref1) { + asc = _ref1[name]; + _results.push(asc ? name : "" + name + " desc"); + } + return _results; + }))(); + return odata = { + table: components != null ? components.table : void 0, + filters: ODataFilterQueryVisitor.convert(components.filters, encodeForUri), + ordering: ordering != null ? ordering.toString() : void 0, + skip: components != null ? components.skip : void 0, + take: components != null ? components.take : void 0, + selections: components != null ? (_ref1 = components.selections) != null ? _ref1.toString() : void 0 : void 0, + includeTotalCount: components != null ? components.includeTotalCount : void 0 + }; + }; + + + /* + * Convert OData components into a query object + */ + + ODataProvider.prototype.fromOData = (table, filters, ordering, skip, take, selections, includeTotalCount) => { + var direction; + var field; + var item; + var query; + var _i; + var _j; + var _len; + var _len1; + var _ref; + var _ref1; + var _ref2; + var _ref3; + query = new Query(table); + if (filters) { + query.where(filters); + } + if (skip || skip === 0) { + query.skip(skip); + } + if (take || take === 0) { + query.take(take); + } + if (includeTotalCount) { + query.includeTotalCount(); + } + _ref1 = (_ref = selections != null ? selections.split(',') : void 0) != null ? _ref : []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + field = _ref1[_i]; + query.select(field.trim()); + } + _ref2 = ((() => { + var _k; + var _len1; + var _ref2; + var _ref3; + var _results; + _ref3 = (_ref2 = ordering != null ? ordering.split(',') : void 0) != null ? _ref2 : []; + _results = []; + for (_k = 0, _len1 = _ref3.length; _k < _len1; _k++) { + item = _ref3[_k]; + _results.push(item.trim().split(' ')); + } + return _results; + }))(); + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + _ref3 = _ref2[_j], field = _ref3[0], direction = _ref3[1]; + if ((direction != null ? direction.toUpperCase() : void 0) !== 'DESC') { + query.orderBy(field); + } else { + query.orderByDescending(field); + } + } + return query; + }; + + return ODataProvider; + + }))(); + + + /* + * Visitor that converts query expression trees into OData filter statements. + */ + + ODataFilterQueryVisitor = ((_super => { + __extends(ODataFilterQueryVisitor, _super); + + function ODataFilterQueryVisitor(encodeForUri) { + this.encodeForUri = encodeForUri; + } + + ODataFilterQueryVisitor.convert = (filters, encodeForUri) => { + var visitor; + var _ref; + visitor = new ODataFilterQueryVisitor(encodeForUri); + return (_ref = (filters ? visitor.visit(filters) : void 0)) != null ? _ref : null; + }; + + ODataFilterQueryVisitor.prototype.toOData = function(value) { + var text; + if ((_.isNumber(value)) || (_.isBoolean(value))) { + return value.toString(); + } else if (_.isString(value)) { + value = value.replace(/'/g, "''"); + if ((this.encodeForUri != null) && this.encodeForUri === true) { + value = encodeURIComponent(value); + } + return "'" + value + "'"; + } else if (_.isDate(value)) { + + /* + * Dates are expected in the format + * "datetime'yyyy-mm-ddThh:mm[:ss[.fffffff]]'" + * which JSON.stringify gives us by default + */ + text = JSON.stringify(value); + if (text.length > 2) { + text = text.slice(1, +(text.length - 2) + 1 || 9e9); + } + text = text.replace(/(T\d{2}:\d{2}:\d{2})Z$/, (all, time) => { + var msec; + msec = String(value.getMilliseconds() + 1000).substring(1); + return "" + time + "." + msec + "Z"; + }); + return "datetime'" + text + "'"; + } else if (!value) { + return "null"; + } else { + throw "Unsupported literal value " + value; + } + }; + + ODataFilterQueryVisitor.prototype.ConstantExpression = function(node) { + return this.toOData(node.value); + }; + + ODataFilterQueryVisitor.prototype.MemberExpression = node => node.member; + + ODataFilterQueryVisitor.prototype.UnaryExpression = function(node) { + if (node.operator === Q.UnaryOperators.Not) { + return "not " + (this.visit(node.operand)); + } else if (node.operator === Q.UnaryOperators.Negate) { + return "(0 sub " + (this.visit(node.operand)) + ")"; + } else { + throw "Unsupported operator " + node.operator; + } + }; + + ODataFilterQueryVisitor.prototype.BinaryExpression = function(node) { + var mapping; + var op; + mapping = { + And: 'and', + Or: 'or', + Add: 'add', + Subtract: 'sub', + Multiply: 'mul', + Divide: 'div', + Modulo: 'mod', + GreaterThan: 'gt', + GreaterThanOrEqual: 'ge', + LessThan: 'lt', + LessThanOrEqual: 'le', + NotEqual: 'ne', + Equal: 'eq' + }; + op = mapping[node.operator]; + if (op) { + return "(" + (this.visit(node.left)) + " " + op + " " + (this.visit(node.right)) + ")"; + } else { + throw "Unsupported operator " + node.operator; + } + }; + + ODataFilterQueryVisitor.prototype.InvocationExpression = function(node) { + var mapping; + var method; + mapping = { + Length: 'length', + ToUpperCase: 'toupper', + ToLowerCase: 'tolower', + Trim: 'trim', + IndexOf: 'indexof', + Replace: 'replace', + Substring: 'substring', + Concat: 'concat', + Day: 'day', + Month: 'month', + Year: 'year', + Floor: 'floor', + Ceiling: 'ceiling', + Round: 'round' + }; + method = mapping[node.method]; + if (method) { + return "" + method + "(" + (this.visit(node.args)) + ")"; + } else { + throw "Invocation of unsupported method " + node.method; + } + }; + + ODataFilterQueryVisitor.prototype.LiteralExpression = function (node) { + var ch; + var inString; + var literal; + var parenBalance; + var _i; + var _len; + var _ref; + literal = ''; + parenBalance = 0; + inString = false; + _ref = node.queryString; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + ch = _ref[_i]; + if (parenBalance < 0) { + break; + } else if (inString) { + literal += ch; + inString = ch !== "'"; + } else if (ch === '?') { + if ((!node.args) || (node.args.length <= 0)) { + throw "Too few arguments for " + node.queryString + "."; + } + literal += this.toOData(node.args.shift()); + } else if (ch === "'") { + literal += ch; + inString = true; + } else if (ch === '(') { + parenBalance += 1; + literal += ch; + } else if (ch === ')') { + parenBalance -= 1; + literal += ch; + } else { + literal += ch; + } + } + if (node.args && node.args.length > 0) { + throw "Too many arguments for " + node.queryString; + } + if (parenBalance !== 0) { + throw "Unbalanced parentheses in " + node.queryString; + } + if (literal.trim().length > 0) { + return "(" + literal + ")"; + } else { + return literal; + } + }; + + + return ODataFilterQueryVisitor; + + }))(Q.QueryExpressionVisitor); + })).call(this); }; $__modules__.PartialEvaluator = function (exports) { @@ -2381,232 +2518,259 @@ * ---------------------------------------------------------------------------- */ - (function() { - var IndependenceNominator, JS, PartialEvaluator, _, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - _ = require('./Utilities'); - - JS = require('./JavaScriptNodes'); - - - /* - * Partially evaluate a complex expression in the context of its environment. - * This allows us to support arbitrary JavaScript expressions even though we - * only explicitly transform a subset of expressions into QueryExpressions. - * - * For example, assuming we have an expression like (x) -> @id == x + 1 with an - * environment where x == 12, then the entire right hand side of the comparison - * is independent of any values computed by the query and could be replaced with - * the literal value 13. - */ - - exports.PartialEvaluator = PartialEvaluator = (function(_super) { - __extends(PartialEvaluator, _super); - - function PartialEvaluator(context) { - this.context = context; - } - - PartialEvaluator.prototype.visit = function(node) { - var key, params, source, thunk, value, values, _ref, _ref1, _ref2, _ref3; - if (!node.__independent || node.type === 'Literal' || (!node.type)) { - - /* - * If the node isn't independent or it's already a literal, then - * just keep walking the tree - */ - return PartialEvaluator.__super__.visit.call(this, node); - } else { - - /* - * Otherwse we'll evaluate the node in the context of the - * environment by either looking up identifiers directly or - * evaluating whole sub expressions - */ - if (node.type === 'Identifier' && this.context.environment[node.name]) { - return new JS.Literal(this.context.environment[node.name]); - } else { - - /* - * Evaluate the source of the sub expression in the context - * of the environment - */ - source = this.context.source.slice(node != null ? (_ref = node.range) != null ? _ref[0] : void 0 : void 0, +((node != null ? (_ref1 = node.range) != null ? _ref1[1] : void 0 : void 0) - 1) + 1 || 9e9); - params = (_ref2 = (function() { - var _ref3, _results; - _ref3 = this.context.environment; - _results = []; - for (key in _ref3) { - value = _ref3[key]; - _results.push(key); - } - return _results; - }).call(this)) != null ? _ref2 : []; - values = (_ref3 = (function() { - var _ref4, _results; - _ref4 = this.context.environment; - _results = []; - for (key in _ref4) { - value = _ref4[key]; - _results.push(JSON.stringify(value)); - } - return _results; - }).call(this)) != null ? _ref3 : []; - thunk = "(function(" + params + ") { return " + source + "; })(" + values + ")"; - value = eval(thunk); - return new JS.Literal(value); - } + ((() => { + var IndependenceNominator; + var JS; + var PartialEvaluator; + var _; + var __hasProp = {}.hasOwnProperty; + var __extends = (child, parent) => { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + _ = require('./Utilities'); + + JS = require('./JavaScriptNodes'); + + + /* + * Partially evaluate a complex expression in the context of its environment. + * This allows us to support arbitrary JavaScript expressions even though we + * only explicitly transform a subset of expressions into QueryExpressions. + * + * For example, assuming we have an expression like (x) -> @id == x + 1 with an + * environment where x == 12, then the entire right hand side of the comparison + * is independent of any values computed by the query and could be replaced with + * the literal value 13. + */ + + exports.PartialEvaluator = PartialEvaluator = ((_super => { + __extends(PartialEvaluator, _super); + + function PartialEvaluator(context) { + this.context = context; } - }; - - PartialEvaluator.evaluate = function(context) { - var evaluator, nominator; - nominator = new IndependenceNominator(context); - nominator.visit(context.expression); - evaluator = new PartialEvaluator(context); - return evaluator.visit(context.expression); - }; - - return PartialEvaluator; - - })(JS.JavaScriptVisitor); - - - /* - * Nominate independent nodes in an expression tree that don't depend on any - * server side values. - */ - - exports.IndependenceNominator = IndependenceNominator = (function(_super) { - __extends(IndependenceNominator, _super); - - function IndependenceNominator(context) { - this.context = context; - } - - IndependenceNominator.prototype.Literal = function(node) { - IndependenceNominator.__super__.Literal.call(this, node); - node.__independent = true; - node.__hasThisExp = false; - return node; - }; - - IndependenceNominator.prototype.ThisExpression = function(node) { - IndependenceNominator.__super__.ThisExpression.call(this, node); - node.__independent = false; - node.__hasThisExp = true; - return node; - }; - - IndependenceNominator.prototype.Identifier = function(node) { - IndependenceNominator.__super__.Identifier.call(this, node); - node.__independent = true; - node.__hasThisExp = false; - return node; - }; - - IndependenceNominator.prototype.MemberExpression = function(node) { - var _ref; - IndependenceNominator.__super__.MemberExpression.call(this, node); - - /* - * Undo independence of identifiers when they're members of this.* or - * this.member.* (the latter allows for member functions) - */ - node.__hasThisExp = (_ref = node.object) != null ? _ref.__hasThisExp : void 0; - if (node.__hasThisExp) { - node.__independent = false; - if (node != null) { - node.property.__independent = false; - } - } - return node; - }; - - IndependenceNominator.prototype.CallExpression = function(node) { - IndependenceNominator.__super__.CallExpression.call(this, node); - node.__hasThisExp = node.callee.__hasThisExp; - return node; - }; - - IndependenceNominator.prototype.ObjectExpression = function(node) { - var independence, setter, _i, _j, _len, _len1, _ref, _ref1; - IndependenceNominator.__super__.ObjectExpression.call(this, node); - - /* - * Prevent literal key identifiers from being evaluated out of - * context - */ - _ref = node.properties; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - setter = _ref[_i]; - setter.key.__independent = false; - } - - /* - * An object literal is independent if all of its values are - * independent - */ - independence = true; - _ref1 = node.properties; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - setter = _ref1[_j]; - independence &= setter.value.__independent; - } - node.__independent = independence ? true : false; - return node; - }; - - IndependenceNominator.prototype.visit = function(node) { - - /* - * Call the base visit method which will both visit all of our - * subexpressions and also call the couple of overrides above which - * handle the base independence cases - */ - var independence, isIndependent, name, v, value, _i, _len; - IndependenceNominator.__super__.visit.call(this, node); - - /* - * If the node's independence wasn't determined automatically by the - * base cases above, then it's independence is determined by checking - * all of its values and aggregating their independence - */ - if (!(Object.prototype.hasOwnProperty.call(node, '__independent'))) { - independence = true; - isIndependent = function(node) { + + PartialEvaluator.prototype.visit = function(node) { + var key; + var params; + var source; + var thunk; + var value; + var values; var _ref; - if (_.isObject(node)) { - return (_ref = value.__independent) != null ? _ref : false; + var _ref1; + var _ref2; + var _ref3; + if (!node.__independent || node.type === 'Literal' || (!node.type)) { + + /* + * If the node isn't independent or it's already a literal, then + * just keep walking the tree + */ + return PartialEvaluator.__super__.visit.call(this, node); } else { - return true; - } - }; - for (name in node) { - value = node[name]; - if (_.isArray(value)) { - for (_i = 0, _len = value.length; _i < _len; _i++) { - v = value[_i]; - independence &= isIndependent(v); + + /* + * Otherwse we'll evaluate the node in the context of the + * environment by either looking up identifiers directly or + * evaluating whole sub expressions + */ + if (node.type === 'Identifier' && this.context.environment[node.name]) { + return new JS.Literal(this.context.environment[node.name]); + } else { + + /* + * Evaluate the source of the sub expression in the context + * of the environment + */ + source = this.context.source.slice(node != null ? (_ref = node.range) != null ? _ref[0] : void 0 : void 0, +((node != null ? (_ref1 = node.range) != null ? _ref1[1] : void 0 : void 0) - 1) + 1 || 9e9); + params = (_ref2 = (function() { + var _ref3; + var _results; + _ref3 = this.context.environment; + _results = []; + for (key in _ref3) { + value = _ref3[key]; + _results.push(key); + } + return _results; + }).call(this)) != null ? _ref2 : []; + values = (_ref3 = (function() { + var _ref4; + var _results; + _ref4 = this.context.environment; + _results = []; + for (key in _ref4) { + value = _ref4[key]; + _results.push(JSON.stringify(value)); + } + return _results; + }).call(this)) != null ? _ref3 : []; + thunk = "(function(" + params + ") { return " + source + "; })(" + values + ")"; + value = eval(thunk); + return new JS.Literal(value); } - } else if (_.isObject(value)) { - independence &= isIndependent(value); + } + }; + + PartialEvaluator.evaluate = context => { + var evaluator; + var nominator; + nominator = new IndependenceNominator(context); + nominator.visit(context.expression); + evaluator = new PartialEvaluator(context); + return evaluator.visit(context.expression); + }; + + return PartialEvaluator; + + }))(JS.JavaScriptVisitor); + + + /* + * Nominate independent nodes in an expression tree that don't depend on any + * server side values. + */ + + exports.IndependenceNominator = IndependenceNominator = ((_super => { + __extends(IndependenceNominator, _super); + + function IndependenceNominator(context) { + this.context = context; + } + + IndependenceNominator.prototype.Literal = function(node) { + IndependenceNominator.__super__.Literal.call(this, node); + node.__independent = true; + node.__hasThisExp = false; + return node; + }; + + IndependenceNominator.prototype.ThisExpression = function(node) { + IndependenceNominator.__super__.ThisExpression.call(this, node); + node.__independent = false; + node.__hasThisExp = true; + return node; + }; + + IndependenceNominator.prototype.Identifier = function(node) { + IndependenceNominator.__super__.Identifier.call(this, node); + node.__independent = true; + node.__hasThisExp = false; + return node; + }; + + IndependenceNominator.prototype.MemberExpression = function(node) { + var _ref; + IndependenceNominator.__super__.MemberExpression.call(this, node); + + /* + * Undo independence of identifiers when they're members of this.* or + * this.member.* (the latter allows for member functions) + */ + node.__hasThisExp = (_ref = node.object) != null ? _ref.__hasThisExp : void 0; + if (node.__hasThisExp) { + node.__independent = false; + if (node != null) { + node.property.__independent = false; } } - - /* &= will turn true/false into 1/0 so we'll turn it back */ - node.__independent = independence ? true : false; - } - return node; - }; - - return IndependenceNominator; - - })(JS.JavaScriptVisitor); - - }).call(this); + return node; + }; + + IndependenceNominator.prototype.CallExpression = function(node) { + IndependenceNominator.__super__.CallExpression.call(this, node); + node.__hasThisExp = node.callee.__hasThisExp; + return node; + }; + + IndependenceNominator.prototype.ObjectExpression = function(node) { + var independence; + var setter; + var _i; + var _j; + var _len; + var _len1; + var _ref; + var _ref1; + IndependenceNominator.__super__.ObjectExpression.call(this, node); + + /* + * Prevent literal key identifiers from being evaluated out of + * context + */ + _ref = node.properties; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + setter = _ref[_i]; + setter.key.__independent = false; + } + + /* + * An object literal is independent if all of its values are + * independent + */ + independence = true; + _ref1 = node.properties; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + setter = _ref1[_j]; + independence &= setter.value.__independent; + } + node.__independent = independence ? true : false; + return node; + }; + + IndependenceNominator.prototype.visit = function(node) { + /* + * Call the base visit method which will both visit all of our + * subexpressions and also call the couple of overrides above which + * handle the base independence cases + */ + var independence; + + var isIndependent; + var name; + var v; + var value; + var _i; + var _len; + IndependenceNominator.__super__.visit.call(this, node); + + /* + * If the node's independence wasn't determined automatically by the + * base cases above, then it's independence is determined by checking + * all of its values and aggregating their independence + */ + if (!(Object.prototype.hasOwnProperty.call(node, '__independent'))) { + independence = true; + isIndependent = node => { + var _ref; + if (_.isObject(node)) { + return (_ref = value.__independent) != null ? _ref : false; + } else { + return true; + } + }; + for (name in node) { + value = node[name]; + if (_.isArray(value)) { + for (_i = 0, _len = value.length; _i < _len; _i++) { + v = value[_i]; + independence &= isIndependent(v); + } + } else if (_.isObject(value)) { + independence &= isIndependent(value); + } + } + + /* &= will turn true/false into 1/0 so we'll turn it back */ + node.__independent = independence ? true : false; + } + return node; + }; + + return IndependenceNominator; + + }))(JS.JavaScriptVisitor); + })).call(this); }; $__modules__.Query = function (exports) { @@ -2621,265 +2785,297 @@ /* Pull in references */ - (function() { - var JavaScript, ODataProvider, Q, Query, _, - __slice = [].slice; - - _ = require('./Utilities'); - - Q = require('./QueryNodes'); - - JavaScript = require('./JavaScript').JavaScript; - - - /* - * Define a query that can be translated into a desired query language and - * executed remotely. - */ - - exports.Query = Query = (function() { - function Query(table, context) { - var _context, _filters, _includeTotalCount, _ordering, _projection, _selections, _skip, _table, _take, _version; - if (!table || !(_.isString(table))) { - throw 'Expected the name of a table!'; + ((() => { + var JavaScript; + var ODataProvider; + var Q; + var Query; + var _; + var __slice = [].slice; + + _ = require('./Utilities'); + + Q = require('./QueryNodes'); + + JavaScript = require('./JavaScript').JavaScript; + + + /* + * Define a query that can be translated into a desired query language and + * executed remotely. + */ + + exports.Query = Query = ((() => { + function Query(table, context) { + var _context; + var _filters; + var _includeTotalCount; + var _ordering; + var _projection; + var _selections; + var _skip; + var _table; + var _take; + var _version; + if (!table || !(_.isString(table))) { + throw 'Expected the name of a table!'; + } + + /* Store the table name and any extra context */ + _table = table; + _context = context; + + /* Private Query component members */ + _filters = null; + _projection = null; + _selections = []; + _ordering = {}; + _skip = null; + _take = null; + _includeTotalCount = false; + + /* + * Keep a version flag that's updated on each mutation so we can + * track whether changes have been made. This is to enable caching + * of compiled queries without reevaluating unless necessary. + */ + _version = 0; + + /* Get the individual components of the query */ + this.getComponents = () => ({ + filters: _filters, + selections: _selections, + projection: _projection, + ordering: _ordering, + skip: _skip, + take: _take, + table: _table, + context: _context, + includeTotalCount: _includeTotalCount, + version: _version + }); + + /* + * Set the individual components of the query (this is primarily + * meant to be used for rehydrating a query). + */ + this.setComponents = function(components) { + var _ref; + var _ref1; + var _ref2; + var _ref3; + var _ref4; + var _ref5; + var _ref6; + var _ref7; + var _ref8; + _version++; + _filters = (_ref = components != null ? components.filters : void 0) != null ? _ref : null; + _selections = (_ref1 = components != null ? components.selections : void 0) != null ? _ref1 : []; + _projection = (_ref2 = components != null ? components.projection : void 0) != null ? _ref2 : null; + _ordering = (_ref3 = components != null ? components.ordering : void 0) != null ? _ref3 : {}; + _skip = (_ref4 = components != null ? components.skip : void 0) != null ? _ref4 : null; + _take = (_ref5 = components != null ? components.take : void 0) != null ? _ref5 : null; + _includeTotalCount = (_ref6 = components != null ? components.includeTotalCount : void 0) != null ? _ref6 : false; + _table = (_ref7 = components != null ? components.table : void 0) != null ? _ref7 : null; + _context = (_ref8 = components != null ? components.context : void 0) != null ? _ref8 : null; + return this; + }; + + /* + * Add a constraint to a query. Constraints can take the form of + * a function with a single return statement, key/value pairs of + * equality comparisons, or provider-specific literal strings (note + * that not all providers support literals). + */ + this.where = function() { + var args; + var constraint; + var expr; + var name; + var value; + constraint = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + _version++; + + /* + * Translate the constraint from its high level form into a + * QueryExpression tree that can be manipulated by a query + * provider + */ + expr = ((() => { + if (_.isFunction(constraint)) { + return JavaScript.transformConstraint(constraint, args); + } else if (_.isObject(constraint)) { + + /* + * Turn an object of key value pairs into a series of + * equality expressions that are and'ed together to form + * a single expression + */ + return Q.QueryExpression.groupClauses(Q.BinaryOperators.And, ((() => { + var _results; + _results = []; + for (name in constraint) { + value = constraint[name]; + _results.push(expr = new Q.BinaryExpression(Q.BinaryOperators.Equal, new Q.MemberExpression(name), new Q.ConstantExpression(value))); + } + return _results; + }))()); + } else if (_.isString(constraint)) { + + /* + * Store the literal query along with any arguments for + * providers that support basic string replacement (i.e., + * something like where('name eq ?', 'Steve')) + */ + return new Q.LiteralExpression(constraint, args); + } else { + throw "Expected a function, object, or string, not " + constraint; + } + }))(); + + /* Merge the new filters with any existing filters */ + _filters = Q.QueryExpression.groupClauses(Q.BinaryOperators.And, [_filters, expr]); + return this; + }; + + /* + * Project the query results. A projection can either be defined as + * a set of fields that we'll pull back (instead of the entire row) + * or a function that will transform a row into a new type. If a + * function is used, we'll analyze the function to pull back the + * minimal number of fields required. + */ + this.select = function(...args) { + var param; + var parameters; + var projectionOrParameter; + var _i; + var _len; + projectionOrParameter = args[0], parameters = 2 <= args.length ? __slice.call(args, 1) : []; + _version++; + if (_.isString(projectionOrParameter)) { + + /* Add all the literal string parameters */ + _selections.push(projectionOrParameter); + for (_i = 0, _len = parameters.length; _i < _len; _i++) { + param = parameters[_i]; + if (!(_.isString(param))) { + throw "Expected string parameters, not " + param; + } + _selections.push(param); + } + } else if (_.isFunction(projectionOrParameter)) { + + /* Set the projection and calculate the fields it uses */ + _projection = projectionOrParameter; + _selections = JavaScript.getProjectedFields(_projection); + } else { + throw "Expected a string or a function, not " + projectionOrParameter; + } + return this; + }; + this.orderBy = function(...args) { + var param; + var parameters; + var _i; + var _len; + parameters = 1 <= args.length ? __slice.call(args, 0) : []; + _version++; + for (_i = 0, _len = parameters.length; _i < _len; _i++) { + param = parameters[_i]; + if (!(_.isString(param))) { + throw "Expected string parameters, not " + param; + } + _ordering[param] = true; + } + return this; + }; + this.orderByDescending = function(...args) { + var param; + var parameters; + var _i; + var _len; + parameters = 1 <= args.length ? __slice.call(args, 0) : []; + _version++; + for (_i = 0, _len = parameters.length; _i < _len; _i++) { + param = parameters[_i]; + if (!(_.isString(param))) { + throw "Expected string parameters, not " + param; + } + _ordering[param] = false; + } + return this; + }; + this.skip = function(count) { + _version++; + if (!(_.isNumber(count))) { + throw "Expected a number, not " + count; + } + _skip = count; + return this; + }; + this.take = function(count) { + _version++; + if (!(_.isNumber(count))) { + throw "Expected a number, not " + count; + } + _take = count; + return this; + }; + + /* + * Indicate that the query should include the total count for all the + * records that would have been returned ignoring any take paging + * limit clause specified by client or server. + */ + this.includeTotalCount = function() { + _version++; + _includeTotalCount = true; + return this; + }; } - - /* Store the table name and any extra context */ - _table = table; - _context = context; - - /* Private Query component members */ - _filters = null; - _projection = null; - _selections = []; - _ordering = {}; - _skip = null; - _take = null; - _includeTotalCount = false; - + + /* - * Keep a version flag that's updated on each mutation so we can - * track whether changes have been made. This is to enable caching - * of compiled queries without reevaluating unless necessary. + * Static method to register custom provider types. A custom provider is + * an object with a toQuery method that takes a Query instance and + * returns a compiled query for that provider. */ - _version = 0; - - /* Get the individual components of the query */ - this.getComponents = function() { - return { - filters: _filters, - selections: _selections, - projection: _projection, - ordering: _ordering, - skip: _skip, - take: _take, - table: _table, - context: _context, - includeTotalCount: _includeTotalCount, - version: _version + + Query.registerProvider = (name, provider) => { + Query.Providers[name] = provider; + return Query.prototype["to" + name] = function() { + return provider != null ? typeof provider.toQuery === "function" ? provider.toQuery(this) : void 0 : void 0; }; }; - + + /* - * Set the individual components of the query (this is primarily - * meant to be used for rehydrating a query). + * Expose the registered providers via the Query.Providers namespace. */ - this.setComponents = function(components) { - var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; - _version++; - _filters = (_ref = components != null ? components.filters : void 0) != null ? _ref : null; - _selections = (_ref1 = components != null ? components.selections : void 0) != null ? _ref1 : []; - _projection = (_ref2 = components != null ? components.projection : void 0) != null ? _ref2 : null; - _ordering = (_ref3 = components != null ? components.ordering : void 0) != null ? _ref3 : {}; - _skip = (_ref4 = components != null ? components.skip : void 0) != null ? _ref4 : null; - _take = (_ref5 = components != null ? components.take : void 0) != null ? _ref5 : null; - _includeTotalCount = (_ref6 = components != null ? components.includeTotalCount : void 0) != null ? _ref6 : false; - _table = (_ref7 = components != null ? components.table : void 0) != null ? _ref7 : null; - _context = (_ref8 = components != null ? components.context : void 0) != null ? _ref8 : null; - return this; - }; - + + Query.Providers = {}; + + /* - * Add a constraint to a query. Constraints can take the form of - * a function with a single return statement, key/value pairs of - * equality comparisons, or provider-specific literal strings (note - * that not all providers support literals). + * Expose the query expressions and visitors externally via a + * Query.Expressions namespace. */ - this.where = function() { - var args, constraint, expr, name, value; - constraint = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; - _version++; - - /* - * Translate the constraint from its high level form into a - * QueryExpression tree that can be manipulated by a query - * provider - */ - expr = (function() { - if (_.isFunction(constraint)) { - return JavaScript.transformConstraint(constraint, args); - } else if (_.isObject(constraint)) { - - /* - * Turn an object of key value pairs into a series of - * equality expressions that are and'ed together to form - * a single expression - */ - return Q.QueryExpression.groupClauses(Q.BinaryOperators.And, (function() { - var _results; - _results = []; - for (name in constraint) { - value = constraint[name]; - _results.push(expr = new Q.BinaryExpression(Q.BinaryOperators.Equal, new Q.MemberExpression(name), new Q.ConstantExpression(value))); - } - return _results; - })()); - } else if (_.isString(constraint)) { - - /* - * Store the literal query along with any arguments for - * providers that support basic string replacement (i.e., - * something like where('name eq ?', 'Steve')) - */ - return new Q.LiteralExpression(constraint, args); - } else { - throw "Expected a function, object, or string, not " + constraint; - } - })(); - - /* Merge the new filters with any existing filters */ - _filters = Q.QueryExpression.groupClauses(Q.BinaryOperators.And, [_filters, expr]); - return this; - }; - - /* - * Project the query results. A projection can either be defined as - * a set of fields that we'll pull back (instead of the entire row) - * or a function that will transform a row into a new type. If a - * function is used, we'll analyze the function to pull back the - * minimal number of fields required. - */ - this.select = function() { - var param, parameters, projectionOrParameter, _i, _len; - projectionOrParameter = arguments[0], parameters = 2 <= arguments.length ? __slice.call(arguments, 1) : []; - _version++; - if (_.isString(projectionOrParameter)) { - - /* Add all the literal string parameters */ - _selections.push(projectionOrParameter); - for (_i = 0, _len = parameters.length; _i < _len; _i++) { - param = parameters[_i]; - if (!(_.isString(param))) { - throw "Expected string parameters, not " + param; - } - _selections.push(param); - } - } else if (_.isFunction(projectionOrParameter)) { - - /* Set the projection and calculate the fields it uses */ - _projection = projectionOrParameter; - _selections = JavaScript.getProjectedFields(_projection); - } else { - throw "Expected a string or a function, not " + projectionOrParameter; - } - return this; - }; - this.orderBy = function() { - var param, parameters, _i, _len; - parameters = 1 <= arguments.length ? __slice.call(arguments, 0) : []; - _version++; - for (_i = 0, _len = parameters.length; _i < _len; _i++) { - param = parameters[_i]; - if (!(_.isString(param))) { - throw "Expected string parameters, not " + param; - } - _ordering[param] = true; - } - return this; - }; - this.orderByDescending = function() { - var param, parameters, _i, _len; - parameters = 1 <= arguments.length ? __slice.call(arguments, 0) : []; - _version++; - for (_i = 0, _len = parameters.length; _i < _len; _i++) { - param = parameters[_i]; - if (!(_.isString(param))) { - throw "Expected string parameters, not " + param; - } - _ordering[param] = false; - } - return this; - }; - this.skip = function(count) { - _version++; - if (!(_.isNumber(count))) { - throw "Expected a number, not " + count; - } - _skip = count; - return this; - }; - this.take = function(count) { - _version++; - if (!(_.isNumber(count))) { - throw "Expected a number, not " + count; - } - _take = count; - return this; - }; - - /* - * Indicate that the query should include the total count for all the - * records that would have been returned ignoring any take paging - * limit clause specified by client or server. - */ - this.includeTotalCount = function() { - _version++; - _includeTotalCount = true; - return this; - }; - } - - - /* - * Static method to register custom provider types. A custom provider is - * an object with a toQuery method that takes a Query instance and - * returns a compiled query for that provider. - */ - - Query.registerProvider = function(name, provider) { - Query.Providers[name] = provider; - return Query.prototype["to" + name] = function() { - return provider != null ? typeof provider.toQuery === "function" ? provider.toQuery(this) : void 0 : void 0; - }; - }; - - - /* - * Expose the registered providers via the Query.Providers namespace. - */ - - Query.Providers = {}; - - - /* - * Expose the query expressions and visitors externally via a - * Query.Expressions namespace. - */ - - Query.Expressions = Q; - - return Query; - - })(); - - - /* Register the built in OData provider */ - - ODataProvider = require('./ODataProvider').ODataProvider; - - Query.registerProvider('OData', new ODataProvider); - - }).call(this); + + Query.Expressions = Q; + + return Query; + + }))(); + + + /* Register the built in OData provider */ + + ODataProvider = require('./ODataProvider').ODataProvider; + + Query.registerProvider('OData', new ODataProvider); + })).call(this); }; $__modules__.QueryNodes = function (exports) { @@ -2900,294 +3096,301 @@ /* Get the base Node class. */ - (function() { - var BinaryExpression, ConstantExpression, InvocationExpression, LiteralExpression, MemberExpression, Node, QueryExpression, QueryExpressionVisitor, UnaryExpression, Visitor, _ref, - __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - - _ref = require('./Node'), Node = _ref.Node, Visitor = _ref.Visitor; - - - /* - * Provides the base class from which the classes that represent expression tree - * nodes are derived. - */ - - exports.QueryExpression = QueryExpression = (function(_super) { - __extends(QueryExpression, _super); - - function QueryExpression() { - QueryExpression.__super__.constructor.call(this); - } - - + ((() => { + var BinaryExpression; + var ConstantExpression; + var InvocationExpression; + var LiteralExpression; + var MemberExpression; + var Node; + var QueryExpression; + var QueryExpressionVisitor; + var UnaryExpression; + var Visitor; + var _ref; + var __hasProp = {}.hasOwnProperty; + var __extends = (child, parent) => { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + _ref = require('./Node'), Node = _ref.Node, Visitor = _ref.Visitor; + + /* - * Group a sequence of clauses together with a given operator (like And - * or Or). + * Provides the base class from which the classes that represent expression tree + * nodes are derived. */ - - QueryExpression.groupClauses = function(operator, clauses) { - var combine; - combine = function(left, right) { - if (!left) { - return right; - } else if (!right) { - return left; - } else { - return new BinaryExpression(operator, left, right); - } + + exports.QueryExpression = QueryExpression = ((_super => { + __extends(QueryExpression, _super); + + function QueryExpression() { + QueryExpression.__super__.constructor.call(this); + } + + + /* + * Group a sequence of clauses together with a given operator (like And + * or Or). + */ + + QueryExpression.groupClauses = (operator, clauses) => { + var combine; + combine = (left, right) => { + if (!left) { + return right; + } else if (!right) { + return left; + } else { + return new BinaryExpression(operator, left, right); + } + }; + return clauses.reduce(combine, null); }; - return clauses.reduce(combine, null); + + return QueryExpression; + + }))(Node); + + exports.QueryExpressionVisitor = QueryExpressionVisitor = ((_super => { + __extends(QueryExpressionVisitor, _super); + + function QueryExpressionVisitor() { + QueryExpressionVisitor.__super__.constructor.call(this); + } + + QueryExpressionVisitor.prototype.QueryExpression = node => node; + + return QueryExpressionVisitor; + + }))(Visitor); + + + /* + * Represents an expression that has a constant value. + */ + + exports.ConstantExpression = ConstantExpression = ((_super => { + __extends(ConstantExpression, _super); + + + /* + * @value: The value of the constant expression. + */ + + function ConstantExpression(value) { + this.value = value; + ConstantExpression.__super__.constructor.call(this); + } + + return ConstantExpression; + + }))(QueryExpression); + + QueryExpressionVisitor.prototype.ConstantExpression = function(node) { + return this.QueryExpression(node); }; - - return QueryExpression; - - })(Node); - - exports.QueryExpressionVisitor = QueryExpressionVisitor = (function(_super) { - __extends(QueryExpressionVisitor, _super); - - function QueryExpressionVisitor() { - QueryExpressionVisitor.__super__.constructor.call(this); - } - - QueryExpressionVisitor.prototype.QueryExpression = function(node) { + + + /* + * Represents accessing a field. + */ + + exports.MemberExpression = MemberExpression = ((_super => { + __extends(MemberExpression, _super); + + + /* + * @member: Gets the field to be accessed. + */ + + function MemberExpression(member) { + this.member = member; + MemberExpression.__super__.constructor.call(this); + } + + return MemberExpression; + + }))(QueryExpression); + + QueryExpressionVisitor.prototype.MemberExpression = function(node) { + return this.QueryExpression(node); + }; + + + /* + * Represents an expression that has a binary operator. + */ + + exports.BinaryExpression = BinaryExpression = ((_super => { + __extends(BinaryExpression, _super); + + + /* + * @operator: The operator of the binary expression. + * @left: The left operand of the binary operation. + * @right: The right operand of the binary operation. + */ + + function BinaryExpression(operator, left, right) { + this.operator = operator; + this.left = left; + this.right = right; + BinaryExpression.__super__.constructor.call(this); + } + + return BinaryExpression; + + }))(QueryExpression); + + QueryExpressionVisitor.prototype.BinaryExpression = function(node) { + node = this.QueryExpression(node); + node.left = this.visit(node.left); + node.right = this.visit(node.right); return node; }; - - return QueryExpressionVisitor; - - })(Visitor); - - - /* - * Represents an expression that has a constant value. - */ - - exports.ConstantExpression = ConstantExpression = (function(_super) { - __extends(ConstantExpression, _super); - - + + /* - * @value: The value of the constant expression. + * Represents the known binary operators. */ - - function ConstantExpression(value) { - this.value = value; - ConstantExpression.__super__.constructor.call(this); - } - - return ConstantExpression; - - })(QueryExpression); - - QueryExpressionVisitor.prototype.ConstantExpression = function(node) { - return this.QueryExpression(node); - }; - - - /* - * Represents accessing a field. - */ - - exports.MemberExpression = MemberExpression = (function(_super) { - __extends(MemberExpression, _super); - - + + exports.BinaryOperators = { + And: 'And', + Or: 'Or', + Add: 'Add', + Subtract: 'Subtract', + Multiply: 'Multiply', + Divide: 'Divide', + Modulo: 'Modulo', + GreaterThan: 'GreaterThan', + GreaterThanOrEqual: 'GreaterThanOrEqual', + LessThan: 'LessThan', + LessThanOrEqual: 'LessThanOrEqual', + NotEqual: 'NotEqual', + Equal: 'Equal' + }; + + /* - * @member: Gets the field to be accessed. + * Represents the known unary operators. */ - - function MemberExpression(member) { - this.member = member; - MemberExpression.__super__.constructor.call(this); - } - - return MemberExpression; - - })(QueryExpression); - - QueryExpressionVisitor.prototype.MemberExpression = function(node) { - return this.QueryExpression(node); - }; - - - /* - * Represents an expression that has a binary operator. - */ - - exports.BinaryExpression = BinaryExpression = (function(_super) { - __extends(BinaryExpression, _super); - - + + exports.UnaryExpression = UnaryExpression = ((_super => { + __extends(UnaryExpression, _super); + + + /* + * @operator: The operator of the unary expression. + * @operand: The operand of the unary expression. + */ + + function UnaryExpression(operator, operand) { + this.operator = operator; + this.operand = operand; + UnaryExpression.__super__.constructor.call(this); + } + + return UnaryExpression; + + }))(QueryExpression); + + QueryExpressionVisitor.prototype.UnaryExpression = function(node) { + node = this.QueryExpression(node); + node.operand = this.visit(node.operand); + return node; + }; + + /* - * @operator: The operator of the binary expression. - * @left: The left operand of the binary operation. - * @right: The right operand of the binary operation. + * Represents the known unary operators. */ - - function BinaryExpression(operator, left, right) { - this.operator = operator; - this.left = left; - this.right = right; - BinaryExpression.__super__.constructor.call(this); - } - - return BinaryExpression; - - })(QueryExpression); - - QueryExpressionVisitor.prototype.BinaryExpression = function(node) { - node = this.QueryExpression(node); - node.left = this.visit(node.left); - node.right = this.visit(node.right); - return node; - }; - - - /* - * Represents the known binary operators. - */ - - exports.BinaryOperators = { - And: 'And', - Or: 'Or', - Add: 'Add', - Subtract: 'Subtract', - Multiply: 'Multiply', - Divide: 'Divide', - Modulo: 'Modulo', - GreaterThan: 'GreaterThan', - GreaterThanOrEqual: 'GreaterThanOrEqual', - LessThan: 'LessThan', - LessThanOrEqual: 'LessThanOrEqual', - NotEqual: 'NotEqual', - Equal: 'Equal' - }; - - - /* - * Represents the known unary operators. - */ - - exports.UnaryExpression = UnaryExpression = (function(_super) { - __extends(UnaryExpression, _super); - - + + exports.UnaryOperators = { + Not: 'Not', + Negate: 'Negate', + Increment: 'Increment', + Decrement: 'Decrement' + }; + + /* - * @operator: The operator of the unary expression. - * @operand: The operand of the unary expression. + * Represents a method invocation. */ - - function UnaryExpression(operator, operand) { - this.operator = operator; - this.operand = operand; - UnaryExpression.__super__.constructor.call(this); - } - - return UnaryExpression; - - })(QueryExpression); - - QueryExpressionVisitor.prototype.UnaryExpression = function(node) { - node = this.QueryExpression(node); - node.operand = this.visit(node.operand); - return node; - }; - - - /* - * Represents the known unary operators. - */ - - exports.UnaryOperators = { - Not: 'Not', - Negate: 'Negate', - Increment: 'Increment', - Decrement: 'Decrement' - }; - - - /* - * Represents a method invocation. - */ - - exports.InvocationExpression = InvocationExpression = (function(_super) { - __extends(InvocationExpression, _super); - - + + exports.InvocationExpression = InvocationExpression = ((_super => { + __extends(InvocationExpression, _super); + + + /* + * @method: The name of the method to invoke. + * @args: The arguments to the method. + */ + + function InvocationExpression(method, args) { + this.method = method; + this.args = args; + InvocationExpression.__super__.constructor.call(this); + } + + return InvocationExpression; + + }))(QueryExpression); + + QueryExpressionVisitor.prototype.InvocationExpression = function(node) { + node = this.QueryExpression(node); + node.args = this.visit(node.args); + return node; + }; + + /* - * @method: The name of the method to invoke. - * @args: The arguments to the method. + * Represents the known unary operators. */ - - function InvocationExpression(method, args) { - this.method = method; - this.args = args; - InvocationExpression.__super__.constructor.call(this); - } - - return InvocationExpression; - - })(QueryExpression); - - QueryExpressionVisitor.prototype.InvocationExpression = function(node) { - node = this.QueryExpression(node); - node.args = this.visit(node.args); - return node; - }; - - - /* - * Represents the known unary operators. - */ - - exports.Methods = { - Length: 'Length', - ToUpperCase: 'ToUpperCase', - ToLowerCase: 'ToLowerCase', - Trim: 'Trim', - IndexOf: 'IndexOf', - Replace: 'Replace', - Substring: 'Substring', - Concat: 'Concat', - Day: 'Day', - Month: 'Month', - Year: 'Year', - Floor: 'Floor', - Ceiling: 'Ceiling', - Round: 'Round' - }; - - - /* - * Represents a literal string in the query language. - */ - - exports.LiteralExpression = LiteralExpression = (function(_super) { - __extends(LiteralExpression, _super); - - + + exports.Methods = { + Length: 'Length', + ToUpperCase: 'ToUpperCase', + ToLowerCase: 'ToLowerCase', + Trim: 'Trim', + IndexOf: 'IndexOf', + Replace: 'Replace', + Substring: 'Substring', + Concat: 'Concat', + Day: 'Day', + Month: 'Month', + Year: 'Year', + Floor: 'Floor', + Ceiling: 'Ceiling', + Round: 'Round' + }; + + /* - * @queryString - * @args + * Represents a literal string in the query language. */ - - function LiteralExpression(queryString, args) { - this.queryString = queryString; - this.args = args != null ? args : []; - LiteralExpression.__super__.constructor.call(this); - } - - return LiteralExpression; - - })(QueryExpression); - - QueryExpressionVisitor.prototype.LiteralExpression = function(node) { - return this.QueryExpression(node); - }; - - }).call(this); + + exports.LiteralExpression = LiteralExpression = ((_super => { + __extends(LiteralExpression, _super); + + + /* + * @queryString + * @args + */ + + function LiteralExpression(queryString, args) { + this.queryString = queryString; + this.args = args != null ? args : []; + LiteralExpression.__super__.constructor.call(this); + } + + return LiteralExpression; + + }))(QueryExpression); + + QueryExpressionVisitor.prototype.LiteralExpression = function(node) { + return this.QueryExpression(node); + }; + })).call(this); }; $__modules__.Utilities = function (exports) { @@ -3199,121 +3402,117 @@ * ---------------------------------------------------------------------------- */ - (function() { - var classOf, - __slice = [].slice; - - classOf = function(obj) { - return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); - }; - - if (Array.prototype.reduce == null) { - Array.prototype.reduce = function() { - var accumulator, array, arrayLength, currentIndex, currentValue, moreArgs; - accumulator = arguments[0], moreArgs = 2 <= arguments.length ? __slice.call(arguments, 1) : []; - array = this; - arrayLength = array.length; - currentIndex = 0; - currentValue = void 0; - if (array == null) { - throw new TypeError("Object is null or undefined"); - } - if (typeof accumulator !== "function") { - throw new TypeError("First argument is not callable"); - } - if (moreArgs.length === 0) { - if (arrayLength === 0) { - throw new TypeError("Array length is 0 and no second argument"); - } else { - currentValue = array[0]; - currentIndex = 1; - } - } else { - currentValue = moreArgs[0]; - } - while (currentIndex < arrayLength) { - if (currentIndex in array) { - currentValue = accumulator.call(void 0, currentValue, array[currentIndex], array); - } - ++currentIndex; - } - return currentValue; - }; - } - - if (Array.prototype.map == null) { - Array.prototype.map = function(callback, thisArg) { - var elem, index, inputArray, len, outputArray, _i, _len; - if (typeof this === "undefined" || this === null) { - throw new TypeError("this is null or not defined"); - } - if (typeof callback !== "function") { - throw new TypeError(callback + " is not a function"); - } - thisArg = thisArg ? thisArg : void 0; - inputArray = Object(this); - len = inputArray.length >>> 0; - outputArray = new Array(len); - for (index = _i = 0, _len = inputArray.length; _i < _len; index = ++_i) { - elem = inputArray[index]; - if (index in inputArray) { - outputArray[index] = callback.call(thisArg, elem, index, inputArray); - } - } - return outputArray; - }; - } - - if (Array.isArray == null) { - Array.isArray = function(vArg) { - return Object.prototype.toString.call(vArg) === "[object Array]"; - }; - } - - exports.isObject = function(obj) { - return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() === 'object'; - }; - - exports.isString = function(obj) { - return typeof obj === 'string'; - }; - - exports.isFunction = function(obj) { - return typeof obj === 'function'; - }; - - exports.isArray = Array.isArray; - - exports.isNumber = function(obj) { - return typeof obj === 'number'; - }; - - exports.isBoolean = function(obj) { - return typeof obj === 'boolean'; - }; - - exports.isDate = function(obj) { - return classOf(obj) === 'date'; - }; - - exports.functionName = function(fn) { - var index, prefix, source; - if (typeof Function.prototype.name === 'function') { - return Function.prototype.name.call(fn); - } else { - source = fn.toString(); - prefix = 'function '; - if (source.slice(0, +(prefix.length - 1) + 1 || 9e9) === prefix) { - index = source.indexOf('(', prefix.length); - if (index > prefix.length) { - return source.slice(prefix.length, +(index - 1) + 1 || 9e9); - } - } - return null; + ((() => { + var classOf; + var __slice = [].slice; + + classOf = obj => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); + + if (Array.prototype.reduce == null) { + Array.prototype.reduce = function(...args) { + var accumulator; + var array; + var arrayLength; + var currentIndex; + var currentValue; + var moreArgs; + accumulator = args[0], moreArgs = 2 <= args.length ? __slice.call(args, 1) : []; + array = this; + arrayLength = array.length; + currentIndex = 0; + currentValue = void 0; + if (array == null) { + throw new TypeError("Object is null or undefined"); + } + if (typeof accumulator !== "function") { + throw new TypeError("First argument is not callable"); + } + if (moreArgs.length === 0) { + if (arrayLength === 0) { + throw new TypeError("Array length is 0 and no second argument"); + } else { + currentValue = array[0]; + currentIndex = 1; + } + } else { + currentValue = moreArgs[0]; + } + while (currentIndex < arrayLength) { + if (currentIndex in array) { + currentValue = accumulator.call(void 0, currentValue, array[currentIndex], array); + } + ++currentIndex; + } + return currentValue; + }; } - }; - - }).call(this); + + if (Array.prototype.map == null) { + Array.prototype.map = function(callback, thisArg) { + var elem; + var index; + var inputArray; + var len; + var outputArray; + var _i; + var _len; + if (typeof this === "undefined" || this === null) { + throw new TypeError("this is null or not defined"); + } + if (typeof callback !== "function") { + throw new TypeError(callback + " is not a function"); + } + thisArg = thisArg ? thisArg : void 0; + inputArray = Object(this); + len = inputArray.length >>> 0; + outputArray = new Array(len); + for (index = _i = 0, _len = inputArray.length; _i < _len; index = ++_i) { + elem = inputArray[index]; + if (index in inputArray) { + outputArray[index] = callback.call(thisArg, elem, index, inputArray); + } + } + return outputArray; + }; + } + + if (Array.isArray == null) { + Array.isArray = vArg => Object.prototype.toString.call(vArg) === "[object Array]"; + } + + exports.isObject = obj => Object.prototype.toString.call(obj).slice(8, -1).toLowerCase() === 'object'; + + exports.isString = obj => typeof obj === 'string'; + + exports.isFunction = obj => typeof obj === 'function'; + + exports.isArray = Array.isArray; + + exports.isNumber = obj => typeof obj === 'number'; + + exports.isBoolean = obj => typeof obj === 'boolean'; + + exports.isDate = obj => classOf(obj) === 'date'; + + exports.functionName = fn => { + var index; + var prefix; + var source; + if (typeof Function.prototype.name === 'function') { + return Function.prototype.name.call(fn); + } else { + source = fn.toString(); + prefix = 'function '; + if (source.slice(0, +(prefix.length - 1) + 1 || 9e9) === prefix) { + index = source.indexOf('(', prefix.length); + if (index > prefix.length) { + return source.slice(prefix.length, +(index - 1) + 1 || 9e9); + } + } + return null; + } + }; + })).call(this); }; $__modules__.esprima = function (exports) { @@ -3360,7 +3559,7 @@ parseUnaryExpression: true, parseStatement: true, parseSourceElement: true */ - (function (root, factory) { + (((root, factory) => { 'use strict'; // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, @@ -3372,28 +3571,28 @@ } else { factory((root.esprima = {})); } - }(this, function (exports) { + })(this, exports => { 'use strict'; - - var Token, - TokenName, - FnExprTokens, - Syntax, - PropertyKind, - Messages, - Regex, - SyntaxTreeDelegate, - source, - strict, - index, - lineNumber, - lineStart, - length, - delegate, - lookahead, - state, - extra; - + + var Token; + var TokenName; + var FnExprTokens; + var Syntax; + var PropertyKind; + var Messages; + var Regex; + var SyntaxTreeDelegate; + var source; + var strict; + var index; + var lineNumber; + var lineStart; + var length; + var delegate; + var lookahead; + var state; + var extra; + Token = { BooleanLiteral: 1, EOF: 2, @@ -3405,7 +3604,7 @@ StringLiteral: 8, RegularExpression: 9 }; - + TokenName = {}; TokenName[Token.BooleanLiteral] = 'Boolean'; TokenName[Token.EOF] = ''; @@ -3416,7 +3615,7 @@ TokenName[Token.Punctuator] = 'Punctuator'; TokenName[Token.StringLiteral] = 'String'; TokenName[Token.RegularExpression] = 'RegularExpression'; - + // A function following one of those tokens is an expression. FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new', 'return', 'case', 'delete', 'throw', 'void', @@ -3427,7 +3626,7 @@ '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&', '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=', '<=', '<', '>', '!=', '!==']; - + Syntax = { AssignmentExpression: 'AssignmentExpression', ArrayExpression: 'ArrayExpression', @@ -3470,13 +3669,13 @@ WhileStatement: 'WhileStatement', WithStatement: 'WithStatement' }; - + PropertyKind = { Data: 1, Get: 2, Set: 4 }; - + // Error messages should be identical to V8. Messages = { UnexpectedToken: 'Unexpected token %0', @@ -3513,39 +3712,39 @@ StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', StrictReservedWord: 'Use of future reserved word in strict mode' }; - + // See also tools/generate-unicode-regex.py. Regex = { NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') }; - + // Ensure the condition is true, otherwise throw an error. // This is only to have a better contract semantic, i.e. another safety net // to catch a logic error. The condition shall be fulfilled in normal case. // Do NOT use this to enforce a certain condition on any user input. - + function assert(condition, message) { if (!condition) { throw new Error('ASSERT: ' + message); } } - + function isDecimalDigit(ch) { return (ch >= 48 && ch <= 57); // 0..9 } - + function isHexDigit(ch) { return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; } - + function isOctalDigit(ch) { return '01234567'.indexOf(ch) >= 0; } - - + + // 7.2 White Space - + function isWhiteSpace(ch) { return (ch === 32) || // space (ch === 9) || // tab @@ -3554,15 +3753,15 @@ (ch === 0xA0) || (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0); } - + // 7.3 Line Terminators - + function isLineTerminator(ch) { return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029); } - + // 7.6 Identifier Names and Identifiers - + function isIdentifierStart(ch) { return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) (ch >= 65 && ch <= 90) || // A..Z @@ -3570,7 +3769,7 @@ (ch === 92) || // \ (backslash) ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); } - + function isIdentifierPart(ch) { return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) (ch >= 65 && ch <= 90) || // A..Z @@ -3579,9 +3778,9 @@ (ch === 92) || // \ (backslash) ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); } - + // 7.6.1.2 Future Reserved Words - + function isFutureReservedWord(id) { switch (id) { case 'class': @@ -3595,7 +3794,7 @@ return false; } } - + function isStrictModeReservedWord(id) { switch (id) { case 'implements': @@ -3612,13 +3811,13 @@ return false; } } - + function isRestrictedWord(id) { return id === 'eval' || id === 'arguments'; } - + // 7.6.1.1 Keywords - + function isKeyword(id) { if (strict && isStrictModeReservedWord(id)) { return true; @@ -3654,9 +3853,9 @@ return false; } } - + // 7.4 Comments - + function addComment(type, value, start, end, loc) { var comment; @@ -3672,8 +3871,8 @@ state.lastCommentStart = start; comment = { - type: type, - value: value + type, + value }; if (extra.range) { comment.range = [start, end]; @@ -3683,10 +3882,13 @@ } extra.comments.push(comment); } - + function skipSingleLineComment() { - var start, loc, ch, comment; - + var start; + var loc; + var ch; + var comment; + start = index - 2; loc = { start: { @@ -3694,7 +3896,7 @@ column: index - lineStart - 2 } }; - + while (index < length) { ch = source.charCodeAt(index); ++index; @@ -3715,7 +3917,7 @@ return; } } - + if (extra.comments) { comment = source.slice(start + 2, index); loc.end = { @@ -3725,10 +3927,13 @@ addComment('Line', comment, start, index, loc); } } - + function skipMultiLineComment() { - var start, loc, ch, comment; - + var start; + var loc; + var ch; + var comment; + if (extra.comments) { start = index - 2; loc = { @@ -3738,7 +3943,7 @@ } }; } - + while (index < length) { ch = source.charCodeAt(index); if (isLineTerminator(ch)) { @@ -3771,10 +3976,10 @@ ++index; } } - + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); } - + function skipComment() { var ch; @@ -3808,10 +4013,13 @@ } } } - + function scanHexEscape(prefix) { - var i, len, ch, code = 0; - + var i; + var len; + var ch; + var code = 0; + len = (prefix === 'u') ? 4 : 2; for (i = 0; i < len; ++i) { if (index < length && isHexDigit(source[index])) { @@ -3823,13 +4031,14 @@ } return String.fromCharCode(code); } - + function getEscapedIdentifier() { - var ch, id; - + var ch; + var id; + ch = source.charCodeAt(index++); id = String.fromCharCode(ch); - + // '\u' (char #92, char #117) denotes an escaped character. if (ch === 92) { if (source.charCodeAt(index) !== 117) { @@ -3842,7 +4051,7 @@ } id = ch; } - + while (index < length) { ch = source.charCodeAt(index); if (!isIdentifierPart(ch)) { @@ -3865,13 +4074,14 @@ id += ch; } } - + return id; } - + function getIdentifier() { - var start, ch; - + var start; + var ch; + start = index++; while (index < length) { ch = source.charCodeAt(index); @@ -3886,18 +4096,20 @@ break; } } - + return source.slice(start, index); } - + function scanIdentifier() { - var start, id, type; - + var start; + var id; + var type; + start = index; - + // Backslash (char #92) starts an escaped character. id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier(); - + // There is no keyword or literal with only one character. // Thus, it must be an identifier. if (id.length === 1) { @@ -3911,28 +4123,28 @@ } else { type = Token.Identifier; } - + return { - type: type, + type, value: id, - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - - + + // 7.7 Punctuators - + function scanPunctuator() { - var start = index, - code = source.charCodeAt(index), - code2, - ch1 = source[index], - ch2, - ch3, - ch4; - + var start = index; + var code = source.charCodeAt(index); + var code2; + var ch1 = source[index]; + var ch2; + var ch3; + var ch4; + switch (code) { // Check for most common single-character punctuators. @@ -3959,8 +4171,8 @@ return { type: Token.Punctuator, value: String.fromCharCode(code), - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; @@ -3984,8 +4196,8 @@ return { type: Token.Punctuator, value: String.fromCharCode(code) + String.fromCharCode(code2), - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; @@ -4000,8 +4212,8 @@ return { type: Token.Punctuator, value: source.slice(start, index), - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; default: @@ -4010,92 +4222,92 @@ } break; } - + // Peek more characters. - + ch2 = source[index + 1]; ch3 = source[index + 2]; ch4 = source[index + 3]; - + // 4-character punctuator: >>>= - + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { if (ch4 === '=') { index += 4; return { type: Token.Punctuator, value: '>>>=', - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } } - + // 3-character punctuators: === !== >>> <<= >>= - + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { index += 3; return { type: Token.Punctuator, value: '>>>', - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + if (ch1 === '<' && ch2 === '<' && ch3 === '=') { index += 3; return { type: Token.Punctuator, value: '<<=', - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + if (ch1 === '>' && ch2 === '>' && ch3 === '=') { index += 3; return { type: Token.Punctuator, value: '>>=', - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + // Other 2-character punctuators: ++ -- << >> && || - + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { index += 2; return { type: Token.Punctuator, value: ch1 + ch2, - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { ++index; return { type: Token.Punctuator, value: ch1, - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); } - + // 7.8.3 Numeric Literals - + function scanHexLiteral(start) { var number = ''; @@ -4117,12 +4329,12 @@ return { type: Token.NumericLiteral, value: parseInt('0x' + number, 16), - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + function scanOctalLiteral(start) { var number = '0' + source[index++]; while (index < length) { @@ -4140,19 +4352,21 @@ type: Token.NumericLiteral, value: parseInt(number, 8), octal: true, - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + function scanNumericLiteral() { - var number, start, ch; - + var number; + var start; + var ch; + ch = source[index]; assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), 'Numeric literal must start with a decimal digit or a decimal point'); - + start = index; number = ''; if (ch !== '.') { @@ -4181,7 +4395,7 @@ } ch = source[index]; } - + if (ch === '.') { number += source[index++]; while (isDecimalDigit(source.charCodeAt(index))) { @@ -4189,7 +4403,7 @@ } ch = source[index]; } - + if (ch === 'e' || ch === 'E') { number += source[index++]; @@ -4205,32 +4419,39 @@ throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); } } - + if (isIdentifierStart(source.charCodeAt(index))) { throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); } - + return { type: Token.NumericLiteral, value: parseFloat(number), - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [start, index] }; } - + // 7.8.4 String Literals - + function scanStringLiteral() { - var str = '', quote, start, ch, code, unescaped, restore, octal = false; - + var str = ''; + var quote; + var start; + var ch; + var code; + var unescaped; + var restore; + var octal = false; + quote = source[index]; assert((quote === '\'' || quote === '"'), 'String literal must starts with a quote'); - + start = index; ++index; - + while (index < length) { ch = source[index++]; @@ -4310,32 +4531,40 @@ str += ch; } } - + if (quote !== '') { throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); } - + return { type: Token.StringLiteral, value: str, - octal: octal, - lineNumber: lineNumber, - lineStart: lineStart, + octal, + lineNumber, + lineStart, range: [start, index] }; } - + function scanRegExp() { - var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; - + var str; + var ch; + var start; + var pattern; + var flags; + var value; + var classMarker = false; + var restore; + var terminated = false; + lookahead = null; skipComment(); - + start = index; ch = source[index]; assert(ch === '/', 'Regular expression literal must start with a slash'); str = source[index++]; - + while (index < length) { ch = source[index++]; str += ch; @@ -4361,14 +4590,14 @@ } } } - + if (!terminated) { throwError({}, Messages.UnterminatedRegExp); } - + // Exclude leading and trailing slash. pattern = str.substr(1, str.length - 2); - + flags = ''; while (index < length) { ch = source[index]; @@ -4401,42 +4630,42 @@ str += ch; } } - + try { value = new RegExp(pattern, flags); } catch (e) { throwError({}, Messages.InvalidRegExp); } - + peek(); - - + + if (extra.tokenize) { return { type: Token.RegularExpression, - value: value, - lineNumber: lineNumber, - lineStart: lineStart, + value, + lineNumber, + lineStart, range: [start, index] }; } return { literal: str, - value: value, + value, range: [start, index] }; } - + function isIdentifierName(token) { return token.type === Token.Identifier || token.type === Token.Keyword || token.type === Token.BooleanLiteral || token.type === Token.NullLiteral; } - + function advanceSlash() { - var prevToken, - checkToken; + var prevToken; + var checkToken; // Using the following algorithm: // https://github.com/mozilla/sweet.js/wiki/design prevToken = extra.tokens[extra.tokens.length - 1]; @@ -4493,7 +4722,7 @@ } return scanPunctuator(); } - + function advance() { var ch; @@ -4502,8 +4731,8 @@ if (index >= length) { return { type: Token.EOF, - lineNumber: lineNumber, - lineStart: lineStart, + lineNumber, + lineStart, range: [index, index] }; } @@ -4544,7 +4773,7 @@ return scanPunctuator(); } - + function lex() { var token; @@ -4561,10 +4790,12 @@ return token; } - + function peek() { - var pos, line, start; - + var pos; + var line; + var start; + pos = index; line = lineNumber; start = lineStart; @@ -4573,12 +4804,12 @@ lineNumber = line; lineStart = start; } - + SyntaxTreeDelegate = { name: 'SyntaxTree', - markStart: function () { + markStart() { if (extra.loc) { state.markerStack.push(index - lineStart); state.markerStack.push(lineNumber); @@ -4588,7 +4819,7 @@ } }, - markEnd: function (node) { + markEnd(node) { if (extra.range) { node.range = [state.markerStack.pop(), index]; } @@ -4608,7 +4839,7 @@ return node; }, - markEndIf: function (node) { + markEndIf(node) { if (node.range || node.loc) { if (extra.loc) { state.markerStack.pop(); @@ -4623,184 +4854,184 @@ return node; }, - postProcess: function (node) { + postProcess(node) { if (extra.source) { node.loc.source = extra.source; } return node; }, - createArrayExpression: function (elements) { + createArrayExpression(elements) { return { type: Syntax.ArrayExpression, - elements: elements + elements }; }, - createAssignmentExpression: function (operator, left, right) { + createAssignmentExpression(operator, left, right) { return { type: Syntax.AssignmentExpression, - operator: operator, - left: left, - right: right + operator, + left, + right }; }, - createBinaryExpression: function (operator, left, right) { + createBinaryExpression(operator, left, right) { var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression; return { - type: type, - operator: operator, - left: left, - right: right + type, + operator, + left, + right }; }, - createBlockStatement: function (body) { + createBlockStatement(body) { return { type: Syntax.BlockStatement, - body: body + body }; }, - createBreakStatement: function (label) { + createBreakStatement(label) { return { type: Syntax.BreakStatement, - label: label + label }; }, - createCallExpression: function (callee, args) { + createCallExpression(callee, args) { return { type: Syntax.CallExpression, - callee: callee, + callee, 'arguments': args }; }, - createCatchClause: function (param, body) { + createCatchClause(param, body) { return { type: Syntax.CatchClause, - param: param, - body: body + param, + body }; }, - createConditionalExpression: function (test, consequent, alternate) { + createConditionalExpression(test, consequent, alternate) { return { type: Syntax.ConditionalExpression, - test: test, - consequent: consequent, - alternate: alternate + test, + consequent, + alternate }; }, - createContinueStatement: function (label) { + createContinueStatement(label) { return { type: Syntax.ContinueStatement, - label: label + label }; }, - createDebuggerStatement: function () { + createDebuggerStatement() { return { type: Syntax.DebuggerStatement }; }, - createDoWhileStatement: function (body, test) { + createDoWhileStatement(body, test) { return { type: Syntax.DoWhileStatement, - body: body, - test: test + body, + test }; }, - createEmptyStatement: function () { + createEmptyStatement() { return { type: Syntax.EmptyStatement }; }, - createExpressionStatement: function (expression) { + createExpressionStatement(expression) { return { type: Syntax.ExpressionStatement, - expression: expression + expression }; }, - createForStatement: function (init, test, update, body) { + createForStatement(init, test, update, body) { return { type: Syntax.ForStatement, - init: init, - test: test, - update: update, - body: body + init, + test, + update, + body }; }, - createForInStatement: function (left, right, body) { + createForInStatement(left, right, body) { return { type: Syntax.ForInStatement, - left: left, - right: right, - body: body, + left, + right, + body, each: false }; }, - createFunctionDeclaration: function (id, params, defaults, body) { + createFunctionDeclaration(id, params, defaults, body) { return { type: Syntax.FunctionDeclaration, - id: id, - params: params, - defaults: defaults, - body: body, + id, + params, + defaults, + body, rest: null, generator: false, expression: false }; }, - createFunctionExpression: function (id, params, defaults, body) { + createFunctionExpression(id, params, defaults, body) { return { type: Syntax.FunctionExpression, - id: id, - params: params, - defaults: defaults, - body: body, + id, + params, + defaults, + body, rest: null, generator: false, expression: false }; }, - createIdentifier: function (name) { + createIdentifier(name) { return { type: Syntax.Identifier, - name: name + name }; }, - createIfStatement: function (test, consequent, alternate) { + createIfStatement(test, consequent, alternate) { return { type: Syntax.IfStatement, - test: test, - consequent: consequent, - alternate: alternate + test, + consequent, + alternate }; }, - createLabeledStatement: function (label, body) { + createLabeledStatement(label, body) { return { type: Syntax.LabeledStatement, - label: label, - body: body + label, + body }; }, - createLiteral: function (token) { + createLiteral(token) { return { type: Syntax.Literal, value: token.value, @@ -4808,163 +5039,166 @@ }; }, - createMemberExpression: function (accessor, object, property) { + createMemberExpression(accessor, object, property) { return { type: Syntax.MemberExpression, computed: accessor === '[', - object: object, - property: property + object, + property }; }, - createNewExpression: function (callee, args) { + createNewExpression(callee, args) { return { type: Syntax.NewExpression, - callee: callee, + callee, 'arguments': args }; }, - createObjectExpression: function (properties) { + createObjectExpression(properties) { return { type: Syntax.ObjectExpression, - properties: properties + properties }; }, - createPostfixExpression: function (operator, argument) { + createPostfixExpression(operator, argument) { return { type: Syntax.UpdateExpression, - operator: operator, - argument: argument, + operator, + argument, prefix: false }; }, - createProgram: function (body) { + createProgram(body) { return { type: Syntax.Program, - body: body + body }; }, - createProperty: function (kind, key, value) { + createProperty(kind, key, value) { return { type: Syntax.Property, - key: key, - value: value, - kind: kind + key, + value, + kind }; }, - createReturnStatement: function (argument) { + createReturnStatement(argument) { return { type: Syntax.ReturnStatement, - argument: argument + argument }; }, - createSequenceExpression: function (expressions) { + createSequenceExpression(expressions) { return { type: Syntax.SequenceExpression, - expressions: expressions + expressions }; }, - createSwitchCase: function (test, consequent) { + createSwitchCase(test, consequent) { return { type: Syntax.SwitchCase, - test: test, - consequent: consequent + test, + consequent }; }, - createSwitchStatement: function (discriminant, cases) { + createSwitchStatement(discriminant, cases) { return { type: Syntax.SwitchStatement, - discriminant: discriminant, - cases: cases + discriminant, + cases }; }, - createThisExpression: function () { + createThisExpression() { return { type: Syntax.ThisExpression }; }, - createThrowStatement: function (argument) { + createThrowStatement(argument) { return { type: Syntax.ThrowStatement, - argument: argument + argument }; }, - createTryStatement: function (block, guardedHandlers, handlers, finalizer) { + createTryStatement(block, guardedHandlers, handlers, finalizer) { return { type: Syntax.TryStatement, - block: block, - guardedHandlers: guardedHandlers, - handlers: handlers, - finalizer: finalizer + block, + guardedHandlers, + handlers, + finalizer }; }, - createUnaryExpression: function (operator, argument) { + createUnaryExpression(operator, argument) { if (operator === '++' || operator === '--') { return { type: Syntax.UpdateExpression, - operator: operator, - argument: argument, + operator, + argument, prefix: true }; } return { type: Syntax.UnaryExpression, - operator: operator, - argument: argument, + operator, + argument, prefix: true }; }, - createVariableDeclaration: function (declarations, kind) { + createVariableDeclaration(declarations, kind) { return { type: Syntax.VariableDeclaration, - declarations: declarations, - kind: kind + declarations, + kind }; }, - createVariableDeclarator: function (id, init) { + createVariableDeclarator(id, init) { return { type: Syntax.VariableDeclarator, - id: id, - init: init + id, + init }; }, - createWhileStatement: function (test, body) { + createWhileStatement(test, body) { return { type: Syntax.WhileStatement, - test: test, - body: body + test, + body }; }, - createWithStatement: function (object, body) { + createWithStatement(object, body) { return { type: Syntax.WithStatement, - object: object, - body: body + object, + body }; } }; - + // Return true if there is a line terminator before the next token. - + function peekLineTerminator() { - var pos, line, start, found; - + var pos; + var line; + var start; + var found; + pos = index; line = lineNumber; start = lineStart; @@ -4973,23 +5207,24 @@ index = pos; lineNumber = line; lineStart = start; - + return found; } - + // Throw an exception - + function throwError(token, messageFormat) { - var error, - args = Array.prototype.slice.call(arguments, 2), - msg = messageFormat.replace( - /%(\d)/g, - function (whole, index) { - assert(index < args.length, 'Message reference must be in range'); - return args[index]; - } - ); - + var error; + var args = Array.prototype.slice.call(arguments, 2); + + var msg = messageFormat.replace( + /%(\d)/g, + (whole, index) => { + assert(index < args.length, 'Message reference must be in range'); + return args[index]; + } + ); + if (typeof token.lineNumber === 'number') { error = new Error('Line ' + token.lineNumber + ': ' + msg); error.index = token.range[0]; @@ -5001,14 +5236,14 @@ error.lineNumber = lineNumber; error.column = index - lineStart + 1; } - + error.description = msg; throw error; } - - function throwErrorTolerant() { + + function throwErrorTolerant(...args) { try { - throwError.apply(null, arguments); + throwError(...args); } catch (e) { if (extra.errors) { extra.errors.push(e); @@ -5017,10 +5252,10 @@ } } } - - + + // Throw an exception because of the token. - + function throwUnexpected(token) { if (token.type === Token.EOF) { throwError(token, Messages.UnexpectedEOS); @@ -5051,41 +5286,41 @@ // BooleanLiteral, NullLiteral, or Punctuator. throwError(token, Messages.UnexpectedToken, token.value); } - + // Expect the next token to match the specified punctuator. // If not, an exception will be thrown. - + function expect(value) { var token = lex(); if (token.type !== Token.Punctuator || token.value !== value) { throwUnexpected(token); } } - + // Expect the next token to match the specified keyword. // If not, an exception will be thrown. - + function expectKeyword(keyword) { var token = lex(); if (token.type !== Token.Keyword || token.value !== keyword) { throwUnexpected(token); } } - + // Return true if the next token matches the specified punctuator. - + function match(value) { return lookahead.type === Token.Punctuator && lookahead.value === value; } - + // Return true if the next token matches the specified keyword - + function matchKeyword(keyword) { return lookahead.type === Token.Keyword && lookahead.value === keyword; } - + // Return true if the next token is an assignment operator - + function matchAssign() { var op; @@ -5106,7 +5341,7 @@ op === '^=' || op === '|='; } - + function consumeSemicolon() { var line; @@ -5131,15 +5366,15 @@ throwUnexpected(lookahead); } } - + // Return true if provided expression is LeftHandSideExpression - + function isLeftHandSide(expr) { return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; } - + // 11.1.4 Array Initialiser - + function parseArrayInitialiser() { var elements = []; @@ -5162,12 +5397,13 @@ return delegate.createArrayExpression(elements); } - + // 11.1.5 Object Initialiser - + function parsePropertyFunction(param, first) { - var previousStrict, body; - + var previousStrict; + var body; + previousStrict = strict; skipComment(); delegate.markStart(); @@ -5178,7 +5414,7 @@ strict = previousStrict; return delegate.markEnd(delegate.createFunctionExpression(null, param, [], body)); } - + function parseObjectPropertyKey() { var token; @@ -5198,14 +5434,18 @@ return delegate.markEnd(delegate.createIdentifier(token.value)); } - + function parseObjectProperty() { - var token, key, id, value, param; - + var token; + var key; + var id; + var value; + var param; + token = lookahead; skipComment(); delegate.markStart(); - + if (token.type === Token.Identifier) { id = parseObjectPropertyKey(); @@ -5247,12 +5487,18 @@ return delegate.markEnd(delegate.createProperty('init', key, value)); } } - + function parseObjectInitialiser() { - var properties = [], property, name, key, kind, map = {}, toString = String; - + var properties = []; + var property; + var name; + var key; + var kind; + var map = {}; + var toString = String; + expect('{'); - + while (!match('}')) { property = parseObjectProperty(); @@ -5289,14 +5535,14 @@ expect(','); } } - + expect('}'); - + return delegate.createObjectExpression(properties); } - + // 11.1.6 The Grouping Operator - + function parseGroupExpression() { var expr; @@ -5308,20 +5554,22 @@ return expr; } - - + + // 11.1 Primary Expressions - + function parsePrimaryExpression() { - var type, token, expr; - + var type; + var token; + var expr; + if (match('(')) { return parseGroupExpression(); } - + type = lookahead.type; delegate.markStart(); - + if (type === Token.Identifier) { expr = delegate.createIdentifier(lex().value); } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { @@ -5351,16 +5599,16 @@ } else if (match('/') || match('/=')) { expr = delegate.createLiteral(scanRegExp()); } - + if (expr) { return delegate.markEnd(expr); } - + throwUnexpected(lex()); } - + // 11.2 Left-Hand-Side Expressions - + function parseArguments() { var args = []; @@ -5380,7 +5628,7 @@ return args; } - + function parseNonComputedProperty() { var token; @@ -5393,13 +5641,13 @@ return delegate.markEnd(delegate.createIdentifier(token.value)); } - + function parseNonComputedMember() { expect('.'); return parseNonComputedProperty(); } - + function parseComputedMember() { var expr; @@ -5411,25 +5659,29 @@ return expr; } - + function parseNewExpression() { - var callee, args; - + var callee; + var args; + delegate.markStart(); expectKeyword('new'); callee = parseLeftHandSideExpression(); args = match('(') ? parseArguments() : []; - + return delegate.markEnd(delegate.createNewExpression(callee, args)); } - + function parseLeftHandSideExpressionAllowCall() { - var marker, expr, args, property; - + var marker; + var expr; + var args; + var property; + marker = createLocationMarker(); - + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); - + while (match('.') || match('[') || match('(')) { if (match('(')) { args = parseArguments(); @@ -5446,17 +5698,19 @@ marker.apply(expr); } } - + return expr; } - + function parseLeftHandSideExpression() { - var marker, expr, property; - + var marker; + var expr; + var property; + marker = createLocationMarker(); - + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); - + while (match('.') || match('[')) { if (match('[')) { property = parseComputedMember(); @@ -5470,18 +5724,19 @@ marker.apply(expr); } } - + return expr; } - + // 11.3 Postfix Expressions - + function parsePostfixExpression() { - var expr, token; - + var expr; + var token; + delegate.markStart(); expr = parseLeftHandSideExpressionAllowCall(); - + if (lookahead.type === Token.Punctuator) { if ((match('++') || match('--')) && !peekLineTerminator()) { // 11.3.1, 11.3.2 @@ -5497,17 +5752,18 @@ expr = delegate.createPostfixExpression(token.value, expr); } } - + return delegate.markEndIf(expr); } - + // 11.4 Unary Operators - + function parseUnaryExpression() { - var token, expr; - + var token; + var expr; + delegate.markStart(); - + if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { expr = parsePostfixExpression(); } else if (match('++') || match('--')) { @@ -5537,10 +5793,10 @@ } else { expr = parsePostfixExpression(); } - + return delegate.markEndIf(expr); } - + function binaryPrecedence(token, allowIn) { var prec = 0; @@ -5611,7 +5867,7 @@ return prec; } - + // 11.5 Multiplicative Operators // 11.6 Additive Operators // 11.7 Bitwise Shift Operators @@ -5619,16 +5875,26 @@ // 11.9 Equality Operators // 11.10 Binary Bitwise Operators // 11.11 Binary Logical Operators - + function parseBinaryExpression() { - var marker, markers, expr, token, prec, previousAllowIn, stack, right, operator, left, i; - + var marker; + var markers; + var expr; + var token; + var prec; + var previousAllowIn; + var stack; + var right; + var operator; + var left; + var i; + previousAllowIn = state.allowIn; state.allowIn = true; - + marker = createLocationMarker(); left = parseUnaryExpression(); - + token = lookahead; prec = binaryPrecedence(token, previousAllowIn); if (prec === 0) { @@ -5636,12 +5902,12 @@ } token.prec = prec; lex(); - + markers = [marker, createLocationMarker()]; right = parseUnaryExpression(); - + stack = [left, token, right]; - + while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) { // Reduce: make a binary expression from the three topmost entries. @@ -5668,9 +5934,9 @@ expr = parseUnaryExpression(); stack.push(expr); } - + state.allowIn = previousAllowIn; - + // Final reduce to clean-up the stack. i = stack.length - 1; expr = stack[i]; @@ -5684,19 +5950,22 @@ marker.apply(expr); } } - + return expr; } - - + + // 11.12 Conditional Operator - + function parseConditionalExpression() { - var expr, previousAllowIn, consequent, alternate; - + var expr; + var previousAllowIn; + var consequent; + var alternate; + delegate.markStart(); expr = parseBinaryExpression(); - + if (match('?')) { lex(); previousAllowIn = state.allowIn; @@ -5710,19 +5979,22 @@ } else { delegate.markEnd({}); } - + return expr; } - + // 11.13 Assignment Operators - + function parseAssignmentExpression() { - var token, left, right, node; - + var token; + var left; + var right; + var node; + token = lookahead; delegate.markStart(); node = left = parseConditionalExpression(); - + if (matchAssign()) { // LeftHandSideExpression if (!isLeftHandSide(left)) { @@ -5738,12 +6010,12 @@ right = parseAssignmentExpression(); node = delegate.createAssignmentExpression(token.value, left, right); } - + return delegate.markEndIf(node); } - + // 11.14 Comma Operator - + function parseExpression() { var expr; @@ -5764,13 +6036,13 @@ return delegate.markEndIf(expr); } - + // 12.1 Block - + function parseStatementList() { - var list = [], - statement; - + var list = []; + var statement; + while (index < length) { if (match('}')) { break; @@ -5781,10 +6053,10 @@ } list.push(statement); } - + return list; } - + function parseBlock() { var block; @@ -5798,9 +6070,9 @@ return delegate.markEnd(delegate.createBlockStatement(block)); } - + // 12.2 Variable Statement - + function parseVariableIdentifier() { var token; @@ -5814,19 +6086,20 @@ return delegate.markEnd(delegate.createIdentifier(token.value)); } - + function parseVariableDeclaration(kind) { - var init = null, id; - + var init = null; + var id; + skipComment(); delegate.markStart(); id = parseVariableIdentifier(); - + // 12.2.1 if (strict && isRestrictedWord(id.name)) { throwErrorTolerant({}, Messages.StrictVarName); } - + if (kind === 'const') { expect('='); init = parseAssignmentExpression(); @@ -5834,10 +6107,10 @@ lex(); init = parseAssignmentExpression(); } - + return delegate.markEnd(delegate.createVariableDeclarator(id, init)); } - + function parseVariableDeclarationList(kind) { var list = []; @@ -5851,7 +6124,7 @@ return list; } - + function parseVariableStatement() { var declarations; @@ -5863,7 +6136,7 @@ return delegate.createVariableDeclaration(declarations, 'var'); } - + // kind may be `const` or `let` // Both are experimental and not in the specification yet. // see http://wiki.ecmascript.org/doku.php?id=harmony:const @@ -5882,116 +6155,129 @@ return delegate.markEnd(delegate.createVariableDeclaration(declarations, kind)); } - + // 12.3 Empty Statement - + function parseEmptyStatement() { expect(';'); return delegate.createEmptyStatement(); } - + // 12.4 Expression Statement - + function parseExpressionStatement() { var expr = parseExpression(); consumeSemicolon(); return delegate.createExpressionStatement(expr); } - + // 12.5 If statement - + function parseIfStatement() { - var test, consequent, alternate; - + var test; + var consequent; + var alternate; + expectKeyword('if'); - + expect('('); - + test = parseExpression(); - + expect(')'); - + consequent = parseStatement(); - + if (matchKeyword('else')) { lex(); alternate = parseStatement(); } else { alternate = null; } - + return delegate.createIfStatement(test, consequent, alternate); } - + // 12.6 Iteration Statements - + function parseDoWhileStatement() { - var body, test, oldInIteration; - + var body; + var test; + var oldInIteration; + expectKeyword('do'); - + oldInIteration = state.inIteration; state.inIteration = true; - + body = parseStatement(); - + state.inIteration = oldInIteration; - + expectKeyword('while'); - + expect('('); - + test = parseExpression(); - + expect(')'); - + if (match(';')) { lex(); } - + return delegate.createDoWhileStatement(body, test); } - + function parseWhileStatement() { - var test, body, oldInIteration; - + var test; + var body; + var oldInIteration; + expectKeyword('while'); - + expect('('); - + test = parseExpression(); - + expect(')'); - + oldInIteration = state.inIteration; state.inIteration = true; - + body = parseStatement(); - + state.inIteration = oldInIteration; - + return delegate.createWhileStatement(test, body); } - + function parseForVariableDeclaration() { - var token, declarations; - + var token; + var declarations; + delegate.markStart(); token = lex(); declarations = parseVariableDeclarationList(); - + return delegate.markEnd(delegate.createVariableDeclaration(declarations, token.value)); } - + function parseForStatement() { - var init, test, update, left, right, body, oldInIteration; - + var init; + var test; + var update; + var left; + var right; + var body; + var oldInIteration; + init = test = update = null; - + expectKeyword('for'); - + expect('('); - + if (match(';')) { lex(); } else { @@ -6028,7 +6314,7 @@ expect(';'); } } - + if (typeof left === 'undefined') { if (!match(';')) { @@ -6040,28 +6326,29 @@ update = parseExpression(); } } - + expect(')'); - + oldInIteration = state.inIteration; state.inIteration = true; - + body = parseStatement(); - + state.inIteration = oldInIteration; - + return (typeof left === 'undefined') ? delegate.createForStatement(init, test, update, body) : delegate.createForInStatement(left, right, body); } - + // 12.7 The continue statement - + function parseContinueStatement() { - var label = null, key; - + var label = null; + var key; + expectKeyword('continue'); - + // Optimize the most common form: 'continue;'. if (source.charCodeAt(index) === 59) { lex(); @@ -6072,7 +6359,7 @@ return delegate.createContinueStatement(null); } - + if (peekLineTerminator()) { if (!state.inIteration) { throwError({}, Messages.IllegalContinue); @@ -6080,7 +6367,7 @@ return delegate.createContinueStatement(null); } - + if (lookahead.type === Token.Identifier) { label = parseVariableIdentifier(); @@ -6089,23 +6376,24 @@ throwError({}, Messages.UnknownLabel, label.name); } } - + consumeSemicolon(); - + if (label === null && !state.inIteration) { throwError({}, Messages.IllegalContinue); } - + return delegate.createContinueStatement(label); } - + // 12.8 The break statement - + function parseBreakStatement() { - var label = null, key; - + var label = null; + var key; + expectKeyword('break'); - + // Catch the very common case first: immediately a semicolon (char #59). if (source.charCodeAt(index) === 59) { lex(); @@ -6116,7 +6404,7 @@ return delegate.createBreakStatement(null); } - + if (peekLineTerminator()) { if (!(state.inIteration || state.inSwitch)) { throwError({}, Messages.IllegalBreak); @@ -6124,7 +6412,7 @@ return delegate.createBreakStatement(null); } - + if (lookahead.type === Token.Identifier) { label = parseVariableIdentifier(); @@ -6133,18 +6421,18 @@ throwError({}, Messages.UnknownLabel, label.name); } } - + consumeSemicolon(); - + if (label === null && !(state.inIteration || state.inSwitch)) { throwError({}, Messages.IllegalBreak); } - + return delegate.createBreakStatement(label); } - + // 12.9 The return statement - + function parseReturnStatement() { var argument = null; @@ -6177,36 +6465,37 @@ return delegate.createReturnStatement(argument); } - + // 12.10 The with statement - + function parseWithStatement() { - var object, body; - + var object; + var body; + if (strict) { throwErrorTolerant({}, Messages.StrictModeWith); } - + expectKeyword('with'); - + expect('('); - + object = parseExpression(); - + expect(')'); - + body = parseStatement(); - + return delegate.createWithStatement(object, body); } - + // 12.10 The swith statement - + function parseSwitchCase() { - var test, - consequent = [], - statement; - + var test; + var consequent = []; + var statement; + skipComment(); delegate.markStart(); if (matchKeyword('default')) { @@ -6217,7 +6506,7 @@ test = parseExpression(); } expect(':'); - + while (index < length) { if (match('}') || matchKeyword('default') || matchKeyword('case')) { break; @@ -6225,34 +6514,38 @@ statement = parseStatement(); consequent.push(statement); } - + return delegate.markEnd(delegate.createSwitchCase(test, consequent)); } - + function parseSwitchStatement() { - var discriminant, cases, clause, oldInSwitch, defaultFound; - + var discriminant; + var cases; + var clause; + var oldInSwitch; + var defaultFound; + expectKeyword('switch'); - + expect('('); - + discriminant = parseExpression(); - + expect(')'); - + expect('{'); - + if (match('}')) { lex(); return delegate.createSwitchStatement(discriminant); } - + cases = []; - + oldInSwitch = state.inSwitch; state.inSwitch = true; defaultFound = false; - + while (index < length) { if (match('}')) { break; @@ -6266,16 +6559,16 @@ } cases.push(clause); } - + state.inSwitch = oldInSwitch; - + expect('}'); - + return delegate.createSwitchStatement(discriminant, cases); } - + // 12.13 The throw statement - + function parseThrowStatement() { var argument; @@ -6291,57 +6584,60 @@ return delegate.createThrowStatement(argument); } - + // 12.14 The try statement - + function parseCatchClause() { - var param, body; - + var param; + var body; + skipComment(); delegate.markStart(); expectKeyword('catch'); - + expect('('); if (match(')')) { throwUnexpected(lookahead); } - + param = parseVariableIdentifier(); // 12.14.1 if (strict && isRestrictedWord(param.name)) { throwErrorTolerant({}, Messages.StrictCatchVariable); } - + expect(')'); body = parseBlock(); return delegate.markEnd(delegate.createCatchClause(param, body)); } - + function parseTryStatement() { - var block, handlers = [], finalizer = null; - + var block; + var handlers = []; + var finalizer = null; + expectKeyword('try'); - + block = parseBlock(); - + if (matchKeyword('catch')) { handlers.push(parseCatchClause()); } - + if (matchKeyword('finally')) { lex(); finalizer = parseBlock(); } - + if (handlers.length === 0 && !finalizer) { throwError({}, Messages.NoCatchOrFinally); } - + return delegate.createTryStatement(block, [], handlers, finalizer); } - + // 12.15 The debugger statement - + function parseDebuggerStatement() { expectKeyword('debugger'); @@ -6349,22 +6645,22 @@ return delegate.createDebuggerStatement(); } - + // 12 Statements - + function parseStatement() { - var type = lookahead.type, - expr, - labeledBody, - key; - + var type = lookahead.type; + var expr; + var labeledBody; + var key; + if (type === Token.EOF) { throwUnexpected(lookahead); } - + skipComment(); delegate.markStart(); - + if (type === Token.Punctuator) { switch (lookahead.value) { case ';': @@ -6377,7 +6673,7 @@ break; } } - + if (type === Token.Keyword) { switch (lookahead.value) { case 'break': @@ -6412,9 +6708,9 @@ break; } } - + expr = parseExpression(); - + // 12.12 Labelled Statements if ((expr.type === Syntax.Identifier) && match(':')) { lex(); @@ -6429,22 +6725,29 @@ delete state.labelSet[key]; return delegate.markEnd(delegate.createLabeledStatement(expr, labeledBody)); } - + consumeSemicolon(); - + return delegate.markEnd(delegate.createExpressionStatement(expr)); } - + // 13 Function Definition - + function parseFunctionSourceElements() { - var sourceElement, sourceElements = [], token, directive, firstRestricted, - oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody; - + var sourceElement; + var sourceElements = []; + var token; + var directive; + var firstRestricted; + var oldLabelSet; + var oldInIteration; + var oldInSwitch; + var oldInFunctionBody; + skipComment(); delegate.markStart(); expect('{'); - + while (index < length) { if (lookahead.type !== Token.StringLiteral) { break; @@ -6469,17 +6772,17 @@ } } } - + oldLabelSet = state.labelSet; oldInIteration = state.inIteration; oldInSwitch = state.inSwitch; oldInFunctionBody = state.inFunctionBody; - + state.labelSet = {}; state.inIteration = false; state.inSwitch = false; state.inFunctionBody = true; - + while (index < length) { if (match('}')) { break; @@ -6490,21 +6793,27 @@ } sourceElements.push(sourceElement); } - + expect('}'); - + state.labelSet = oldLabelSet; state.inIteration = oldInIteration; state.inSwitch = oldInSwitch; state.inFunctionBody = oldInFunctionBody; - + return delegate.markEnd(delegate.createBlockStatement(sourceElements)); } - + function parseParams(firstRestricted) { - var param, params = [], token, stricted, paramSet, key, message; + var param; + var params = []; + var token; + var stricted; + var paramSet; + var key; + var message; expect('('); - + if (!match(')')) { paramSet = {}; while (index < length) { @@ -6540,23 +6849,31 @@ expect(','); } } - + expect(')'); - + return { - params: params, - stricted: stricted, - firstRestricted: firstRestricted, - message: message + params, + stricted, + firstRestricted, + message }; } - + function parseFunctionDeclaration() { - var id, params = [], body, token, stricted, tmp, firstRestricted, message, previousStrict; - + var id; + var params = []; + var body; + var token; + var stricted; + var tmp; + var firstRestricted; + var message; + var previousStrict; + skipComment(); delegate.markStart(); - + expectKeyword('function'); token = lookahead; id = parseVariableIdentifier(); @@ -6573,7 +6890,7 @@ message = Messages.StrictReservedWord; } } - + tmp = parseParams(firstRestricted); params = tmp.params; stricted = tmp.stricted; @@ -6581,7 +6898,7 @@ if (tmp.message) { message = tmp.message; } - + previousStrict = strict; body = parseFunctionSourceElements(); if (strict && firstRestricted) { @@ -6591,16 +6908,24 @@ throwErrorTolerant(stricted, message); } strict = previousStrict; - + return delegate.markEnd(delegate.createFunctionDeclaration(id, params, [], body)); } - + function parseFunctionExpression() { - var token, id = null, stricted, firstRestricted, message, tmp, params = [], body, previousStrict; - + var token; + var id = null; + var stricted; + var firstRestricted; + var message; + var tmp; + var params = []; + var body; + var previousStrict; + delegate.markStart(); expectKeyword('function'); - + if (!match('(')) { token = lookahead; id = parseVariableIdentifier(); @@ -6618,7 +6943,7 @@ } } } - + tmp = parseParams(firstRestricted); params = tmp.params; stricted = tmp.stricted; @@ -6626,7 +6951,7 @@ if (tmp.message) { message = tmp.message; } - + previousStrict = strict; body = parseFunctionSourceElements(); if (strict && firstRestricted) { @@ -6636,12 +6961,12 @@ throwErrorTolerant(stricted, message); } strict = previousStrict; - + return delegate.markEnd(delegate.createFunctionExpression(id, params, [], body)); } - + // 14 Program - + function parseSourceElement() { if (lookahead.type === Token.Keyword) { switch (lookahead.value) { @@ -6659,10 +6984,14 @@ return parseStatement(); } } - + function parseSourceElements() { - var sourceElement, sourceElements = [], token, directive, firstRestricted; - + var sourceElement; + var sourceElements = []; + var token; + var directive; + var firstRestricted; + while (index < length) { token = lookahead; if (token.type !== Token.StringLiteral) { @@ -6687,7 +7016,7 @@ } } } - + while (index < length) { sourceElement = parseSourceElement(); if (typeof sourceElement === 'undefined') { @@ -6697,7 +7026,7 @@ } return sourceElements; } - + function parseProgram() { var body; @@ -6708,10 +7037,14 @@ body = parseSourceElements(); return delegate.markEnd(delegate.createProgram(body)); } - + function collectToken() { - var start, loc, token, range, value; - + var start; + var loc; + var token; + var range; + var value; + skipComment(); start = index; loc = { @@ -6720,32 +7053,35 @@ column: index - lineStart } }; - + token = extra.advance(); loc.end = { line: lineNumber, column: index - lineStart }; - + if (token.type !== Token.EOF) { range = [token.range[0], token.range[1]]; value = source.slice(token.range[0], token.range[1]); extra.tokens.push({ type: TokenName[token.type], - value: value, - range: range, - loc: loc + value, + range, + loc }); } - + return token; } - + function collectRegex() { - var pos, loc, regex, token; - + var pos; + var loc; + var regex; + var token; + skipComment(); - + pos = index; loc = { start: { @@ -6753,13 +7089,13 @@ column: index - lineStart } }; - + regex = extra.scanRegExp(); loc.end = { line: lineNumber, column: index - lineStart }; - + if (!extra.tokenize) { // Pop the previous token, which is likely '/' or '/=' if (extra.tokens.length > 0) { @@ -6775,16 +7111,19 @@ type: 'RegularExpression', value: regex.literal, range: [pos, index], - loc: loc + loc }); } - + return regex; } - + function filterTokenLocation() { - var i, entry, token, tokens = []; - + var i; + var entry; + var token; + var tokens = []; + for (i = 0; i < extra.tokens.length; ++i) { entry = extra.tokens[i]; token = { @@ -6799,10 +7138,10 @@ } tokens.push(token); } - + extra.tokens = tokens; } - + function createLocationMarker() { if (!extra.loc && !extra.range) { @@ -6814,13 +7153,13 @@ return { marker: [index, lineNumber, index - lineStart, 0, 0, 0], - end: function () { + end() { this.marker[3] = index; this.marker[4] = lineNumber; this.marker[5] = index - lineStart; }, - apply: function (node) { + apply(node) { if (extra.range) { node.range = [this.marker[0], this.marker[3]]; } @@ -6840,7 +7179,7 @@ } }; } - + function patch() { if (typeof extra.tokens !== 'undefined') { extra.advance = advance; @@ -6850,24 +7189,24 @@ scanRegExp = collectRegex; } } - + function unpatch() { if (typeof extra.scanRegExp === 'function') { advance = extra.advance; scanRegExp = extra.scanRegExp; } } - + function tokenize(code, options) { - var toString, - token, - tokens; - + var toString; + var token; + var tokens; + toString = String; if (typeof code !== 'string' && !(code instanceof String)) { code = toString(code); } - + delegate = SyntaxTreeDelegate; source = code; index = 0; @@ -6883,12 +7222,12 @@ inSwitch: false, lastCommentStart: -1, }; - + extra = {}; - + // Options matching. options = options || {}; - + // Of course we collect tokens here. options.tokens = true; extra.tokens = []; @@ -6896,17 +7235,17 @@ // The following two fields are necessary to compute the Regex tokens. extra.openParenToken = -1; extra.openCurlyToken = -1; - + extra.range = (typeof options.range === 'boolean') && options.range; extra.loc = (typeof options.loc === 'boolean') && options.loc; - + if (typeof options.comment === 'boolean' && options.comment) { extra.comments = []; } if (typeof options.tolerant === 'boolean' && options.tolerant) { extra.errors = []; } - + if (length > 0) { if (typeof source[0] === 'undefined') { // Try first to convert to a string. This is good as fast path @@ -6917,9 +7256,9 @@ } } } - + patch(); - + try { peek(); if (lookahead.type === Token.EOF) { @@ -6959,15 +7298,16 @@ } return tokens; } - + function parse(code, options) { - var program, toString; - + var program; + var toString; + toString = String; if (typeof code !== 'string' && !(code instanceof String)) { code = toString(code); } - + delegate = SyntaxTreeDelegate; source = code; index = 0; @@ -6984,7 +7324,7 @@ lastCommentStart: -1, markerStack: [] }; - + extra = {}; if (typeof options !== 'undefined') { extra.range = (typeof options.range === 'boolean') && options.range; @@ -7004,7 +7344,7 @@ extra.errors = []; } } - + if (length > 0) { if (typeof source[0] === 'undefined') { // Try first to convert to a string. This is good as fast path @@ -7015,7 +7355,7 @@ } } } - + patch(); try { program = parseProgram(); @@ -7035,41 +7375,41 @@ unpatch(); extra = {}; } - + return program; } - + // Sync with package.json and component.json. exports.version = '1.1.0-dev'; - + exports.tokenize = tokenize; - + exports.parse = parse; - + // Deep copy. - exports.Syntax = (function () { - var name, types = {}; - + exports.Syntax = ((() => { + var name; + var types = {}; + if (typeof Object.create === 'function') { types = Object.create(null); } - + for (name in Syntax) { if (Syntax.hasOwnProperty(name)) { types[name] = Syntax[name]; } } - + if (typeof Object.freeze === 'function') { Object.freeze(types); } - + return types; - }()); - + })()); })); /* vim: set sw=4 ts=4 et tw=80 : */ }; require('NodeExports'); -})(this || exports); +}))(this || exports); diff --git a/runtime/consolelogwriter.js b/runtime/consolelogwriter.js index 216fb92..b8ad1b8 100644 --- a/runtime/consolelogwriter.js +++ b/runtime/consolelogwriter.js @@ -5,9 +5,10 @@ // This module is responsible for directing logging to the console. // Implements same public functions as logwriter.js. -var core = require('./core'), - util = require('util'), - events = require('events'); +var core = require('./core'); + +var util = require('util'); +var events = require('events'); exports = module.exports = ConsoleLogWriter; diff --git a/runtime/core.js b/runtime/core.js index a67e47b..c0c4daa 100644 --- a/runtime/core.js +++ b/runtime/core.js @@ -3,18 +3,19 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -var _ = require('underscore'), - _str = require('underscore.string'); +var _ = require('underscore'); + +var _str = require('underscore.string'); _.mixin(_str.exports()); -(function (exports) { +((exports => { function curry(fn) { - var slice = Array.prototype.slice, - args = slice.call(arguments, 1); + var slice = Array.prototype.slice; + var args = slice.call(arguments, 1); return function () { - return fn.apply(null, args.concat(slice.call(arguments))); + return fn(...args.concat(slice.call(arguments))); }; } @@ -26,7 +27,7 @@ _.mixin(_str.exports()); } function defineClass(ctor, instanceMembers, classMembers) { - ctor = ctor || function () { }; + ctor = ctor || (() => { }); if (instanceMembers) { extend(ctor.prototype, instanceMembers); } @@ -41,14 +42,12 @@ _.mixin(_str.exports()); var prototype = {}; extend(prototype, basePrototype); - var getPrototype = function (name, fn) { - return function () { - var tmp = this._super; - this._super = basePrototype; - var ret = fn.apply(this, arguments); - this._super = tmp; - return ret; - }; + var getPrototype = (name, fn) => function(...args) { + var tmp = this._super; + this._super = basePrototype; + var ret = fn.apply(this, args); + this._super = tmp; + return ret; }; if (instanceMembers) { @@ -60,16 +59,14 @@ _.mixin(_str.exports()); } ctor = ctor ? - (function (fn) { - return function () { - var tmp = this._super; - this._super = basePrototype; - var ret = fn.apply(this, arguments); - this._super = tmp; - return ret; - }; - })(ctor) - : function () { }; + ((fn => function(...args) { + var tmp = this._super; + this._super = basePrototype; + var ret = fn.apply(this, args); + this._super = tmp; + return ret; + }))(ctor) + : () => { }; ctor.prototype = prototype; ctor.prototype.constructor = ctor; @@ -318,12 +315,12 @@ _.mixin(_str.exports()); // If this is a merge conflict, the first parameter will be the original item // involved in the update or delete Object.defineProperty(this, 'isMergeConflict', { - get: function () { + get() { return code === ErrorCodes.MergeConflict; } }); Object.defineProperty(this, 'isConflict', { - get: function () { + get() { return code === ErrorCodes.Conflict; } }); @@ -344,7 +341,7 @@ _.mixin(_str.exports()); this.code = code; } }, { - toString: function () { + toString() { if (this.innerError) { return this.innerError.toString(); // Preserve error type prefix (ie: SyntaxError:, SqlError:) } else { @@ -432,9 +429,7 @@ _.mixin(_str.exports()); function getSystemProperty(name) { name = name.toLowerCase(); - return _.find(supportedSystemProperties, function (property) { - return property.name.toLowerCase() === name; - }); + return _.find(supportedSystemProperties, property => property.name.toLowerCase() === name); } function validateAndNormalizeSystemProperties(systemProperties) { @@ -449,15 +444,13 @@ _.mixin(_str.exports()); // Check for the '*' (all system properties) value if (isStarSystemProperty(systemProperties)) { - normalizedSystemProperties = supportedSystemProperties.map(function (property) { - return property.name; - }); + normalizedSystemProperties = supportedSystemProperties.map(property => property.name); } else { // otherwise, validate each individual system property - _.each(systemProperties, function (systemProperty) { - var original = systemProperty, - isKnownProperty = false; + _.each(systemProperties, systemProperty => { + var original = systemProperty; + var isKnownProperty = false; if (isString(systemProperty)) { // remove any whitespace and make all lower case @@ -595,9 +588,7 @@ _.mixin(_str.exports()); // Following paths in call stack do not point to file that caused the error. var ignorePaths = ['Microsoft.Azure.Zumo.Runtime.Node.Test']; function isIgnoredPathInFrame(frame) { - var found = _.any(ignorePaths, function(path) { - return frame.indexOf(path) > 0; - }); + var found = _.any(ignorePaths, path => frame.indexOf(path) > 0); return found; } @@ -658,7 +649,7 @@ _.mixin(_str.exports()); var value; Object.defineProperty(target, name, { - get: function () { + get() { if (value === undefined) { // if we haven't accessed the value yet, get it // and cache it @@ -683,7 +674,7 @@ _.mixin(_str.exports()); if (!Array.isArray(array)) { throw Error('First parameter must be an array'); } - array.forEach(function (item) { + array.forEach(item => { var key = keySelector(item); map[key] = item; }); @@ -693,7 +684,7 @@ _.mixin(_str.exports()); // should use this version of stringify to ensure that all // byte arrays (Buffers in node.js) are serialized correctly. function stringify(itemToStringify) { - return JSON.stringify(itemToStringify, function (item, value) { + return JSON.stringify(itemToStringify, (item, value) => { if (Buffer.isBuffer(value)) { value = value.toString('base64'); } @@ -705,10 +696,10 @@ _.mixin(_str.exports()); // run the specified array of functions in sequence // series: array of functions // done: the callback to call after all have been run - series: function (series, done) { + series(series, done) { var stepIdx = 0; - var next = function (err) { + var next = err => { if (err || stepIdx == (series.length)) { done(err); } @@ -723,16 +714,16 @@ _.mixin(_str.exports()); // run the specified array of functions in parallel // series: array of functions // done: the callback to call after all have been run - parallel: function (series, done) { + parallel(series, done) { var completed = 0; - var complete = function (err) { + var complete = err => { if (err || ++completed == series.length) { done(err); } }; // start all functions in parallel - series.forEach(function (f) { + series.forEach(f => { f(complete); }); } @@ -919,4 +910,4 @@ _.mixin(_str.exports()); var stringIdValidatorRegex = /([\u0000-\u001F]|[\u007F-\u009F]|["\+\?\\\/\`]|^\.{1,2}$)/; -})(typeof exports === 'undefined' ? (this.core = {}) : exports); +}))(typeof exports === 'undefined' ? (this.core = {}) : exports); diff --git a/runtime/encryptor.js b/runtime/encryptor.js index 819790e..d4f9737 100644 --- a/runtime/encryptor.js +++ b/runtime/encryptor.js @@ -9,7 +9,7 @@ var crypto = require('crypto'); function Encryptor() { } -Encryptor.encrypt = function (key, plaintext) { +Encryptor.encrypt = (key, plaintext) => { if (typeof plaintext !== 'string') { throw new Error('plaintext must be a string.'); } @@ -18,7 +18,7 @@ Encryptor.encrypt = function (key, plaintext) { return data; }; -Encryptor.decrypt = function (key, data) { +Encryptor.decrypt = (key, data) => { var cipher = crypto.createDecipher('aes-256-cbc', key); var plaintext = cipher.update(data, 'base64', 'utf8') + cipher.final('utf8'); return plaintext; diff --git a/runtime/filehelpers.js b/runtime/filehelpers.js index 3059780..1aef874 100644 --- a/runtime/filehelpers.js +++ b/runtime/filehelpers.js @@ -4,9 +4,10 @@ // // Provides helper functions for interacting with the file system -var fs = require('fs'), - _ = require('underscore'), - _str = require('underscore.string'); +var fs = require('fs'); + +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -18,7 +19,7 @@ exports.require = require; var retriableFileErrorCodes = ['EBUSY']; -exports.removeExtension = function (fileName) { +exports.removeExtension = fileName => { if (fileName) { var idx = fileName.lastIndexOf('.'); if (idx > 0) { @@ -31,14 +32,14 @@ exports.removeExtension = function (fileName) { // read a file asyncronously using the specified retry policy // maxRetries and retryInterval are optional exports.readFileWithRetries = function (filePath, logger, callback, maxRetries, retryInterval) { - var self = this, - retryCount = 0; + var self = this; + var retryCount = 0; maxRetries = maxRetries || 3; retryInterval = retryInterval || 500; function readFileWithRetries() { - self.fs.readFile(filePath, 'utf8', function (err, data) { + self.fs.readFile(filePath, 'utf8', (err, data) => { if (err) { // if the error is retriable, try again, up to the max retry count if (retriableFileErrorCodes.indexOf(err.code) !== -1 && retryCount++ < maxRetries) { @@ -64,9 +65,9 @@ exports.readFileWithRetries = function (filePath, logger, callback, maxRetries, // read a node module using the specified retry policy // maxRetries and retryInterval are optional exports.requireWithRetries = function (filePath, logger, callback, maxRetries, retryInterval) { - var self = this, - retryCount = 0, - loadedModule; + var self = this; + var retryCount = 0; + var loadedModule; maxRetries = maxRetries || 3; retryInterval = retryInterval || 500; diff --git a/runtime/filewatcher.js b/runtime/filewatcher.js index d9a8586..0697a9e 100644 --- a/runtime/filewatcher.js +++ b/runtime/filewatcher.js @@ -4,10 +4,11 @@ // // A simple filewatcher that monitors a single file for changes. -var core = require('./core'), - fs = require('fs'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('./core'); + +var fs = require('fs'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -39,7 +40,7 @@ FileWatcher.prototype._createFileWatcher = function () { this.logger.trace(logSource, _.sprintf("Starting filewatcher on file '%s'.", this.filepath)); // get the initial timestamp - this.fs.stat(this.filepath, function (err, stats) { + this.fs.stat(this.filepath, (err, stats) => { if (!err) { self.lastModified = stats.mtime; } @@ -54,8 +55,8 @@ FileWatcher.prototype._createFileWatcher = function () { // than fs.watch, because for networked files polling is the only reliable // way of detecting changes (e.g. fs.watch file handles periodically become // invalid). - self.interval = setInterval(function () { - self.fs.stat(self.filepath, function (err, stats) { + self.interval = setInterval(() => { + self.fs.stat(self.filepath, (err, stats) => { if (!err) { // determine whether the file has changed since the last time we checked if (self.lastModified && self.lastModified.getTime() < stats.mtime.getTime()) { diff --git a/runtime/jsonwebtoken.js b/runtime/jsonwebtoken.js index 375df64..b412e49 100644 --- a/runtime/jsonwebtoken.js +++ b/runtime/jsonwebtoken.js @@ -4,11 +4,12 @@ // // This module provides a json web token implementation -var crypto = require('crypto'), - Encryptor = require('./encryptor'), - Buffer = require('buffer').Buffer, - core = require('./core'), - _ = require('underscore'); +var crypto = require('crypto'); + +var Encryptor = require('./encryptor'); +var Buffer = require('buffer').Buffer; +var core = require('./core'); +var _ = require('underscore'); exports = module.exports; @@ -34,7 +35,7 @@ exports.windowsLiveSigningSuffix = JsonWebToken.windowsLiveSigningSuffix; // envelope is an object or string containing JWT envelope // key is an object containing both the crypto key and the key used to build signature // signingSuffix contains a suffix that is appended to the standard JWT signingKey -exports.create = function (claims, envelope, key, signingSuffix) { +exports.create = (claims, envelope, key, signingSuffix) => { var jwt = new JsonWebToken(key, signingSuffix); jwt.setEnvelope(envelope); @@ -60,7 +61,7 @@ exports.create = function (claims, envelope, key, signingSuffix) { // x5t JWTs: [{ x5t: '', certs: ['', ''] }] // kid JWTs: { 'id': 'cert1', 'id1': 'cert2' } // signingSuffix contains a suffix that is appended to the standard JWT signingKey when validating the signature -exports.parse = function (token, keyOrCertificates, signingSuffix) { +exports.parse = (token, keyOrCertificates, signingSuffix) => { var jwt = new JsonWebToken(keyOrCertificates, signingSuffix); // Get the token segments & perform validation @@ -81,9 +82,7 @@ exports.parse = function (token, keyOrCertificates, signingSuffix) { }; // This is a test hook to allow replay of expired tokens for unit tests -exports.now = function () { - return new Date(); -}; +exports.now = () => new Date(); // determine whether this JWT instance has expired JsonWebToken.prototype.isExpired = function () { @@ -145,9 +144,7 @@ JsonWebToken.prototype.verifyRsaSha256Signature = function () { JsonWebToken.prototype.verifyRsaSha256SignatureX5t = function () { var self = this; - var matchedPublicX5TSets = _.find(this._certificates, function (x5TCertificates) { - return x5TCertificates.x5t === self.envelope.x5t; - }); + var matchedPublicX5TSets = _.find(this._certificates, x5TCertificates => x5TCertificates.x5t === self.envelope.x5t); if (!matchedPublicX5TSets) { // The cert was not found. Return this information in the error, @@ -158,9 +155,7 @@ JsonWebToken.prototype.verifyRsaSha256SignatureX5t = function () { } // Now check all certs listed as matching against the JWT signature - return _.some(matchedPublicX5TSets.certs, function (publicKey) { - return self.verifySignatureByCert(publicKey); - }); + return _.some(matchedPublicX5TSets.certs, publicKey => self.verifySignatureByCert(publicKey)); }; JsonWebToken.prototype.verifyRsaSha256SignatureKid = function() { diff --git a/runtime/logger.js b/runtime/logger.js index f044018..faab5e2 100644 --- a/runtime/logger.js +++ b/runtime/logger.js @@ -2,11 +2,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -var core = require('./core'), - _ = require('underscore'), - _str = require('underscore.string'), - LogWriter = require('./logwriter'), - ConsoleLogWriter = require('./consolelogwriter'); +var core = require('./core'); + +var _ = require('underscore'); +var _str = require('underscore.string'); +var LogWriter = require('./logwriter'); +var ConsoleLogWriter = require('./consolelogwriter'); _.mixin(_str.exports()); @@ -73,7 +74,7 @@ Logger.prototype.log = function (level, type, source, summary, details, immediat // all entries regardless of log level // we do this to to dump as much information as possible to the logs // in unhandled exception scenarios - this.bufferedRequestLogEntries.forEach(function (entry) { + this.bufferedRequestLogEntries.forEach(entry => { self.logWriter.writeSystem(entry); }); this.bufferedRequestLogEntries = []; @@ -158,7 +159,7 @@ Logger.prototype.logUserUnhandled = function (err) { Logger.prototype.logMetrics = function (metrics) { var self = this; - metrics.forEach(function (metric) { + metrics.forEach(metric => { self.logWriter.writeMetric(metric); }); }; @@ -174,11 +175,11 @@ function createSystemLogEntry(requestID, timestamp, level, type, source, summary var entry = { activityID: requestID, timeCreated: timestamp, - level: level, - type: type, - source: source, - summary: summary, - details: details + level, + type, + source, + summary, + details }; return entry; @@ -199,9 +200,9 @@ Logger.prototype._createUserLogEntry = function createUserLogEntry(source, type, var entry = { timeCreated: this._getTimestamp(), - type: type, - source: source, - message: message + type, + source, + message }; return entry; @@ -230,7 +231,7 @@ Logger.prototype.clear = function () { }; // performs global initialization of the Logger -Logger.initialize = function (logServiceURL, logServiceToken, isLoggingServiceDisabled) { +Logger.initialize = (logServiceURL, logServiceToken, isLoggingServiceDisabled) => { if (isLoggingServiceDisabled) { Logger.writer = new ConsoleLogWriter(); } else { @@ -240,11 +241,11 @@ Logger.initialize = function (logServiceURL, logServiceToken, isLoggingServiceDi // force an immediate flush of all cached log entries // not yet written -Logger.flush = function () { +Logger.flush = () => { Logger.writer.flush(); }; // clear all cached log entries -Logger.clear = function () { +Logger.clear = () => { Logger.writer.clear(); }; \ No newline at end of file diff --git a/runtime/logwriter.js b/runtime/logwriter.js index d34bdb6..8ca0efe 100644 --- a/runtime/logwriter.js +++ b/runtime/logwriter.js @@ -6,13 +6,14 @@ // It maintains a cache of log entries and flushes them in batches to the logging service // at regular intervals. -var core = require('./core'), - http = require('http'), - url = require('url'), - util = require('util'), - events = require('events'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('./core'); + +var http = require('http'); +var url = require('url'); +var util = require('util'); +var events = require('events'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -83,7 +84,7 @@ LogWriter.prototype.queueFlush = function () { // on the logging service by batching multiple log entries // into a single request. var self = this; - this.timer = setTimeout(function () { + this.timer = setTimeout(() => { self.flush(); }, this.flushTimeout); } @@ -129,8 +130,9 @@ LogWriter.prototype.clear = function () { LogWriter.prototype._enforceSystemLogBufferLimit = function () { if (this.systemLogs.length > this.maxLogEntryFlushCount) { // fist, grab the first half of the logs - var count = this.systemLogs.length, - logs = this.systemLogs.slice(0, this.maxLogEntryFlushCount / 2); + var count = this.systemLogs.length; + + var logs = this.systemLogs.slice(0, this.maxLogEntryFlushCount / 2); // add a truncation entry to indicate logs were truncated var truncationEntry = logs.slice(-1)[0]; @@ -159,13 +161,13 @@ LogWriter.prototype._write = function (path, logEntries) { return; } - var self = this, - retryCount = 0; + var self = this; + var retryCount = 0; // POST the log entries to the remote log service try { // define a function to actually build and issue the POST request - var postLogs = function (logEntries) { + var postLogs = logEntries => { var logData = core.stringify(logEntries); var logSize = Buffer.byteLength(logData, 'utf8'); @@ -173,7 +175,7 @@ LogWriter.prototype._write = function (path, logEntries) { // multiple batches, recursively if necessary. if (logSize > self.maxRequestSize) { var batches = self._splitEntries(logEntries); - batches.forEach(function (batch) { + batches.forEach(batch => { postLogs(batch); }); return; @@ -182,7 +184,7 @@ LogWriter.prototype._write = function (path, logEntries) { var options = { host: self.logServiceURL.hostname, port: self.logServiceURL.port, - path: path, + path, method: 'POST', headers: { 'Host': self.logServiceURL.hostname, @@ -195,7 +197,7 @@ LogWriter.prototype._write = function (path, logEntries) { function retryRequest(e) { // if the request failed, retry up to the maximum retry limit if (++retryCount <= self.requestRetryMaxAttempts) { - setTimeout(function () { + setTimeout(() => { postLogs(logEntries); }, self.requestRetryInterval); } else { @@ -205,7 +207,7 @@ LogWriter.prototype._write = function (path, logEntries) { } } - var req = self._createHttpRequest(options, function (res) { + var req = self._createHttpRequest(options, res => { if (res.statusCode >= 400) { // Node's HTTP stack won't emit the error event for all error responses, so we need to handle errors here too. var err = new Error("Error encountered communicating with the logging service, status code: " + res.statusCode); @@ -240,13 +242,11 @@ LogWriter.prototype._write = function (path, logEntries) { }; // factored as a method to facilitate testability/mocking -LogWriter.prototype._createHttpRequest = function (options, callback) { - return http.request(options, function (res) { - callback(res); - }); -}; +LogWriter.prototype._createHttpRequest = (options, callback) => http.request(options, res => { + callback(res); +}); -LogWriter.prototype._splitEntries = function (entries) { +LogWriter.prototype._splitEntries = entries => { var batch1 = entries.slice(0, entries.length / 2); var batch2 = entries.slice(entries.length / 2); return [batch1, batch2]; diff --git a/runtime/metrics.js b/runtime/metrics.js index f49d14e..6bcce80 100644 --- a/runtime/metrics.js +++ b/runtime/metrics.js @@ -26,7 +26,7 @@ function Metrics(logger, sampleTimeout) { // Aggregate and send the logs every sampleTimeout ms if (sampleTimeout) { - setInterval(function() { + setInterval(() => { self.flush(); }, sampleTimeout); } @@ -37,11 +37,11 @@ Metrics.prototype.reset = function() { this.events = {}; }; -Metrics.prototype.startEvent = function (name) { +Metrics.prototype.startEvent = name => { name = name.toLowerCase(); var now = new Date(); return { - name: name, + name, startTime: now.getTime() }; }; @@ -80,7 +80,7 @@ Metrics.prototype.event = function (name) { name = name.toLowerCase(); var event = { - name: name, + name, value: 0 // Events that are triggered via this function are for counting only }; @@ -235,8 +235,6 @@ InstallationsProcessor.prototype._setCacheExpiry = function (date) { this.cacheExpiry = expiry; }; -InstallationsProcessor.prototype._addDays = function (date, days) { - // return a new date with the specified number of - // days added to the specified date - return new Date(date.setDate(date.getDate() + days)); -}; \ No newline at end of file +InstallationsProcessor.prototype._addDays = (date, days) => // return a new date with the specified number of +// days added to the specified date +new Date(date.setDate(date.getDate() + days)); \ No newline at end of file diff --git a/runtime/newrelicadapter.js b/runtime/newrelicadapter.js index 0fa320c..a2e7418 100644 --- a/runtime/newrelicadapter.js +++ b/runtime/newrelicadapter.js @@ -4,11 +4,12 @@ // // Provides functionality for loading the New Relic module if found, and setting the appropriate configuration defaults -var path = require('path'), - resource = require('./resources'), - core = require('./core'), - _ = require('underscore'), - source = 'NewRelicAdapter'; +var path = require('path'); + +var resource = require('./resources'); +var core = require('./core'); +var _ = require('underscore'); +var source = 'NewRelicAdapter'; exports = module.exports = NewRelicAdapter; @@ -29,10 +30,9 @@ NewRelicAdapter.prototype.initialize = function (configPath, environment, module // Skip initialization if there is no license key specified if (environment.NEW_RELIC_LICENSE_KEY) { - - var userdirectory = path.join(this.configPath, core.getScriptsDirName(configPath)), - configFilePath = path.join(environment.NEW_RELIC_HOME || userdirectory, 'newrelic.js'), - useConfigFile = fs.existsSync(configFilePath); + var userdirectory = path.join(this.configPath, core.getScriptsDirName(configPath)); + var configFilePath = path.join(environment.NEW_RELIC_HOME || userdirectory, 'newrelic.js'); + var useConfigFile = fs.existsSync(configFilePath); // Allow the user to drop a 'newrelic.js' file into their service folder to configure the agent. // If no such file is found, provide default settings @@ -52,10 +52,10 @@ NewRelicAdapter.prototype.initialize = function (configPath, environment, module this.loaded = true; var traceDetails = useConfigFile ? "Config file found at: " + configFilePath : "No config file found at: " + configFilePath + " - using default New Relic settings"; - this.systemTraceLogs.push({ source: source, summary: 'New Relic agent loaded successfully', details: traceDetails }); + this.systemTraceLogs.push({ source, summary: 'New Relic agent loaded successfully', details: traceDetails }); } catch (ex) { - this.systemTraceLogs.push({ source: source, summary: 'Failed to load New Relic module', details: ex.toString() }); + this.systemTraceLogs.push({ source, summary: 'Failed to load New Relic module', details: ex.toString() }); this.userLogs.push({ source: '', type: 'error', message: resource.newRelicError }); } } @@ -65,11 +65,11 @@ NewRelicAdapter.prototype.complete = function (logger, metrics) { core.ensureParamNotNull(logger, 'logger'); core.ensureParamNotNull(metrics, 'metrics'); - this.userLogs.forEach(function (log) { + this.userLogs.forEach(log => { logger.logUser(log.source, log.type, log.message); }); - this.systemTraceLogs.forEach(function (log) { + this.systemTraceLogs.forEach(log => { logger.trace(log.source, log.summary, log.details); }); diff --git a/runtime/push/nhregistrationhandler.js b/runtime/push/nhregistrationhandler.js index 3f17b0b..c5fd4a4 100644 --- a/runtime/push/nhregistrationhandler.js +++ b/runtime/push/nhregistrationhandler.js @@ -8,13 +8,14 @@ // GET http://myapp.azure-mobile.net/push/registrations?deviceId=&platform= // These endpoints facilitate the client's registrations for NotificationHubs -var StatusCodes = require('../statuscodes').StatusCodes, - _ = require('underscore'), - _str = require('underscore.string'), - ApnsHandler = require('./nhregistrationhelpers/apns'), - GcmHandler = require('./nhregistrationhelpers/gcm'), - MpnsHandler = require('./nhregistrationhelpers/mpns'), - WnsHandler = require('./nhregistrationhelpers/wns'); +var StatusCodes = require('../statuscodes').StatusCodes; + +var _ = require('underscore'); +var _str = require('underscore.string'); +var ApnsHandler = require('./nhregistrationhelpers/apns'); +var GcmHandler = require('./nhregistrationhelpers/gcm'); +var MpnsHandler = require('./nhregistrationhelpers/mpns'); +var WnsHandler = require('./nhregistrationhelpers/wns'); _.mixin(_str.exports()); exports = module.exports = NhRegistrationHandler; @@ -35,15 +36,15 @@ function NhRegistrationHandler(notificationHubService, extensionManager) { // POST http://myapp.azure-mobile.net/push/registrationsids // Success returns 201 NhRegistrationHandler.prototype.handlePost = function (req) { - var context = req._context, - responseCallback = context.responseCallback, - headers, - logger = context.logger, - metrics = context.metrics, - metricName = 'registration.createId'; + var context = req._context; + var responseCallback = context.responseCallback; + var headers; + var logger = context.logger; + var metrics = context.metrics; + var metricName = 'registration.createId'; try { - this.notificationHubService.createRegistrationId(function (error, response) { + this.notificationHubService.createRegistrationId((error, response) => { try { if (error) { metrics.event(_.sprintf('%s.%s', metricName, 'error')); @@ -90,16 +91,16 @@ NhRegistrationHandler.prototype.handlePost = function (req) { // } // Success returns 204 NhRegistrationHandler.prototype.handlePut = function (req) { - var context = req._context, - requestBody = req.body, - responseCallback = context.responseCallback, - platform, - registration, - logger = context.logger, - metrics = context.metrics, - metricName = 'registration.update', - installationId = req.headers['x-zumo-installation-id'], - self = this; + var context = req._context; + var requestBody = req.body; + var responseCallback = context.responseCallback; + var platform; + var registration; + var logger = context.logger; + var metrics = context.metrics; + var metricName = 'registration.update'; + var installationId = req.headers['x-zumo-installation-id']; + var self = this; if (!requestBody) { throw new core.MobileServiceError('Creating or updating registrations requires a body containing a push registration', core.ErrorCodes.BadInput); @@ -118,7 +119,7 @@ NhRegistrationHandler.prototype.handlePut = function (req) { } } - this.extensionManager.runPushRegistrationScript(requestBody, req.user, function (scriptError) { + this.extensionManager.runPushRegistrationScript(requestBody, req.user, scriptError => { try { if (scriptError) { handleUserScriptError(logger, responseCallback, scriptError, 'Registration script failed with error'); @@ -129,7 +130,7 @@ NhRegistrationHandler.prototype.handlePut = function (req) { registration.Tags = registration.Tags.join(); - self.notificationHubService.createOrUpdateRegistration(registration, function (error) { + self.notificationHubService.createOrUpdateRegistration(registration, error => { try { if (error) { metrics.event(_.sprintf('%s.%s', metricName, 'error')); @@ -163,7 +164,7 @@ NhRegistrationHandler.prototype.handlePut = function (req) { // The first 2 parts of a inputRegistration for any service are: // 1. registrationId (required) // 2. tags (optional -NhRegistrationHandler.prototype.transformInputToNhBaseRegistration = function (inputRegistration) { +NhRegistrationHandler.prototype.transformInputToNhBaseRegistration = inputRegistration => { var registration = {}; // The _ property on the registration is used by notificationHubService for storing various metadata such as the type of the registration object for SOAP @@ -191,14 +192,14 @@ NhRegistrationHandler.prototype.transformInputToNhBaseRegistration = function (i // DELETE http://myapp.azure-mobile.net/push/registrations/ // Success returns 200 NhRegistrationHandler.prototype.handleDelete = function (req) { - var context = req._context, - responseCallback = context.responseCallback, - logger = context.logger, - metrics = context.metrics, - metricName = 'registration.delete'; + var context = req._context; + var responseCallback = context.responseCallback; + var logger = context.logger; + var metrics = context.metrics; + var metricName = 'registration.delete'; try { - this.notificationHubService.deleteRegistration(context.parsedRequest.id, function (error) { + this.notificationHubService.deleteRegistration(context.parsedRequest.id, error => { try { if (error) { metrics.event(_.sprintf('%s.%s', metricName, 'error')); @@ -225,13 +226,13 @@ NhRegistrationHandler.prototype.handleDelete = function (req) { // GET http://myapp.azure-mobile.net/push/registrations?deviceId=&platform= // Success returns 200 NhRegistrationHandler.prototype.handleGet = function (req) { - var context = req._context, - platform = req.query.platform, - platformHandler, - logger = context.logger, - responseCallback = context.responseCallback, - metricName = _.sprintf('registration.list.%s', platform), - metrics = context.metrics; + var context = req._context; + var platform = req.query.platform; + var platformHandler; + var logger = context.logger; + var responseCallback = context.responseCallback; + var metricName = _.sprintf('registration.list.%s', platform); + var metrics = context.metrics; try { if (!req.query.deviceId) { @@ -240,7 +241,7 @@ NhRegistrationHandler.prototype.handleGet = function (req) { platformHandler = this.getHandler(platform); - platformHandler.listRegistrations(req.query.deviceId, function (error, response) { + platformHandler.listRegistrations(req.query.deviceId, (error, response) => { try { handleListRegistrationsResponse(req, error, response, platform, platformHandler); } catch (e) { @@ -256,11 +257,11 @@ NhRegistrationHandler.prototype.handleGet = function (req) { // callback for converting the response for listing registrations function handleListRegistrationsResponse(req, error, response, platform, platformHandler) { - var context = req._context, - responseCallback = context.responseCallback, - logger = context.logger, - metrics = context.metrics, - metricName = _.sprintf('registration.list.%s', platform); + var context = req._context; + var responseCallback = context.responseCallback; + var logger = context.logger; + var metrics = context.metrics; + var metricName = _.sprintf('registration.list.%s', platform); if (error) { metrics.event(_.sprintf('%s.%s', metricName, 'error')); @@ -291,7 +292,7 @@ NhRegistrationHandler.prototype.getHandler = function (platform) { // Converting a success response for listing registrations to output format function convertToOutputRegistrationArray(platformHandler, nhListResponse) { var registrations = []; - _.each(nhListResponse, function (regFromNh) { convertToOutputRegistration(platformHandler, regFromNh, registrations); }); + _.each(nhListResponse, regFromNh => { convertToOutputRegistration(platformHandler, regFromNh, registrations); }); return registrations; } diff --git a/runtime/push/nhregistrationhelpers/apns.js b/runtime/push/nhregistrationhelpers/apns.js index fdfa696..b0bb827 100644 --- a/runtime/push/nhregistrationhelpers/apns.js +++ b/runtime/push/nhregistrationhelpers/apns.js @@ -59,13 +59,11 @@ ApnsHandler.prototype.listRegistrations = function (deviceId, callback) { }; // Provides the specific property to snag the unique registration Id from -ApnsHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) { - return regFromNh.DeviceToken; -}; +ApnsHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.DeviceToken; // Converts any optional template members from Service Bus for this notifcation service into members of registration object // for transfer to the client -ApnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function (regFromNh, registration) { +ApnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = (regFromNh, registration) => { if (regFromNh.Expiry) { registration.expiry = regFromNh.Expiry; } diff --git a/runtime/push/nhregistrationhelpers/gcm.js b/runtime/push/nhregistrationhelpers/gcm.js index 773efb8..bd5cd4d 100644 --- a/runtime/push/nhregistrationhelpers/gcm.js +++ b/runtime/push/nhregistrationhelpers/gcm.js @@ -54,13 +54,11 @@ GcmHandler.prototype.listRegistrations = function (deviceId, callback) { }; // Provides the specific property to snag the unique registration Id from -GcmHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) { - return regFromNh.GcmRegistrationId; -}; +GcmHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.GcmRegistrationId; // Converts any optional template members from Service Bus for this notifcation service into members of registration object // for transfer to the client // regFromNh, registration are default params, but are unused // Gcm currently has no optimal template properties -GcmHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function () { +GcmHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = () => { }; \ No newline at end of file diff --git a/runtime/push/nhregistrationhelpers/mpns.js b/runtime/push/nhregistrationhelpers/mpns.js index ca7f310..ec49629 100644 --- a/runtime/push/nhregistrationhelpers/mpns.js +++ b/runtime/push/nhregistrationhelpers/mpns.js @@ -4,8 +4,9 @@ // // This module is the helper to assist nhregistrationhandler with Mpns registration operations -var core = require('../../core'), - _ = require('underscore'); +var core = require('../../core'); + +var _ = require('underscore'); exports = module.exports = MpnsHandler; @@ -39,7 +40,10 @@ MpnsHandler.prototype.transformInputToNhRegistration = function (inputRegistrati registration.BodyTemplate = inputRegistration.templateBody; if (inputRegistration.headers) { registration.MpnsHeaders = {}; - registration.MpnsHeaders.MpnsHeader = _.map(inputRegistration.headers, function (value, headerName) { return { Header: headerName, Value: value }; }); + registration.MpnsHeaders.MpnsHeader = _.map(inputRegistration.headers, (value, headerName) => ({ + Header: headerName, + Value: value + })); } if (inputRegistration.templateName) { @@ -60,17 +64,15 @@ MpnsHandler.prototype.listRegistrations = function (deviceId, callback) { }; // Provides the specific property to snag the unique registration Id from -MpnsHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) { - return regFromNh.ChannelUri; -}; +MpnsHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.ChannelUri; // Converts any optional template members from Service Bus for this notifcation service into members of registration object // for transfer to the client -MpnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function (regFromNh, registration) { +MpnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = (regFromNh, registration) => { if (regFromNh.MpnsHeaders) { if (regFromNh.MpnsHeaders.MpnsHeader) { registration.headers = {}; - _.each(regFromNh.MpnsHeaders.MpnsHeader, function (header) { + _.each(regFromNh.MpnsHeaders.MpnsHeader, header => { registration.headers[header.Header] = header.Value; }, registration.headers); } diff --git a/runtime/push/nhregistrationhelpers/wns.js b/runtime/push/nhregistrationhelpers/wns.js index ef30385..5dc6923 100644 --- a/runtime/push/nhregistrationhelpers/wns.js +++ b/runtime/push/nhregistrationhelpers/wns.js @@ -4,8 +4,9 @@ // // This module is the helper to assist nhregistrationhandler with Wns registration operations -var core = require('../../core'), - _ = require('underscore'); +var core = require('../../core'); + +var _ = require('underscore'); exports = module.exports = WnsHandler; @@ -39,7 +40,10 @@ WnsHandler.prototype.transformInputToNhRegistration = function (inputRegistratio registration.BodyTemplate = inputRegistration.templateBody; if (inputRegistration.headers) { registration.WnsHeaders = {}; - registration.WnsHeaders.WnsHeader = _.map(inputRegistration.headers, function (value, headerName) { return { Header: headerName, Value: value }; }); + registration.WnsHeaders.WnsHeader = _.map(inputRegistration.headers, (value, headerName) => ({ + Header: headerName, + Value: value + })); } if (inputRegistration.templateName) { @@ -60,18 +64,16 @@ WnsHandler.prototype.listRegistrations = function (deviceId, callback) { }; // Provides the specific property to snag the unique registration Id from -WnsHandler.prototype.getDeviceIdFromNhRegistration = function (regFromNh) { - return regFromNh.ChannelUri; -}; +WnsHandler.prototype.getDeviceIdFromNhRegistration = regFromNh => regFromNh.ChannelUri; // Converts any optional template members from Service Bus for this notifcation service into members of registration object // for transfer to the client -WnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = function (regFromNh, registration) { +WnsHandler.prototype.convertOptionalTemplatePropsToOutputRegistration = (regFromNh, registration) => { if (regFromNh.WnsHeaders) { if (regFromNh.WnsHeaders.WnsHeader) { registration.headers = {}; // {"WnsHeader":[{"Header":"X-WNS-TTL","Value":"1"},{"Header":"X-WNS-Type","Value":"wns/toast"}]} - _.each(regFromNh.WnsHeaders.WnsHeader, function (header) { + _.each(regFromNh.WnsHeaders.WnsHeader, header => { registration.headers[header.Header] = header.Value; }, registration.headers); } diff --git a/runtime/push/pushadapter.js b/runtime/push/pushadapter.js index ae898b7..5d3c3ff 100644 --- a/runtime/push/pushadapter.js +++ b/runtime/push/pushadapter.js @@ -4,16 +4,17 @@ // // This module is used to create an azure notificationHubService -var ZumoCallback = require('../script/zumocallback'), - notify = require('./scripthelpers/notify'), - notifyWns = require('./scripthelpers/notify-wns'), - notifyMpns = require('./scripthelpers/notify-mpns'), - notifyApns = require('./scripthelpers/notify-apns'), - notifyGcm = require('./scripthelpers/notify-gcm'), - NhRegistrationHandler = require('./nhregistrationhandler'), - path = require('path'), - _ = require('underscore'), - azure; +var ZumoCallback = require('../script/zumocallback'); + +var notify = require('./scripthelpers/notify'); +var notifyWns = require('./scripthelpers/notify-wns'); +var notifyMpns = require('./scripthelpers/notify-mpns'); +var notifyApns = require('./scripthelpers/notify-apns'); +var notifyGcm = require('./scripthelpers/notify-gcm'); +var NhRegistrationHandler = require('./nhregistrationhandler'); +var path = require('path'); +var _ = require('underscore'); +var azure; exports = module.exports = PushAdapter; @@ -62,18 +63,10 @@ PushAdapter.prototype.createPushForScripts = function (source, logger, metrics, } else if (!this.notificationHubPush) { var self = this; // define lazy properties for push provider wrappers - core.createLazyProperty(push, 'wns', function () { - return notify.createWrappedClient(self.directPushClients.wnsClient, source, logger, metrics, responseCallback); - }); - core.createLazyProperty(push, 'mpns', function () { - return notify.createWrappedClient(self.directPushClients.mpnsClient, source, logger, metrics, responseCallback); - }); - core.createLazyProperty(push, 'apns', function () { - return notify.createWrappedClient(self.directPushClients.apnsClient, source, logger, metrics, responseCallback); - }); - core.createLazyProperty(push, 'gcm', function () { - return notify.createWrappedClient(self.directPushClients.gcmClient, source, logger, metrics, responseCallback); - }); + core.createLazyProperty(push, 'wns', () => notify.createWrappedClient(self.directPushClients.wnsClient, source, logger, metrics, responseCallback)); + core.createLazyProperty(push, 'mpns', () => notify.createWrappedClient(self.directPushClients.mpnsClient, source, logger, metrics, responseCallback)); + core.createLazyProperty(push, 'apns', () => notify.createWrappedClient(self.directPushClients.apnsClient, source, logger, metrics, responseCallback)); + core.createLazyProperty(push, 'gcm', () => notify.createWrappedClient(self.directPushClients.gcmClient, source, logger, metrics, responseCallback)); } return push; diff --git a/runtime/push/scripthelpers/apnconnectionfactory.js b/runtime/push/scripthelpers/apnconnectionfactory.js index e7312cf..264916e 100644 --- a/runtime/push/scripthelpers/apnconnectionfactory.js +++ b/runtime/push/scripthelpers/apnconnectionfactory.js @@ -1,13 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -var core = require('../../core'), - resources = require('../../resources'), - StatusCodes = require('../../statuscodes').StatusCodes, - _ = require('underscore'), - _str = require('underscore.string'), - apns = require('apn'); +var core = require('../../core'); -var ApnConnectionFactory = (function () { +var resources = require('../../resources'); +var StatusCodes = require('../../statuscodes').StatusCodes; +var _ = require('underscore'); +var _str = require('underscore.string'); +var apns = require('apn'); + +var ApnConnectionFactory = ((() => { function ApnConnectionFactory(certLoader, passphrase, gateway, timeout) { this.certLoader = certLoader; @@ -43,7 +44,7 @@ var ApnConnectionFactory = (function () { var pfxData = this.certLoader(); this.options = { - pfxData: pfxData, + pfxData, passphrase: this.passphrase, gateway: this.gateway }; @@ -62,14 +63,14 @@ var ApnConnectionFactory = (function () { ApnConnectionFactory.prototype._disposeConnection = function () { if (this.connection !== null) { var self = this; - this.connection.sockets.forEach(function (socket) { + this.connection.sockets.forEach(socket => { self.connection.destroyConnection(socket); }); } }; return ApnConnectionFactory; -})(); +}))(); module.exports = exports = ApnConnectionFactory; diff --git a/runtime/push/scripthelpers/notify-apns.js b/runtime/push/scripthelpers/notify-apns.js index 43c60fc..d1d2060 100644 --- a/runtime/push/scripthelpers/notify-apns.js +++ b/runtime/push/scripthelpers/notify-apns.js @@ -4,14 +4,15 @@ // This module supports sending push notifications to iOS clients using the // Apple Push Notification Service -var core = require('../../core'), - resources = require('../../resources'), - apns = require('apn'), - notify = require('./notify'), - fs = require('fs'), - _ = require('underscore'), - _str = require('underscore.string'), - ApnConnectionFactory = require('./apnconnectionfactory'); +var core = require('../../core'); + +var resources = require('../../resources'); +var apns = require('apn'); +var notify = require('./notify'); +var fs = require('fs'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var ApnConnectionFactory = require('./apnconnectionfactory'); _.mixin(_str.exports()); @@ -29,7 +30,7 @@ var statusDescriptions = { 255: 'None (unknown)' }; -exports.getCertLoader = function (apnsCertificatePath) { +exports.getCertLoader = apnsCertificatePath => { var pfxData = null; function getCertificate(action) { @@ -42,7 +43,7 @@ exports.getCertLoader = function (apnsCertificatePath) { return getCertificate; }; -exports.createApnsContext = function (apnsCertificatePath, apnsPassword, apnsMode) { +exports.createApnsContext = (apnsCertificatePath, apnsPassword, apnsMode) => { var gateway = (apnsMode == 'Prod') ? 'gateway.push.apple.com' : 'gateway.sandbox.push.apple.com'; @@ -56,7 +57,7 @@ exports.createApnsContext = function (apnsCertificatePath, apnsPassword, apnsMod // when sending notifications. We use an 'interval' of 0 below to ensure the feedback instance // doesn't set it's own timer. var feedbackOptions = null; - var feedbackOptionsFactory = function () { + var feedbackOptionsFactory = () => { if (!feedbackOptions) { feedbackOptions = { pfxData: getCertificate('get APNS feedback'), @@ -89,7 +90,7 @@ exports.createApnsContext = function (apnsCertificatePath, apnsPassword, apnsMod return result; }; -exports.send = function (connectionFactory, deviceToken, payload, ignore, errorCallback) { +exports.send = (connectionFactory, deviceToken, payload, ignore, errorCallback) => { var connection = connectionFactory.getConnection(); if (!core.isString(deviceToken)) { @@ -108,7 +109,7 @@ exports.send = function (connectionFactory, deviceToken, payload, ignore, errorC // Create the error callback; there is no success callback because Apple doesn't // respond if the notification was received and validated successfully. - notification.errorCallback = function (error) { + notification.errorCallback = error => { if (checkCertError(error, errorCallback)) { return; } @@ -130,7 +131,7 @@ exports.send = function (connectionFactory, deviceToken, payload, ignore, errorC connection.sendNotification(notification); }; -exports.createNotificationFromPayload = function (payload) { +exports.createNotificationFromPayload = payload => { var notification; if (payload.aps) { @@ -162,19 +163,19 @@ exports.createNotificationFromPayload = function (payload) { return notification; }; -exports.getFeedback = function (feedbackOptionsFactory, ignore, callback) { +exports.getFeedback = (feedbackOptionsFactory, ignore, callback) => { var feedbackOptions = feedbackOptionsFactory(); var options = {}; core.extend(options, feedbackOptions); // Set the feedback callback; this is the success callback - options.feedback = function (feedback) { + options.feedback = feedback => { // We need to convert the feedback we get from the APN // module to something more user friendly var converted = []; - feedback.forEach(function (item) { + feedback.forEach(item => { converted.push({ deviceToken: item.device.toString(), timeStamp: new Date(item.time * 1000) @@ -185,7 +186,7 @@ exports.getFeedback = function (feedbackOptionsFactory, ignore, callback) { }; // Set the errorCAllback; this is the error callback - options.errorCallback = function (error) { + options.errorCallback = error => { if (checkCertError(error, callback)) { return; } diff --git a/runtime/push/scripthelpers/notify-gcm.js b/runtime/push/scripthelpers/notify-gcm.js index df5c972..8189018 100644 --- a/runtime/push/scripthelpers/notify-gcm.js +++ b/runtime/push/scripthelpers/notify-gcm.js @@ -4,18 +4,19 @@ // This module supports sending push notifications to Android clients using // Google Cloud Messaging -var dpush = require('dpush'), - notify = require('./notify'), - resources = require('../../resources'); +var dpush = require('dpush'); -exports.createGcmContext = function (googleApiKey) { +var notify = require('./notify'); +var resources = require('../../resources'); + +exports.createGcmContext = googleApiKey => { var result = {}; // transform the dpush.send and dpush.sendAdvanced methods // gcm.send(recipiendId, message, [options]) -> dpush.send(googleApiKey, recipientId, message, callback): - result.send = notify.createWrapper(dpush, 'send', 2, 'gcm', null, null, true, true, function (args) { + result.send = notify.createWrapper(dpush, 'send', 2, 'gcm', null, null, true, true, args => { if (!googleApiKey) { throw new Error(resources.googleApiKeyMissing); } @@ -37,7 +38,7 @@ exports.createGcmContext = function (googleApiKey) { // gcm.sendAdvanced(content, retryCount, [options]) -> dpush.sendAdvanced(googleApiKey, content, retryCount, callback): - result.sendAdvanced = notify.createWrapper(dpush, 'sendAdvanced', 2, 'gcm', null, null, true, true, function (args) { + result.sendAdvanced = notify.createWrapper(dpush, 'sendAdvanced', 2, 'gcm', null, null, true, true, args => { if (!googleApiKey) { throw new Error(resources.googleApiKeyMissing); } diff --git a/runtime/push/scripthelpers/notify-mpns.js b/runtime/push/scripthelpers/notify-mpns.js index 725c273..63f9fdd 100644 --- a/runtime/push/scripthelpers/notify-mpns.js +++ b/runtime/push/scripthelpers/notify-mpns.js @@ -4,11 +4,12 @@ // This module supports sending push notifications to Windows Phone 8 clients using // Microsoft Push Notification Services -var core = require('../../core'), - mpns = require('mpns'), - notify = require('./notify'); +var core = require('../../core'); -exports.createMpnsContext = function () { +var mpns = require('mpns'); +var notify = require('./notify'); + +exports.createMpnsContext = () => { // - channel URL is passed to callbacks as part of the result or error object function visitResult(item, args) { diff --git a/runtime/push/scripthelpers/notify-wns.js b/runtime/push/scripthelpers/notify-wns.js index 6f76336..74b4e73 100644 --- a/runtime/push/scripthelpers/notify-wns.js +++ b/runtime/push/scripthelpers/notify-wns.js @@ -4,14 +4,14 @@ // This module supports sending push notifications to Windows 8 clients using // Windows Notification Services -var wns = require('wns'), - notify = require('./notify'), - core = require('../../core'); +var wns = require('wns'); -exports.createWnsContext = function (client_secret, client_id) { +var notify = require('./notify'); +var core = require('../../core'); - var result = {}, - accessTokenContainer = {}; +exports.createWnsContext = (client_secret, client_id) => { + var result = {}; + var accessTokenContainer = {}; // - accessToken is not passed back to the caller throught the callback // - only x-wns-* HTTP response headers are returned in the result or error @@ -26,7 +26,7 @@ exports.createWnsContext = function (client_secret, client_id) { } if (typeof item.headers === 'object') { - Object.getOwnPropertyNames(item.headers).forEach(function (header) { + Object.getOwnPropertyNames(item.headers).forEach(header => { if (header.toLowerCase().indexOf('x-wns-') !== 0) { delete item.headers[header]; } diff --git a/runtime/push/scripthelpers/notify.js b/runtime/push/scripthelpers/notify.js index 35dbdd4..823a760 100644 --- a/runtime/push/scripthelpers/notify.js +++ b/runtime/push/scripthelpers/notify.js @@ -4,12 +4,13 @@ // This module is the base for sending push notifications via Windows Azure Mobile Services // WNS, MPNS, and APNS all use this module to build out their notification client objects. -var StatusCodes = require('../../statuscodes').StatusCodes, - core = require('../../core'), - scriptErrors = require('../../script/scripterror'), - ZumoCallback = require('../../script/zumocallback'), - _ = require('underscore'), - _str = require('underscore.string'); +var StatusCodes = require('../../statuscodes').StatusCodes; + +var core = require('../../core'); +var scriptErrors = require('../../script/scripterror'); +var ZumoCallback = require('../../script/zumocallback'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -18,7 +19,17 @@ var logSource = "Push"; // transform methods to fit ZUMO esthetics: // - success and error callbacks are separate and specified as properties of the options object // - user can call these methods either with a single channel URL (or deviceToken) or with an array of channels (or deviceTokens) -exports.createWrapper = function (module, method, argsLength, moduleName, visitResult, visitOptions, disableAtomizingChannelArrays, skipModuleOptions, finalizeArgs) { +exports.createWrapper = ( + module, + method, + argsLength, + moduleName, + visitResult, + visitOptions, + disableAtomizingChannelArrays, + skipModuleOptions, + finalizeArgs +) => { var wrapper = function () { // Copy the arguments array and extract the pipelineContext var args = Array.prototype.slice.call(arguments); @@ -53,7 +64,7 @@ exports.createWrapper = function (module, method, argsLength, moduleName, visitR options = empty; } - var visitor = function (errOrResult) { + var visitor = errOrResult => { if (visitResult) { errOrResult = visitResult(errOrResult, args); } @@ -125,7 +136,7 @@ exports.createWrapper = function (module, method, argsLength, moduleName, visitR return wrapper; }; -exports.createWrappedClient = function (module, source, logger, metrics, responseCallback) { +exports.createWrappedClient = (module, source, logger, metrics, responseCallback) => { // We instantiate the push client (wns, mpns, etc) when the server starts but we need to provide logging // and responseCallbacks per request. In this method we are wrapping the client with @@ -133,10 +144,10 @@ exports.createWrappedClient = function (module, source, logger, metrics, respons // Create the pipeline context object var pipelineContext = { - logger: logger, - responseCallback: responseCallback, + logger, + responseCallback, scriptSource: source, - metrics: metrics + metrics }; // Curry the pipelineContext object into every method diff --git a/runtime/query/expressions.js b/runtime/query/expressions.js index 6872c31..b0b052c 100644 --- a/runtime/query/expressions.js +++ b/runtime/query/expressions.js @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (global) { +((global => { var core = require('../core'); @@ -39,7 +39,7 @@ Expression = core.defineClass( null, { - accept: function (visitor) { + accept(visitor) { return visitor.visit(this); } }, @@ -51,7 +51,7 @@ this.value = value; this.expressionType = ExpressionType.Constant; }, { - accept: function (visitor) { + accept(visitor) { return visitor.visitConstant(this); } }, @@ -64,7 +64,7 @@ this.right = right; this.expressionType = expressionType; }, { - accept: function (visitor) { + accept(visitor) { return visitor.visitBinary(this); } }, @@ -76,7 +76,7 @@ this.operand = operand; this.expressionType = expressionType; }, { - accept: function (visitor) { + accept(visitor) { return visitor.visitUnary(this); } }, @@ -90,7 +90,7 @@ this.member = member; this.expressionType = ExpressionType.MemberAccess; }, { - accept: function (visitor) { + accept(visitor) { return visitor.visitMember(this); } }, @@ -104,7 +104,7 @@ this.args = args; this.expressionType = ExpressionType.Call; }, { - accept: function (visitor) { + accept(visitor) { return visitor.visitFunction(this); } }, @@ -114,7 +114,7 @@ function () { this.ExpressionType = ExpressionType.Parameter; }, { - accept: function (visitor) { + accept(visitor) { return visitor.visitParameter(this); } }, @@ -127,10 +127,10 @@ this.operand = operand; this.expressionType = ExpressionType.Convert; }, { - accept: function (visitor) { + accept(visitor) { return visitor.visitUnary(this); } }, null); -})(typeof exports === "undefined" ? this : exports); \ No newline at end of file +}))(typeof exports === "undefined" ? this : exports); \ No newline at end of file diff --git a/runtime/query/expressionvisitor.js b/runtime/query/expressionvisitor.js index 1ae8f19..813a9ca 100644 --- a/runtime/query/expressionvisitor.js +++ b/runtime/query/expressionvisitor.js @@ -2,22 +2,22 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (global) { +((global => { var core = require('../core'); require('./expressions'); var instanceMembers = { - visit: function (expr) { + visit(expr) { return expr.accept(this); }, - visitConstant: function (expr) { + visitConstant(expr) { return expr; }, - visitBinary: function (expr) { + visitBinary(expr) { var left = null; var right = null; @@ -34,7 +34,7 @@ return expr; }, - visitUnary: function (expr) { + visitUnary(expr) { var operand = this.visit(expr.operand); if (operand != expr.operand) { return new UnaryExpression(operand, expr.expressionType); @@ -42,15 +42,15 @@ return expr; }, - visitMember: function (expr) { + visitMember(expr) { return expr; }, - visitParameter: function (expr) { + visitParameter(expr) { return expr; }, - visitFunction: function (expr) { + visitFunction(expr) { var updated = false; var instance = expr.instance; @@ -61,10 +61,10 @@ } } - var args = [expr.args.length], - i = 0, - self = this; - expr.args.forEach(function (arg) { + var args = [expr.args.length]; + var i = 0; + var self = this; + expr.args.forEach(arg => { var newArg = self.visit(arg); args[i++] = arg; if (newArg != arg) { @@ -81,4 +81,4 @@ ExpressionVisitor = core.defineClass(null, instanceMembers); -})(typeof exports === "undefined" ? this : exports); \ No newline at end of file +}))(typeof exports === "undefined" ? this : exports); \ No newline at end of file diff --git a/runtime/query/queryparser.js b/runtime/query/queryparser.js index c119ab6..35d5b11 100644 --- a/runtime/query/queryparser.js +++ b/runtime/query/queryparser.js @@ -2,15 +2,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (global) { - +((global => { require('./expressions'); - var _ = require('underscore'), - _str = require('underscore.string'), - core = require('../core'); + var _ = require('underscore'); + var _str = require('underscore.string'); + var core = require('../core'); - _.mixin(_str.exports()); + _.mixin(_str.exports()); TokenId = { Unknown: 'Unknown', @@ -54,13 +53,13 @@ }; var classMembers = { - filter: function (predicate) { + filter(predicate) { var parser = new QueryParser(predicate); var filter = parser.parse(); return filter; }, - orderBy: function (ordering) { + orderBy(ordering) { var parser = new QueryParser(ordering); var orderings = parser.parseOrdering(); return orderings; @@ -68,7 +67,7 @@ }; var instanceMembers = { - parse: function () { + parse() { var exprPos = this.token.pos; var expr = this._parseExpression(); @@ -76,7 +75,7 @@ return expr; }, - parseOrdering: function () { + parseOrdering() { var orderings = []; while (true) { var expr = this._parseExpression(); @@ -90,7 +89,7 @@ } orderings.push({ selector: expr, - ascending: ascending + ascending }); if (this.token.id != TokenId.Comma) { break; @@ -101,16 +100,16 @@ return orderings; }, - _tokenIdentifierIs: function (id) { + _tokenIdentifierIs(id) { return this.token.id == TokenId.Identifier && id == this.token.text; }, - _parseExpression: function () { + _parseExpression() { return this._parseLogicalOr(); }, // 'or' operator - _parseLogicalOr: function () { + _parseLogicalOr() { var left = this._parseLogicalAnd(); while (this.token.id == TokenId.Or) { this._nextToken(); @@ -121,7 +120,7 @@ }, // 'and' operator - _parseLogicalAnd: function () { + _parseLogicalAnd() { var left = this._parseComparison(); while (this.token.id == TokenId.And) { this._nextToken(); @@ -131,7 +130,7 @@ return left; }, - _parseComparison: function () { + _parseComparison() { var left = this._parseAdditive(); while (this.token.id == TokenId.Equal || this.token.id == TokenId.NotEqual || this.token.id == TokenId.GreaterThan || this.token.id == TokenId.GreaterThanEqual || this.token.id == TokenId.LessThan || this.token.id == TokenId.LessThanEqual) { @@ -167,7 +166,7 @@ }, // 'add','sub' operators - _parseAdditive: function () { + _parseAdditive() { var left = this._parseMultiplicative(); while (this.token.id == TokenId.Add || this.token.id == TokenId.Sub) { var opId = this.token.id; @@ -186,7 +185,7 @@ }, // 'mul', 'div', 'mod' operators - _parseMultiplicative: function () { + _parseMultiplicative() { var left = this._parseUnary(); while (this.token.id == TokenId.Multiply || this.token.id == TokenId.Divide || this.token.id == TokenId.Modulo) { @@ -209,7 +208,7 @@ }, // -, 'not' unary operators - _parseUnary: function () { + _parseUnary() { if (this.token.id == TokenId.Minus || this.token.id == TokenId.Not) { var opId = this.token.id; var opPos = this.token.pos; @@ -232,7 +231,7 @@ return this._parsePrimary(); }, - _parsePrimary: function () { + _parsePrimary() { var expr = this._parsePrimaryStart(); while (true) { if (this.token.id == TokenId.Dot) { @@ -246,7 +245,7 @@ return expr; }, - _parseMemberAccess: function (instance) { + _parseMemberAccess(instance) { var errorPos = this.token.pos; var id = this._getIdentifier(); this._nextToken(); @@ -264,7 +263,7 @@ } }, - _parseMappedFunction: function (mappedMember, errorPos) { + _parseMappedFunction(mappedMember, errorPos) { var type = mappedMember.type; var mappedMemberName = mappedMember.memberName; var args; @@ -310,7 +309,7 @@ } }, - _beginValidateFunction: function (functionName, errorPos) { + _beginValidateFunction(functionName, errorPos) { if (functionName === 'replace') { // Security: nested calls to replace must be prevented to avoid an exploit // wherein the client can force the server to allocate arbitrarily large @@ -322,7 +321,7 @@ } }, - _completeValidateFunction: function (functionName, functionArgs, errorPos) { + _completeValidateFunction(functionName, functionArgs, errorPos) { // validate parameters switch (functionName) { case 'day': @@ -367,7 +366,7 @@ this.inStringReplace = false; }, - _validateFunctionParameters: function (functionName, args, expectedArgCount) { + _validateFunctionParameters(functionName, args, expectedArgCount) { if (args.length !== expectedArgCount) { var error = _.sprintf("Function '%s' requires %d %s", functionName, expectedArgCount, (expectedArgCount > 1) ? "parameters." : "parameter."); @@ -375,7 +374,7 @@ } }, - _parseArgumentList: function () { + _parseArgumentList() { this._validateToken(TokenId.OpenParen, "'(' expected"); this._nextToken(); var args = this.token.id != TokenId.CloseParen ? this._parseArguments() : []; @@ -384,7 +383,7 @@ return args; }, - _parseArguments: function () { + _parseArguments() { var args = []; while (true) { args.push(this._parseExpression()); @@ -396,7 +395,7 @@ return args; }, - _mapFunction: function (functionName) { + _mapFunction(functionName) { var mappedMember = this._mapStringFunction(functionName); if (mappedMember !== null) { return mappedMember; @@ -415,7 +414,7 @@ return null; }, - _mapStringFunction: function (functionName) { + _mapStringFunction(functionName) { if (functionName == 'startswith') { return new MappedMemberInfo('string', functionName, false, true); } @@ -436,7 +435,7 @@ } else if (functionName == 'substringof') { var memberInfo = new MappedMemberInfo('string', functionName, false, true); - memberInfo.mapParams = function (args) { + memberInfo.mapParams = args => { // reverse the order of arguments for string.Contains var tmp = args[0]; args[0] = args[1]; @@ -463,7 +462,7 @@ return null; }, - _mapDateFunction: function (functionName) { + _mapDateFunction(functionName) { if (functionName == 'day') { return new MappedMemberInfo('date', functionName, false, true); } @@ -485,7 +484,7 @@ return null; }, - _mapMathFunction: function (functionName) { + _mapMathFunction(functionName) { if (functionName == 'floor') { return new MappedMemberInfo('math', functionName, false, true); } @@ -498,12 +497,12 @@ return null; }, - _getIdentifier: function () { + _getIdentifier() { this._validateToken(TokenId.Identifier, 'Identifier expected'); return this.token.text; }, - _parsePrimaryStart: function () { + _parsePrimaryStart() { switch (this.token.id) { case TokenId.Identifier: return this._parseIdentifier(); @@ -520,7 +519,7 @@ } }, - _parseIntegerLiteral: function () { + _parseIntegerLiteral() { this._validateToken(TokenId.IntegerLiteral); var text = this.token.text; @@ -541,7 +540,7 @@ return new ConstantExpression(value); }, - _parseRealLiteral: function () { + _parseRealLiteral() { this._validateToken(TokenId.RealLiteral); var text = this.token.text; @@ -561,7 +560,7 @@ return new ConstantExpression(value); }, - _parseParenExpression: function () { + _parseParenExpression() { this._validateToken(TokenId.OpenParen, "'(' expected"); this._nextToken(); var e = this._parseExpression(); @@ -570,7 +569,7 @@ return e; }, - _parseIdentifier: function () { + _parseIdentifier() { this._validateToken(TokenId.Identifier); var value = this.keywords[this.token.text]; if (value) { @@ -593,7 +592,7 @@ throw this._parseError(_.sprintf("Unknown identifier '%s'", this.token.text)); }, - _parseTypeConstruction: function (type) { + _parseTypeConstruction(type) { var typeIdentifier = this.token.text; var errorPos = this.token.pos; this._nextToken(); @@ -631,7 +630,7 @@ return typeExpression; }, - _parseStringLiteral: function () { + _parseStringLiteral() { this._validateToken(TokenId.StringLiteral); var quote = this.token.text[0]; // Unwrap string (remove surrounding quotes) and unwrap escaped quotes. @@ -641,13 +640,13 @@ return new ConstantExpression(s); }, - _validateToken: function (tokenId, error) { + _validateToken(tokenId, error) { if (this.token.id != tokenId) { throw this._parseError(error || 'Syntax error'); } }, - _createKeywords: function () { + _createKeywords() { return { "true": new ConstantExpression(true), "false": new ConstantExpression(false), @@ -659,12 +658,12 @@ }; }, - _setTextPos: function (pos) { + _setTextPos(pos) { this.textPos = pos; this.ch = this.textPos < this.textLen ? this.text[this.textPos] : '\\0'; }, - _nextToken: function () { + _nextToken() { while (this._isWhiteSpace(this.ch)) { this._nextChar(); } @@ -762,7 +761,7 @@ this.token.id = this._reclassifyToken(this.token); }, - _reclassifyToken: function (token) { + _reclassifyToken(token) { if (token.id == TokenId.Identifier) { if (token.text == "or") { return TokenId.Or; @@ -811,33 +810,33 @@ return token.id; }, - _nextChar: function () { + _nextChar() { if (this.textPos < this.textLen) { this.textPos++; } this.ch = this.textPos < this.textLen ? this.text[this.textPos] : '\\0'; }, - _isWhiteSpace: function (ch) { + _isWhiteSpace(ch) { return (/\s/).test(ch); }, - _validateDigit: function () { + _validateDigit() { if (!core.isDigit(this.ch)) { throw this._parseError('Digit expected', this.textPos); } }, - _parseError: function (error, pos) { + _parseError(error, pos) { pos = pos || this.token.pos || 0; return new Error(error + ' (at index ' + pos + ')'); }, - _isIdentifierStart: function (ch) { + _isIdentifierStart(ch) { return core.isLetter(ch); }, - _isIdentifierPart: function (ch) { + _isIdentifierPart(ch) { if (this._isIdentifierStart(ch)) { return true; } @@ -855,5 +854,4 @@ }; QueryParser = core.defineClass(ctor, instanceMembers, classMembers); - -})(typeof exports === "undefined" ? this : exports); \ No newline at end of file +}))(typeof exports === "undefined" ? this : exports); \ No newline at end of file diff --git a/runtime/request/authentication/aad.js b/runtime/request/authentication/aad.js index 5190540..03ec763 100644 --- a/runtime/request/authentication/aad.js +++ b/runtime/request/authentication/aad.js @@ -6,17 +6,18 @@ // login modules, it implements a very specific interface that is documented in // ../loginhandler.js. -var core = require('../../core'), - crypto = require('crypto'), - jsonWebToken = require('../../jsonwebtoken'), - Buffer = require('buffer').Buffer, - LoginHandler = require('../loginhandler.js'), - AadCert = require('./aadcert'), - certCacheHelper = require('./certcachehelper'), - _ = require('underscore'), - _str = require('underscore.string'), - request = require('request'), - xml2js = require('xml2js'); +var core = require('../../core'); + +var crypto = require('crypto'); +var jsonWebToken = require('../../jsonwebtoken'); +var Buffer = require('buffer').Buffer; +var LoginHandler = require('../loginhandler.js'); +var AadCert = require('./aadcert'); +var certCacheHelper = require('./certcachehelper'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var request = require('request'); +var xml2js = require('xml2js'); _.mixin(_str.exports()); @@ -46,7 +47,7 @@ AadLoginHandler.prototype.initialize = function (done) { this._initializeIssuers(done); }; -AadLoginHandler.prototype.isNewServerFlowRequest = function (request) { +AadLoginHandler.prototype.isNewServerFlowRequest = request => { var isNewFlow = true; // If the query includes either a 'id_token' parameter or an 'error' parameter @@ -74,7 +75,7 @@ AadLoginHandler.prototype.getNewServerFlowResponseHeaders = function (request, c callback(null, headers); }; -AadLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) { +AadLoginHandler.prototype.getProviderTokenFromClientFlowRequest = (request, callback) => { callback(new core.MobileServiceError('POST of AAD token is not supported.', core.ErrorCodes.MethodNotAllowed), null); }; @@ -90,11 +91,11 @@ AadLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (requ return; } - var clientId = this.authenticationCredentials.aad.clientId, - idToken = request.query.id_token, - self = this; + var clientId = this.authenticationCredentials.aad.clientId; + var idToken = request.query.id_token; + var self = this; - certCacheHelper.validateToken(this.aadCert, idToken, function (error, validatedToken) { + certCacheHelper.validateToken(this.aadCert, idToken, (error, validatedToken) => { if (error) { callback(error, null); return; @@ -119,7 +120,7 @@ AadLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (requ }); }; -AadLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, claims, callback, options) { +AadLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = (request, claims, callback, options) => { var authorizationDetails = { providerId: claims.sub, // sub is the only 100% unique claims field that is on all AAD users regardless of their type claims: { @@ -136,8 +137,8 @@ AadLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (r // resolve any configured tenant domains to their corresponding issuer values // by querying AAD metadata for each AadLoginHandler.prototype._initializeIssuers = function (done) { - var tenants = this.authenticationCredentials.aad.tenants, - self = this; + var tenants = this.authenticationCredentials.aad.tenants; + var self = this; if (!tenants) { // if no tenants are configured, no work to do @@ -148,21 +149,19 @@ AadLoginHandler.prototype._initializeIssuers = function (done) { // create a set of tasks, each of which will query AAD metadata // for a tenant domain and return the corresponding issuer self.validIssuers = []; - var tasks = _.map(tenants, function (tenant) { - return function (done) { - self._getIssuerForTenantDomain(tenant, function (err, issuer) { - if (err) { - var msg = _.sprintf( - "Error attempting to query tenant metadata for tenant '%s'. Please verify that each of the " + - "tenants specified is a valid tenant domain (e.g., abc.onmicrosoft.com). %s", tenant, err); - var ex = new core.MobileServiceError(msg, core.ErrorCodes.BadInput); - self.logger.logUser('', LogType.Error, ex); - throw ex; - } - self.validIssuers.push(issuer); - done(); - }); - }; + var tasks = _.map(tenants, tenant => done => { + self._getIssuerForTenantDomain(tenant, (err, issuer) => { + if (err) { + var msg = _.sprintf( + "Error attempting to query tenant metadata for tenant '%s'. Please verify that each of the " + + "tenants specified is a valid tenant domain (e.g., abc.onmicrosoft.com). %s", tenant, err); + var ex = new core.MobileServiceError(msg, core.ErrorCodes.BadInput); + self.logger.logUser('', LogType.Error, ex); + throw ex; + } + self.validIssuers.push(issuer); + done(); + }); }); // now execute the tasks in parallel @@ -172,10 +171,10 @@ AadLoginHandler.prototype._initializeIssuers = function (done) { // Call out to the AAD metadata endpoint for the specified tenant domain // to get the issuer. E.g. test.onmicrosoft.com => https://sts.windows.net/ae549c78-14a5-4fc8-9719-df4e1007990a AadLoginHandler.prototype._getIssuerForTenantDomain = function (tenant, callback) { - var metadataUri = _.sprintf('https://%s/%s/federationmetadata/2007-06/federationmetadata.xml', this.loginEndpoint, tenant), - parser = new xml2js.Parser(); + var metadataUri = _.sprintf('https://%s/%s/federationmetadata/2007-06/federationmetadata.xml', this.loginEndpoint, tenant); + var parser = new xml2js.Parser(); - request(metadataUri, function (err, res, body) { + request(metadataUri, (err, res, body) => { if (res.statusCode != 200) { // if the response body includes error details return them err = body || 'An unspecified error occurred.'; diff --git a/runtime/request/authentication/aadcert.js b/runtime/request/authentication/aadcert.js index fd9b9bd..881a972 100644 --- a/runtime/request/authentication/aadcert.js +++ b/runtime/request/authentication/aadcert.js @@ -43,7 +43,7 @@ AadCert.prototype.getCerts = function (callback, options) { var self = this; // Make call to get the certs - LoginHandler.makeSecureRequest(requestOptions, null, function (error, res, body) { + LoginHandler.makeSecureRequest(requestOptions, null, (error, res, body) => { var result = null; // Ensure that the request was successful if (!error && res.statusCode !== 200) { @@ -68,12 +68,12 @@ AadCert.prototype.getCerts = function (callback, options) { } callback(error, result); - }.bind(this)); + }); }; -AadCert.parseCertificates = function (json) { - var parsedKeys = JSON.parse(json), - certArray = []; +AadCert.parseCertificates = json => { + var parsedKeys = JSON.parse(json); + var certArray = []; for (var keyNum = 0; keyNum < parsedKeys.keys.length; keyNum++) { var x5TCertLabel = parsedKeys.keys[keyNum].x5t; diff --git a/runtime/request/authentication/certcachehelper.js b/runtime/request/authentication/certcachehelper.js index 69bb531..555928e 100644 --- a/runtime/request/authentication/certcachehelper.js +++ b/runtime/request/authentication/certcachehelper.js @@ -8,7 +8,7 @@ var jsonWebToken = require('../../jsonwebtoken'); exports = module.exports; -exports.isExpired = function (expDate, now) { +exports.isExpired = (expDate, now) => { if (!now) { now = new Date(); } @@ -20,7 +20,7 @@ exports.createExpiryDateFromHours = function (hoursInFuture, now) { return this.createExpiryDateFromMinutes(hoursInFuture * 60, now); }; -exports.createExpiryDateFromMinutes = function (minutesInFuture, now) { +exports.createExpiryDateFromMinutes = (minutesInFuture, now) => { if (!now) { now = new Date(); } @@ -34,8 +34,9 @@ exports.createExpiryDateFromMinutes = function (minutesInFuture, now) { exports.refreshIntervalExpired = function (minRefreshIntervalMinutes, lastRefresh) { // We allow a refresh only if we haven't refreshed in the // last minRefreshIntervalMinutes - var notBeforeDate = this.createExpiryDateFromMinutes(minRefreshIntervalMinutes, lastRefresh), - now = new Date(); + var notBeforeDate = this.createExpiryDateFromMinutes(minRefreshIntervalMinutes, lastRefresh); + + var now = new Date(); return this.isExpired(notBeforeDate, now); }; @@ -43,13 +44,13 @@ exports.refreshIntervalExpired = function (minRefreshIntervalMinutes, lastRefres // Attempts to validate the specified token using the provided cert manager. // If the token fails validation due to a kid/x5t lookup failure, a cert // refresh will be performed, and the validation will be attempted once more. -exports.validateToken = function (certManager, token, callback) { +exports.validateToken = (certManager, token, callback) => { var retry = true; // define a function to get the certs and validate the token, // so that in the case of failures we can retry - var validateToken = function (options) { - certManager.getCerts(function (error, certs) { + var validateToken = options => { + certManager.getCerts((error, certs) => { if (error) { callback(error); return; diff --git a/runtime/request/authentication/facebook.js b/runtime/request/authentication/facebook.js index 6b8cdf3..7171490 100644 --- a/runtime/request/authentication/facebook.js +++ b/runtime/request/authentication/facebook.js @@ -6,12 +6,13 @@ // login modules, it implements a very specific interface that is documented in // ../loginhandler.js. -var core = require('../../core'), - jsonWebToken = require('../../jsonwebtoken'), - url = require('url'), - LoginHandler = require('../loginhandler.js'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../../core'); + +var jsonWebToken = require('../../jsonwebtoken'); +var url = require('url'); +var LoginHandler = require('../loginhandler.js'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -35,7 +36,7 @@ function FacebookLoginHandler(authenticationCredentials, logger) { this.logger = logger; } -FacebookLoginHandler.prototype.isNewServerFlowRequest = function (request) { +FacebookLoginHandler.prototype.isNewServerFlowRequest = request => { var isNewFlow = true; // If the query includes either a 'code' parameter or an 'error' parameter @@ -134,7 +135,7 @@ FacebookLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = functi method: 'GET' }; - LoginHandler.makeSecureRequest(graphApi, null, function (error, res, body) { + LoginHandler.makeSecureRequest(graphApi, null, (error, res, body) => { var authorizationDetails = null; // Ensure that the request was successful @@ -185,7 +186,7 @@ FacebookLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = functi }); }; -FacebookLoginHandler.prototype._getUrlByRequestMode = function (request, urlName) { +FacebookLoginHandler.prototype._getUrlByRequestMode = (request, urlName) => { var providerMode = request.query.useBeta ? 'beta' : 'prod'; var url = urls[providerMode][urlName]; return url; @@ -205,7 +206,7 @@ FacebookLoginHandler.prototype._normalizeScope = function () { }; function _retrieveLongLivedAccessToken(options, errorPrefix, callback) { - LoginHandler.makeSecureRequest(options, null, function (error, res, body) { + LoginHandler.makeSecureRequest(options, null, (error, res, body) => { var providerToken = null; diff --git a/runtime/request/authentication/google.js b/runtime/request/authentication/google.js index 68af6bb..1d295bd 100644 --- a/runtime/request/authentication/google.js +++ b/runtime/request/authentication/google.js @@ -6,13 +6,14 @@ // login modules, it implements a very specific interface that is documented in // ../loginhandler.js. -var core = require('../../core'), - jsonWebToken = require('../../jsonwebtoken'), - LoginHandler = require('../loginhandler'), - _ = require('underscore'), - _str = require('underscore.string'), - GoogleCert = require('./googlecert'), - certCacheHelper = require('./certcachehelper'); +var core = require('../../core'); + +var jsonWebToken = require('../../jsonwebtoken'); +var LoginHandler = require('../loginhandler'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var GoogleCert = require('./googlecert'); +var certCacheHelper = require('./certcachehelper'); _.mixin(_str.exports()); @@ -25,7 +26,7 @@ function GoogleLoginHandler(authenticationCredentials, logger) { this.logger = logger; } -GoogleLoginHandler.prototype.isNewServerFlowRequest = function (request) { +GoogleLoginHandler.prototype.isNewServerFlowRequest = request => { var isNewFlow = true; // If the query includes either a 'code' parameter or an 'error' parameter @@ -52,11 +53,11 @@ GoogleLoginHandler.prototype.getNewServerFlowResponseHeaders = function (request }; GoogleLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) { - var body = request.body, - self = this; + var body = request.body; + var self = this; if (_.isObject(body) && _.isString(body.id_token)) { - certCacheHelper.validateToken(this.googleCert, body.id_token, function (error, validatedIdToken) { + certCacheHelper.validateToken(this.googleCert, body.id_token, (error, validatedIdToken) => { if (error) { callback(error); return; @@ -102,16 +103,17 @@ GoogleLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function (r }; GoogleLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, providerInformation, callback, options) { - var self = this, - providerId = providerInformation.id_token.claims.sub, - authorizationDetails = { - providerId: providerId, - claims: { - }, - secrets: { - } - }; - + var self = this; + var providerId = providerInformation.id_token.claims.sub; + + var authorizationDetails = { + providerId, + claims: { + }, + secrets: { + } + }; + var accessToken = providerInformation.access_token; if (accessToken) { // in the client flow, we won't have an access_token @@ -119,15 +121,16 @@ GoogleLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function } if (accessToken && options.usersEnabled) { - var googleUri = '/oauth2/v3/userinfo?access_token=' + encodeURIComponent(accessToken), - graphApi = { - host: 'www.googleapis.com', - port: 443, - path: googleUri, - method: 'GET' - }; + var googleUri = '/oauth2/v3/userinfo?access_token=' + encodeURIComponent(accessToken); - LoginHandler.makeSecureRequest(graphApi, null, function (error, res, body) { + var graphApi = { + host: 'www.googleapis.com', + port: 443, + path: googleUri, + method: 'GET' + }; + + LoginHandler.makeSecureRequest(graphApi, null, (error, res, body) => { if (error || res.statusCode !== 200) { callback(new Error('Failed to retrieve user info for google due to error: ' + error)); } @@ -175,10 +178,11 @@ GoogleLoginHandler.prototype._getProviderToken = function (code, currentUri, idT headers: { 'Content-Type': 'application/x-www-form-urlencoded' } - }, - self = this; + }; - LoginHandler.makeSecureRequest(options, authParams, function (error, res, authBody) { + var self = this; + + LoginHandler.makeSecureRequest(options, authParams, (error, res, authBody) => { // Ensure that the request was successful if (!error && res.statusCode !== 200) { error = new Error('The Google API request failed with HTTP status code ' + res.statusCode); @@ -191,11 +195,12 @@ GoogleLoginHandler.prototype._getProviderToken = function (code, currentUri, idT // Response should contain accessToken and id_token. (If we change initial redirect // to offline, it would also contain refresh_token) - var parsedResponse = JSON.parse(authBody), - idToken = parsedResponse.id_token; + var parsedResponse = JSON.parse(authBody); + + var idToken = parsedResponse.id_token; // Ensure the id_token returned is valid and stash the parsed response to re-use within getAuthorizationDetailsFromProviderToken - certCacheHelper.validateToken(self.googleCert, idToken, function (innerError, responseIdToken) { + certCacheHelper.validateToken(self.googleCert, idToken, (innerError, responseIdToken) => { if (innerError) { callback(innerError); return; diff --git a/runtime/request/authentication/googlecert.js b/runtime/request/authentication/googlecert.js index 3aa1db4..d28a0b5 100644 --- a/runtime/request/authentication/googlecert.js +++ b/runtime/request/authentication/googlecert.js @@ -4,8 +4,9 @@ // // This module provides a way to asynchronously get Google certs to validate Google id tokens -var LoginHandler = require('../loginhandler.js'), - certCacheHelper = require('./certcachehelper'); +var LoginHandler = require('../loginhandler.js'); + +var certCacheHelper = require('./certcachehelper'); exports = module.exports = GoogleCert; @@ -42,7 +43,7 @@ GoogleCert.prototype.getCerts = function (callback, options) { var self = this; // Make call to get the certs - LoginHandler.makeSecureRequest(requestOptions, null, function (error, res, body) { + LoginHandler.makeSecureRequest(requestOptions, null, (error, res, body) => { var result = null; // Ensure that the request was successful diff --git a/runtime/request/authentication/microsoftaccount.js b/runtime/request/authentication/microsoftaccount.js index 524cad9..c245d03 100644 --- a/runtime/request/authentication/microsoftaccount.js +++ b/runtime/request/authentication/microsoftaccount.js @@ -9,11 +9,12 @@ // The server authentication flow is documented at: // http://msdn.microsoft.com/en-us/library/live/hh243647.aspx#authcodegrant -var core = require('../../core'), - jsonWebToken = require('../../jsonwebtoken'), - LoginHandler = require('../loginhandler'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../../core'); + +var jsonWebToken = require('../../jsonwebtoken'); +var LoginHandler = require('../loginhandler'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -25,7 +26,7 @@ function MicrosoftAccountLoginHandler(authenticationCredentials, logger) { this.logger = logger; } -MicrosoftAccountLoginHandler.prototype.isNewServerFlowRequest = function (request) { +MicrosoftAccountLoginHandler.prototype.isNewServerFlowRequest = request => { var isNewFlow = true; // If the query includes either a 'code' parameter or an 'error' parameter @@ -55,7 +56,7 @@ MicrosoftAccountLoginHandler.prototype.getNewServerFlowResponseHeaders = functio callback(null, { Location: microsoftAccountUri }); }; -MicrosoftAccountLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) { +MicrosoftAccountLoginHandler.prototype.getProviderTokenFromClientFlowRequest = (request, callback) => { var error = null; var providerToken = null; @@ -107,7 +108,7 @@ MicrosoftAccountLoginHandler.prototype.getProviderTokenFromServerFlowRequest = f } }; - LoginHandler.makeSecureRequest(options, data, function (error, res, body) { + LoginHandler.makeSecureRequest(options, data, (error, res, body) => { var providerToken = null; @@ -147,13 +148,15 @@ MicrosoftAccountLoginHandler.prototype.getProviderTokenFromServerFlowRequest = f }; MicrosoftAccountLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, providerToken, callback, options) { - var self = this, - // Parse the authentication token portion of the providerToken - unparsedToken = providerToken.authenticationToken, - key = this.authenticationCredentials.microsoftaccount.clientSecret, - parsedToken = null, - error = null, - authorizationDetails = null; + var self = this; + + var // Parse the authentication token portion of the providerToken + unparsedToken = providerToken.authenticationToken; + + var key = this.authenticationCredentials.microsoftaccount.clientSecret; + var parsedToken = null; + var error = null; + var authorizationDetails = null; try { parsedToken = jsonWebToken.parse(unparsedToken, key, jsonWebToken.windowsLiveSigningSuffix); @@ -177,15 +180,16 @@ MicrosoftAccountLoginHandler.prototype.getAuthorizationDetailsFromProviderToken } if (authorizationDetails && authorizationDetails.secrets.accessToken && options.usersEnabled) { - var microsftUri = '/v5.0/me?access_token=' + encodeURIComponent(authorizationDetails.secrets.accessToken), - graphApi = { - host: 'apis.live.net', - port: 443, - path: microsftUri, - method: 'GET' - }; + var microsftUri = '/v5.0/me?access_token=' + encodeURIComponent(authorizationDetails.secrets.accessToken); - LoginHandler.makeSecureRequest(graphApi, null, function (error, res, body) { + var graphApi = { + host: 'apis.live.net', + port: 443, + path: microsftUri, + method: 'GET' + }; + + LoginHandler.makeSecureRequest(graphApi, null, (error, res, body) => { if (error || res.statusCode !== 200) { callback(new Error('Failed to retrieve user info for microsoft account due to error: ' + error)); } diff --git a/runtime/request/authentication/twitter.js b/runtime/request/authentication/twitter.js index 670a256..b72d8c0 100644 --- a/runtime/request/authentication/twitter.js +++ b/runtime/request/authentication/twitter.js @@ -12,13 +12,14 @@ // An Example of this flow can be found at: // https://gist.github.com/555607 -var core = require('../../core'), - jsonWebToken = require('../../jsonwebtoken'), - OAuth = require('oauth').OAuth, - LoginHandler = require('../loginhandler'), - Encryptor = require('../../encryptor'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../../core'); + +var jsonWebToken = require('../../jsonwebtoken'); +var OAuth = require('oauth').OAuth; +var LoginHandler = require('../loginhandler'); +var Encryptor = require('../../encryptor'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -38,7 +39,7 @@ TwitterLoginHandler.prototype.oAuthStateNotSupported = true; // is important. This ensures that the LoginHandler.js will clean up this cookie for us. TwitterLoginHandler.RequestTokenCookieName = 'wams_rt'; -TwitterLoginHandler.prototype.isNewServerFlowRequest = function (request) { +TwitterLoginHandler.prototype.isNewServerFlowRequest = request => { var isNewFlow = true; // If the query includes an 'oauth_verifier' parameter then this is the @@ -57,7 +58,7 @@ TwitterLoginHandler.prototype.getNewServerFlowResponseHeaders = function (reques consumerSecret, currentUri); - oauth.getOAuthRequestToken(function (error, requestToken, requestTokenSecret, results) { + oauth.getOAuthRequestToken((error, requestToken, requestTokenSecret, results) => { if (error) { error = new Error('Unable to obtain OAuth request token from Twitter.'); @@ -84,7 +85,7 @@ TwitterLoginHandler.prototype.getNewServerFlowResponseHeaders = function (reques }); }; -TwitterLoginHandler.prototype.getProviderTokenFromClientFlowRequest = function (request, callback) { +TwitterLoginHandler.prototype.getProviderTokenFromClientFlowRequest = (request, callback) => { var error = new core.MobileServiceError('POST of Twitter token is not supported.', core.ErrorCodes.MethodNotAllowed); callback(error, null); }; @@ -138,7 +139,7 @@ TwitterLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function ( oauth.getOAuthAccessToken(requestToken.rt, requestToken.rts, request.query.oauth_verifier, - function (error, accessToken, accessTokenSecret, results) { + (error, accessToken, accessTokenSecret, results) => { var providerToken = null; if (error) { @@ -148,9 +149,9 @@ TwitterLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function ( // Create a 'providerToken' out of the accessToken, accessTokenSecret and results if (!error) { providerToken = { - accessToken: accessToken, - accessTokenSecret: accessTokenSecret, - results: results + accessToken, + accessTokenSecret, + results }; } @@ -158,7 +159,7 @@ TwitterLoginHandler.prototype.getProviderTokenFromServerFlowRequest = function ( }); }; -TwitterLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = function (request, providerToken, callback, options) { +TwitterLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = (request, providerToken, callback, options) => { var error = null; var authorizationDetails = null; @@ -170,7 +171,7 @@ TwitterLoginHandler.prototype.getAuthorizationDetailsFromProviderToken = functio else { var providerId = providerToken.results.user_id; authorizationDetails = { - providerId: providerId, + providerId, claims: { // name: providerToken.results.name }, diff --git a/runtime/request/dataoperation.js b/runtime/request/dataoperation.js index fdfc117..69c8258 100644 --- a/runtime/request/dataoperation.js +++ b/runtime/request/dataoperation.js @@ -4,15 +4,16 @@ // // This module is encapsulates the data operations invoked by scripts. -var Query = require('../Zumo.Node').Query, - scriptErrors = require('../script/scripterror'), - StatusCodes = require('../statuscodes').StatusCodes, - resource = require('../resources'), - core = require('../core'), - _ = require('underscore'), - _str = require('underscore.string'); +var Query = require('../Zumo.Node').Query; - _.mixin(_str.exports()); +var scriptErrors = require('../script/scripterror'); +var StatusCodes = require('../statuscodes').StatusCodes; +var resource = require('../resources'); +var core = require('../core'); +var _ = require('underscore'); +var _str = require('underscore.string'); + +_.mixin(_str.exports()); exports = module.exports = DataOperation; @@ -41,7 +42,7 @@ DataOperation.prototype.read = function (table, query, options, responseCallback projection = query.getComponents().projection; } - var responseEvaluator = function (results) { + var responseEvaluator = results => { if (query.id !== undefined && results && (results.length === 0)) { return { error: self._handleItemNotFound(query.id) }; } else { @@ -51,7 +52,7 @@ DataOperation.prototype.read = function (table, query, options, responseCallback } } - return { results: results }; + return { results }; } }; @@ -71,7 +72,7 @@ DataOperation.prototype.read = function (table, query, options, responseCallback DataOperation.prototype.update = function (table, item, options, responseCallback, scriptCallback) { var self = this; - var responseEvaluator = function (rowCount) { + var responseEvaluator = rowCount => { if (rowCount === 0) { return { error: self._handleItemNotFound(item.id) }; } else { @@ -86,9 +87,9 @@ DataOperation.prototype.update = function (table, item, options, responseCallbac }; DataOperation.prototype.del = function (table, itemOrId, options, responseCallback, scriptCallback) { - var self = this, - id = itemOrId, - version = null; + var self = this; + var id = itemOrId; + var version = null; if (core.isObject(itemOrId)) { @@ -96,7 +97,7 @@ DataOperation.prototype.del = function (table, itemOrId, options, responseCallba version = itemOrId.__version; } - var responseEvaluator = function (rowCount) { + var responseEvaluator = rowCount => { if (rowCount === 0) { return { error: self._handleItemNotFound(id) }; } else { @@ -131,7 +132,7 @@ function unwrapInlineCount(results) { DataOperation.prototype.createStorageCallback = function (table, successCode, responseCallback, scriptCallback, responseEvaluator) { var self = this; - return function (err, results) { + return (err, results) => { if (typeof responseEvaluator === 'function' && !err) { // Use the passed in response evaluator function to update the error // and results objects passed back from the storage layer. @@ -173,7 +174,7 @@ DataOperation.prototype.createStorageCallback = function (table, successCode, re // if the specified query is a query builder, convert it back to our // query representation -DataOperation.prototype.unwrapQueryBuilder = function (query) { +DataOperation.prototype.unwrapQueryBuilder = query => { if (query && query.constructor === Query) { var unwrapped = {}; @@ -211,6 +212,4 @@ DataOperation.prototype.unwrapQueryBuilder = function (query) { return query; }; -DataOperation.prototype._handleItemNotFound = function (id) { - return new core.MobileServiceError(_.sprintf(resource.itemNotFound, id.toString()), core.ErrorCodes.ItemNotFound); -}; +DataOperation.prototype._handleItemNotFound = id => new core.MobileServiceError(_.sprintf(resource.itemNotFound, id.toString()), core.ErrorCodes.ItemNotFound); diff --git a/runtime/request/datapipeline.js b/runtime/request/datapipeline.js index e599541..5992b13 100644 --- a/runtime/request/datapipeline.js +++ b/runtime/request/datapipeline.js @@ -6,17 +6,18 @@ // if defined for the operation. Script services are exposed to scripts via the context argument // passed to the script function. A separate dataPipeline instance is created per request. -var core = require('../core'), - DataOperation = require('./dataoperation'), - scriptErrors = require('../script/scripterror'), - ScriptState = require('../script/scriptstate'), - ScriptManager = require('../script/scriptmanager'), - resource = require('../resources'), - Query = require('../Zumo.Node').Query, - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../core'); - _.mixin(_str.exports()); +var DataOperation = require('./dataoperation'); +var scriptErrors = require('../script/scripterror'); +var ScriptState = require('../script/scriptstate'); +var ScriptManager = require('../script/scriptmanager'); +var resource = require('../resources'); +var Query = require('../Zumo.Node').Query; +var _ = require('underscore'); +var _str = require('underscore.string'); + +_.mixin(_str.exports()); require('../storage/sqlhelpers'); @@ -51,7 +52,7 @@ DataPipeline.prototype.read = function (query, responseCallback) { // if this is a query by id, we wrap the response callback // so we can do result validation to make sure only a singleton is returned if (query.id) { - responseCallback = _.wrap(responseCallback, function (originalCallback, err, results, statusCode) { + responseCallback = _.wrap(responseCallback, (originalCallback, err, results, statusCode) => { if (results && core.isArray(results)) { if (results.length === 1) { results = results[0]; @@ -89,7 +90,7 @@ DataPipeline.prototype.update = function (item, responseCallback) { // define a pre-execute callback to do validation of the operation // prior to actually executing the data opration - var executeCallback = function (scriptArg) { + var executeCallback = scriptArg => { if (scriptArg.id !== originalId) { var error = new core.MobileServiceError("Update scripts cannot modify the id of the item to be updated.", core.ErrorCodes.ScriptError); @@ -141,7 +142,7 @@ DataPipeline.prototype._executeScript = function (operationName, scriptArg, resp var logSourceName = self.scriptManager.getLogSourceName(this.table, operationName); // Create a small state machine which will manage script execution. var scriptState = new ScriptState(operationName, scriptArg, tableMetadata, responseCallback, self.logger, logSourceName); - scriptState.executeCallback = function (scriptCallback, systemParameters) { + scriptState.executeCallback = (scriptCallback, systemParameters) => { // If the callback doesn't exist or returns true, run the data operation if (!executeCallback || executeCallback(scriptArg)) { var dataOperation = self._createDataOperation(operationName); @@ -150,14 +151,14 @@ DataPipeline.prototype._executeScript = function (operationName, scriptArg, resp } }; - self.operationContext.execute = function (callbackOptions) { + self.operationContext.execute = callbackOptions => { self.logger.trace(logSource, 'Script called execute'); scriptState.execute(callbackOptions); }; self.operationContext.respond = function (statusCode, result) { self.logger.trace(logSource, 'Script called respond'); - scriptState.respond.apply(scriptState, arguments); + scriptState.respond(...arguments); }; var runnerOptions = { @@ -211,22 +212,20 @@ DataPipeline.prototype.getQueryBuilder = function (query) { return queryBuilder; }; -DataPipeline.prototype._wrapWithNoScriptErrorTransforms = function (responseCallback) { - return _.wrap(responseCallback, function (oldCallback, err, result, statusCode) { - // There is no script. Any non application level sql error will be treated - // as an end user input error. - if (SqlHelpers.isSqlError(err) && !SqlHelpers.isApplicationError(err)) { - oldCallback(new core.MobileServiceError(resource.badRequest, core.ErrorCodes.BadInput)); - } else { - oldCallback(err, result, statusCode); - } - }); -}; +DataPipeline.prototype._wrapWithNoScriptErrorTransforms = responseCallback => _.wrap(responseCallback, (oldCallback, err, result, statusCode) => { + // There is no script. Any non application level sql error will be treated + // as an end user input error. + if (SqlHelpers.isSqlError(err) && !SqlHelpers.isApplicationError(err)) { + oldCallback(new core.MobileServiceError(resource.badRequest, core.ErrorCodes.BadInput)); + } else { + oldCallback(err, result, statusCode); + } +}); DataPipeline.prototype._wrapWithUserLogging = function (responseCallback, operationName) { var self = this; - return _.wrap(responseCallback, function (oldCallback, err, result, statusCode) { + return _.wrap(responseCallback, (oldCallback, err, result, statusCode) => { // This callback pass-through will log any unhandled/unlogged SQL error messages // that are about to be passed up stack and returned to the user. // This block of code will log all unhandled SQL errors regardless of diff --git a/runtime/request/diagnosticshandler.js b/runtime/request/diagnosticshandler.js index beaff5c..d1482c6 100644 --- a/runtime/request/diagnosticshandler.js +++ b/runtime/request/diagnosticshandler.js @@ -6,9 +6,10 @@ // which is used by the availability monitoring feature. This endpoint is secured - // it requires the master key header. -var StatusCodes = require('../statuscodes').StatusCodes, - _ = require('underscore'), - _str = require('underscore.string'); +var StatusCodes = require('../statuscodes').StatusCodes; + +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -23,9 +24,9 @@ function DiagnosticsHandler(appName, version, storage) { } DiagnosticsHandler.prototype.handle = function (req, res) { - var logger = req._context.logger, - responseCallback = req._context.responseCallback, - status = StatusCodes.OK; + var logger = req._context.logger; + var responseCallback = req._context.responseCallback; + var status = StatusCodes.OK; logger.trace(logSource, 'Processing request'); @@ -40,7 +41,7 @@ DiagnosticsHandler.prototype.handle = function (req, res) { } }; - this._getSqlStatus(req, function (err, sqlStatus) { + this._getSqlStatus(req, (err, sqlStatus) => { if (err) { // indicate degraded service via the top level status code status = StatusCodes.SERVICE_UNAVAILABLE; @@ -58,19 +59,22 @@ DiagnosticsHandler.prototype.handle = function (req, res) { }; DiagnosticsHandler.prototype._getSqlStatus = function (req, callback) { - var logger = req._context.logger, - sqlStatus = { - statusCode: StatusCodes.OK, - latencyMS: 0 - }, - startTime = new Date(), - options = { - disableUserLog: true - }; + var logger = req._context.logger; + + var sqlStatus = { + statusCode: StatusCodes.OK, + latencyMS: 0 + }; + + var startTime = new Date(); + + var options = { + disableUserLog: true + }; logger.trace(logSource, 'Checking SQL connectivity'); - this.storage.executeSql('SELECT', "SELECT getutcdate() AS currentDate", null, logger, options, function (err) { + this.storage.executeSql('SELECT', "SELECT getutcdate() AS currentDate", null, logger, options, err => { if (err) { sqlStatus.statusCode = StatusCodes.SERVICE_UNAVAILABLE; var errDetails = []; diff --git a/runtime/request/errorhelper.js b/runtime/request/errorhelper.js index 490a167..a7b5d0a 100644 --- a/runtime/request/errorhelper.js +++ b/runtime/request/errorhelper.js @@ -4,12 +4,13 @@ // // This module has helper functions for transforming exceptions to http errors -var core = require('../core.js'), - StatusCodes = require('../statuscodes').StatusCodes; +var core = require('../core.js'); + +var StatusCodes = require('../statuscodes').StatusCodes; ErrorHelper = {}; -ErrorHelper.formatError = function (err, statusCode, requestID) { +ErrorHelper.formatError = (err, statusCode, requestID) => { if (err) { var formattedErr; @@ -75,11 +76,9 @@ ErrorHelper.formatError = function (err, statusCode, requestID) { return err; }; -ErrorHelper.createInternalServerError = function () { - return { - code: StatusCodes.INTERNAL_SERVER_ERROR, - error: 'Error: Internal Server Error' - }; -}; +ErrorHelper.createInternalServerError = () => ({ + code: StatusCodes.INTERNAL_SERVER_ERROR, + error: 'Error: Internal Server Error' +}); exports = module.exports = ErrorHelper; \ No newline at end of file diff --git a/runtime/request/etaghelper.js b/runtime/request/etaghelper.js index f5f1f82..58d1e82 100644 --- a/runtime/request/etaghelper.js +++ b/runtime/request/etaghelper.js @@ -4,12 +4,13 @@ // // This module has helper functions for working with etags -var resource = require('../resources'), - core = require('../core.js'); +var resource = require('../resources'); + +var core = require('../core.js'); ETagHelper = {}; -ETagHelper.doesIfNoneMatchHeaderMatchesEtag = function (ifNoneMatch, etag) { +ETagHelper.doesIfNoneMatchHeaderMatchesEtag = (ifNoneMatch, etag) => { // an if-none-match header can be a '*' or a comma-seperated list // of etage values var doesMatch = false; @@ -24,7 +25,7 @@ ETagHelper.doesIfNoneMatchHeaderMatchesEtag = function (ifNoneMatch, etag) { // check each etag in the if-none-match header against // the response etag - ifNoneMatch.split(",").forEach(function (ifNoneMatchValue) { + ifNoneMatch.split(",").forEach(ifNoneMatchValue => { if (ifNoneMatchValue.trim() === etag) { doesMatch = true; } @@ -35,7 +36,7 @@ ETagHelper.doesIfNoneMatchHeaderMatchesEtag = function (ifNoneMatch, etag) { return doesMatch; }; -ETagHelper.setVersionFromIfMatchHeader = function (request, item, tableMetadata, responseCallback) { +ETagHelper.setVersionFromIfMatchHeader = (request, item, tableMetadata, responseCallback) => { // check for an if-match header and set the body version if (!tableMetadata.supportsConflict) { return true; @@ -55,7 +56,7 @@ ETagHelper.setVersionFromIfMatchHeader = function (request, item, tableMetadata, return true; }; -ETagHelper.parseIfMatchHeader = function (request) { +ETagHelper.parseIfMatchHeader = request => { var ifMatch = request.headers["if-match"]; if (!ifMatch || ifMatch.trim() === '*') { return null; @@ -64,7 +65,7 @@ ETagHelper.parseIfMatchHeader = function (request) { var etags = []; try { ifMatch.split(",") - .forEach(function (etag) { + .forEach(etag => { etag = JSON.parse(etag.trim()); if (!core.isString(etag)) { throw new core.MobileServiceError(resource.invalidIfMatchHeader, core.ErrorCodes.BadInput); diff --git a/runtime/request/html/corshelper.js b/runtime/request/html/corshelper.js index 38c83f6..fad835d 100644 --- a/runtime/request/html/corshelper.js +++ b/runtime/request/html/corshelper.js @@ -5,22 +5,22 @@ // Supplies CORS headers as per app configuration function CorsHelper(options) { - var url = require('url'); var defaultCrossDomainWhitelist = [ { host: 'localhost' } - ], - configuredCrossDomainWhitelist = options.crossDomainWhitelist || defaultCrossDomainWhitelist, - isNullAllowed = false, - allowedHostNamesRegexes = getHostNameRegexesFromConfiguredWhitelist(configuredCrossDomainWhitelist), - allowedHeadersRegex = /^[a-z0-9\-\,\s]{1,500}$/i; // Lenient enough to match any header names we will ever use + ]; // Lenient enough to match any header names we will ever use + + var configuredCrossDomainWhitelist = options.crossDomainWhitelist || defaultCrossDomainWhitelist; + var isNullAllowed = false; + var allowedHostNamesRegexes = getHostNameRegexesFromConfiguredWhitelist(configuredCrossDomainWhitelist); + var allowedHeadersRegex = /^[a-z0-9\-\,\s]{1,500}$/i; this.getCorsHeaders = function (request) { - var incomingHeaders = request.headers || {}, - requestedOrigin = incomingHeaders.origin, - requestedHeaders = incomingHeaders['access-control-request-headers'], - corsHeaders = {}; + var incomingHeaders = request.headers || {}; + var requestedOrigin = incomingHeaders.origin; + var requestedHeaders = incomingHeaders['access-control-request-headers']; + var corsHeaders = {}; if (requestedOrigin && this.isAllowedOrigin(requestedOrigin)) { // CORS doesn't permit multiple origins or wildcards, so the standard @@ -43,17 +43,20 @@ function CorsHelper(options) { return corsHeaders; }; - this.isAllowedOrigin = function (origin) { + this.isAllowedOrigin = origin => { // special case 'null' that is sent from browser on local files if (isNullAllowed && origin === 'null') { return true; } // Extract the components of the origin - var parsedOrigin = url.parse(origin), - originHostName = parsedOrigin && parsedOrigin.hostname, // Note that "host" includes the port; "hostname" doesn't - originProtocol = parsedOrigin && parsedOrigin.protocol, - originPath = parsedOrigin && parsedOrigin.path; + var parsedOrigin = url.parse(origin); + + var // Note that "host" includes the port; "hostname" doesn't + originHostName = parsedOrigin && parsedOrigin.hostname; + + var originProtocol = parsedOrigin && parsedOrigin.protocol; + var originPath = parsedOrigin && parsedOrigin.path; // Validate protocol if (!originProtocol || !isAllowedProtocol(originProtocol)) { @@ -70,17 +73,15 @@ function CorsHelper(options) { return false; } - return allowedHostNamesRegexes.some(function (hostNameRegex) { - return hostNameRegex.test(originHostName); - }); + return allowedHostNamesRegexes.some(hostNameRegex => hostNameRegex.test(originHostName)); }; - + function isAllowedProtocol(protocol) { // This means that filesystem origins ("null") aren't supported right now // even if you allow "*" return protocol === 'http:' || protocol === 'https:' || protocol === 'ms-appx-web:'; } - + function isAllowedPath(path) { // The W3C spec isn't especially clear about host origins should be formatted, // so to be graceful we permit trailing slashes even though I'm not aware of a @@ -114,7 +115,7 @@ function CorsHelper(options) { var result = []; if (whitelist) { - whitelist.forEach(function (whitelistEntry) { + whitelist.forEach(whitelistEntry => { if (!whitelistEntry) { return; } diff --git a/runtime/request/html/crossdomainhandler.js b/runtime/request/html/crossdomainhandler.js index 777f538..a55148c 100644 --- a/runtime/request/html/crossdomainhandler.js +++ b/runtime/request/html/crossdomainhandler.js @@ -17,19 +17,19 @@ exports = module.exports = CrossDomainHandler; -var core = require('../../core'), - templating = require('./templating'), - StatusCodes = require('../../statuscodes').StatusCodes, - logSource = 'CrossDomainHandler'; +var core = require('../../core'); +var templating = require('./templating'); +var StatusCodes = require('../../statuscodes').StatusCodes; +var logSource = 'CrossDomainHandler'; function CrossDomainHandler(corsHelper) { this.corsHelper = corsHelper; } CrossDomainHandler.prototype.handle = function (req, res) { - var logger = req._context.logger, - responseCallback = req._context.responseCallback; - + var logger = req._context.logger; + var responseCallback = req._context.responseCallback; + logger.trace(logSource, 'Processing request'); switch (req.params.crossDomainItem) { @@ -63,13 +63,14 @@ CrossDomainHandler.prototype.handle = function (req, res) { CrossDomainHandler.prototype._getAllowedOriginFromQueryParams = function (request, queryParamName, responseCallback) { // This function returns a truthy value only if it satisfies the whitelist - var queryParams = request.query, - attemptedOrigin = queryParams && queryParams[queryParamName]; + var queryParams = request.query; + + var attemptedOrigin = queryParams && queryParams[queryParamName]; if (attemptedOrigin && this.corsHelper.isAllowedOrigin(attemptedOrigin)) { return attemptedOrigin; } - + responseCallback(new core.MobileServiceError('Not a whitelisted origin: ' + attemptedOrigin), null, StatusCodes.UNAUTHORIZED); return null; }; \ No newline at end of file diff --git a/runtime/request/html/templating.js b/runtime/request/html/templating.js index 04a8e18..cdc1f87 100644 --- a/runtime/request/html/templating.js +++ b/runtime/request/html/templating.js @@ -6,14 +6,14 @@ // We could switch to a proper template engine at some point if desired exports = module.exports = { - render: render + render }; -var fs = require('fs'), - path = require('path'), - StatusCodes = require('../../statuscodes').StatusCodes, - templatesDir = path.resolve(__dirname, 'templates'), - templatesCache = readAllTemplatesSync(templatesDir); // Load only once on app initialization +var fs = require('fs'); // Load only once on app initialization +var path = require('path'); +var StatusCodes = require('../../statuscodes').StatusCodes; +var templatesDir = path.resolve(__dirname, 'templates'); +var templatesCache = readAllTemplatesSync(templatesDir); function render(responseCallback, templateName, data, responseHeaders) { if (!templatesCache.hasOwnProperty(templateName)) { @@ -45,13 +45,11 @@ function replaceTokens(text, tokens) { } function readAllTemplatesSync(dir) { - var files = fs.readdirSync(dir), - htmlFiles = files.filter(function (filename) { - return path.extname(filename) == '.html'; - }), - result = {}; + var files = fs.readdirSync(dir); + var htmlFiles = files.filter(filename => path.extname(filename) == '.html'); + var result = {}; - htmlFiles.forEach(function (filename) { + htmlFiles.forEach(filename => { result[filename] = fs.readFileSync(path.resolve(dir, filename), 'utf8'); }); diff --git a/runtime/request/loginhandler.js b/runtime/request/loginhandler.js index 9276c67..d242923 100644 --- a/runtime/request/loginhandler.js +++ b/runtime/request/loginhandler.js @@ -50,21 +50,21 @@ exports = module.exports = LoginHandler; -var core = require('../core'), - UserService = require('../users/userService'), - jsonWebToken = require('../jsonwebtoken'), - StatusCodes = require('../statuscodes').StatusCodes, - templating = require('./html/templating'), - https = require('https'), - Encryptor = require('../encryptor'), - Twitter = require('./authentication/twitter'), - Google = require('./authentication/google'), - Facebook = require('./authentication/facebook'), - MicrosoftAccount = require('./authentication/microsoftaccount'), - Aad = require('./authentication/aad'), - resources = require('../resources'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../core'); +var UserService = require('../users/userService'); +var jsonWebToken = require('../jsonwebtoken'); +var StatusCodes = require('../statuscodes').StatusCodes; +var templating = require('./html/templating'); +var https = require('https'); +var Encryptor = require('../encryptor'); +var Twitter = require('./authentication/twitter'); +var Google = require('./authentication/google'); +var Facebook = require('./authentication/facebook'); +var MicrosoftAccount = require('./authentication/microsoftaccount'); +var Aad = require('./authentication/aad'); +var resources = require('../resources'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -114,10 +114,10 @@ LoginHandler.prototype.initialize = function (done) { }; LoginHandler.prototype.handle = function (req, res) { - var logger = req._context.logger, - metrics = req._context.metrics, - responseCallback = req._context.responseCallback, - request = req._context.parsedRequest; + var logger = req._context.logger; + var metrics = req._context.metrics; + var responseCallback = req._context.responseCallback; + var request = req._context.parsedRequest; request.query = req.query; // login needs the raw query request.authenticationProvider = req.params.authenticationProvider; @@ -135,10 +135,10 @@ LoginHandler.prototype.handle = function (req, res) { var loginContext = { loginHandler: this, corsHelper: this.corsHelper, - request: request, - responseCallback: responseCallback, - logger: logger, - metrics: metrics + request, + responseCallback, + logger, + metrics }; // If this is a completed server flow, just return OK @@ -199,7 +199,7 @@ LoginHandler.prototype._handleClientFlowRequest = function (loginContext) { logger.trace(logSource, _.sprintf('Getting the %s provider token from the client flow request.', providerName)); // Get the provider's token out of the request - provider.getProviderTokenFromClientFlowRequest(request, function (error, providerToken) { + provider.getProviderTokenFromClientFlowRequest(request, (error, providerToken) => { if (error) { _respondWithError(loginContext, error); return; @@ -208,18 +208,18 @@ LoginHandler.prototype._handleClientFlowRequest = function (loginContext) { logger.trace(logSource, _.sprintf('Getting the %s provider token from the client flow request succeeded.', providerName)); logger.trace(logSource, _.sprintf('Exchanging the %s provider token for a Windows Azure Mobile Services token.', providerName)); - handler.userService.isEnabled(function (err, usersEnabled) { + handler.userService.isEnabled((err, usersEnabled) => { var options = { - usersEnabled: usersEnabled + usersEnabled }; - provider.getAuthorizationDetailsFromProviderToken(request, providerToken, function (innerError, authorizationDetails) { + provider.getAuthorizationDetailsFromProviderToken(request, providerToken, (innerError, authorizationDetails) => { if (innerError) { _respondWithError(loginContext, innerError); return; } - self._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, function (err, responseBody) { + self._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, (err, responseBody) => { if (err) { _respondWithError(loginContext, err); return; @@ -232,7 +232,7 @@ LoginHandler.prototype._handleClientFlowRequest = function (loginContext) { }); }; -LoginHandler.prototype._handleServerFlowRequest = function (loginContext) { +LoginHandler.prototype._handleServerFlowRequest = loginContext => { // A server authentication flow will consist of two requests. The client will first // send a request to initiate the flow for a particular provider and we'll redirect // the client to the provider's login page. After the user logs in with the provider, @@ -267,20 +267,20 @@ LoginHandler.prototype._handleServerFlowRequest = function (loginContext) { // Any errors that might occur when making the request or getting the response are // marshalled to the callback, which has the following signature: // callback(error, response, responseBody) -LoginHandler.makeSecureRequest = function (requestOptions, requestBody, callback) { +LoginHandler.makeSecureRequest = (requestOptions, requestBody, callback) => { - var request = https.request(requestOptions, function (response) { + var request = https.request(requestOptions, response => { var responseBody = ''; - response.on('data', function (data) { + response.on('data', data => { responseBody += data; }); - response.on('end', function () { + response.on('end', () => { callback(null, response, responseBody); }); }); - request.on('error', function (error) { + request.on('error', error => { callback(error, null, null); }); @@ -289,7 +289,7 @@ LoginHandler.makeSecureRequest = function (requestOptions, requestBody, callback // Simplifies reading a value for a cookie from request/response headers. // RETURNS: cookie value or null if there was no such cookie -LoginHandler.getCookieFromHeaders = function (name, headers) { +LoginHandler.getCookieFromHeaders = (name, headers) => { // Get the cookie value and decode it var cookies = _parseCookies(headers); var value = cookies[name]; @@ -302,7 +302,7 @@ LoginHandler.getCookieFromHeaders = function (name, headers) { // Simplifies writing a value for a cookie to response headers. // RETURNS: nothing -LoginHandler.addCookieToHeaders = function (name, value, headers) { +LoginHandler.addCookieToHeaders = (name, value, headers) => { // Create the cookie var encodedValue = encodeURIComponent(value); if (encodedValue === 'deleted') { @@ -332,14 +332,12 @@ LoginHandler.addCookieToHeaders = function (name, value, headers) { headers._parsedCookies[name] = value; }; -LoginHandler.createOAuthRedirectState = function () { - // Per OAuth 2, this function creates a unique per-request state that the - // authentication provider will echo back as a query parameter when redirecting - // client's browser back to the Zumo server. The server will then validate the - // value of the state. This state reflecting mechanism is meant to prevent certain - // class of cross-site scripting attacks. - return Math.floor(Math.random() * 100000000000).toString(16) + (new Date()).getTime().toString(16); -}; +LoginHandler.createOAuthRedirectState = () => // Per OAuth 2, this function creates a unique per-request state that the +// authentication provider will echo back as a query parameter when redirecting +// client's browser back to the Zumo server. The server will then validate the +// value of the state. This state reflecting mechanism is meant to prevent certain +// class of cross-site scripting attacks. +Math.floor(Math.random() * 100000000000).toString(16) + (new Date()).getTime().toString(16); function _handleNewServerFlowRequest(loginContext, currentUri) { // This function handles the first request of the two-request server authentication flow. @@ -365,13 +363,13 @@ function _handleNewServerFlowRequest(loginContext, currentUri) { logger.trace(logSource, _.sprintf('Initializing a new server authentication flow with provider: %s.', providerName)); - loginContext.loginHandler.userService.isEnabled(function (err, usersEnabled) { + loginContext.loginHandler.userService.isEnabled((err, usersEnabled) => { // Get the location header and any others from the provider-specific login handler as // we're going to redirect the client to the login page for the given provider. var options = { - usersEnabled: usersEnabled + usersEnabled }; - provider.getNewServerFlowResponseHeaders(request, currentUri, function (error, headers) { + provider.getNewServerFlowResponseHeaders(request, currentUri, (error, headers) => { if (error) { _redirectWithError(loginContext, error); @@ -435,7 +433,7 @@ function _handleContinuedServerFlowRequest(loginContext, currentUri) { logger.trace(logSource, _.sprintf('Continuing a server authentication flow with provider: %s.', providerName)); - provider.getProviderTokenFromServerFlowRequest(request, currentUri, function (error1, providerToken) { + provider.getProviderTokenFromServerFlowRequest(request, currentUri, (error1, providerToken) => { if (error1) { _performFailedServerFlowAction(loginContext, error1); @@ -445,18 +443,18 @@ function _handleContinuedServerFlowRequest(loginContext, currentUri) { logger.trace(logSource, _.sprintf('Retrieved a %s provider token in a server authentication flow.', providerName)); logger.trace(logSource, _.sprintf('Exchanging the %s provider token for a Windows Azure Mobile Services token.', providerName)); - handler.userService.isEnabled(function (err, usersEnabled) { + handler.userService.isEnabled((err, usersEnabled) => { var options = { - usersEnabled: usersEnabled + usersEnabled }; - provider.getAuthorizationDetailsFromProviderToken(request, providerToken, function (error2, authorizationDetails) { + provider.getAuthorizationDetailsFromProviderToken(request, providerToken, (error2, authorizationDetails) => { if (error2) { _performFailedServerFlowAction(loginContext, error2); return; } - handler._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, function (err, responseBody) { + handler._createResponseForLoginToken(logger, loginContext, authorizationDetails, providerName, (err, responseBody) => { if (err) { _respondWithError(loginContext, err); } @@ -475,8 +473,9 @@ function _performCompletedServerFlowAction(loginContext, oAuthResponse) { if (!completionAction) { // Non-browser clients complete the flow by redirecting to a "done" URL // with the oAuthResponse encoded into the hash - var encodedResponse = encodeURIComponent(JSON.stringify(oAuthResponse)), - redirectUri = _getFinalRedirectUri(loginContext) + '#token=' + encodedResponse; + var encodedResponse = encodeURIComponent(JSON.stringify(oAuthResponse)); + + var redirectUri = _getFinalRedirectUri(loginContext) + '#token=' + encodedResponse; _redirectWithSuccess(loginContext, { Location: redirectUri }); } else { // Browser clients send back a script that posts the token to the window opener @@ -500,8 +499,8 @@ function _performFailedServerFlowAction(loginContext, error) { } function _returnServerFlowCompletionScriptToBrowser(loginContext, completionAction, oAuthResponse, oAuthError) { - var responseCallback = loginContext.responseCallback, - responseHeaders = {}; + var responseCallback = loginContext.responseCallback; + var responseHeaders = {}; // Ensure that all 'wams' cookies get cleaned up. _deleteAllUnsetWAMSCookies(loginContext, responseHeaders); @@ -534,10 +533,10 @@ function _returnServerFlowCompletionScriptToBrowser(loginContext, completionActi } function _validateSingleSignOnRedirectUri(singleSignOnRedirectUri, loginContext) { - var logger = loginContext.logger, - packageSid = _getPackageSid(loginContext), - error = null, - isValid = true; + var logger = loginContext.logger; + var packageSid = _getPackageSid(loginContext); + var error = null; + var isValid = true; if (!packageSid) { error = new Error(resources.packageSidMissing); @@ -565,10 +564,10 @@ function _getPackageSid(loginContext) { } function _validateSingleSignOnRedirectUri(singleSignOnRedirectUri, loginContext) { - var logger = loginContext.logger, - packageSid = _getPackageSid(loginContext), - error = null, - isValid = true; + var logger = loginContext.logger; + var packageSid = _getPackageSid(loginContext); + var error = null; + var isValid = true; if (!packageSid) { error = new Error(resources.packageSidMissing); @@ -596,7 +595,7 @@ function _getPackageSid(loginContext) { } LoginHandler.prototype._createResponseForLoginToken = function (logger, loginContext, authorizationDetails, providerName, callback) { - this.userService.isEnabled(function (err, usersEnabled) { + this.userService.isEnabled((err, usersEnabled) => { if (err) { callback(err); return; @@ -614,7 +613,7 @@ LoginHandler.prototype._createResponseForLoginToken = function (logger, loginCon var providerKey = UserService.getProviderKeyByName(loginContext.provider.name); - this.userService.addUserIdentity(providerKey, authorizationDetails.providerId, properties, function (err, user) { + this.userService.addUserIdentity(providerKey, authorizationDetails.providerId, properties, (err, user) => { if (err) { callback(err); return; @@ -625,17 +624,17 @@ LoginHandler.prototype._createResponseForLoginToken = function (logger, loginCon responseBody.user.id = user.id; callback(null, responseBody); - }.bind(this)); + }); } else { var loginToken = _createLoginTokenFromAuthorizationDetails(loginContext, authorizationDetails, usersEnabled); var responseBody = this._createResponseBodyForLoginToken(loginContext, authorizationDetails, usersEnabled); callback(null, responseBody); } - }.bind(this)); + }); }; -LoginHandler.prototype._createResponseBodyForLoginToken = function (loginContext, authorizationDetails, usersEnabled) { +LoginHandler.prototype._createResponseBodyForLoginToken = (loginContext, authorizationDetails, usersEnabled) => { var loginToken = _createLoginTokenFromAuthorizationDetails(loginContext, authorizationDetails, usersEnabled); var responseBody = { user: { @@ -704,8 +703,8 @@ function _redirectWithSuccess(loginContext, headers) { } function _respondWithError(loginContext, error) { - var providerName = loginContext.request.authenticationProvider, - headers = {}; + var providerName = loginContext.request.authenticationProvider; + var headers = {}; if (loginContext.provider) { // ensure that the metric is logged only after we've validated the provider @@ -724,9 +723,10 @@ function _respondWithError(loginContext, error) { function _redirectWithError(loginContext, error) { // Create a redirect URL that includes the error - var redirectUri = _getFinalRedirectUri(loginContext) + '#error=' + encodeURIComponent(error), - headers = { Location: redirectUri }, - providerName = loginContext.request.authenticationProvider; + var redirectUri = _getFinalRedirectUri(loginContext) + '#error=' + encodeURIComponent(error); + + var headers = { Location: redirectUri }; + var providerName = loginContext.request.authenticationProvider; // Ensure that all 'wams' cookies get cleaned up. _deleteAllUnsetWAMSCookies(loginContext, headers); @@ -750,7 +750,7 @@ function _parseCookies(headers) { var cookies = headers.cookie; var result = {}; if (cookies) { - cookies.split(';').forEach(function (cookie) { + cookies.split(';').forEach(cookie => { cookie = cookie.replace(/ /g, ''); var i = cookie.indexOf('='); if (i > 0) { @@ -775,7 +775,7 @@ function _deleteAllUnsetWAMSCookies(loginContext, responseHeaders) { // Get the cookies sent by the client var cookies = _parseCookies(loginContext.request.headers); - Object.getOwnPropertyNames(cookies).forEach(function (cookieName) { + Object.getOwnPropertyNames(cookies).forEach(cookieName => { // Only delete cookies that begin with 'wams_' if (cookieName.indexOf('wams_') === 0) { @@ -844,8 +844,8 @@ function _addCompletionActionCookie(completionAction, headers) { } function _getCompletionActionFromQueryString(query) { - var completionType = query.completion_type, - completionOrigin = query.completion_origin; + var completionType = query.completion_type; + var completionOrigin = query.completion_origin; if (completionType && completionOrigin) { return { type: completionType, origin: completionOrigin }; } else { diff --git a/runtime/request/middleware/allowhandler.js b/runtime/request/middleware/allowhandler.js index 4f0e3ec..ab182d3 100644 --- a/runtime/request/middleware/allowhandler.js +++ b/runtime/request/middleware/allowhandler.js @@ -6,8 +6,9 @@ // setting the Allow header to the specified methods. Express doesn't seem to provide any support // like this out of the box, so this middleware must be applied to each route with an 'all' specifier. -var StatusCodes = require('../../statuscodes').StatusCodes, - _ = require('underscore'); +var StatusCodes = require('../../statuscodes').StatusCodes; + +var _ = require('underscore'); // pass in as parameters one or more HTTP methods // e.g. allowHandler('get', 'post') or allowHandler(['get', 'post']) @@ -21,13 +22,11 @@ exports = module.exports = function allowHandler() { } // ensure the methods are all uppercase - methods = _.map(methods, function (method) { - return method.toUpperCase(); - }); + methods = _.map(methods, method => method.toUpperCase()); var allowHeader = { 'Allow': methods.join(', ') }; - return function (req, res) { + return (req, res) => { req._context.responseCallback(null, null, StatusCodes.METHOD_NOT_ALLOWED, allowHeader); }; }; \ No newline at end of file diff --git a/runtime/request/middleware/authenticate.js b/runtime/request/middleware/authenticate.js index 2ca41c7..2ff1c89 100644 --- a/runtime/request/middleware/authenticate.js +++ b/runtime/request/middleware/authenticate.js @@ -7,26 +7,27 @@ // level on the request. If the request is unauthenticated, this handler will // end the request. -var StatusCodes = require('../../statuscodes').StatusCodes, - jsonWebToken = require('../../jsonwebtoken'), - User = require('../user'), - UserService = require('../../users/userservice'), - core = require('../../core'), - _ = require('underscore'), - _str = require('underscore.string'); +var StatusCodes = require('../../statuscodes').StatusCodes; + +var jsonWebToken = require('../../jsonwebtoken'); +var User = require('../user'); +var UserService = require('../../users/userservice'); +var core = require('../../core'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); function authenticate(logSource, keys, userService) { - return function (req, res, next) { - var requestContext = req._context, - responseCallback = requestContext.responseCallback, - logger = requestContext.logger, - metrics = requestContext.metrics, - parsedRequest = requestContext.parsedRequest; + return (req, res, next) => { + var requestContext = req._context; + var responseCallback = requestContext.responseCallback; + var logger = requestContext.logger; + var metrics = requestContext.metrics; + var parsedRequest = requestContext.parsedRequest; logger.trace(logSource, 'Authenticating request'); - + if (parsedRequest.authenticationKey) { // determine the key to use, based on operation type var key = (parsedRequest.operation === 'jobs') ? keys.systemKey : keys.masterKey; diff --git a/runtime/request/middleware/authorize.js b/runtime/request/middleware/authorize.js index ad5a1eb..83e01b0 100644 --- a/runtime/request/middleware/authorize.js +++ b/runtime/request/middleware/authorize.js @@ -6,17 +6,18 @@ // permisison of the request with the current auth level of the request. If // the request is not authorized, it will be rejected. -var StatusCodes = require('../../statuscodes').StatusCodes, - LoginHandler = require('../loginhandler'), - core = require('../../core'), - _ = require('underscore'); +var StatusCodes = require('../../statuscodes').StatusCodes; + +var LoginHandler = require('../loginhandler'); +var core = require('../../core'); +var _ = require('underscore'); exports = module.exports = function authorize(logSource, keys) { - return function (req, res, next) { - var requestContext = req._context, - responseCallback = requestContext.responseCallback, - logger = requestContext.logger, - parsedRequest = requestContext.parsedRequest; + return (req, res, next) => { + var requestContext = req._context; + var responseCallback = requestContext.responseCallback; + var logger = requestContext.logger; + var parsedRequest = requestContext.parsedRequest; logger.trace(logSource, 'Authorizing request'); diff --git a/runtime/request/middleware/bodyparser.js b/runtime/request/middleware/bodyparser.js index bc17c16..151ad67 100644 --- a/runtime/request/middleware/bodyparser.js +++ b/runtime/request/middleware/bodyparser.js @@ -8,7 +8,7 @@ // by the default parser. exports = module.exports = function bodyParser() { - return function (req, res, next) { + return (req, res, next) => { if (req._body) { // this flag is set by the default Express body parser // to indicate the body has already been parsed @@ -21,10 +21,10 @@ exports = module.exports = function bodyParser() { var buf = ''; req.setEncoding('utf8'); - req.on('data', function (chunk) { + req.on('data', chunk => { buf += chunk; }); - req.on('end', function () { + req.on('end', () => { try { // currently this parser just takes the raw string value // as the body diff --git a/runtime/request/middleware/errorhandler.js b/runtime/request/middleware/errorhandler.js index 2564a3d..e019824 100644 --- a/runtime/request/middleware/errorhandler.js +++ b/runtime/request/middleware/errorhandler.js @@ -5,11 +5,12 @@ // This middleware sits at the end of the pipeline to catch errors and create a suitable response // If the previous middleware gracefully sent the response then errorHandler won't be called. -var core = require('../../core'), - StatusCodes = require('../../statuscodes').StatusCodes, - scriptErrors = require('../../script/scripterror'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../../core'); + +var StatusCodes = require('../../statuscodes').StatusCodes; +var scriptErrors = require('../../script/scripterror'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -20,11 +21,11 @@ function ErrorHandler(logSource) { } ErrorHandler.prototype.handle = function (err, req, res, next) { - var context = req._context, - logger = context.logger, - writeResponse = context.responseCallback, - parsedRequest = context.parsedRequest; - + var context = req._context; + var logger = context.logger; + var writeResponse = context.responseCallback; + var parsedRequest = context.parsedRequest; + try { var statusCode = StatusCodes.INTERNAL_SERVER_ERROR; if (err.timeout && err.status == 503) { diff --git a/runtime/request/middleware/requestlimit.js b/runtime/request/middleware/requestlimit.js index 6a015e6..77aaf1d 100644 --- a/runtime/request/middleware/requestlimit.js +++ b/runtime/request/middleware/requestlimit.js @@ -5,18 +5,19 @@ // // This middleware ensures the request size is under the specified byte limit -var StatusCodes = require('../../statuscodes').StatusCodes, - resources = require('../../resources'), - core = require('../../core'); +var StatusCodes = require('../../statuscodes').StatusCodes; + +var resources = require('../../resources'); +var core = require('../../core'); var logSource = 'RequestLimit'; exports = module.exports = function requestLimit(maxByteLength) { - return function (req, res, next) { - var logger = req._context.logger, - contentLength = req.headers['content-length'] ? parseInt(req.headers['content-length'], 10) : null, - responseCallback = req._context.responseCallback, - receivedByteLength = 0; + return (req, res, next) => { + var logger = req._context.logger; + var contentLength = req.headers['content-length'] ? parseInt(req.headers['content-length'], 10) : null; + var responseCallback = req._context.responseCallback; + var receivedByteLength = 0; // limit by content-length if (contentLength && contentLength > maxByteLength) { @@ -27,7 +28,7 @@ exports = module.exports = function requestLimit(maxByteLength) { // final catch-all limit, in case a content-length // hasn't been sent - req.on('data', function (chunk) { + req.on('data', chunk => { receivedByteLength += chunk.length; if (receivedByteLength > maxByteLength) { logError(logger); diff --git a/runtime/request/middleware/requirehttps.js b/runtime/request/middleware/requirehttps.js index dbf17cf..9978294 100644 --- a/runtime/request/middleware/requirehttps.js +++ b/runtime/request/middleware/requirehttps.js @@ -11,14 +11,12 @@ // The middleware should be registered very early in the pipeline. -module.exports = function () { - return function (req, res, next) { - var secure = req.secure || req.headers['x-arr-ssl']; +module.exports = () => (req, res, next) => { + var secure = req.secure || req.headers['x-arr-ssl']; - if (!secure) { - res.status(403).send('HTTPS connections are required for this service. Please update your endpoint to use the https protocol.').end(); - } else { - next(); - } - }; + if (!secure) { + res.status(403).send('HTTPS connections are required for this service. Please update your endpoint to use the https protocol.').end(); + } else { + next(); + } }; \ No newline at end of file diff --git a/runtime/request/middleware/versioncheck.js b/runtime/request/middleware/versioncheck.js index ebe45a6..f1c2b3b 100644 --- a/runtime/request/middleware/versioncheck.js +++ b/runtime/request/middleware/versioncheck.js @@ -7,27 +7,25 @@ // // The middleware should be registered early in the pipeline. -module.exports = function () { - return function (req, res, next) { - var version; +module.exports = () => (req, res, next) => { + var version; - // Find any casing of zumo-api-version in querystring - for (var param in req.query) { - if (param.toLowerCase() === 'zumo-api-version') { - version = req.query[param]; - break; - } + // Find any casing of zumo-api-version in querystring + for (var param in req.query) { + if (param.toLowerCase() === 'zumo-api-version') { + version = req.query[param]; + break; } + } - // Fall back to header if not present in querystring - if (!version) { - version = req.headers['zumo-api-version']; - } + // Fall back to header if not present in querystring + if (!version) { + version = req.headers['zumo-api-version']; + } - if (version) { - res.status(400).send('This version (1.0.0) of the server does not support the use of the zumo-api-version in the request. For more information and supported clients see: http://go.microsoft.com/fwlink/?LinkID=690568#1.0.0').end(); - } else { - next(); - } - }; + if (version) { + res.status(400).send('This version (1.0.0) of the server does not support the use of the zumo-api-version in the request. For more information and supported clients see: http://go.microsoft.com/fwlink/?LinkID=690568#1.0.0').end(); + } else { + next(); + } }; \ No newline at end of file diff --git a/runtime/request/request.js b/runtime/request/request.js index 4454ff9..d8985b1 100644 --- a/runtime/request/request.js +++ b/runtime/request/request.js @@ -4,12 +4,12 @@ // // This module provides functions to parse a request into a request object used by the runtime. -(function (global) { +((global => { require('../query/queryparser'); - var _ = require('underscore'), - _str = require('underscore.string'), - core = require('../core'); + var _ = require('underscore'); + var _str = require('underscore.string'); + var core = require('../core'); _.mixin(_str.exports()); @@ -181,5 +181,4 @@ Request = global; Request.parse = parse; Request.validateQuery = validateQuery; - -})(typeof exports === "undefined" ? (this.Request = {}) : exports); +}))(typeof exports === "undefined" ? (this.Request = {}) : exports); diff --git a/runtime/request/requesthandler.js b/runtime/request/requesthandler.js index 5639621..a819944 100644 --- a/runtime/request/requesthandler.js +++ b/runtime/request/requesthandler.js @@ -5,44 +5,45 @@ // This module is responsible for processing HTTP requests end to end. Delegates to specific // handler modules to process different request types (e.g. tables, scheduler, api, login, etc.) -var core = require('../core'), - TableHandler = require('./tablehandler'), - LoginHandler = require('./loginhandler'), - SchedulerHandler = require('./schedulerhandler'), - StatusHandler = require('./statushandler'), - DiagnosticsHandler = require('./diagnosticshandler'), - CrossDomainHandler = require('./html/crossdomainhandler'), - ApiBuilder = require('../script/apibuilder'), - util = require('util'), - StatusCodes = require('../statuscodes').StatusCodes, - fileHelpers = require('../filehelpers'), - CorsHelper = require('./html/corshelper'), - UserService = require('../users/userservice'), - _ = require('underscore'), - _str = require('underscore.string'), - Logger = require('../logger'), - uuid = require('request/uuid'), - resources = require('../resources'), - express = require('express'), - allowHandler = require('./middleware/allowhandler'), - bodyParser = require('./middleware/bodyparser'), - requestLimit = require('./middleware/requestlimit'), - errorHandler = require('./middleware/errorhandler'), - authenticate = require('./middleware/authenticate'), - authorize = require('./middleware/authorize'), - versionCheck = require('./middleware/versioncheck'), - requireHttpsMiddleware = require('./middleware/requirehttps'), - EtagHelper = require('./etaghelper.js'), - ErrorHelper = require('./errorhelper.js'), - Request = require('./request.js'); +var core = require('../core'); + +var TableHandler = require('./tablehandler'); +var LoginHandler = require('./loginhandler'); +var SchedulerHandler = require('./schedulerhandler'); +var StatusHandler = require('./statushandler'); +var DiagnosticsHandler = require('./diagnosticshandler'); +var CrossDomainHandler = require('./html/crossdomainhandler'); +var ApiBuilder = require('../script/apibuilder'); +var util = require('util'); +var StatusCodes = require('../statuscodes').StatusCodes; +var fileHelpers = require('../filehelpers'); +var CorsHelper = require('./html/corshelper'); +var UserService = require('../users/userservice'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var Logger = require('../logger'); +var uuid = require('request/uuid'); +var resources = require('../resources'); +var express = require('express'); +var allowHandler = require('./middleware/allowhandler'); +var bodyParser = require('./middleware/bodyparser'); +var requestLimit = require('./middleware/requestlimit'); +var errorHandler = require('./middleware/errorhandler'); +var authenticate = require('./middleware/authenticate'); +var authorize = require('./middleware/authorize'); +var versionCheck = require('./middleware/versioncheck'); +var requireHttpsMiddleware = require('./middleware/requirehttps'); +var EtagHelper = require('./etaghelper.js'); +var ErrorHelper = require('./errorhelper.js'); +var Request = require('./request.js'); _.mixin(_str.exports()); exports = module.exports = RequestHandler; -var logSource = 'RequestHandler', - version = null, - npmPackageVersion = require('../../package.json').version; +var logSource = 'RequestHandler'; +var version = null; +var npmPackageVersion = require('../../package.json').version; function RequestHandler(configPath, masterKey, systemKey, appName, authenticationCredentials, crossDomainWhitelist, applicationKey, runtimeVersion, requestTimeout, storage, scriptManager, logger, metrics, logLevel, logServiceURL, logServiceToken, maxRequestBodySize, newRelicAdapter, userService, pushAdapter, domainSuffix, requireHttps, skipVersionCheck) { this.requestTimeout = requestTimeout || 30 * 1000; @@ -57,7 +58,7 @@ function RequestHandler(configPath, masterKey, systemKey, appName, authenticatio this.maxRequestBodySize = maxRequestBodySize; this.newRelicAdapter = newRelicAdapter; this.userService = userService || UserService.nullService; - this.corsHelper = new CorsHelper({ crossDomainWhitelist: crossDomainWhitelist }); + this.corsHelper = new CorsHelper({ crossDomainWhitelist }); this.domainSuffix = typeof domainSuffix != "undefined" ? domainSuffix : null; this.requireHttps = typeof(requireHttps) === 'string' && requireHttps.toLowerCase() === 'true'; this.skipVersionCheck = skipVersionCheck; @@ -73,9 +74,9 @@ function RequestHandler(configPath, masterKey, systemKey, appName, authenticatio this.pushAdapter = pushAdapter; this.keys = { - masterKey: masterKey, - applicationKey: applicationKey, - systemKey: systemKey + masterKey, + applicationKey, + systemKey }; } @@ -107,9 +108,9 @@ RequestHandler.prototype.initialize = function (app, extensionManager, done) { this.apiBuilder = new ApiBuilder(app, apiMiddleware, this.scriptManager, this.logger, this.metrics); core.async.parallel([ - function (done) { self.scriptManager.initialize(done); }, - function (done) { self.apiBuilder.build(done); }, - function (done) { self.loginHandler.initialize(done); } + done => { self.scriptManager.initialize(done); }, + done => { self.apiBuilder.build(done); }, + done => { self.loginHandler.initialize(done); } ], done); }; @@ -238,8 +239,8 @@ RequestHandler.prototype._configureRoutes = function (app, sharedMiddleware) { // perform request initialization common to all handlers RequestHandler.prototype._beginRequest = function (req, res, next) { - var requestLogger = this._createRequestLogger(), - self = this; + var requestLogger = this._createRequestLogger(); + var self = this; // Create the requestContext and start a request latency timer req._context = { @@ -289,7 +290,7 @@ RequestHandler.prototype._beginRequest = function (req, res, next) { RequestHandler.prototype._wrapResponse = function (req, res, logger) { var self = this; - res.end = _.wrap(res.end, function (oldEnd, data, encoding) { + res.end = _.wrap(res.end, (oldEnd, data, encoding) => { if (!res.completed) { // a response was produced, so clear the timeout, // if a timeout has been applied to the request. @@ -316,9 +317,9 @@ RequestHandler.prototype._createRequestLogger = function () { }; function validateQuery(req, res, next) { - var requestContext = req._context, - logger = requestContext.logger, - parsedRequest = requestContext.parsedRequest; + var requestContext = req._context; + var logger = requestContext.logger; + var parsedRequest = requestContext.parsedRequest; try { Request.validateQuery(parsedRequest); @@ -334,7 +335,7 @@ function validateQuery(req, res, next) { // Apply this middleware to a route to configure the required authorization // level for that route. Must be applied BEFORE the authorize middleware. function requireAuthorization(requiredLevel) { - return function (req, res, next) { + return (req, res, next) => { // set the required permission, which will be validated by the // authorize middleware req._context.parsedRequest.requiredPermission = requiredLevel; @@ -348,10 +349,10 @@ RequestHandler.prototype._setPushPermission = function (req, res, next) { }; RequestHandler.prototype._validateTable = function (req, res, next, tableName) { - var requestContext = req._context, - responseCallback = requestContext.responseCallback, - parsedRequest = requestContext.parsedRequest, - dataModel = this.scriptManager.getDataModel(); + var requestContext = req._context; + var responseCallback = requestContext.responseCallback; + var parsedRequest = requestContext.parsedRequest; + var dataModel = this.scriptManager.getDataModel(); // verify that the table exists var table = dataModel.getTable(tableName); @@ -375,9 +376,9 @@ RequestHandler.prototype._validateTable = function (req, res, next, tableName) { }; RequestHandler.prototype._validateJob = function (req, res, next, jobName) { - var requestContext = req._context, - responseCallback = requestContext.responseCallback, - dataModel = this.scriptManager.getDataModel(); + var requestContext = req._context; + var responseCallback = requestContext.responseCallback; + var dataModel = this.scriptManager.getDataModel(); // verify that job exists var job = dataModel.getJob(jobName); @@ -394,7 +395,7 @@ RequestHandler.prototype._validateJob = function (req, res, next, jobName) { next(); }; -RequestHandler.prototype._setRequestId = function (req, res, next, id) { +RequestHandler.prototype._setRequestId = (req, res, next, id) => { req._context.parsedRequest.id = id; next(); }; @@ -406,9 +407,9 @@ RequestHandler.prototype.redirectConsole = function () { // simplify the interface of logUser by defaulting the table, operation, etc. var logUser = function (logType) { - var logArgs = Array.prototype.slice.call(arguments, 1), - message = util.format.apply(null, logArgs), - source = core.getUserScriptSource(); + var logArgs = Array.prototype.slice.call(arguments, 1); + var message = util.format.apply(null, logArgs); + var source = core.getUserScriptSource(); if (!source) { // If not coming from user source, log directly to stdout. @@ -430,8 +431,8 @@ RequestHandler.prototype.redirectConsole = function () { }; function parseRequest(req, res, next) { - var requestContext = req._context, - logger = requestContext.logger; + var requestContext = req._context; + var logger = requestContext.logger; var parsedRequest; try { @@ -468,8 +469,9 @@ function bindHandler(handler) { RequestHandler.prototype._traceRequest = function (req, res, next) { // we need to be careful not to log any sensitive request data // (e.g. actual body contents, authentication key values, etc.) - var parsedRequest = req._context.parsedRequest, - logger = req._context.logger; + var parsedRequest = req._context.parsedRequest; + + var logger = req._context.logger; var traceData = { verb: parsedRequest.verb, diff --git a/runtime/request/schedulerhandler.js b/runtime/request/schedulerhandler.js index 45ecbfe..2b7ceba 100644 --- a/runtime/request/schedulerhandler.js +++ b/runtime/request/schedulerhandler.js @@ -4,10 +4,11 @@ // // This module is responsible for scheduler job execution requests -var DataPipeline = require('./datapipeline'), - Storage = require('../storage/storage'), - core = require('../core'), - StatusCodes = require('../statuscodes').StatusCodes; +var DataPipeline = require('./datapipeline'); + +var Storage = require('../storage/storage'); +var core = require('../core'); +var StatusCodes = require('../statuscodes').StatusCodes; exports = module.exports = SchedulerHandler; @@ -21,9 +22,9 @@ function SchedulerHandler(scriptManager, masterKey, appName, metrics) { } SchedulerHandler.prototype.handle = function (req, res) { - var logger = req._context.logger, - responseCallback = req._context.responseCallback, - request = req._context.parsedRequest; + var logger = req._context.logger; + var responseCallback = req._context.responseCallback; + var request = req._context.parsedRequest; request.job = req.params.job; diff --git a/runtime/request/statushandler.js b/runtime/request/statushandler.js index 9c7cc58..53dd0b5 100644 --- a/runtime/request/statushandler.js +++ b/runtime/request/statushandler.js @@ -15,9 +15,9 @@ var logSource = 'StatusHandler'; function StatusHandler() { } -StatusHandler.prototype.handle = function (req, res) { - var logger = req._context.logger, - responseCallback = req._context.responseCallback; +StatusHandler.prototype.handle = (req, res) => { + var logger = req._context.logger; + var responseCallback = req._context.responseCallback; logger.trace(logSource, 'Processing request'); diff --git a/runtime/request/tablehandler.js b/runtime/request/tablehandler.js index 1469399..838b996 100644 --- a/runtime/request/tablehandler.js +++ b/runtime/request/tablehandler.js @@ -4,15 +4,16 @@ // // This module is responsible for handling table requests end to end (query/insert/update/delete). -var DataPipeline = require('./datapipeline'), - core = require('../core'), - StatusCodes = require('../statuscodes').StatusCodes, - resource = require('../resources'), - ETagHelper = require('./etaghelper'), - _ = require('underscore'), - _str = require('underscore.string'); +var DataPipeline = require('./datapipeline'); - _.mixin(_str.exports()); +var core = require('../core'); +var StatusCodes = require('../statuscodes').StatusCodes; +var resource = require('../resources'); +var ETagHelper = require('./etaghelper'); +var _ = require('underscore'); +var _str = require('underscore.string'); + +_.mixin(_str.exports()); exports = module.exports = TableHandler; @@ -25,10 +26,10 @@ function TableHandler(storage, scriptManager, metrics) { } TableHandler.prototype.handle = function (req, res) { - var logger = req._context.logger, - responseCallback = req._context.responseCallback, - request = req._context.parsedRequest, - self = this; + var logger = req._context.logger; + var responseCallback = req._context.responseCallback; + var request = req._context.parsedRequest; + var self = this; request.table = req.params.table; request.id = req.params.id; @@ -39,7 +40,7 @@ TableHandler.prototype.handle = function (req, res) { var dataPipeline = this._createDataPipeline(request, logger); - this.storage.getTableMetadata(request.table, logger, function (err, tableMetadata) { + this.storage.getTableMetadata(request.table, logger, (err, tableMetadata) => { if (err) { responseCallback(err); @@ -72,7 +73,7 @@ TableHandler.prototype.handle = function (req, res) { }); }; -TableHandler.prototype._handleRead = function (request, dataPipeline, responseCallback) { +TableHandler.prototype._handleRead = (request, dataPipeline, responseCallback) => { if (request.id !== undefined) { request.query.id = request.id; } @@ -80,7 +81,7 @@ TableHandler.prototype._handleRead = function (request, dataPipeline, responseCa dataPipeline.read(request.query, responseCallback); }; -TableHandler.prototype._handleUndelete = function (request, tableMetadata, dataPipeline, responseCallback) { +TableHandler.prototype._handleUndelete = (request, tableMetadata, dataPipeline, responseCallback) => { if (!tableMetadata.supportsSoftDelete) { responseCallback(new core.MobileServiceError(resource.undeleteNotSupported, core.ErrorCodes.BadInput)); return; @@ -105,7 +106,7 @@ TableHandler.prototype._handleUndelete = function (request, tableMetadata, dataP dataPipeline.update(item, responseCallback); }; -TableHandler.prototype._handleInsert = function (request, tableMetadata, dataPipeline, responseCallback) { +TableHandler.prototype._handleInsert = (request, tableMetadata, dataPipeline, responseCallback) => { if (request.id !== undefined) { responseCallback(new core.MobileServiceError(resource.idInUrlNotAllowedOnInsert, core.ErrorCodes.BadInput)); return; @@ -128,7 +129,7 @@ TableHandler.prototype._handleInsert = function (request, tableMetadata, dataPip return; } - responseCallback = _.wrap(responseCallback, function (oldCallback, error, result, statusCode) { + responseCallback = _.wrap(responseCallback, (oldCallback, error, result, statusCode) => { var additionalHeaders = null; if (!error && request.body && request.body.id) { // if the insert was successful, add the Location header @@ -141,7 +142,7 @@ TableHandler.prototype._handleInsert = function (request, tableMetadata, dataPip dataPipeline.insert(request.body, responseCallback); }; -TableHandler.prototype._handleUpdate = function (request, tableMetadata, dataPipeline, responseCallback) { +TableHandler.prototype._handleUpdate = (request, tableMetadata, dataPipeline, responseCallback) => { if (!request.id) { responseCallback(new core.MobileServiceError(resource.idValueRequiredOnUpdate, core.ErrorCodes.BadInput)); return; @@ -178,7 +179,7 @@ TableHandler.prototype._handleUpdate = function (request, tableMetadata, dataPip dataPipeline.update(item, responseCallback); }; -TableHandler.prototype._handleDelete = function (request, tableMetadata, dataPipeline, responseCallback) { +TableHandler.prototype._handleDelete = (request, tableMetadata, dataPipeline, responseCallback) => { if (!request.id) { responseCallback(new core.MobileServiceError(resource.idValueRequiredOnDelete, core.ErrorCodes.BadInput)); return; @@ -257,9 +258,7 @@ function isStringIdValid(request, responseCallback) { function isIdFieldValid(request, responseCallback) { // If an object has any id casing other than 'id', return an error. - if (['ID', 'Id', 'iD'].some(function (idFormat) { - return request.body.hasOwnProperty(idFormat); - })) { + if (['ID', 'Id', 'iD'].some(idFormat => request.body.hasOwnProperty(idFormat))) { responseCallback(new core.MobileServiceError(resource.idPropertyCaseMismatch, core.ErrorCodes.BadInput)); return false; } diff --git a/runtime/request/user.js b/runtime/request/user.js index aa4de4d..d9f1c94 100644 --- a/runtime/request/user.js +++ b/runtime/request/user.js @@ -4,10 +4,11 @@ // // This is a module that has logic related to creating user object and getting its identities -var _ = require('underscore'), - _str = require('underscore.string'), - ZumoCallback = require('../script/zumocallback'), - UserService = require('../users/userservice'); +var _ = require('underscore'); + +var _str = require('underscore.string'); +var ZumoCallback = require('../script/zumocallback'); +var UserService = require('../users/userservice'); _.mixin(_str.exports()); @@ -22,7 +23,7 @@ var logSource = 'User'; // metrics: {} // logger: {} // } -exports.create = function (requestContext, keys, userService) { +exports.create = (requestContext, keys, userService) => { userService = userService || UserService.nullService; var request = requestContext.parsedRequest; @@ -53,9 +54,9 @@ function GetIdentitiesHelper(requestContext, token, userService) { } GetIdentitiesHelper.prototype.invoke = function (callbackOrOptions) { - var script = this.requestContext.script || '', - metrics = this.requestContext.metrics, - logger = this.requestContext.logger; + var script = this.requestContext.script || ''; + var metrics = this.requestContext.metrics; + var logger = this.requestContext.logger; if (!callbackOrOptions) { metrics.event('api.user.getIdentities'); @@ -67,10 +68,10 @@ GetIdentitiesHelper.prototype.invoke = function (callbackOrOptions) { }; GetIdentitiesHelper.prototype._getIdentitiesAsync = function (script, callbackOrOptions) { - var metrics = this.requestContext.metrics, - logger = this.requestContext.logger, - self = this, - callback; + var metrics = this.requestContext.metrics; + var logger = this.requestContext.logger; + var self = this; + var callback; if (_.isFunction(callbackOrOptions)) { metrics.event('api.user.getIdentitiesAync'); @@ -82,7 +83,7 @@ GetIdentitiesHelper.prototype._getIdentitiesAsync = function (script, callbackOr callback = ZumoCallback.create(this.requestContext, logSource, script, 'user', 'getIdentities', callbackOrOptions); } - this.userService.isEnabled(function (err, isEnabled) { + this.userService.isEnabled((err, isEnabled) => { if (err) { callback(err); return; diff --git a/runtime/resources.js b/runtime/resources.js index e1cfa30..94dfaa6 100644 --- a/runtime/resources.js +++ b/runtime/resources.js @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (exports) { +((exports => { // storage messages exports.colNotInSchema = "Could not save item because it contains a column that is not in the table schema."; @@ -47,4 +47,4 @@ exports.newRelicError = 'A New Relic license key was found but the module could not be loaded. For more information on how to enable New Relic see http://go.microsoft.com/fwlink/?LinkID=327542'; exports.itemNotFound = "An item with id '%s' does not exist."; -})(typeof exports === 'undefined' ? (this.resource = {}) : exports); +}))(typeof exports === 'undefined' ? (this.resource = {}) : exports); diff --git a/runtime/script/apibuilder.js b/runtime/script/apibuilder.js index 121184f..cf62505 100644 --- a/runtime/script/apibuilder.js +++ b/runtime/script/apibuilder.js @@ -4,15 +4,16 @@ // // This module is responsible for loading and exposing custom apis on the app -var StatusCodes = require('../statuscodes').StatusCodes, - path = require('path'), - core = require('../core'), - Metadata = require('./metadata'), - scriptErrors = require('./scripterror'), - ScriptLoader = require('./scriptloader'), - _ = require('underscore'), - _str = require('underscore.string'), - allowHandler = require('../request/middleware/allowhandler'); +var StatusCodes = require('../statuscodes').StatusCodes; + +var path = require('path'); +var core = require('../core'); +var Metadata = require('./metadata'); +var scriptErrors = require('./scripterror'); +var ScriptLoader = require('./scriptloader'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var allowHandler = require('../request/middleware/allowhandler'); _.mixin(_str.exports()); @@ -65,8 +66,9 @@ ApiBuilder.prototype._handleLoadError = function (err, scriptInfo) { // callback for file load events from script loader ApiBuilder.prototype._handleFileLoad = function (supportedMethods, scriptInfo) { // get or create the api entry for this file - var api = this.apis[scriptInfo.name] || createApi(scriptInfo), - isScript = isScriptFile(scriptInfo.scriptFileName); + var api = this.apis[scriptInfo.name] || createApi(scriptInfo); + + var isScript = isScriptFile(scriptInfo.scriptFileName); if (isScript) { this._loadApi(supportedMethods, api); @@ -82,15 +84,15 @@ ApiBuilder.prototype._handleFileLoad = function (supportedMethods, scriptInfo) { }; ApiBuilder.prototype._loadApi = function (supportedMethods, api) { - var scriptPath = api.scriptPath, - baseRoute = '/api/' + api.name, - scriptSource = '/api/' + api.scriptFileName, - self = this; + var scriptPath = api.scriptPath; + var baseRoute = '/api/' + api.name; + var scriptSource = '/api/' + api.scriptFileName; + var self = this; api.baseRoute = baseRoute; api.reset(); // clear any existing routes this.apis[api.name] = api; - + // clone the base middleware to and add additional to define // the common set of middleware for this api var middleware = self.middleware.slice(0) || []; @@ -106,10 +108,10 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) { api.addRoute(route, method); - handler = _.wrap(handler, function (originalHandler, req, res) { - var logger = req._context.logger, - metrics = req._context.metrics, - responseCallback = req._context.responseCallback; + handler = _.wrap(handler, (originalHandler, req, res) => { + var logger = req._context.logger; + var metrics = req._context.metrics; + var responseCallback = req._context.responseCallback; logger.trace(logSource, 'Invoking user handler'); metrics.event(_.sprintf('api.custom.%s', method)); @@ -136,8 +138,8 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) { // define an api wrapper to intercept route registration calls, etc. var apiWrapper = {}; - _.each(supportedMethods, function (method) { - apiWrapper[method] = function (route, handler) { + _.each(supportedMethods, method => { + apiWrapper[method] = (route, handler) => { if (!_.startsWith(route, '/')) { route = '/' + route; } @@ -160,7 +162,7 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) { // since we don't know what routes the register function would have registered // we configure the api to always error on execution on a public 'all' route api.error = "'register' method of the api failed."; - addRoute('all', baseRoute, middleware, function (req, res) { }); + addRoute('all', baseRoute, middleware, (req, res) => { }); } } @@ -168,7 +170,7 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) { // next load any implicit routes // "prescriptive" form of a custom api, with exported functions // for each http verb - _.each(supportedMethods, function (method) { + _.each(supportedMethods, method => { var handler = apiModule[method]; if (handler) { addRoute(method, baseRoute, middleware, handler); @@ -178,7 +180,7 @@ ApiBuilder.prototype._loadApi = function (supportedMethods, api) { // finally, add an allow handler that will match on all http // methods, to send back proper 405 Allow responses - _.each(api.routes, function (route, path) { + _.each(api.routes, (route, path) => { self.app.all(path, allowHandler(route.methods)); }); }; @@ -191,9 +193,9 @@ function apiLoadErrorHandler(req, res) { // middleware used to set the required permission on the request, // based on the permission configured for the api route function requirePermission(api, req, res, next) { - var requiredPermission = 'admin', - logger = req._context.logger, - parsedRequest = req._context.parsedRequest; + var requiredPermission = 'admin'; + var logger = req._context.logger; + var parsedRequest = req._context.parsedRequest; // if we faild to register the apis or load the metadata file, we don't know what permissions it would have // since we're going to return an error from the api, it is safe to make it public @@ -227,19 +229,19 @@ function requirePermission(api, req, res, next) { // middleware used to set up required state on the request before // calling into user code function prepareRequest(api, scriptManager, req, res, next) { - var logger = req._context.logger, - responseCallback = req._context.responseCallback, - source = '/api/' + api.scriptFileName; + var logger = req._context.logger; + var responseCallback = req._context.responseCallback; + var source = '/api/' + api.scriptFileName; // set the executing script on request context req._context.script = source; // add service to the request - req.service = scriptManager.buildScriptService(source, logger, { responseCallback: responseCallback }); + req.service = scriptManager.buildScriptService(source, logger, { responseCallback }); // to keep the script apis consistent, we define a 'respond' // which delegates to send - req.respond = function (statusCode, body) { + req.respond = (statusCode, body) => { res.send(statusCode, body); }; diff --git a/runtime/script/extensionmanager.js b/runtime/script/extensionmanager.js index 693879e..8dddaee 100644 --- a/runtime/script/extensionmanager.js +++ b/runtime/script/extensionmanager.js @@ -4,20 +4,21 @@ // // This module is responsible for loading and running extension scripts -var path = require('path'), - fs = require('fs'), - core = require('../core'), - _ = require('underscore'), - _str = require('underscore.string'); +var path = require('path'); + +var fs = require('fs'); +var core = require('../core'); +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); exports = module.exports = ExtensionManager; -var logSource = 'ExtensionManager', - extensionsDirectory = 'extensions', - startupFileName = 'startup.js', - pushFileName = 'push.js'; +var logSource = 'ExtensionManager'; +var extensionsDirectory = 'extensions'; +var startupFileName = 'startup.js'; +var pushFileName = 'push.js'; ExtensionManager.pushMetadataFileName = 'push.json'; @@ -43,7 +44,7 @@ ExtensionManager.prototype.initialize = function (done) { var options = { load: this._onScriptLoad.bind(this), - error: function (err) { + error(err) { self.logger.logUser(logSource, LogType.Error, err.toString()); done(); } @@ -56,7 +57,7 @@ ExtensionManager.prototype.runPushRegistrationScript = function (registration, u var options = { swallowError: false, args: registration, - extraContext: { user: user } + extraContext: { user } }; this.runExtensionScript(pushFileName, 'register', options, done); @@ -121,8 +122,8 @@ ExtensionManager.prototype._getExtension = function (name) { }; ExtensionManager.prototype._callExtension = function (name, module, method, options, context, done) { - var self = this, - doneCalled = false; + var self = this; + var doneCalled = false; var fn = module[method]; if (!core.isFunction(fn)) { @@ -148,7 +149,7 @@ ExtensionManager.prototype._callExtension = function (name, module, method, opti extensionArgs.push(context); if (options && _.isNumber(options.scriptTimeout)) { - var callbackWrapper = function (error) { + var callbackWrapper = error => { if (!doneCalled) { doneCalled = true; if (options && !options.swallowError) { @@ -164,7 +165,7 @@ ExtensionManager.prototype._callExtension = function (name, module, method, opti extensionArgs.push(done); } - fn.apply(null, extensionArgs); + fn(...extensionArgs); } catch (e) { this.logger.logUser(logSource, LogType.Error, _.sprintf('Failed to execute \'%s\' of %s due to error: %s', method, name, e.toString())); if (options && !options.swallowError) { @@ -174,7 +175,7 @@ ExtensionManager.prototype._callExtension = function (name, module, method, opti if (options && _.isNumber(options.scriptTimeout)) { // if module fails to call 'done' with in time limit then we call it ourself to resume execution - setTimeout(function () { + setTimeout(() => { if (!doneCalled) { doneCalled = true; var errorMessage = _.sprintf('\'%s\' of \'%s\' failed to call \'done\' method with in %d ms', method, name, options.scriptTimeout); diff --git a/runtime/script/metadata.js b/runtime/script/metadata.js index 576c481..81c91b7 100644 --- a/runtime/script/metadata.js +++ b/runtime/script/metadata.js @@ -4,16 +4,17 @@ // // Encapsulates script metadata -var core = require('../core'), - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../core'); + +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); exports = module.exports = Metadata; -var supportedHttpMethods = ['get', 'put', 'post', 'patch', 'delete'], - tableOperations = ['read', 'insert', 'update', 'delete']; +var supportedHttpMethods = ['get', 'put', 'post', 'patch', 'delete']; +var tableOperations = ['read', 'insert', 'update', 'delete']; function Metadata(metadata, filename) { this.metadata = metadata; @@ -44,15 +45,13 @@ Metadata.prototype.getRouteMetadata = function (route, method) { }; Metadata.prototype._matchRoute = function (route) { - var normalizedRoute = _.trim(route, '/'), - routeMetadata = null; + var normalizedRoute = _.trim(route, '/'); + var routeMetadata = null; // Search for a route match by normalizing both values // by removing any leading/trailing slashes. E.g., we want // match /a/b with a/b or a/b/, etc. - var matchedRoute = _.chain(this.metadata.routes).keys().find(function (routeKey) { - return normalizedRoute == _.trim(routeKey, '/'); - }).value(); + var matchedRoute = _.chain(this.metadata.routes).keys().find(routeKey => normalizedRoute == _.trim(routeKey, '/')).value(); if (matchedRoute) { routeMetadata = this.metadata.routes[matchedRoute]; @@ -66,15 +65,15 @@ Metadata.prototype._matchRoute = function (route) { }; function validateMetadata(metadata, fileName) { - var validMetadataProperties = ['permission'], - validPermissions = ['application', 'user', 'authenticated', 'admin', 'public']; + var validMetadataProperties = ['permission']; + var validPermissions = ['application', 'user', 'authenticated', 'admin', 'public']; function throwMetadataError(reason) { throw new Error(_.sprintf("Invalid metadata file '%s': %s", fileName, reason)); } function validateRouteMetadata(route, routeMetadata) { - _.each(routeMetadata, function (value, key) { + _.each(routeMetadata, (value, key) => { if (validMetadataProperties.indexOf(key) < 0) { throwMetadataError(_.sprintf("Invalid route metadata for route '%s'. '%s' is not a valid metadata property.", route, key)); } @@ -94,7 +93,7 @@ function validateMetadata(metadata, fileName) { throwMetadataError("'routes' must be an object, mapping routes to route metadata."); } - _.each(routes, function (routeMetadata, route) { + _.each(routes, (routeMetadata, route) => { // validate the route if (!route) { throwMetadataError(_.sprintf("Invalid route path '%s'", route)); @@ -104,7 +103,7 @@ function validateMetadata(metadata, fileName) { } if (isMethodMap(routeMetadata)) { - _.each(routeMetadata, function (routeMetadataMap, methodOrOp) { + _.each(routeMetadata, (routeMetadataMap, methodOrOp) => { if (!isHttpMethodOrTableOperation(methodOrOp)) { throwMetadataError(_.sprintf("Invalid route metadata for route '%s'. '%s' is not a supported http method or table operation.", route, methodOrOp)); } diff --git a/runtime/script/scriptcache.js b/runtime/script/scriptcache.js index 02bd8fe..8c2bb3f 100644 --- a/runtime/script/scriptcache.js +++ b/runtime/script/scriptcache.js @@ -22,7 +22,5 @@ ScriptCache.prototype.get = function (key) { return this.cache[key.toLowerCase()]; }; -ScriptCache.prototype.getKey = function (scriptType, filename) { - // important to retain the filename extension to ensure uniqueness - return scriptType + '-' + filename; -}; +ScriptCache.prototype.getKey = (scriptType, filename) => // important to retain the filename extension to ensure uniqueness +scriptType + '-' + filename; diff --git a/runtime/script/scripterror.js b/runtime/script/scripterror.js index 2b649ea..0e57c58 100644 --- a/runtime/script/scripterror.js +++ b/runtime/script/scripterror.js @@ -2,13 +2,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -var _ = require('underscore'), - _str = require('underscore.string'), - core = require('../core'); +var _ = require('underscore'); + +var _str = require('underscore.string'); +var core = require('../core'); _.mixin(_str.exports()); -exports.handleScriptError = function (error, source, logger, responseCallback, message) { +exports.handleScriptError = (error, source, logger, responseCallback, message) => { if (error instanceof core.MobileServiceError && !error.loggedToUser && (error.code === core.ErrorCodes.ScriptError || error.code === undefined)) { if (!message) { message = _.sprintf("Error in script '%s'.", source); diff --git a/runtime/script/scriptloader.js b/runtime/script/scriptloader.js index 744f3e0..a01de84 100644 --- a/runtime/script/scriptloader.js +++ b/runtime/script/scriptloader.js @@ -4,22 +4,23 @@ // // Wraps a script cache and provides funcionality for loading scripts into the cache -var fs = require('fs'), - path = require('path'), - ScriptCache = require('./scriptcache'), - StatusCodes = require('../statuscodes'), - fileHelpers = require('../filehelpers'), - _ = require('underscore'), - _str = require('underscore.string'), - core = require('../core'), - Metadata = require('./metadata'); +var fs = require('fs'); + +var path = require('path'); +var ScriptCache = require('./scriptcache'); +var StatusCodes = require('../statuscodes'); +var fileHelpers = require('../filehelpers'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var core = require('../core'); +var Metadata = require('./metadata'); _.mixin(_str.exports()); exports = module.exports = ScriptLoader; -var logSource = 'ScriptLoader', - dataModelFileName = 'datamodel.json'; +var logSource = 'ScriptLoader'; +var dataModelFileName = 'datamodel.json'; function ScriptLoader(configPath, cache, logger) { this.configPath = configPath; @@ -35,13 +36,13 @@ ScriptLoader.prototype.load = function (done) { // only after we've loaded all directories do we complete core.async.series([ - function (done) { self._loadDataModel(done); }, - function (done) { + done => { self._loadDataModel(done); }, + done => { core.async.parallel([ - function (done) { self._loadTablesDirectory(done); }, - function (done) { self._loadJobsDirectory(done); }, - function (done) { self.loadScriptDirectory('shared', null, done); } - ], function () { + done => { self._loadTablesDirectory(done); }, + done => { self._loadJobsDirectory(done); }, + done => { self.loadScriptDirectory('shared', null, done); } + ], () => { if (done) { done(); } @@ -67,7 +68,7 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done this.logger.trace(logSource, _.sprintf("Loading scripts directory '%s'", filepath)); - fs.readdir(filepath, function (err, files) { + fs.readdir(filepath, (err, files) => { if (err) { if (options && core.isFunction(options.error)) { options.error(err); @@ -77,9 +78,9 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done throw err; } - var scriptsLoaded = 0, - numScriptsToLoad = files.length, - loadCallbackCount = 0; + var scriptsLoaded = 0; + var numScriptsToLoad = files.length; + var loadCallbackCount = 0; function loadComplete() { self.logger.trace(logSource, _.sprintf("%d %s script(s) loaded", scriptsLoaded, scriptType)); @@ -116,7 +117,7 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done loadComplete(); } else { - files.forEach(function (file) { + files.forEach(file => { self._loadScript(scriptType, filepath, file, options, completeLoad); }); } @@ -124,8 +125,8 @@ ScriptLoader.prototype.loadScriptDirectory = function (scriptType, options, done }; ScriptLoader.prototype.getDataModel = function () { - var key = this.cache.getKey('config', dataModelFileName), - dataModelEntry = this.cache.get(key); + var key = this.cache.getKey('config', dataModelFileName); + var dataModelEntry = this.cache.get(key); if (!dataModelEntry) { // since the datamodel file is loaded on startup, and the @@ -138,9 +139,9 @@ ScriptLoader.prototype.getDataModel = function () { }; ScriptLoader.prototype.getMetadata = function (scriptType, rootFileName) { - var metadataFileName = rootFileName + '.json', - key = this.cache.getKey(scriptType, metadataFileName), - metadataEntry = this.cache.get(key); + var metadataFileName = rootFileName + '.json'; + var key = this.cache.getKey(scriptType, metadataFileName); + var metadataEntry = this.cache.get(key); if (metadataEntry && metadataEntry.module) { return metadataEntry.module; @@ -163,10 +164,10 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o this.logger.trace(logSource, _.sprintf("Loading '%s' into the script cache", filename)); - var self = this, - scriptPath = path.join(filepath, filename), - scriptInfo = getScriptInfo(filepath, filename), - key = self.cache.getKey(scriptType, filename); + var self = this; + var scriptPath = path.join(filepath, filename); + var scriptInfo = getScriptInfo(filepath, filename); + var key = self.cache.getKey(scriptType, filename); function completeLoad(err) { if (!err) { @@ -181,7 +182,7 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o if (isModule(scriptType, filepath, filename)) { // first clear any existing require cache entry then load/reload delete require.cache[scriptPath]; - fileHelpers.requireWithRetries(scriptPath, this.logger, function (err, loadedModule) { + fileHelpers.requireWithRetries(scriptPath, this.logger, (err, loadedModule) => { if (!err) { if (isMetadataFile(filename)) { try { @@ -205,7 +206,7 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o }, this.maxFileOperationRetries, this.fileOperationRetryIntervalMS); } else { - fileHelpers.readFileWithRetries(scriptPath, this.logger, function (err, script) { + fileHelpers.readFileWithRetries(scriptPath, this.logger, (err, script) => { if (!err) { scriptInfo.script = script; completeLoad(); @@ -222,7 +223,7 @@ ScriptLoader.prototype._loadScript = function (scriptType, filepath, filename, o } }; -ScriptLoader.logScriptLoadError = function (logger, err, scriptType, fileName) { +ScriptLoader.logScriptLoadError = (logger, err, scriptType, fileName) => { var source = _.sprintf('/%s/%s', scriptType, fileName); logger.logUser(source, LogType.Error, _.sprintf("Failed to load script file '%s': %s", fileName, core.sanitizeUserCallStack(err))); }; @@ -271,7 +272,7 @@ ScriptLoader.prototype._loadTablesDirectory = function (done) { var dataModelIsValid = dataModel && dataModel.tables && Array.isArray(dataModel.tables); this.loadScriptDirectory('table', { - load: function (scriptInfo) { + load(scriptInfo) { if (dataModelIsValid && isMetadataFile(scriptInfo.scriptFileName) && // and this is a json file for a table !dataModel.getTable(scriptInfo.name)) { // and table is not already added @@ -289,7 +290,7 @@ ScriptLoader.prototype._loadJobsDirectory = function (done) { var dataModelIsValid = dataModel && dataModel.jobs && Array.isArray(dataModel.jobs); this.loadScriptDirectory('scheduler', { - load: function (scriptInfo) { + load(scriptInfo) { if (dataModelIsValid && path.extname(scriptInfo.scriptFileName).toLowerCase() === '.js' && // and this is a script file for a job !dataModel.getJob(scriptInfo.name)) { // and job is not already added @@ -304,12 +305,12 @@ ScriptLoader.prototype._loadJobsDirectory = function (done) { ScriptLoader.prototype._loadDataModel = function (done) { var options = { - filter: function (filename) { + filter(filename) { // in the root config dir, we only load the single // datamodel.json file return filename.toLowerCase() === dataModelFileName; }, - load: function (scriptInfo) { + load(scriptInfo) { configureDataModel(scriptInfo.module); } }; @@ -319,8 +320,8 @@ ScriptLoader.prototype._loadDataModel = function (done) { // extend the raw dataModel module by adding helper functions function configureDataModel(dataModel) { - var tableMap = dataModel._tableMap = {}, - jobMap = dataModel._jobMap = {}; + var tableMap = dataModel._tableMap = {}; + var jobMap = dataModel._jobMap = {}; function nameSelector(item) { return item.name.toLowerCase(); @@ -334,13 +335,9 @@ function configureDataModel(dataModel) { core.toLookup(dataModel.jobs, jobMap, nameSelector); } - dataModel.getTable = function (tableName) { - return tableMap[tableName.toLowerCase()]; - }; + dataModel.getTable = tableName => tableMap[tableName.toLowerCase()]; - dataModel.getJob = function (jobName) { - return jobMap[jobName.toLowerCase()]; - }; + dataModel.getJob = jobName => jobMap[jobName.toLowerCase()]; } // returns true if the specified file is a js or json file diff --git a/runtime/script/scriptmanager.js b/runtime/script/scriptmanager.js index 264f3e7..7186f99 100644 --- a/runtime/script/scriptmanager.js +++ b/runtime/script/scriptmanager.js @@ -5,19 +5,20 @@ // This module is responsible for execution of a script including exposing capabilities to scripts via globals // and any arguments that need to be passed to user-defined functions. -var vm = require('vm'), - core = require('../core'), - util = require('util'), - scriptErrors = require('./scripterror'), - StatusCodes = require('../statuscodes').StatusCodes, - sqlAdapter = require('./sqladapter'), - tripwire = require('tripwire'), - Table = require('./table'), - ScriptLoader = require('./scriptloader'), - path = require('path'), - _ = require('underscore'), - _str = require('underscore.string'), - config = require('mobileservice-config'); +var vm = require('vm'); + +var core = require('../core'); +var util = require('util'); +var scriptErrors = require('./scripterror'); +var StatusCodes = require('../statuscodes').StatusCodes; +var sqlAdapter = require('./sqladapter'); +var tripwire = require('tripwire'); +var Table = require('./table'); +var ScriptLoader = require('./scriptloader'); +var path = require('path'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var config = require('mobileservice-config'); _.mixin(_str.exports()); @@ -54,8 +55,9 @@ ScriptManager.prototype.getTablePermission = function (tableName, operation) { } // otherwise default to the datamodel permissions - var dataModel = this.getDataModel(), - table = dataModel.getTable(tableName); + var dataModel = this.getDataModel(); + + var table = dataModel.getTable(tableName); if (table && table.permissions) { permission = table.permissions[operation]; @@ -87,7 +89,7 @@ ScriptManager.prototype.hasTableScript = function (table, operation) { return this.scriptLoader.getTableScript(table, scriptErrors.normalizeOperationName(operation)) !== null; }; -ScriptManager.prototype.getLogSourceName = function (table, operation) { +ScriptManager.prototype.getLogSourceName = (table, operation) => { var normalizedOperationName = scriptErrors.normalizeOperationName(operation); var source = scriptErrors.getTableScriptSource(table, normalizedOperationName); return source; @@ -108,7 +110,7 @@ ScriptManager.prototype.runFeedbackScript = function (interval) { var self = this; // Set the feedback script to run every interval ms - this.feedbackInterval = setInterval(function () { + this.feedbackInterval = setInterval(() => { self._runFeedbackScript(); }, interval); @@ -155,13 +157,13 @@ ScriptManager.prototype._run = function (script, scriptFileName, scriptDirectory // create or less often used is defined below as create on-demand property getters. var sandbox = { _args: scriptArgs, - Buffer: Buffer, - setTimeout: setTimeout, - clearTimeout: clearTimeout, - setInterval: setInterval, - clearInterval: clearInterval, + Buffer, + setTimeout, + clearTimeout, + setInterval, + clearInterval, statusCodes: StatusCodes, - process: process + process }; sandbox.require = this._createRequire(scriptDirectoryName); @@ -181,7 +183,7 @@ ScriptManager.prototype._run = function (script, scriptFileName, scriptDirectory // Go async before executing the user script to create a new call stack; this ensures // we don't have to check for and re-throw tripwire exceptions. - process.nextTick(function () { + process.nextTick(() => { try { // first run the user script to define the operation in the context var context = vm.createContext(sandbox); @@ -223,10 +225,10 @@ ScriptManager.prototype._createServicesForSandbox = function (services, source, // if no response callback has been specified, use an empty function // to ignore any responses. For example, cron and apnsfeedback scripts // don't pass a response callback. - var responseCallback = options && options.responseCallback ? options.responseCallback : function () { }; + var responseCallback = options && options.responseCallback ? options.responseCallback : () => { }; services.tables = { - getTable: function (tableName) { + getTable(tableName) { if (!core.isString(tableName)) { throw new core.MobileServiceError("Table name cannot be null or empty.", core.ErrorCodes.ScriptError); } @@ -237,9 +239,7 @@ ScriptManager.prototype._createServicesForSandbox = function (services, source, // expose the current table name programmatically in server scripts as tables.current. if (options.currentTableName !== undefined) { - core.createLazyProperty(services.tables, 'current', function () { - return new Table(self.storage, options.currentTableName, source, logger, self.metrics, responseCallback); - }); + core.createLazyProperty(services.tables, 'current', () => new Table(self.storage, options.currentTableName, source, logger, self.metrics, responseCallback)); } services.console = this._createConsoleObject(source, logger); @@ -247,15 +247,13 @@ ScriptManager.prototype._createServicesForSandbox = function (services, source, services.push = this.pushAdapter.createPushForScripts(source, logger, this.metrics, responseCallback); // define lazy property for mssql wrapper - core.createLazyProperty(services, 'mssql', function () { - return sqlAdapter.create(self.storage.connection, logger, self.metrics, source, responseCallback); - }); + core.createLazyProperty(services, 'mssql', () => sqlAdapter.create(self.storage.connection, logger, self.metrics, source, responseCallback)); }; ScriptManager.prototype._createRequire = function (scriptDirectoryName) { var self = this; - return function (moduleOrPath) { + return moduleOrPath => { var fxUtil; try { // we need to use fxUtil.require to simulate origin of script to be inside scripts directory diff --git a/runtime/script/scriptstate.js b/runtime/script/scriptstate.js index 5a341c9..80a874c 100644 --- a/runtime/script/scriptstate.js +++ b/runtime/script/scriptstate.js @@ -4,12 +4,13 @@ // // State machine for orchestrating script callback execution -var core = require('../core'), - resources = require('../resources'), - scriptErrors = require('./scripterror'), - StatusCodes = require('../statuscodes').StatusCodes, - _ = require('underscore'), - _str = require('underscore.string'); +var core = require('../core'); + +var resources = require('../resources'); +var scriptErrors = require('./scripterror'); +var StatusCodes = require('../statuscodes').StatusCodes; +var _ = require('underscore'); +var _str = require('underscore.string'); _.mixin(_str.exports()); @@ -26,7 +27,7 @@ function ScriptState(operation, scriptArg, tableMetadata, responseCallback, logg // Define an interceptor response callback which will allow us to // capture and save results until respond has been called - this.responseCallback = _.wrap(responseCallback, function (oldCallback, err, results, statusCode, byUser) { + this.responseCallback = _.wrap(responseCallback, (oldCallback, err, results, statusCode, byUser) => { if (self.responseComplete) { if (byUser) { var stack = new core.MobileServiceError(resources.responseAlreadySent, core.ErrorCodes.ScriptError).stack; @@ -77,7 +78,7 @@ ScriptState.prototype.execute = function (callbackOptions) { // runtime, which we then dispatch to any callback functions // provided by the script. var self = this; - var scriptCallback = function (err, results) { + var scriptCallback = (err, results) => { // Because the conflict handler can call back into context.execute() // we need to update the saved data (from the original conflict). Also, @@ -144,7 +145,7 @@ ScriptState.prototype._executeCallbackOption = function (callback, args) { this.delayResponse = true; try { - callback.apply(null, args); + callback(...args); } catch (err) { // If an exception occurred in the handler, we need to unblock the response, @@ -206,7 +207,7 @@ ScriptState.validateRespondParameters = function (statusOrError, body) { ScriptState.prototype._saveResponseData = function (error, results, statusCode) { this.responseData = { err: error, - results: results, + results, statusCode: statusCode || null }; }; diff --git a/runtime/script/sqladapter.js b/runtime/script/sqladapter.js index ec2a0d4..63095d8 100644 --- a/runtime/script/sqladapter.js +++ b/runtime/script/sqladapter.js @@ -4,12 +4,13 @@ // // Adapts the sqlserver module for direct use from ZUMO scripts -var core = require('../core'), - sqlserver = require('sqlserver'), - scriptErrors = require('./scripterror'), - util = require('util'); +var core = require('../core'); -module.exports.create = function(connectionString, logger, metrics, source, responseCallback) { +var sqlserver = require('sqlserver'); +var scriptErrors = require('./scripterror'); +var util = require('util'); + +module.exports.create = (connectionString, logger, metrics, source, responseCallback) => { var adapter = new SqlAdapter(connectionString, logger, metrics, source, responseCallback); return adapter.createMSSQLModule(); }; @@ -29,28 +30,22 @@ SqlAdapter.prototype.createMSSQLModule = function () { self.logger.trace(logSource, 'Creating MSSQL Module', self.getTraceDetails()); return { - open: function (callbackOptions) { + open(callbackOptions) { var traceDetails = self.getTraceDetails("open"); var args = self.prepareArgs('open', null, callbackOptions, traceDetails, "Unable to open connection: "); - self.executeSqlServerFunction(traceDetails, function () { - return sqlserver.open(self.connectionString, args.callback); - }); + self.executeSqlServerFunction(traceDetails, () => sqlserver.open(self.connectionString, args.callback)); }, - query: function (query, paramsOrCallback, callbackOptions) { + query(query, paramsOrCallback, callbackOptions) { var traceDetails = self.getTraceDetails("query", query); var args = self.prepareArgs('query', paramsOrCallback, callbackOptions, traceDetails, "Error occurred executing query: "); - self.executeSqlServerFunction(traceDetails, function () { - return sqlserver.query(self.connectionString, query, args.params, args.callback); - }); + self.executeSqlServerFunction(traceDetails, () => sqlserver.query(self.connectionString, query, args.params, args.callback)); }, - queryRaw: function (query, paramsOrCallback, callbackOptions) { + queryRaw(query, paramsOrCallback, callbackOptions) { var traceDetails = self.getTraceDetails("queryRaw", query); var args = self.prepareArgs('queryRaw', paramsOrCallback, callbackOptions, traceDetails, "Error occurred executing query: "); - self.executeSqlServerFunction(traceDetails, function () { - return sqlserver.queryRaw(self.connectionString, query, args.params, args.callback); - }); + self.executeSqlServerFunction(traceDetails, () => sqlserver.queryRaw(self.connectionString, query, args.params, args.callback)); } }; }; @@ -92,7 +87,7 @@ SqlAdapter.prototype.prepareArgs = function (method, paramsOrCallbackOptions, ca params = [params]; } - return { params: params, callback: this.constructCallback(callbackOptions, traceDetails, errormsg) }; + return { params, callback: this.constructCallback(callbackOptions, traceDetails, errormsg) }; }; SqlAdapter.prototype.executeSqlServerFunction = function (traceDetails, sqlServerFunction) { @@ -118,7 +113,7 @@ SqlAdapter.prototype.constructCallback = function (callbackOptions, traceDetails traceDetails.error = err.toString(); if (callbackOptions && callbackOptions.error) { self.logger.trace(logSource, 'Call into MSSQL Module failed - Calling user error callback', traceDetails); - self.executeUserCallback(traceDetails, function () { + self.executeUserCallback(traceDetails, () => { callbackOptions.error(scriptErrors.prepareUserError(err)); }); } else { @@ -131,7 +126,7 @@ SqlAdapter.prototype.constructCallback = function (callbackOptions, traceDetails // Skip the error argument, pass the rest. var args = Array.prototype.slice.call(arguments).slice(1); - self.executeUserCallback(traceDetails, function () { + self.executeUserCallback(traceDetails, () => { callbackOptions.success.apply(null, args); }); } @@ -156,7 +151,7 @@ SqlAdapter.prototype.getTraceDetails = function (sqlFunction, query) { // for example connection string, etc. var traceDetails = { source: this.source, - sqlFunction: sqlFunction + sqlFunction }; if (query) { diff --git a/runtime/script/table.js b/runtime/script/table.js index 84f3b1a..7e4eb3f 100644 --- a/runtime/script/table.js +++ b/runtime/script/table.js @@ -6,20 +6,21 @@ // user's server side scripts. A table object is returned when a user // runs tables.getTable passing in the name of a table. -var DataOperation = require('../request/dataoperation'), - core = require('../core'), - scriptErrors = require('./scripterror'), - Query = require('../Zumo.Node').Query, - _ = require('underscore'), - _str = require('underscore.string'); +var DataOperation = require('../request/dataoperation'); - _.mixin(_str.exports()); +var core = require('../core'); +var scriptErrors = require('./scripterror'); +var Query = require('../Zumo.Node').Query; +var _ = require('underscore'); +var _str = require('underscore.string'); + +_.mixin(_str.exports()); exports = module.exports = Table; function Table(storage, table, source, logger, metrics, responseCallback) { - var validateItemForTableOperation = function (item, operation, mustHaveId) { + var validateItemForTableOperation = (item, operation, mustHaveId) => { if (!core.isObject(item)) { throw new core.MobileServiceError(_.sprintf("Operation '%s' on table '%s' failed. The parameter 'item' must be an object.", scriptErrors.normalizeOperationName(operation), table), core.ErrorCodes.ScriptError); } @@ -28,7 +29,7 @@ function Table(storage, table, source, logger, metrics, responseCallback) { } }; - var handleError = function (error, callback, callbackOptions) { + var handleError = (error, callback, callbackOptions) => { if (error.loggedToUser) { callback(error); } else if (!callbackOptions || !callbackOptions.error) { @@ -42,11 +43,9 @@ function Table(storage, table, source, logger, metrics, responseCallback) { } }; - this.getTableName = function () { - return table; - }; + this.getTableName = () => table; - this.read = function (queryOrCallbackOptions, callbackOptions) { + this.read = (queryOrCallbackOptions, callbackOptions) => { var query = null; if (queryOrCallbackOptions && queryOrCallbackOptions.constructor == Query) { @@ -64,31 +63,31 @@ function Table(storage, table, source, logger, metrics, responseCallback) { _executeTableOperation('read', table, query, callbackOptions); }; - this.insert = function (item, callbackOptions) { + this.insert = (item, callbackOptions) => { validateItemForTableOperation(item, 'insert', false); _executeTableOperation('insert', table, item, callbackOptions); }; - this.update = function (item, callbackOptions) { + this.update = (item, callbackOptions) => { validateItemForTableOperation(item, 'update', true); _executeTableOperation('update', table, item, callbackOptions); }; - this.del = function (itemOrId, callbackOptions) { + this.del = (itemOrId, callbackOptions) => { if (core.isObject(itemOrId)) { validateItemForTableOperation(itemOrId, 'del', true); } _executeTableOperation('del', table, itemOrId, callbackOptions); }; - this.lookup = function (id, callbackOptions) { + this.lookup = (id, callbackOptions) => { if (!id) { throw new core.MobileServiceError(_.sprintf("Operation 'lookup' on table '%s' failed. The id argument is invalid.", table), core.ErrorCodes.ScriptError); } - var query = { id: id }; + var query = { id }; var newCallbackOptions = _.clone(callbackOptions); if (callbackOptions && callbackOptions.success) { - newCallbackOptions.success = function (results) { + newCallbackOptions.success = results => { callbackOptions.success(results[0]); }; } @@ -104,21 +103,21 @@ function Table(storage, table, source, logger, metrics, responseCallback) { throw new core.MobileServiceError(_.sprintf("Operation '%s' on table '%s' failed. Arguments to table operations cannot be null or undefined.", scriptErrors.normalizeOperationName(operationName), table), core.ErrorCodes.ScriptError); } - storage.getTableMetadata(table, logger, function (error, tableMetadata) { - + storage.getTableMetadata(table, logger, (error, tableMetadata) => { if (error) { handleError(error, responseCallback, callbackOptions); return; } - - var systemProperties = [], - validateOptions = { - supportsConflict: (operationName === 'update' || operationName === 'del') && - tableMetadata.supportsConflict, - supportsIncludeDeleted: (operationName == 'read' && - tableMetadata.supportsSoftDelete) - }; + var systemProperties = []; + + var validateOptions = { + supportsConflict: (operationName === 'update' || operationName === 'del') && + tableMetadata.supportsConflict, + + supportsIncludeDeleted: (operationName == 'read' && + tableMetadata.supportsSoftDelete) + }; try { // callback options aren't required for a table operation, but if specified, must @@ -135,12 +134,12 @@ function Table(storage, table, source, logger, metrics, responseCallback) { } var includeDeleted = callbackOptions && callbackOptions.includeDeleted; - + // Define the callback that the data operation will call back // when it completes. We'll receive the error/result data from the // runtime, which we then dispatch to any callback functions // provided by the script. - var scriptCallback = function (error, results) { + var scriptCallback = (error, results) => { if (callbackOptions) { if (!error) { if (callbackOptions.success) { @@ -160,7 +159,7 @@ function Table(storage, table, source, logger, metrics, responseCallback) { }; // Take over the existing response callback to facilitate with error handling - responseCallback = _.wrap(responseCallback, function (oldCallback, error) { + responseCallback = _.wrap(responseCallback, (oldCallback, error) => { // If there is not an error or there is an error and callbackOptions.error exists, don't do anything because it has already been handled by the user. if (error) { handleError(error, oldCallback, callbackOptions); @@ -168,7 +167,7 @@ function Table(storage, table, source, logger, metrics, responseCallback) { }); var dataOperation = new DataOperation(storage, source, logger); - var options = { systemProperties: systemProperties, includeDeleted: includeDeleted }; + var options = { systemProperties, includeDeleted }; dataOperation[operationName](table, operationArg, options, responseCallback, scriptCallback); }); } @@ -179,18 +178,18 @@ function Table(storage, table, source, logger, metrics, responseCallback) { // forward on directly to a new Query instance. var queryOperators = ['where', 'select', 'orderBy', 'orderByDescending', 'skip', 'take', 'includeTotalCount']; -var copyOperator = function (operator) { - Table.prototype[operator] = function () { +var copyOperator = operator => { + Table.prototype[operator] = function(...args) { var self = this; // Creates a new query. var query = new Query(self.getTableName()); - query.read = function (callbackOptions) { + query.read = callbackOptions => { self.read(query, callbackOptions); }; - return query[operator].apply(query, arguments); + return query[operator](...args); }; }; var i = 0; diff --git a/runtime/script/zumocallback.js b/runtime/script/zumocallback.js index 9d9676f..755c8ef 100644 --- a/runtime/script/zumocallback.js +++ b/runtime/script/zumocallback.js @@ -4,9 +4,10 @@ // // This module contains helper method for converting zumo style success/error option object into node style async callback. -var _ = require('underscore'), - _str = require('underscore.string'), - scriptErrors = require('./scripterror'); +var _ = require('underscore'); + +var _str = require('underscore.string'); +var scriptErrors = require('./scripterror'); _.mixin(_str.exports()); @@ -30,7 +31,16 @@ ZumoCallback.moduleFailFormat = "Call into %s Module failed - %s"; // options is the options object that needs to be transformed into node style callback // visitError is a function(error){...} that will be called before error callback is called // visitResult is a function(result){...} that will be called before success callback is called -ZumoCallback.create = function (context, logSource, source, moduleName, method, options, visitError, visitResult) { +ZumoCallback.create = ( + context, + logSource, + source, + moduleName, + method, + options, + visitError, + visitResult +) => { if (typeof options.success !== 'undefined' && !_.isFunction(options.success)) { context.logger.trace(logSource, _.sprintf(ZumoCallback.moduleFailFormat, moduleName, "Invalid success callback option"), ZumoCallback.getTraceDetails(source, method)); throw new core.MobileServiceError('The options.success callback, if specified, must be a function.', core.ErrorCodes.ScriptError); @@ -41,7 +51,7 @@ ZumoCallback.create = function (context, logSource, source, moduleName, method, throw new core.MobileServiceError('The options.error callback, if specified, must be a function.', core.ErrorCodes.ScriptError); } - return function (error, result) { + return (error, result) => { // visit error and result if (error && visitError) { error = visitError(error); @@ -74,9 +84,9 @@ ZumoCallback.create = function (context, logSource, source, moduleName, method, }; }; -ZumoCallback.getTraceDetails = function (source, method, error) { +ZumoCallback.getTraceDetails = (source, method, error) => { var details = { - source: source + source }; if (method) { @@ -101,7 +111,17 @@ ZumoCallback.getTraceDetails = function (source, method, error) { // - allowedMethodPrefix -- Which method prefixes will be wrapped. (Example: ['send', 'receive'] // - disallowedMethodPrefix -- Which methods that match allowed will be excluded because they have no callback (Example: ['sendNull']) // - responseCallback, -- is the request's default responseCallback in case user does not provice a callback -ZumoCallback.wrapObject = function (objectToWrap, moduleNamePrefix, logSource, source, logger, metrics, allowedMethodPrefixes, disallowedMethodPrefixes, responseCallback) { +ZumoCallback.wrapObject = ( + objectToWrap, + moduleNamePrefix, + logSource, + source, + logger, + metrics, + allowedMethodPrefixes, + disallowedMethodPrefixes, + responseCallback +) => { var wrapperObject = {}; for (var prop in objectToWrap) { // if this is a method that should be wrapped, wrap it @@ -165,7 +185,7 @@ function wrapperMethod(logSource, source, logger, metrics, responseCallback, mod } // create callback - var callback = ZumoCallback.create({ metrics: metrics, logger: logger, responseCallback: responseCallback }, logSource, source, moduleName, methodName, options); + var callback = ZumoCallback.create({ metrics, logger, responseCallback }, logSource, source, moduleName, methodName, options); args.push(callback); try { @@ -188,7 +208,5 @@ function shouldWrapMethod(methodName, methodObject, allowedMethodPrefixes, disal // returns true if if the methodName starts with any string in methodPrefixList and false otherwise function methodNamePrefixInList(methodName, methodPrefixList) { return _.find(methodPrefixList, - function (methodPrefix) { - return _str.startsWith(methodName, methodPrefix); - }); + methodPrefix => _str.startsWith(methodName, methodPrefix)); } \ No newline at end of file diff --git a/runtime/server.js b/runtime/server.js index 804f4b8..071839e 100644 --- a/runtime/server.js +++ b/runtime/server.js @@ -4,34 +4,35 @@ // // This module creates and initializes the HTTP server -var path = require('path'), - NewRelicAdapter = require('./newrelicadapter'), - core = require('./core'); +var path = require('path'); + +var NewRelicAdapter = require('./newrelicadapter'); +var core = require('./core'); // If the customer has turned on New Relic we need to load this before anything else // so it can hook itself into the appropriate modules var newRelicAdapter = new NewRelicAdapter(); newRelicAdapter.initialize(resolveConfigPath(process.env, __dirname)); -var RequestHandler = require('./request/requesthandler'), - FileWatcher = require('./filewatcher'), - net = require('net'), - Request = require('./request/request'), - Logger = require('./logger'), - StatusCodes = require('./statuscodes').StatusCodes, - core = require('./core'), - tripwire = require('tripwire'), - Metrics = require('./metrics'), - ScriptManager = require('./script/scriptmanager'), - ExtensionManager = require('./script/extensionmanager'), - Storage = require('./storage/Storage'), - UserService = require('./users/userservice'), - resource = require('./resources'), - _ = require('underscore'), - _str = require('underscore.string'), - express = require('express'), - PushAdapter = require('./push/pushadapter'), - util = require('util'); +var RequestHandler = require('./request/requesthandler'); +var FileWatcher = require('./filewatcher'); +var net = require('net'); +var Request = require('./request/request'); +var Logger = require('./logger'); +var StatusCodes = require('./statuscodes').StatusCodes; +var core = require('./core'); +var tripwire = require('tripwire'); +var Metrics = require('./metrics'); +var ScriptManager = require('./script/scriptmanager'); +var ExtensionManager = require('./script/extensionmanager'); +var Storage = require('./storage/Storage'); +var UserService = require('./users/userservice'); +var resource = require('./resources'); +var _ = require('underscore'); +var _str = require('underscore.string'); +var express = require('express'); +var PushAdapter = require('./push/pushadapter'); +var util = require('util'); _.mixin(_str.exports()); @@ -74,8 +75,8 @@ Server.resolveConfigPath = resolveConfigPath; Server.newRelicAdapter = newRelicAdapter; Server.getAuthenticationCredentials = getAuthenticationCredentials; -Server.prototype.listen = function () { - this._server.listen.apply(this._server, arguments); +Server.prototype.listen = function(...args) { + this._server.listen(...args); }; Server.prototype._initializeLogging = function (env, options) { @@ -85,7 +86,7 @@ Server.prototype._initializeLogging = function (env, options) { this._globalLogger = options.logger || new Logger(LogLevel[env.MS_LogLevel]); - Logger.writer.on('error', function (err) { + Logger.writer.on('error', err => { // we need this handler here to prevent errors // from bubbling up to the global exception handler, which would // cause the process to be killed @@ -98,11 +99,11 @@ Server.prototype._initializeLogging = function (env, options) { }; Server.prototype._createAndInitializeServices = function (env) { - var maxRequestBodySize = (env.MS_MaxRequestBodySizeKB || 1024) * 1024, - authenticationCredentials = getAuthenticationCredentials(env), - crossDomainWhitelist = parseJsonSetting(env.MS_CrossDomainWhitelist, this._globalLogger), - previewFeatures = parseJsonSetting(env.MS_PreviewFeatures, this._globalLogger), - configPath = resolveConfigPath(env, __dirname); + var maxRequestBodySize = (env.MS_MaxRequestBodySizeKB || 1024) * 1024; + var authenticationCredentials = getAuthenticationCredentials(env); + var crossDomainWhitelist = parseJsonSetting(env.MS_CrossDomainWhitelist, this._globalLogger); + var previewFeatures = parseJsonSetting(env.MS_PreviewFeatures, this._globalLogger); + var configPath = resolveConfigPath(env, __dirname); this._metrics = new Metrics(this._globalLogger, this._metricsFlushTimeout); // Five minutes default @@ -120,8 +121,8 @@ Server.prototype._createAndInitializeServices = function (env) { }; Server.prototype._createHttpServer = function (env) { - var server, - self = this; + var server; + var self = this; if (env.pfx) { server = require('https').createServer({ pfx: env.pfx, passphrase: env.passphrase }, this._app); @@ -133,24 +134,24 @@ Server.prototype._createHttpServer = function (env) { // override the listen function so the server only starts listening // once all async initialization is complete var originalListen = server.listen; - server.listen = function () { - var listenArgs = arguments; + server.listen = function(...args) { + var listenArgs = args; var asyncStartupFunctions = [ - function (done) { self._extensionManager.initialize(done); }, - function (done) { self._requestHandler.initialize(self._app, self._extensionManager, done); } + done => { self._extensionManager.initialize(done); }, + done => { self._requestHandler.initialize(self._app, self._extensionManager, done); } ]; if (!self._pushAdapter.notificationHubPush) { - asyncStartupFunctions.push(function (done) { + asyncStartupFunctions.push(done => { self._scriptManager.runFeedbackScript(3600000); done(); }); } - asyncStartupFunctions.push(function (done) { self._extensionManager.runStartupScript(done); }); + asyncStartupFunctions.push(done => { self._extensionManager.runStartupScript(done); }); - core.async.series(asyncStartupFunctions, function () { + core.async.series(asyncStartupFunctions, () => { originalListen.apply(server, listenArgs); self._setupFileWatcher(); self._globalLogger.log(LogLevel.Verbose, LogType.Information, logSource, "Server started and listening."); @@ -165,12 +166,12 @@ Server.prototype._setupFileWatcher = function () { var self = this; var sentinelFilePath = path.join(this._homePath, 'site/wwwroot/sentinel'); - this._fileWatcher = new FileWatcher(sentinelFilePath, self._globalLogger, this._sentinelFilePollInterval, function () { + this._fileWatcher = new FileWatcher(sentinelFilePath, self._globalLogger, this._sentinelFilePollInterval, () => { self._fileWatcher.stop(); self._triggerRecycle(); }); - this._server.on('listening', function () { + this._server.on('listening', () => { self._fileWatcher.start(); }); }; @@ -187,7 +188,7 @@ Server.prototype._triggerRecycle = function () { // to process any outstanding requests, but new requests will // be routed by IIS Node to new instances. var stream = this.net.connect(this._iisNodeControlPipe); - stream.on('error', function (err) { + stream.on('error', err => { // if we get a stream error, we fall back to a // "hard shutdown" after logging the error self._shutdownProcess(0); @@ -204,12 +205,12 @@ Server.prototype._triggerRecycle = function () { }; Server.prototype._registerUncaughtExceptionListenerAndCreateHttpServer = function (env, logger) { - var tripwireContext = {}, - tripwireKeepalive = parseInt(env.MS_TripwireKeepalive, 10) || 5000, - self = this; + var tripwireContext = {}; + var tripwireKeepalive = parseInt(env.MS_TripwireKeepalive, 10) || 5000; + var self = this; // 99.9% of the time async errors will end up here and we assume all async errors belong to user code - this._onUncaughtException = function (e) { + this._onUncaughtException = e => { process.removeAllListeners('uncaughtException'); var exitCode; @@ -256,12 +257,12 @@ Server.prototype._shutdownProcess = function (exitCode, timeout) { // Wait a short period of time to allow any other logger instances a chance // to flush themselves (based on their flush timeouts). - setTimeout(function () { + setTimeout(() => { process.exit(exitCode); }, timeout); }; -Server.prototype._logGlobalException = function (e, isTripWireError, logger) { +Server.prototype._logGlobalException = (e, isTripWireError, logger) => { if (e.loggedToSystem || e.loggedToUser) { // we've already logged this error return; diff --git a/runtime/statuscodes.js b/runtime/statuscodes.js index f0383f5..023623b 100644 --- a/runtime/statuscodes.js +++ b/runtime/statuscodes.js @@ -4,7 +4,7 @@ // // Module containing 'enum' definitions for http status codes -(function (exports) { +((exports => { var core = require('./core'); @@ -32,4 +32,4 @@ exports.StatusCodes = StatusCodes; -})(typeof exports === 'undefined' ? (this.StatusCodes = {}) : exports); \ No newline at end of file +}))(typeof exports === 'undefined' ? (this.StatusCodes = {}) : exports); \ No newline at end of file diff --git a/runtime/storage/sqlbooleanizer.js b/runtime/storage/sqlbooleanizer.js index 1222540..4100169 100644 --- a/runtime/storage/sqlbooleanizer.js +++ b/runtime/storage/sqlbooleanizer.js @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (global) { +((global => { var core = require('../core'); @@ -13,7 +13,7 @@ var instanceMembers = { - visitUnary: function (expr) { + visitUnary(expr) { var operand = this.visit(expr.operand); if (operand && expr.expressionType == ExpressionType.Not) { @@ -29,7 +29,7 @@ return expr; }, - visitBinary: function (expr) { + visitBinary(expr) { var left = null; var right = null; @@ -128,7 +128,7 @@ SqlBooleanizer = core.deriveClass(ExpressionVisitor, null, instanceMembers); - SqlBooleanizer.booleanize = function (expr) { + SqlBooleanizer.booleanize = expr => { var booleanizer = new SqlBooleanizer(); expr = booleanizer.visit(expr); @@ -137,4 +137,4 @@ return expr; }; -})(typeof exports === "undefined" ? this : exports); \ No newline at end of file +}))(typeof exports === "undefined" ? this : exports); \ No newline at end of file diff --git a/runtime/storage/sqlformatter.js b/runtime/storage/sqlformatter.js index 7b694ba..72abae6 100644 --- a/runtime/storage/sqlformatter.js +++ b/runtime/storage/sqlformatter.js @@ -2,18 +2,17 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (global) { +((global => { + var core = require('../core'); + var _ = require('underscore'); + var _str = require('underscore.string'); - var core = require('../core'), - _ = require('underscore'), - _str = require('underscore.string'); - - require('../query/expressions'); - require('../query/expressionvisitor'); - require('../query/queryparser'); - require('./sqlbooleanizer'); - require('./typeconverter'); - require('./sqlhelpers'); + require('../query/expressions'); + require('../query/expressionvisitor'); + require('../query/queryparser'); + require('./sqlbooleanizer'); + require('./typeconverter'); + require('./sqlhelpers'); _.mixin(_str.exports()); @@ -24,7 +23,7 @@ var instanceMembers = { - format: function (query) { + format(query) { this.sql = ''; this.paramNumber = 0; this.parameters = []; @@ -47,7 +46,7 @@ this.sql = this.sql.trim(); }, - _formatQuery: function (query) { + _formatQuery(query) { var formattedSql; var selection = query.select ? this._formatSelection(query.select, query.systemProperties) : '*'; @@ -86,9 +85,10 @@ return formattedSql; }, - _formatPagedQuery: function (query) { - var formattedSql, selection = '', - aliasedSelection = ''; + _formatPagedQuery(query) { + var formattedSql; + var selection = ''; + var aliasedSelection = ''; if (query.select) { selection = this._formatSelection(query.select, query.systemProperties); @@ -117,7 +117,7 @@ return formattedSql; }, - _formatCountQuery: function (table, query) { + _formatCountQuery(table, query) { var filter; if (query.filter || query.id !== undefined || this.tableMetadata.supportsSoftDelete) { @@ -132,7 +132,7 @@ return sql; }, - _formatOrderBy: function (query, defaultOrder) { + _formatOrderBy(query, defaultOrder) { var orderBy = query.orderBy; if (!orderBy) { @@ -151,7 +151,7 @@ var order = ''; var self = this; - orderings.forEach(function (ordering) { + orderings.forEach(ordering => { if (order.length > 0) { order += ', '; } @@ -166,24 +166,24 @@ return order; }, - _formatSelection: function (selection, systemProperties, prefix) { + _formatSelection(selection, systemProperties, prefix) { systemProperties = (systemProperties || []).map(core.systemPropertyToColumnName); - var formattedSelection = '', - columns = selection.split(',').concat(systemProperties); + var formattedSelection = ''; + var columns = selection.split(',').concat(systemProperties); - columns.forEach(function (column) { + columns.forEach(column => { var member = column.trim(); if (formattedSelection.length > 0) { formattedSelection += ', '; } formattedSelection += (prefix || '') + SqlHelpers.formatMember(member); - }); + }); return formattedSelection; }, - _formatFilter: function (query, defaultFilter) { + _formatFilter(query, defaultFilter) { // if we already have a parsed filter use it, // otherwise parse the filter var filterExpr; @@ -231,13 +231,13 @@ // run the final query translation pipeline on the specified // expression, modifying the expression tree as needed - _finalizeExpression: function (expr) { + _finalizeExpression(expr) { expr = SqlBooleanizer.booleanize(expr); expr = TypeConverter.convertTypes(expr, this.tableMetadata); return expr; }, - visitBinary: function (expr) { + visitBinary(expr) { this.sql += '('; var left = null; @@ -322,7 +322,7 @@ return expr; }, - visitConstant: function (expr) { + visitConstant(expr) { if (expr.value === null) { this.sql += 'NULL'; return expr; @@ -333,11 +333,11 @@ return expr; }, - _createParameter: function (value) { + _createParameter(value) { var parameter = { name: '@p' + (this.paramNumber++).toString(), pos: this.paramNumber, - value: value + value }; this.parameters.push(parameter); @@ -347,7 +347,7 @@ return '?'; }, - visitMember: function (expr) { + visitMember(expr) { if (typeof expr.member === 'string') { this.sql += SqlHelpers.formatMember(expr.member); } @@ -358,7 +358,7 @@ return expr; }, - visitUnary: function (expr) { + visitUnary(expr) { if (expr.expressionType == ExpressionType.Not) { this.sql += 'NOT '; this.visit(expr.operand); @@ -372,14 +372,14 @@ return expr; }, - visitFunction: function (expr) { + visitFunction(expr) { if (expr.memberInfo) { this._formatMappedFunction(expr); } return expr; }, - _formatMappedFunction: function (expr) { + _formatMappedFunction(expr) { if (expr.memberInfo.type == 'string') { this._formatMappedStringMember(expr.instance, expr.memberInfo, expr.args); } @@ -391,13 +391,13 @@ } }, - _formatMappedMember: function (expr) { + _formatMappedMember(expr) { if (expr.member.type == 'string') { this._formatMappedStringMember(expr.instance, expr.member, null); } }, - _formatMappedDateMember: function (instance, mappedMemberInfo, args) { + _formatMappedDateMember(instance, mappedMemberInfo, args) { var functionName = mappedMemberInfo.memberName; if (functionName == 'day') { @@ -432,7 +432,7 @@ } }, - _formatMappedMathMember: function (instance, mappedMemberInfo, args) { + _formatMappedMathMember(instance, mappedMemberInfo, args) { var functionName = mappedMemberInfo.memberName; if (functionName == 'floor') { @@ -455,7 +455,7 @@ } }, - _formatMappedStringMember: function (instance, mappedMemberInfo, args) { + _formatMappedStringMember(instance, mappedMemberInfo, args) { var functionName = mappedMemberInfo.memberName; if (functionName == 'substringof') { @@ -579,5 +579,4 @@ } SqlFormatter = core.deriveClass(ExpressionVisitor, ctor, instanceMembers); - -})(typeof exports === "undefined" ? this : exports); \ No newline at end of file +}))(typeof exports === "undefined" ? this : exports); \ No newline at end of file diff --git a/runtime/storage/sqlhelpers.js b/runtime/storage/sqlhelpers.js index 41024a6..5a51a50 100644 --- a/runtime/storage/sqlhelpers.js +++ b/runtime/storage/sqlhelpers.js @@ -2,12 +2,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (global) { - - var _ = require('underscore'), - _str = require('underscore.string'), - resource = require('../resources'), - core = require('../core'); +((global => { + var _ = require('underscore'); + var _str = require('underscore.string'); + var resource = require('../resources'); + var core = require('../core'); _.mixin(_str.exports()); @@ -56,18 +55,18 @@ var classMembers = { // inspects the specified error (including innerError) and returns // the sqlstate if it exists - getSqlErrorCode: function (err) { + getSqlErrorCode(err) { if (err) { return err.innerError ? err.innerError.sqlstate : err.sqlstate; } }, // determines whether the specified error is a sql error - isSqlError: function (err) { + isSqlError(err) { return err && !!this.getSqlErrorCode(err); }, - isThrottleError: function (err) { + isThrottleError(err) { // There are a set of SqlAzure specific throttle errors that we must identify by // error number, in addition to the general HY000 sql state they return. These are: // http://social.technet.microsoft.com/wiki/contents/articles/1541.windows-azure-sql-database-connection-management.aspx @@ -81,7 +80,7 @@ // has an error code that matches one of our // 'retry' codes, indicating that the failed sql // operation should be reattempted. - isTemporaryError: function (err) { + isTemporaryError(err) { var errCode = err.sqlstate; if (errCode) { for (var idx in SqlTemporaryErrorCodes) { @@ -100,12 +99,10 @@ // Returns true if the specified sql error is considered to be // an application controlled issue. Returns false if the error is // likely due to bad input data (e.g. wrong data type, null constraint, etc) - isApplicationError: function (err) { + isApplicationError(err) { var sqlErrorCode = this.getSqlErrorCode(err); if (sqlErrorCode) { - return _.any(SqlApplicationErrorCodes, function (code) { - return sqlErrorCode == code; - }); + return _.any(SqlApplicationErrorCodes, code => sqlErrorCode == code); } return false; }, @@ -113,7 +110,7 @@ // Returns true if the specified sql error should be considered // a "system" sql error that we should log to our system log. // See here for more info on ODBC status codes: http://msdn.microsoft.com/en-us/library/ms714687.aspx - isSystemSqlError: function (err) { + isSystemSqlError(err) { var sqlErrorCode = this.getSqlErrorCode(err); if (!sqlErrorCode) { return false; @@ -135,7 +132,7 @@ // // When used with proper sql parameterization techniques, this // mitigates SQL INJECTION attacks. - isValidIdentifier: function (identifier) { + isValidIdentifier(identifier) { if (!identifier || !core.isString(identifier) || identifier.length > 128) { return false; } @@ -157,7 +154,7 @@ return true; }, - validateIdentifier: function (identifier) { + validateIdentifier(identifier) { if (!this.isValidIdentifier(identifier)) { throw new core.MobileServiceError(_.sprintf(resource.invalidIdentifier, identifier), core.ErrorCodes.BadInput); } @@ -166,24 +163,24 @@ // SECURITY - sql generation relies on these format functions to // validate identifiers to mitigate sql injection attacks // in the dynamic sql we generate - formatTableName: function (schemaName, tableName) { + formatTableName(schemaName, tableName) { this.validateIdentifier(schemaName); this.validateIdentifier(tableName); return _.sprintf('[%s].[%s]', schemaName, tableName); }, - formatSchemaName: function (appName) { + formatSchemaName(appName) { // Hyphens are not supported in schema names return appName.replace(/-/g, '_'); }, - formatMember: function (memberName) { + formatMember(memberName) { this.validateIdentifier(memberName); return _.sprintf('[%s]', memberName); }, // map json datatypes to SqlTypes - getSqlType: function (value) { + getSqlType(value) { var type = core.classof(value); switch (type) { case 'string': @@ -201,5 +198,4 @@ }; SqlHelpers = core.defineClass(null, null, classMembers); - -})(typeof exports === "undefined" ? this : exports); +}))(typeof exports === "undefined" ? this : exports); diff --git a/runtime/storage/storage.js b/runtime/storage/storage.js index b3e8996..344dcbc 100644 --- a/runtime/storage/storage.js +++ b/runtime/storage/storage.js @@ -2,12 +2,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -var sql = require('sqlserver'), - _ = require('underscore'), - _str = require('underscore.string'), - resource = require('../resources'), - core = require('../core'), - TableMetadata = require('./tablemetadata'); +var sql = require('sqlserver'); + +var _ = require('underscore'); +var _str = require('underscore.string'); +var resource = require('../resources'); +var core = require('../core'); +var TableMetadata = require('./tablemetadata'); _.mixin(_str.exports()); @@ -43,7 +44,7 @@ Storage.prototype.getTableMetadata = function (table, logger, callback) { } var self = this; - this._getTableColumns(table, logger, function (error, columns) { + this._getTableColumns(table, logger, (error, columns) => { if (error) { callback(error); return; @@ -70,9 +71,9 @@ Storage.prototype.insert = function (table, item, logger, options, callback) { // item can either be a singleton or a homogeneous array // of items to insert in a single batch var insertOptions = { - table: table, - item: item, - logger: logger, + table, + item, + logger, retry: this.dynamicSchemaEnabled, systemProperties: this._getSystemPropertiesFromOptions(options) }; @@ -82,7 +83,7 @@ Storage.prototype.insert = function (table, item, logger, options, callback) { Storage.prototype.update = function (table, id, item, logger, options, callback) { var self = this; - this._validateId(table, id, logger, function (error) { + this._validateId(table, id, logger, error => { if (error) { callback(error); return; @@ -99,10 +100,10 @@ Storage.prototype.update = function (table, id, item, logger, options, callback) } var updateOptions = { - table: table, - id: id, - item: item, - logger: logger, + table, + id, + item, + logger, retry: self.dynamicSchemaEnabled, systemProperties: self._getSystemPropertiesFromOptions(options) }; @@ -113,7 +114,7 @@ Storage.prototype.update = function (table, id, item, logger, options, callback) Storage.prototype.del = function (table, id, version, logger, options, callback) { var self = this; - this._validateId(table, id, logger, function (error) { + this._validateId(table, id, logger, error => { if (error) { callback(error); return; @@ -136,7 +137,7 @@ Storage.prototype._getTableMetadataAndSupportedSystemProperties = function (tabl // get the table metadata var self = this; - this.getTableMetadata(table, logger, function (error, tableMetadata) { + this.getTableMetadata(table, logger, (error, tableMetadata) => { if (error) { callback(error); return; @@ -145,7 +146,7 @@ Storage.prototype._getTableMetadataAndSupportedSystemProperties = function (tabl // check that only supported system properties are being requested var supportedSystemProperties = []; if (tableMetadata && tableMetadata.hasStringId) { - systemProperties.forEach(function (property) { + systemProperties.forEach(property => { if (_.contains(tableMetadata.systemProperties, property)) { supportedSystemProperties.push(property); } @@ -163,17 +164,17 @@ Storage.prototype._clearTableMetadata = function (table) { this.metadata[table] = null; }; -Storage.prototype._getSystemPropertiesFromOptions = function (options) { +Storage.prototype._getSystemPropertiesFromOptions = options => { var systemProperties = options ? options.systemProperties || [] : []; return systemProperties; }; -Storage.prototype._validateProperty = function (propertyName, value) { +Storage.prototype._validateProperty = (propertyName, value) => { // property name must be a valid identifier SqlHelpers.validateIdentifier(propertyName); // if there is a system property, make sure it is cased correctly - var systemColumnName = _.find(core.supportedSystemColumns, function (c) { return c.toLowerCase() === propertyName; }); + var systemColumnName = _.find(core.supportedSystemColumns, c => c.toLowerCase() === propertyName); if (systemColumnName && propertyName !== systemColumnName) { throw new core.MobileServiceError(_.sprintf("If a value for the property '%s' is specified, the property name must be cased correctly.", systemColumn), core.ErrorCodes.BadInput); } @@ -189,7 +190,7 @@ Storage.prototype._updateSchema = function (table, item, logger, callback) { var retryCount = 0; function tryUpdateSchema() { - self._getColumnsToAdd(table, item, logger, function (err, cols) { + self._getColumnsToAdd(table, item, logger, (err, cols) => { if (err) { callback(err); return; @@ -207,7 +208,7 @@ Storage.prototype._updateSchema = function (table, item, logger, callback) { // so we don't need to do so again here var addColumnsSql = ''; var columnsToAddError = null; - cols.forEach(function (col) { + cols.forEach(col => { if (core.isSystemColumnName(col) && self.metadata[table].hasStringId) { columnsToAddError = new core.MobileServiceError(_.sprintf("The column '%s' can not be dynamically added. Columns that begin with a '__' are considered system columns.", col), core.ErrorCodes.BadInput); @@ -228,7 +229,7 @@ Storage.prototype._updateSchema = function (table, item, logger, callback) { var cmdText = _.sprintf("ALTER TABLE %s ADD %s;", tableName, addColumnsSql); logger.trace(logSource, 'Updating schema', 'SQL: ' + cmdText); - self._executeSql('ALTER', cmdText, null, logger, null, callback, function (err) { + self._executeSql('ALTER', cmdText, null, logger, null, callback, err => { if (!err) { logger.trace(logSource, 'Schema update succeeded.'); callback(null); @@ -258,7 +259,7 @@ Storage.prototype._getTableColumns = function (table, logger, callback) { var statement = _.sprintf("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND TABLE_SCHEMA = '%s'", table, this.schemaName); var self = this; - this._executeSql('SELECT', statement, null, logger, null, callback, function (error, results) { + this._executeSql('SELECT', statement, null, logger, null, callback, (error, results) => { if (error) { callback(error); return; @@ -279,7 +280,7 @@ Storage.prototype._getTableColumns = function (table, logger, callback) { Storage.prototype._getColumnsToAdd = function (table, item, logger, callback) { var self = this; - this._getTableColumns(table, logger, function (error, results) { + this._getTableColumns(table, logger, (error, results) => { if (error) { callback(error); return; @@ -315,19 +316,19 @@ Storage.prototype._getColumnsToAdd = function (table, item, logger, callback) { }; Storage.prototype._update = function (options, callback) { - var table = options.table, - systemProperties = options.systemProperties, - logger = options.logger, - item = options.item, - updateStatement = options.updateStatement, - parameters = options.parameters, - self = this; + var table = options.table; + var systemProperties = options.systemProperties; + var logger = options.logger; + var item = options.item; + var updateStatement = options.updateStatement; + var parameters = options.parameters; + var self = this; if (item.__version) { item.__version = core.normalizeVersion(item.__version); } - this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, function (error, systemProperties, tableMetadata) { + this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, (error, systemProperties, tableMetadata) => { if (error) { callback(error); return; @@ -339,7 +340,7 @@ Storage.prototype._update = function (options, callback) { } else { // we are building the update statement for the first time - self._buildSqlUpdate(options, tableMetadata, systemProperties, function (error, updateStatement, parameters, version) { + self._buildSqlUpdate(options, tableMetadata, systemProperties, (error, updateStatement, parameters, version) => { if (error) { callback(error); return; @@ -360,21 +361,21 @@ Storage.prototype._update = function (options, callback) { }; Storage.prototype._executeSqlUpdate = function (options, callback) { - var self = this, - table = options.table, - id = options.id, - systemProperties = options.systemProperties, - logger = options.logger, - item = options.item, - version = options.version, - updateRowCount = 0, - updateStatement = options.updateStatement, - parameters = options.parameters, - lastResult = null; + var self = this; + var table = options.table; + var id = options.id; + var systemProperties = options.systemProperties; + var logger = options.logger; + var item = options.item; + var version = options.version; + var updateRowCount = 0; + var updateStatement = options.updateStatement; + var parameters = options.parameters; + var lastResult = null; logger.trace(logSource, 'Executing update', 'SQL: ' + updateStatement); - this._executeSql('UPDATE', updateStatement, parameters, logger, null, callback, function (error, results, more, rowCount) { + this._executeSql('UPDATE', updateStatement, parameters, logger, null, callback, (error, results, more, rowCount) => { if (error) { self._handleUpdateError(error, options, logger, callback); return; @@ -410,7 +411,7 @@ Storage.prototype._executeSqlUpdate = function (options, callback) { // when update or delete statement affects 0 records this method checks to see if the version check failed or the record does not exist Storage.prototype._handleUpdateOrDeleteFailure = function (logger, table, item, callback, forOperation) { - this._readItemForError(logger, table, item.id, function (error, result) { + this._readItemForError(logger, table, item.id, (error, result) => { if (error || !result) { callback(error, result); return; @@ -431,13 +432,13 @@ Storage.prototype._handleUpdateOrDeleteFailure = function (logger, table, item, Storage.prototype._readItemForError = function (logger, table, id, callback, readErrorFormat) { var query = { - table: table, - id: id + table, + id }; var queryOptions = { systemProperties: ['*'], includeDeleted: true }; - this.query(query, logger, queryOptions, function (error, results) { + this.query(query, logger, queryOptions, (error, results) => { if (error) { logger.trace(logSource, _.sprintf(readErrorFormat, error.toString())); if (callback) { @@ -458,19 +459,18 @@ Storage.prototype._readItemForError = function (logger, table, id, callback, rea }; Storage.prototype._buildSqlUpdate = function (options, tableMetadata, systemProperties, callback) { - var table = options.table, - item = options.item, - logger = options.logger, - id = options.id; - - var tableName = SqlHelpers.formatTableName(this.schemaName, table), - setStatements = '', - selectItemProperties = '', - versionValue = '', - hasStringId = tableMetadata.hasStringId, - updateStmt = '', - binaryColumns = tableMetadata.binaryColumns, - parameters = []; + var table = options.table; + var item = options.item; + var logger = options.logger; + var id = options.id; + var tableName = SqlHelpers.formatTableName(this.schemaName, table); + var setStatements = ''; + var selectItemProperties = ''; + var versionValue = ''; + var hasStringId = tableMetadata.hasStringId; + var updateStmt = ''; + var binaryColumns = tableMetadata.binaryColumns; + var parameters = []; for (var prop in item) { var value = item[prop]; @@ -541,7 +541,7 @@ Storage.prototype._buildSqlUpdate = function (options, tableMetadata, systemProp // Add the SELECT clause if the id is a string if (hasStringId) { if (systemProperties) { - _.each(systemProperties, function (systemProperty) { + _.each(systemProperties, systemProperty => { if (!versionValue || systemProperty !== 'version') { if (selectItemProperties.length > 0) { selectItemProperties += ', '; @@ -554,12 +554,12 @@ Storage.prototype._buildSqlUpdate = function (options, tableMetadata, systemProp updateStmt += _.sprintf("; SELECT %s FROM %s WHERE [id] = ?", selectItemProperties, tableName); parameters.push(id); } - } + } callback(null, updateStmt, parameters, versionValue); }; -Storage.prototype._trySetVersionParameter = function (version, parameters, callback) { +Storage.prototype._trySetVersionParameter = (version, parameters, callback) => { var versionBuffer = null; try { versionBuffer = new Buffer(version, 'base64'); @@ -572,7 +572,7 @@ Storage.prototype._trySetVersionParameter = function (version, parameters, callb return true; }; -Storage.prototype._handleUpdateSuccess = function (updateRowCount, item, results, logger, callback) { +Storage.prototype._handleUpdateSuccess = (updateRowCount, item, results, logger, callback) => { logger.trace(logSource, 'Update completed successfully. Rows affected: ' + updateRowCount); if (callback) { @@ -606,7 +606,7 @@ Storage.prototype._handleUpdateError = function (error, options, logger, callbac Storage.prototype._retryUpdate = function (options, callback) { var self = this; - this._updateSchema(options.table, options.item, options.logger, function (error) { + this._updateSchema(options.table, options.item, options.logger, error => { if (error) { callback(error); return; @@ -619,17 +619,17 @@ Storage.prototype._retryUpdate = function (options, callback) { }; Storage.prototype._del = function (table, id, version, logger, callback) { - var parameters = [], - item = { id: id, __version: version }, - tableName = SqlHelpers.formatTableName(this.schemaName, table), - deleteStmt = _.sprintf("DELETE FROM %s WHERE [id] = ?", tableName), - sqlEventName = 'DELETE', - forOperation = 'delete', - errorPrefix = 'Delete', - self = this; + var parameters = []; + var item = { id, __version: version }; + var tableName = SqlHelpers.formatTableName(this.schemaName, table); + var deleteStmt = _.sprintf("DELETE FROM %s WHERE [id] = ?", tableName); + var sqlEventName = 'DELETE'; + var forOperation = 'delete'; + var errorPrefix = 'Delete'; + var self = this; parameters.push(id); - this.getTableMetadata(table, logger, function (error, tableMetadata) { + this.getTableMetadata(table, logger, (error, tableMetadata) => { if (error) { callback(error); return; @@ -653,7 +653,7 @@ Storage.prototype._del = function (table, id, version, logger, callback) { logger.trace(logSource, 'Executing delete', 'SQL: ' + deleteStmt); var deleteRowCount = 0; - self._executeSql(sqlEventName, deleteStmt, parameters, logger, null, callback, function (err, results, more, rowCount) { + self._executeSql(sqlEventName, deleteStmt, parameters, logger, null, callback, (err, results, more, rowCount) => { if (!err) { // The row count should always be 1 since the delete is based on the primary key // but this callback mught be invoked multiple times, and the rowCount might be set on @@ -685,15 +685,15 @@ Storage.prototype._del = function (table, id, version, logger, callback) { }; Storage.prototype._insert = function (options, callback) { - var table = options.table, - systemProperties = options.systemProperties, - logger = options.logger, - item = options.item, - insertStatement = options.insertStatement, - parameters = options.parameters, - self = this; + var table = options.table; + var systemProperties = options.systemProperties; + var logger = options.logger; + var item = options.item; + var insertStatement = options.insertStatement; + var parameters = options.parameters; + var self = this; - this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, function (error, systemProperties, tableMetadata) { + this._getTableMetadataAndSupportedSystemProperties(table, systemProperties, logger, (error, systemProperties, tableMetadata) => { if (error) { callback(error); return; @@ -705,7 +705,7 @@ Storage.prototype._insert = function (options, callback) { } else { // we are building the insert statement for the first time - self._buildSqlInsert(table, item, tableMetadata, systemProperties, logger, function (error, insertStatement, parameters) { + self._buildSqlInsert(table, item, tableMetadata, systemProperties, logger, (error, insertStatement, parameters) => { if (error) { callback(error); return; @@ -722,15 +722,15 @@ Storage.prototype._insert = function (options, callback) { }; Storage.prototype._executeSqlInsert = function (options, callback) { - var self = this, - logger = options.logger, - item = options.item, - insertStatement = options.insertStatement, - parameters = options.parameters; + var self = this; + var logger = options.logger; + var item = options.item; + var insertStatement = options.insertStatement; + var parameters = options.parameters; logger.trace(logSource, 'Executing insert', 'SQL: ' + insertStatement); - this._executeSql('INSERT', insertStatement, parameters, logger, null, callback, function (error, results, more) { + this._executeSql('INSERT', insertStatement, parameters, logger, null, callback, (error, results, more) => { if (error) { self._handleInsertError(error, options, logger, callback); return; @@ -743,16 +743,16 @@ Storage.prototype._executeSqlInsert = function (options, callback) { }; Storage.prototype._buildSqlInsert = function (table, item, tableMetadata, systemProperties, logger, callback) { - var parameters = [], - hasStringId = tableMetadata.hasStringId, - binaryColumns = tableMetadata.binaryColumns, - tableName = SqlHelpers.formatTableName(this.schemaName, table), - self = this, - invalidIdError = null, - columnNames = '', - valueParams = ''; + var parameters = []; + var hasStringId = tableMetadata.hasStringId; + var binaryColumns = tableMetadata.binaryColumns; + var tableName = SqlHelpers.formatTableName(this.schemaName, table); + var self = this; + var invalidIdError = null; + var columnNames = ''; + var valueParams = ''; - _.each(item, function (value, prop) { + _.each(item, (value, prop) => { if (!invalidIdError) { // validate the property try { @@ -826,7 +826,7 @@ Storage.prototype._buildSqlInsert = function (table, item, tableMetadata, system if (hasStringId) { var selectItemProperties = '[appTable].[id] AS [id]'; if (systemProperties) { - systemProperties.forEach(function (systemProperty) { + systemProperties.forEach(systemProperty => { selectItemProperties += _.sprintf(', [appTable].[__%1$s] AS [__%1$s]', systemProperty); }); } @@ -840,7 +840,7 @@ Storage.prototype._buildSqlInsert = function (table, item, tableMetadata, system callback(null, insertStmt, parameters); }; -Storage.prototype._handleInsertSuccess = function (item, results, logger, callback) { +Storage.prototype._handleInsertSuccess = (item, results, logger, callback) => { logger.trace(logSource, 'Insert completed successfully.'); if (callback) { @@ -878,7 +878,7 @@ Storage.prototype._retryInsert = function (options, callback) { // this of course assumes homogenous arrays var item = core.isArray(options.item) ? options.item[0] : options.item; - this._updateSchema(options.table, item, options.logger, function (err) { + this._updateSchema(options.table, item, options.logger, err => { if (!err) { // the schema update succeeded, so retry the insert options.retry = false; @@ -893,7 +893,7 @@ Storage.prototype._retryInsert = function (options, callback) { Storage.prototype._query = function (query, logger, callback) { // ensure only supported system properties are being requested var self = this; - this._getTableMetadataAndSupportedSystemProperties(query.table, query.systemProperties, logger, function (error, systemProperties, tableMetadata) { + this._getTableMetadataAndSupportedSystemProperties(query.table, query.systemProperties, logger, (error, systemProperties, tableMetadata) => { if (error) { callback(error); return; @@ -901,7 +901,7 @@ Storage.prototype._query = function (query, logger, callback) { query.systemProperties = systemProperties; - self._buildSqlQuery(query, tableMetadata, function (error, sqlStatement, parameters) { + self._buildSqlQuery(query, tableMetadata, (error, sqlStatement, parameters) => { if (error) { callback(error); return; @@ -910,7 +910,7 @@ Storage.prototype._query = function (query, logger, callback) { logger.trace(logSource, 'Executing query', 'SQL: ' + sqlStatement); var allResults = []; - self._executeSql('SELECT', sqlStatement, parameters, logger, null, callback, function (error, results, more) { + self._executeSql('SELECT', sqlStatement, parameters, logger, null, callback, (error, results, more) => { if (error) { self._handleQueryError(query, error, logger, callback); } @@ -939,7 +939,7 @@ Storage.prototype._buildSqlQuery = function (query, tableMetadata, callback) { // build the parameter values array var parameters = []; - _.each(formatter.parameters, function (parameter) { + _.each(formatter.parameters, parameter => { parameters.push(parameter.value); }); @@ -966,11 +966,11 @@ Storage.prototype._handleQueryError = function (query, error, logger, callback) } }; -Storage.prototype._getSystemPropertiesToDeleteFromQueryResults = function (query, tableMetadata) { +Storage.prototype._getSystemPropertiesToDeleteFromQueryResults = (query, tableMetadata) => { // get a normalized (trimmed, all lowercase) list of the select properties var selectedProperties = []; if (query.select) { - query.select.split(',').forEach(function (selectedProperty) { + query.select.split(',').forEach(selectedProperty => { selectedProperty = selectedProperty.trim(); if (selectedProperty.length > 0) { selectedProperty = selectedProperty.toLowerCase(); @@ -980,7 +980,7 @@ Storage.prototype._getSystemPropertiesToDeleteFromQueryResults = function (query } var systemPropertiesToDelete = []; - tableMetadata.systemProperties.forEach(function (systemProperty) { + tableMetadata.systemProperties.forEach(systemProperty => { // don't delete any requested system properties if (!_.contains(query.systemProperties, systemProperty)) { var columnName = core.systemPropertyToColumnName(systemProperty.toLowerCase()); @@ -1009,14 +1009,14 @@ Storage.prototype._handleQuerySuccess = function (query, results, tableMetadata, // iterate through the results to remove row numbers or system properties // that were not requested if (pagedQuery || systemPropertiesToDelete.length > 0) { - _.each(queryResult, function (result) { + _.each(queryResult, result => { // delete the row numbers if the query was paged if (pagedQuery) { delete result.ROW_NUMBER; } // delete the system property if it wasn't requested - _.each(_.keys(result), function (property) { + _.each(_.keys(result), property => { if (_.contains(systemPropertiesToDelete, property.toLowerCase())) { delete result[property]; } @@ -1040,7 +1040,7 @@ Storage.prototype._handleQuerySuccess = function (query, results, tableMetadata, }; // Intended to only be called for unhandled errors that have been caught -Storage.prototype._handleSystemError = function (error, logger, callback) { +Storage.prototype._handleSystemError = (error, logger, callback) => { if (core.isRuntimeError(error)) { logger.error(logSource, error); } @@ -1054,7 +1054,7 @@ Storage.prototype._handleSystemError = function (error, logger, callback) { }; Storage.prototype._validateId = function (table, id, logger, callback) { - this.getTableMetadata(table, logger, function (error, tableMetadata) { + this.getTableMetadata(table, logger, (error, tableMetadata) => { var idType = tableMetadata.idType; error = null; if (!id || @@ -1074,7 +1074,7 @@ Storage.prototype._validateId = function (table, id, logger, callback) { // } Storage.prototype.executeSql = function (sqlEventName, sqlStmt, parameters, logger, options, callback) { try { - this._executeSql(sqlEventName, sqlStmt, parameters, logger, options, function (err) { + this._executeSql(sqlEventName, sqlStmt, parameters, logger, options, err => { callback(err); }, callback); } @@ -1088,16 +1088,16 @@ Storage.prototype.executeSql = function (sqlEventName, sqlStmt, parameters, logg Storage.prototype._executeSql = function (sqlEventName, sqlStmt, parameters, logger, options, callback, sqlCallback) { options = options || {}; - var self = this, - rowCount, - retryCount = 0, - disableUserLog = options.disableUserLog || false; + var self = this; + var rowCount; + var retryCount = 0; + var disableUserLog = options.disableUserLog || false; // to facilitate retries, define a function that will actually execute the sql function executeSql() { try { var event = self.metrics.startEvent('sql.command.' + sqlEventName); - var stmt = self.sql.query(self.connection, sqlStmt, parameters, function (err, results, more) { + var stmt = self.sql.query(self.connection, sqlStmt, parameters, (err, results, more) => { self.metrics.endEvent(event); if (err) { @@ -1142,7 +1142,7 @@ Storage.prototype._executeSql = function (sqlEventName, sqlStmt, parameters, log }); if (stmt) { - stmt.on('rowcount', function (result) { + stmt.on('rowcount', result => { rowCount = result; }); } diff --git a/runtime/storage/tablemetadata.js b/runtime/storage/tablemetadata.js index f1ba863..a719ffa 100644 --- a/runtime/storage/tablemetadata.js +++ b/runtime/storage/tablemetadata.js @@ -4,9 +4,10 @@ // // This class captures the metadata about a table in user database. -var _ = require('underscore'), - _str = require('underscore.string'); - core = require('../core'); +var _ = require('underscore'); + +var _str = require('underscore.string'); +core = require('../core'); _.mixin(_str.exports()); @@ -18,7 +19,7 @@ function TableMetadata () { this.binaryColumns = []; Object.defineProperty(this, 'hasStringId', { - get: function () { return this.idType === 'string'; } + get() { return this.idType === 'string'; } }); } @@ -59,7 +60,7 @@ TableMetadata.prototype._addSystemColumn = function (column) { } }; -TableMetadata.prototype._getTableIdType = function (type) { +TableMetadata.prototype._getTableIdType = type => { if (type.indexOf('int') >= 0) { return 'number'; } @@ -69,12 +70,12 @@ TableMetadata.prototype._getTableIdType = function (type) { return 'unknown'; }; -TableMetadata.fromColumns = function (columns) { +TableMetadata.fromColumns = columns => { // the default table metadata var metadata = new TableMetadata(); // iterate over the columns - _.each(columns, function (column) { + _.each(columns, column => { metadata._addColumn(column); }); diff --git a/runtime/storage/typeconverter.js b/runtime/storage/typeconverter.js index 613c8d2..490199c 100644 --- a/runtime/storage/typeconverter.js +++ b/runtime/storage/typeconverter.js @@ -2,10 +2,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ---------------------------------------------------------------------------- -(function (global) { - - var core = require('../core'), - _ = require('underscore'); +((global => { + var core = require('../core'); + var _ = require('underscore'); require('../query/expressions'); require('../query/expressionvisitor'); @@ -18,7 +17,7 @@ var instanceMembers = { - visitBinary: function (expr) { + visitBinary(expr) { var left = expr.left ? this.visit(expr.left) : null; var right = expr.right ? this.visit(expr.right) : null; @@ -36,13 +35,13 @@ return expr; }, - _isStringConstant: function(expr) { + _isStringConstant(expr) { return expr && expr.expressionType === ExpressionType.Constant && core.isString(expr.value); }, - _isBinaryMemberAccess: function (expr) { + _isBinaryMemberAccess(expr) { return expr && expr.expressionType === ExpressionType.MemberAccess && core.isString(expr.member) && @@ -52,12 +51,11 @@ TypeConverter = core.deriveClass(ExpressionVisitor, ctor, instanceMembers); - TypeConverter.convertTypes = function (expr, tableMetadata) { + TypeConverter.convertTypes = (expr, tableMetadata) => { var converter = new TypeConverter(tableMetadata); expr = converter.visit(expr); return expr; }; - -})(typeof exports === "undefined" ? this : exports); \ No newline at end of file +}))(typeof exports === "undefined" ? this : exports); \ No newline at end of file diff --git a/runtime/users/userproperties.js b/runtime/users/userproperties.js index af7b208..64a15a3 100644 --- a/runtime/users/userproperties.js +++ b/runtime/users/userproperties.js @@ -7,10 +7,13 @@ // { secrets: { ... }, claims: {... } } // where secrets and claims are key value pairs of data about user -var Encryptor = require('../encryptor'), - VERSION = 1, // version of encryption algorithm - KEYID = 0; // in future when we support key rollover, we will increment this every time key changes - // we will keep at least two master keys (with their key ids) at all times i.e. current and previous +var Encryptor = require('../encryptor'); // in future when we support key rollover, we will increment this every time key changes +// we will keep at least two master keys (with their key ids) at all times i.e. current and previous + +var // version of encryption algorithm +VERSION = 1; + +var KEYID = 0; function UserProperties(masterKey) { this.encryptionKey = masterKey + 'USR'; diff --git a/runtime/users/userservice.js b/runtime/users/userservice.js index 06bc5c9..a5846a9 100644 --- a/runtime/users/userservice.js +++ b/runtime/users/userservice.js @@ -4,13 +4,14 @@ // // This class encapsulates the business logic for promoting anonymous user to registered user and adding identity of an existing user -var _ = require('underscore'), - _str = require('underscore.string'), - core = require('../core.js'), - Storage = require('../storage/storage.js'), - UserStore = require('./userstore.js'), - UserProperties = require('./userproperties'), - logSource = 'UserService'; +var _ = require('underscore'); + +var _str = require('underscore.string'); +var core = require('../core.js'); +var Storage = require('../storage/storage.js'); +var UserStore = require('./userstore.js'); +var UserProperties = require('./userproperties'); +var logSource = 'UserService'; _.mixin(_str.exports()); @@ -25,7 +26,7 @@ function UserService(logger, userStore, userProperties, encryptClaims) { UserService.prototype.isEnabled = function (callback) { var self = this; - this.userStore.isEnabled(function (err, isEnabled) { + this.userStore.isEnabled((err, isEnabled) => { if (err) { return self._handleStorageError(err, callback); } @@ -38,7 +39,7 @@ UserService.prototype.isEnabled = function (callback) { UserService.prototype.getUserIdentities = function (id, callback) { var self = this; - this.getUserById(id, function (err, user) { + this.getUserById(id, (err, user) => { if (err) { callback(err); return; @@ -51,7 +52,7 @@ UserService.prototype.getUserIdentities = function (id, callback) { // { microsoft: { userId: 1234, email: 'someone@example.com'}, // facebook: { userId: 345, name: 'john' } } self._getAllProviderProperties(user) - .forEach(function (item) { + .forEach(item => { if (item.properties) { var identity = self._userPropertiesToIdentity(item.provider, item.providerId, item.properties); identities[item.provider] = identity; @@ -67,7 +68,7 @@ UserService.prototype.getUserIdentities = function (id, callback) { UserService.prototype.getUserById = function (id, callback) { var self = this; - this.userStore.getUserById(id, function (err, user) { + this.userStore.getUserById(id, (err, user) => { if (err) { return self._handleStorageError(err, callback); } @@ -75,7 +76,7 @@ UserService.prototype.getUserById = function (id, callback) { if (user) { // provider properties are packed in storage and need to be unpacked self._getAllProviderProperties(user) - .forEach(function (item) { + .forEach(item => { user[item.key] = self.userProperties.unpack(item.properties); }); } @@ -99,7 +100,7 @@ UserService.prototype.addUserIdentity = function (provider, providerId, properti properties = this.userProperties.pack(properties); - this.userStore.getUserByProviderId(provider, providerId, function (err, user) { + this.userStore.getUserByProviderId(provider, providerId, (err, user) => { if (err) { return self._handleStorageError(err, callback); } @@ -114,14 +115,14 @@ UserService.prototype.addUserIdentity = function (provider, providerId, properti }; // returns all providers on user object -UserService.prototype._getAllProviderProperties = function (user) { +UserService.prototype._getAllProviderProperties = user => { // user table in database has columns for each provider, prefixed by provider name - var allProperties = _.filter(Object.keys(user), function (propName) { return _.endsWith(propName, 'Properties'); }) - .map(function (propName) { + var allProperties = _.filter(Object.keys(user), propName => _.endsWith(propName, 'Properties')) + .map(propName => { var provider = _.strLeft(propName, 'Properties'); return { key: propName, - provider: provider, + provider, providerId: user[provider + 'Id'], properties: user[propName] }; @@ -131,7 +132,7 @@ UserService.prototype._getAllProviderProperties = function (user) { }; // converts the properties object into user identity object returned from user.getIdentities() -UserService.prototype._userPropertiesToIdentity = function (provider, providerId, properties) { +UserService.prototype._userPropertiesToIdentity = (provider, providerId, properties) => { var claims = properties.claims || {}; var identity = _.extend(claims, properties.secrets); if (providerId) { @@ -144,7 +145,7 @@ UserService.prototype._userPropertiesToIdentity = function (provider, providerId UserService.prototype._createUser = function (provider, providerId, properties, callback) { var self = this; - this.userStore.createUser(provider, providerId, properties, function (err, user) { + this.userStore.createUser(provider, providerId, properties, (err, user) => { if (err) { return self._handleStorageError(err, callback); } @@ -154,9 +155,9 @@ UserService.prototype._createUser = function (provider, providerId, properties, }; UserService.prototype._addIdentityToUser = function (user, provider, providerId, properties, callback) { - var self = this, - idKey = provider + 'Id', - propertiesKey = provider + 'Properties'; + var self = this; + var idKey = provider + 'Id'; + var propertiesKey = provider + 'Properties'; var modified = user[idKey] !== providerId || user[propertiesKey] !== properties; if (!modified) { @@ -167,7 +168,7 @@ UserService.prototype._addIdentityToUser = function (user, provider, providerId, user[idKey] = providerId.toString(); user[propertiesKey] = properties; - this.userStore.updateUser(user, function (err, rowCount) { + this.userStore.updateUser(user, (err, rowCount) => { if (err) { return self._handleStorageError(err, callback); } @@ -183,9 +184,9 @@ UserService.prototype._handleStorageError = function (err, callback) { // implements null object pattern by creating a user service like object that is always disabled. Object.defineProperty(UserService, 'nullService', { - get: function () { + get() { return { - isEnabled: function (callback) { + isEnabled(callback) { callback(null, false); } }; @@ -193,7 +194,7 @@ Object.defineProperty(UserService, 'nullService', { }); // factory method for creating user service instance -UserService.create = function (options, previewFeatures, metrics, logger) { +UserService.create = (options, previewFeatures, metrics, logger) => { options = options || {}; var featureEnabled = _.contains(previewFeatures, 'Users'); @@ -212,12 +213,10 @@ UserService.create = function (options, previewFeatures, metrics, logger) { }; // get provider name by provider specific user id issued by zumo -UserService.getProviderNameByUserId = function (userId) { - return _.strLeft(userId, ':'); -}; +UserService.getProviderNameByUserId = userId => _.strLeft(userId, ':'); // returns full name of provider for short code -UserService.getProviderNameByKey = function (key) { +UserService.getProviderNameByKey = key => { var name = key.toLowerCase(); if (name == 'microsoft') { name = 'MicrosoftAccount'; @@ -226,7 +225,7 @@ UserService.getProviderNameByKey = function (key) { }; // derive short code for provider from its full name -UserService.getProviderKeyByName = function (name) { +UserService.getProviderKeyByName = name => { var key = name.toLowerCase(); if (key == 'microsoftaccount') { key = 'microsoft'; diff --git a/runtime/users/userstore.js b/runtime/users/userstore.js index 250e324..82666b8 100644 --- a/runtime/users/userstore.js +++ b/runtime/users/userstore.js @@ -25,7 +25,7 @@ UserStore.prototype.isEnabled = function (callback) { top: 1 }; - this.storage.query(query, this.logger, null, function (err, results) { + this.storage.query(query, this.logger, null, (err, results) => { var tableNotFoundError = self._isTableNotFoundError(err); // if it is an error but not the expected table found error then we're not able to determine at this time whether users feature is enabled or not if (err && !tableNotFoundError) { @@ -45,13 +45,14 @@ UserStore.prototype.isEnabled = function (callback) { // get user by 3rd party identity provider specific user id UserStore.prototype.getUserByProviderId = function (provider, providerId, callback) { - var self = this, - query = { - table: tableName, - filter: provider + "Id eq '" + providerId + "'" - }; + var self = this; - this.storage.query(query, this.logger, null, function (err, results) { + var query = { + table: tableName, + filter: provider + "Id eq '" + providerId + "'" + }; + + this.storage.query(query, this.logger, null, (err, results) => { if (err) { self._callErrorCallback(err, callback); return; @@ -70,7 +71,7 @@ UserStore.prototype.getUserByProviderId = function (provider, providerId, callba UserStore.prototype.updateUser = function (user, callback) { var self = this; - this.storage.update(tableName, user.id, user, this.logger, null, function (err, rowCount) { + this.storage.update(tableName, user.id, user, this.logger, null, (err, rowCount) => { if (err) { self._callErrorCallback(err, callback); return; @@ -82,13 +83,13 @@ UserStore.prototype.updateUser = function (user, callback) { // create new user in the storage UserStore.prototype.createUser = function (provider, providerId, providerProperties, callback) { - var self = this, - user = {}; + var self = this; + var user = {}; user[provider + 'Id'] = providerId; user[provider + 'Properties'] = providerProperties; - this.storage.insert(tableName, user, this.logger, null, function (err, insertedUser) { + this.storage.insert(tableName, user, this.logger, null, (err, insertedUser) => { if (err) { self._callErrorCallback(err, callback); return; @@ -100,14 +101,15 @@ UserStore.prototype.createUser = function (provider, providerId, providerPropert // get user by unique id UserStore.prototype.getUserById = function (userId, callback) { - var self = this, - query = { - table: tableName, - filter: "id eq '" + userId + "'", - top: 1 - }; + var self = this; - this.storage.query(query, this.logger, null, function (err, results) { + var query = { + table: tableName, + filter: "id eq '" + userId + "'", + top: 1 + }; + + this.storage.query(query, this.logger, null, (err, results) => { if (err) { self._callErrorCallback(err, callback); return; @@ -126,7 +128,7 @@ UserStore.prototype._callErrorCallback = function (err, callback) { } }; -UserStore.prototype._isTableNotFoundError = function (err) { +UserStore.prototype._isTableNotFoundError = err => { var isTableNotFound = err && err.innerError && err.innerError.sqlstate === '42S02' &&