)]}'
{"version":3,"sources":["check/match.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,W;;AAEA,uC;AACA,2B;;AAEA,4D;;AAEA,G;AACA,mE;AACA,kE;AACA,E;AACA,4E;AACA,uB;AACA,kB;AACA,wC;AACA,qD;AACA,kB;AACA,G;AACA,mC;AACA,qD;AACA,I;AACA,mE;AACA,0E;AACA,sE;AACA,wE;AACA,yE;AACA,8D;AACA,oE;AACA,iB;AACA,+B;AACA,O;AACA,iC;AACA,iB;AACA,iD;AACA,6C;AACA,c;AACA,G;AACA,E;;AAEA,G;AACA,mB;AACA,0D;AACA,G;AACA,S;AACA,gC;AACA,iC;AACA,I;AACA,mC;AACA,2C;AACA,I;AACA,mB;AACA,+B;AACA,gC;AACA,I;AACA,uC;AACA,wC;AACA,I;AACA,wC;AACA,yC;AACA,I;AACA,wC;AACA,2B;;AAEA,mE;AACA,6D;AACA,yC;AACA,6E;AACA,gF;AACA,a;AACA,qC;AACA,mB;AACA,gF;AACA,+D;AACA,gE;AACA,K;;AAEA,gF;AACA,8E;AACA,oD;AACA,gF;AACA,4E;AACA,+E;;AAEA,K;AACA,4D;AACA,oB;AACA,0C;AACA,uE;AACA,K;AACA,mC;AACA,S;AACA,mC;AACA,kB;AACA,iB;AACA,mC;AACA,qB;AACA,8B;AACA,c;AACA,K;AACA,I;;AAEA,gF;AACA,gF;AACA,0C;AACA,I;AACA,8E;AACA,4D;AACA,2E;AACA,oC;AACA,O;AACA,2E;AACA,wD;AACA,kB;AACA,G;AACA,E;;AAEA,mC;AACA,yB;AACA,E;;AAEA,gC;AACA,yB;AACA,uE;AACA,yB;AACA,E;;AAEA,kC;AACA,6B;AACA,E;;AAEA,0C;AACA,yB;AACA,E;;AAEA,2C;AACA,yB;AACA,E;;AAEA,oB;AACA,qB;AACA,qB;AACA,uB;AACA,uE;AACA,0B;AACA,0B;AACA,E;;AAEA,8C;AACA,oB;AACA,4B;AACA,W;;AAEA,wB;AACA,sD;AACA,iD;AACA,yC;AACA,8C;AACA,e;AACA,yE;AACA,0C;AACA,K;AACA,G;AACA,yB;AACA,uB;AACA,a;AACA,0E;AACA,G;;AAEA,sE;AACA,mE;AACA,0B;AACA,a;AACA,4D;AACA,kD;AACA,G;;AAEA,qD;AACA,kC;AACA,+E;AACA,gF;AACA,uE;AACA,kD;AACA,6E;AACA,oD;AACA,2D;AACA,Y;AACA,kD;AACA,8E;AACA,G;;AAEA,yD;AACA,yB;AACA,wC;;AAEA,iE;AACA,iC;AACA,6B;AACA,oE;AACA,4C;AACA,qD;AACA,6E;AACA,K;;AAEA,kD;AACA,W;AACA,+C;AACA,qB;AACA,yC;AACA,mD;AACA,S;AACA,kB;AACA,O;AACA,O;AACA,W;AACA,G;;AAEA,2E;AACA,6D;AACA,iC;AACA,iC;AACA,a;AACA,iC;AACA,2D;AACA,G;;;AAGA,kC;AACA,sD;;AAEA,iC;AACA,sD;AACA,W;AACA,gD;AACA,iC;AACA,e;AACA,qB;AACA,4E;AACA,kB;AACA,0C;AACA,oB;AACA,O;AACA,K;AACA,iC;AACA,6E;AACA,G;;AAEA,uE;AACA,iB;AACA,oC;AACA,iC;AACA,a;AACA,wD;AACA,oE;AACA,G;;AAEA,iC;AACA,wB;AACA,2C;AACA,8B;AACA,8B;AACA,G;AACA,4C;AACA,8B;AACA,0C;AACA,sC;AACA,G;;AAEA,kC;AACA,qD;;AAEA,2E;AACA,6E;AACA,+D;AACA,gC;AACA,kE;AACA,qB;AACA,uD;AACA,mC;AACA,mD;;AAEA,4B;AACA,4B;AACA,8C;AACA,uC;AACA,iD;AACA,Q;AACA,yC;AACA,K;;AAEA,0C;AACA,S;AACA,yC;AACA,sD;AACA,qC;AACA,gD;AACA,sD;AACA,c;AACA,gC;AACA,+C;AACA,gC;AACA,uD;AACA,S;AACA,O;AACA,mB;AACA,qC;AACA,+C;AACA,gB;AACA,K;AACA,K;;AAEA,uD;AACA,uD;AACA,K;AACA,E;;AAEA,oD;AACA,kB;AACA,0E;AACA,2B;AACA,4B;AACA,6E;AACA,4E;AACA,+B;AACA,sB;AACA,iC;AACA,E;;AAEA,qC;AACA,8B;AACA,oB;AACA,sC;AACA,a;AACA,8E;AACA,0E;AACA,0B;AACA,mD;AACA,0D;AACA,K;AACA,I;AACA,uC;AACA,oB;AACA,gD;AACA,+E;AACA,4E;AACA,gB;AACA,mE;AACA,gF;AACA,+B;AACA,oB;AACA,O;AACA,K;AACA,iB;AACA,I;AACA,uD;AACA,oB;AACA,8B;AACA,+D;AACA,wC;AACA,G;AACA,G;;AAEA,+E;AACA,0E;AACA,yE;AACA,uE;AACA,8E;AACA,8E;AACA,gB;;AAEA,uD;AACA,qB;AACA,yC;AACA,yD;AACA,0B;AACA,+E;AACA,gC;;AAEA,8B;AACA,4B;AACA,oB;AACA,E","file":"/packages/check.js","sourcesContent":["// XXX docs\n\n// Things we explicitly do NOT support:\n//    - heterogenous arrays\n\nvar currentArgumentChecker = new Meteor.EnvironmentVariable;\n\n/**\n * @summary Check that a value matches a [pattern](#matchpatterns).\n * If the value does not match the pattern, throw a `Match.Error`.\n *\n * Particularly useful to assert that arguments to a function have the right\n * types and structure.\n * @locus Anywhere\n * @param {Any} value The value to check\n * @param {MatchPattern} pattern The pattern to match\n * `value` against\n */\ncheck = function (value, pattern) {\n  // Record that check got called, if somebody cared.\n  //\n  // We use getOrNullIfOutsideFiber so that it's OK to call check()\n  // from non-Fiber server contexts; the downside is that if you forget to\n  // bindEnvironment on some random callback in your method/publisher,\n  // it might not find the argumentChecker and you'll get an error about\n  // not checking an argument that it looks like you're checking (instead\n  // of just getting a \"Node code must run in a Fiber\" error).\n  var argChecker = currentArgumentChecker.getOrNullIfOutsideFiber();\n  if (argChecker)\n    argChecker.checking(value);\n  try {\n    checkSubtree(value, pattern);\n  } catch (err) {\n    if ((err instanceof Match.Error) && err.path)\n      err.message += \" in field \" + err.path;\n    throw err;\n  }\n};\n\n/**\n * @namespace Match\n * @summary The namespace for all Match types and methods.\n */\nMatch = {\n  Optional: function (pattern) {\n    return new Optional(pattern);\n  },\n  OneOf: function (/*arguments*/) {\n    return new OneOf(_.toArray(arguments));\n  },\n  Any: ['__any__'],\n  Where: function (condition) {\n    return new Where(condition);\n  },\n  ObjectIncluding: function (pattern) {\n    return new ObjectIncluding(pattern);\n  },\n  ObjectWithValues: function (pattern) {\n    return new ObjectWithValues(pattern);\n  },\n  // Matches only signed 32-bit integers\n  Integer: ['__integer__'],\n\n  // XXX matchers should know how to describe themselves for errors\n  Error: Meteor.makeErrorType(\"Match.Error\", function (msg) {\n    this.message = \"Match error: \" + msg;\n    // The path of the value that failed to match. Initially empty, this gets\n    // populated by catching and rethrowing the exception as it goes back up the\n    // stack.\n    // E.g.: \"vals[3].entity.created\"\n    this.path = \"\";\n    // If this gets sent over DDP, don't give full internal details but at least\n    // provide something better than 500 Internal server error.\n    this.sanitizedError = new Meteor.Error(400, \"Match failed\");\n  }),\n\n  // Tests to see if value matches pattern. Unlike check, it merely returns true\n  // or false (unless an error other than Match.Error was thrown). It does not\n  // interact with _failIfArgumentsAreNotAllChecked.\n  // XXX maybe also implement a Match.match which returns more information about\n  //     failures but without using exception handling or doing what check()\n  //     does with _failIfArgumentsAreNotAllChecked and Meteor.Error conversion\n\n  /**\n   * @summary Returns true if the value matches the pattern.\n   * @locus Anywhere\n   * @param {Any} value The value to check\n   * @param {MatchPattern} pattern The pattern to match `value` against\n   */\n  test: function (value, pattern) {\n    try {\n      checkSubtree(value, pattern);\n      return true;\n    } catch (e) {\n      if (e instanceof Match.Error)\n        return false;\n      // Rethrow other errors.\n      throw e;\n    }\n  },\n\n  // Runs `f.apply(context, args)`. If check() is not called on every element of\n  // `args` (either directly or in the first level of an array), throws an error\n  // (using `description` in the message).\n  //\n  _failIfArgumentsAreNotAllChecked: function (f, context, args, description) {\n    var argChecker = new ArgumentChecker(args, description);\n    var result = currentArgumentChecker.withValue(argChecker, function () {\n      return f.apply(context, args);\n    });\n    // If f didn't itself throw, make sure it checked all of its arguments.\n    argChecker.throwUnlessAllArgumentsHaveBeenChecked();\n    return result;\n  }\n};\n\nvar Optional = function (pattern) {\n  this.pattern = pattern;\n};\n\nvar OneOf = function (choices) {\n  if (_.isEmpty(choices))\n    throw new Error(\"Must provide at least one choice to Match.OneOf\");\n  this.choices = choices;\n};\n\nvar Where = function (condition) {\n  this.condition = condition;\n};\n\nvar ObjectIncluding = function (pattern) {\n  this.pattern = pattern;\n};\n\nvar ObjectWithValues = function (pattern) {\n  this.pattern = pattern;\n};\n\nvar typeofChecks = [\n  [String, \"string\"],\n  [Number, \"number\"],\n  [Boolean, \"boolean\"],\n  // While we don't allow undefined in EJSON, this is good for optional\n  // arguments with OneOf.\n  [undefined, \"undefined\"]\n];\n\nvar checkSubtree = function (value, pattern) {\n  // Match anything!\n  if (pattern === Match.Any)\n    return;\n\n  // Basic atomic types.\n  // Do not match boxed objects (e.g. String, Boolean)\n  for (var i = 0; i < typeofChecks.length; ++i) {\n    if (pattern === typeofChecks[i][0]) {\n      if (typeof value === typeofChecks[i][1])\n        return;\n      throw new Match.Error(\"Expected \" + typeofChecks[i][1] + \", got \" +\n                            typeof value);\n    }\n  }\n  if (pattern === null) {\n    if (value === null)\n      return;\n    throw new Match.Error(\"Expected null, got \" + EJSON.stringify(value));\n  }\n\n  // Strings and numbers match literally.  Goes well with Match.OneOf.\n  if (typeof pattern === \"string\" || typeof pattern === \"number\") {\n    if (value === pattern)\n      return;\n    throw new Match.Error(\"Expected \" + pattern + \", got \" +\n                          EJSON.stringify(value));\n  }\n\n  // Match.Integer is special type encoded with array\n  if (pattern === Match.Integer) {\n    // There is no consistent and reliable way to check if variable is a 64-bit\n    // integer. One of the popular solutions is to get reminder of division by 1\n    // but this method fails on really large floats with big precision.\n    // E.g.: 1.348192308491824e+23 % 1 === 0 in V8\n    // Bitwise operators work consistantly but always cast variable to 32-bit\n    // signed integer according to JavaScript specs.\n    if (typeof value === \"number\" && (value | 0) === value)\n      return\n    throw new Match.Error(\"Expected Integer, got \"\n                + (value instanceof Object ? EJSON.stringify(value) : value));\n  }\n\n  // \"Object\" is shorthand for Match.ObjectIncluding({});\n  if (pattern === Object)\n    pattern = Match.ObjectIncluding({});\n\n  // Array (checked AFTER Any, which is implemented as an Array).\n  if (pattern instanceof Array) {\n    if (pattern.length !== 1)\n      throw Error(\"Bad pattern: arrays must have one type element\" +\n                  EJSON.stringify(pattern));\n    if (!_.isArray(value) && !_.isArguments(value)) {\n      throw new Match.Error(\"Expected array, got \" + EJSON.stringify(value));\n    }\n\n    _.each(value, function (valueElement, index) {\n      try {\n        checkSubtree(valueElement, pattern[0]);\n      } catch (err) {\n        if (err instanceof Match.Error) {\n          err.path = _prependPath(index, err.path);\n        }\n        throw err;\n      }\n    });\n    return;\n  }\n\n  // Arbitrary validation checks. The condition can return false or throw a\n  // Match.Error (ie, it can internally use check()) to fail.\n  if (pattern instanceof Where) {\n    if (pattern.condition(value))\n      return;\n    // XXX this error is terrible\n    throw new Match.Error(\"Failed Match.Where validation\");\n  }\n\n\n  if (pattern instanceof Optional)\n    pattern = Match.OneOf(undefined, pattern.pattern);\n\n  if (pattern instanceof OneOf) {\n    for (var i = 0; i < pattern.choices.length; ++i) {\n      try {\n        checkSubtree(value, pattern.choices[i]);\n        // No error? Yay, return.\n        return;\n      } catch (err) {\n        // Other errors should be thrown. Match errors just mean try another\n        // choice.\n        if (!(err instanceof Match.Error))\n          throw err;\n      }\n    }\n    // XXX this error is terrible\n    throw new Match.Error(\"Failed Match.OneOf or Match.Optional validation\");\n  }\n\n  // A function that isn't something we special-case is assumed to be a\n  // constructor.\n  if (pattern instanceof Function) {\n    if (value instanceof pattern)\n      return;\n    throw new Match.Error(\"Expected \" + (pattern.name ||\n                                         \"particular constructor\"));\n  }\n\n  var unknownKeysAllowed = false;\n  var unknownKeyPattern;\n  if (pattern instanceof ObjectIncluding) {\n    unknownKeysAllowed = true;\n    pattern = pattern.pattern;\n  }\n  if (pattern instanceof ObjectWithValues) {\n    unknownKeysAllowed = true;\n    unknownKeyPattern = [pattern.pattern];\n    pattern = {};  // no required keys\n  }\n\n  if (typeof pattern !== \"object\")\n    throw Error(\"Bad pattern: unknown pattern type\");\n\n  // An object, with required and optional keys. Note that this does NOT do\n  // structural matches against objects of special types that happen to match\n  // the pattern: this really needs to be a plain old {Object}!\n  if (typeof value !== 'object')\n    throw new Match.Error(\"Expected object, got \" + typeof value);\n  if (value === null)\n    throw new Match.Error(\"Expected object, got null\");\n  if (value.constructor !== Object)\n    throw new Match.Error(\"Expected plain object\");\n\n  var requiredPatterns = {};\n  var optionalPatterns = {};\n  _.each(pattern, function (subPattern, key) {\n    if (subPattern instanceof Optional)\n      optionalPatterns[key] = subPattern.pattern;\n    else\n      requiredPatterns[key] = subPattern;\n  });\n\n  _.each(value, function (subValue, key) {\n    try {\n      if (_.has(requiredPatterns, key)) {\n        checkSubtree(subValue, requiredPatterns[key]);\n        delete requiredPatterns[key];\n      } else if (_.has(optionalPatterns, key)) {\n        checkSubtree(subValue, optionalPatterns[key]);\n      } else {\n        if (!unknownKeysAllowed)\n          throw new Match.Error(\"Unknown key\");\n        if (unknownKeyPattern) {\n          checkSubtree(subValue, unknownKeyPattern[0]);\n        }\n      }\n    } catch (err) {\n      if (err instanceof Match.Error)\n        err.path = _prependPath(key, err.path);\n      throw err;\n    }\n  });\n\n  _.each(requiredPatterns, function (subPattern, key) {\n    throw new Match.Error(\"Missing key '\" + key + \"'\");\n  });\n};\n\nvar ArgumentChecker = function (args, description) {\n  var self = this;\n  // Make a SHALLOW copy of the arguments. (We'll be doing identity checks\n  // against its contents.)\n  self.args = _.clone(args);\n  // Since the common case will be to check arguments in order, and we splice\n  // out arguments when we check them, make it so we splice out from the end\n  // rather than the beginning.\n  self.args.reverse();\n  self.description = description;\n};\n\n_.extend(ArgumentChecker.prototype, {\n  checking: function (value) {\n    var self = this;\n    if (self._checkingOneValue(value))\n      return;\n    // Allow check(arguments, [String]) or check(arguments.slice(1), [String])\n    // or check([foo, bar], [String]) to count... but only if value wasn't\n    // itself an argument.\n    if (_.isArray(value) || _.isArguments(value)) {\n      _.each(value, _.bind(self._checkingOneValue, self));\n    }\n  },\n  _checkingOneValue: function (value) {\n    var self = this;\n    for (var i = 0; i < self.args.length; ++i) {\n      // Is this value one of the arguments? (This can have a false positive if\n      // the argument is an interned primitive, but it's still a good enough\n      // check.)\n      // (NaN is not === to itself, so we have to check specially.)\n      if (value === self.args[i] || (_.isNaN(value) && _.isNaN(self.args[i]))) {\n        self.args.splice(i, 1);\n        return true;\n      }\n    }\n    return false;\n  },\n  throwUnlessAllArgumentsHaveBeenChecked: function () {\n    var self = this;\n    if (!_.isEmpty(self.args))\n      throw new Error(\"Did not check() all arguments during \" +\n                      self.description);\n  }\n});\n\nvar _jsKeywords = [\"do\", \"if\", \"in\", \"for\", \"let\", \"new\", \"try\", \"var\", \"case\",\n  \"else\", \"enum\", \"eval\", \"false\", \"null\", \"this\", \"true\", \"void\", \"with\",\n  \"break\", \"catch\", \"class\", \"const\", \"super\", \"throw\", \"while\", \"yield\",\n  \"delete\", \"export\", \"import\", \"public\", \"return\", \"static\", \"switch\",\n  \"typeof\", \"default\", \"extends\", \"finally\", \"package\", \"private\", \"continue\",\n  \"debugger\", \"function\", \"arguments\", \"interface\", \"protected\", \"implements\",\n  \"instanceof\"];\n\n// Assumes the base of path is already escaped properly\n// returns key + base\nvar _prependPath = function (key, base) {\n  if ((typeof key) === \"number\" || key.match(/^[0-9]+$/))\n    key = \"[\" + key + \"]\";\n  else if (!key.match(/^[a-z_$][0-9a-z_$]*$/i) || _.contains(_jsKeywords, key))\n    key = JSON.stringify([key]);\n\n  if (base && base[0] !== \"[\")\n    return key + '.' + base;\n  return key + base;\n};\n\n"]}