properties.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. 'use strict';
  2. module.exports = function generate_properties(it, $keyword, $ruleType) {
  3. var out = ' ';
  4. var $lvl = it.level;
  5. var $dataLvl = it.dataLevel;
  6. var $schema = it.schema[$keyword];
  7. var $schemaPath = it.schemaPath + it.util.getProperty($keyword);
  8. var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
  9. var $breakOnError = !it.opts.allErrors;
  10. var $data = 'data' + ($dataLvl || '');
  11. var $errs = 'errs__' + $lvl;
  12. var $it = it.util.copy(it);
  13. var $closingBraces = '';
  14. $it.level++;
  15. var $nextValid = 'valid' + $it.level;
  16. var $key = 'key' + $lvl,
  17. $idx = 'idx' + $lvl,
  18. $dataNxt = $it.dataLevel = it.dataLevel + 1,
  19. $nextData = 'data' + $dataNxt,
  20. $dataProperties = 'dataProperties' + $lvl;
  21. var $schemaKeys = Object.keys($schema || {}).filter(notProto),
  22. $pProperties = it.schema.patternProperties || {},
  23. $pPropertyKeys = Object.keys($pProperties).filter(notProto),
  24. $aProperties = it.schema.additionalProperties,
  25. $someProperties = $schemaKeys.length || $pPropertyKeys.length,
  26. $noAdditional = $aProperties === false,
  27. $additionalIsSchema = typeof $aProperties == 'object' && Object.keys($aProperties).length,
  28. $removeAdditional = it.opts.removeAdditional,
  29. $checkAdditional = $noAdditional || $additionalIsSchema || $removeAdditional,
  30. $ownProperties = it.opts.ownProperties,
  31. $currentBaseId = it.baseId;
  32. var $required = it.schema.required;
  33. if ($required && !(it.opts.$data && $required.$data) && $required.length < it.opts.loopRequired) {
  34. var $requiredHash = it.util.toHash($required);
  35. }
  36. function notProto(p) {
  37. return p !== '__proto__';
  38. }
  39. out += 'var ' + ($errs) + ' = errors;var ' + ($nextValid) + ' = true;';
  40. if ($ownProperties) {
  41. out += ' var ' + ($dataProperties) + ' = undefined;';
  42. }
  43. if ($checkAdditional) {
  44. if ($ownProperties) {
  45. out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; ';
  46. } else {
  47. out += ' for (var ' + ($key) + ' in ' + ($data) + ') { ';
  48. }
  49. if ($someProperties) {
  50. out += ' var isAdditional' + ($lvl) + ' = !(false ';
  51. if ($schemaKeys.length) {
  52. if ($schemaKeys.length > 8) {
  53. out += ' || validate.schema' + ($schemaPath) + '.hasOwnProperty(' + ($key) + ') ';
  54. } else {
  55. var arr1 = $schemaKeys;
  56. if (arr1) {
  57. var $propertyKey, i1 = -1,
  58. l1 = arr1.length - 1;
  59. while (i1 < l1) {
  60. $propertyKey = arr1[i1 += 1];
  61. out += ' || ' + ($key) + ' == ' + (it.util.toQuotedString($propertyKey)) + ' ';
  62. }
  63. }
  64. }
  65. }
  66. if ($pPropertyKeys.length) {
  67. var arr2 = $pPropertyKeys;
  68. if (arr2) {
  69. var $pProperty, $i = -1,
  70. l2 = arr2.length - 1;
  71. while ($i < l2) {
  72. $pProperty = arr2[$i += 1];
  73. out += ' || ' + (it.usePattern($pProperty)) + '.test(' + ($key) + ') ';
  74. }
  75. }
  76. }
  77. out += ' ); if (isAdditional' + ($lvl) + ') { ';
  78. }
  79. if ($removeAdditional == 'all') {
  80. out += ' delete ' + ($data) + '[' + ($key) + ']; ';
  81. } else {
  82. var $currentErrorPath = it.errorPath;
  83. var $additionalProperty = '\' + ' + $key + ' + \'';
  84. if (it.opts._errorDataPathProperty) {
  85. it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
  86. }
  87. if ($noAdditional) {
  88. if ($removeAdditional) {
  89. out += ' delete ' + ($data) + '[' + ($key) + ']; ';
  90. } else {
  91. out += ' ' + ($nextValid) + ' = false; ';
  92. var $currErrSchemaPath = $errSchemaPath;
  93. $errSchemaPath = it.errSchemaPath + '/additionalProperties';
  94. var $$outStack = $$outStack || [];
  95. $$outStack.push(out);
  96. out = ''; /* istanbul ignore else */
  97. if (it.createErrors !== false) {
  98. out += ' { keyword: \'' + ('additionalProperties') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { additionalProperty: \'' + ($additionalProperty) + '\' } ';
  99. if (it.opts.messages !== false) {
  100. out += ' , message: \'';
  101. if (it.opts._errorDataPathProperty) {
  102. out += 'is an invalid additional property';
  103. } else {
  104. out += 'should NOT have additional properties';
  105. }
  106. out += '\' ';
  107. }
  108. if (it.opts.verbose) {
  109. out += ' , schema: false , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
  110. }
  111. out += ' } ';
  112. } else {
  113. out += ' {} ';
  114. }
  115. var __err = out;
  116. out = $$outStack.pop();
  117. if (!it.compositeRule && $breakOnError) {
  118. /* istanbul ignore if */
  119. if (it.async) {
  120. out += ' throw new ValidationError([' + (__err) + ']); ';
  121. } else {
  122. out += ' validate.errors = [' + (__err) + ']; return false; ';
  123. }
  124. } else {
  125. out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
  126. }
  127. $errSchemaPath = $currErrSchemaPath;
  128. if ($breakOnError) {
  129. out += ' break; ';
  130. }
  131. }
  132. } else if ($additionalIsSchema) {
  133. if ($removeAdditional == 'failing') {
  134. out += ' var ' + ($errs) + ' = errors; ';
  135. var $wasComposite = it.compositeRule;
  136. it.compositeRule = $it.compositeRule = true;
  137. $it.schema = $aProperties;
  138. $it.schemaPath = it.schemaPath + '.additionalProperties';
  139. $it.errSchemaPath = it.errSchemaPath + '/additionalProperties';
  140. $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
  141. var $passData = $data + '[' + $key + ']';
  142. $it.dataPathArr[$dataNxt] = $key;
  143. var $code = it.validate($it);
  144. $it.baseId = $currentBaseId;
  145. if (it.util.varOccurences($code, $nextData) < 2) {
  146. out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' ';
  147. } else {
  148. out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' ';
  149. }
  150. out += ' if (!' + ($nextValid) + ') { errors = ' + ($errs) + '; if (validate.errors !== null) { if (errors) validate.errors.length = errors; else validate.errors = null; } delete ' + ($data) + '[' + ($key) + ']; } ';
  151. it.compositeRule = $it.compositeRule = $wasComposite;
  152. } else {
  153. $it.schema = $aProperties;
  154. $it.schemaPath = it.schemaPath + '.additionalProperties';
  155. $it.errSchemaPath = it.errSchemaPath + '/additionalProperties';
  156. $it.errorPath = it.opts._errorDataPathProperty ? it.errorPath : it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
  157. var $passData = $data + '[' + $key + ']';
  158. $it.dataPathArr[$dataNxt] = $key;
  159. var $code = it.validate($it);
  160. $it.baseId = $currentBaseId;
  161. if (it.util.varOccurences($code, $nextData) < 2) {
  162. out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' ';
  163. } else {
  164. out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' ';
  165. }
  166. if ($breakOnError) {
  167. out += ' if (!' + ($nextValid) + ') break; ';
  168. }
  169. }
  170. }
  171. it.errorPath = $currentErrorPath;
  172. }
  173. if ($someProperties) {
  174. out += ' } ';
  175. }
  176. out += ' } ';
  177. if ($breakOnError) {
  178. out += ' if (' + ($nextValid) + ') { ';
  179. $closingBraces += '}';
  180. }
  181. }
  182. var $useDefaults = it.opts.useDefaults && !it.compositeRule;
  183. if ($schemaKeys.length) {
  184. var arr3 = $schemaKeys;
  185. if (arr3) {
  186. var $propertyKey, i3 = -1,
  187. l3 = arr3.length - 1;
  188. while (i3 < l3) {
  189. $propertyKey = arr3[i3 += 1];
  190. var $sch = $schema[$propertyKey];
  191. if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) {
  192. var $prop = it.util.getProperty($propertyKey),
  193. $passData = $data + $prop,
  194. $hasDefault = $useDefaults && $sch.default !== undefined;
  195. $it.schema = $sch;
  196. $it.schemaPath = $schemaPath + $prop;
  197. $it.errSchemaPath = $errSchemaPath + '/' + it.util.escapeFragment($propertyKey);
  198. $it.errorPath = it.util.getPath(it.errorPath, $propertyKey, it.opts.jsonPointers);
  199. $it.dataPathArr[$dataNxt] = it.util.toQuotedString($propertyKey);
  200. var $code = it.validate($it);
  201. $it.baseId = $currentBaseId;
  202. if (it.util.varOccurences($code, $nextData) < 2) {
  203. $code = it.util.varReplace($code, $nextData, $passData);
  204. var $useData = $passData;
  205. } else {
  206. var $useData = $nextData;
  207. out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ';
  208. }
  209. if ($hasDefault) {
  210. out += ' ' + ($code) + ' ';
  211. } else {
  212. if ($requiredHash && $requiredHash[$propertyKey]) {
  213. out += ' if ( ' + ($useData) + ' === undefined ';
  214. if ($ownProperties) {
  215. out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') ';
  216. }
  217. out += ') { ' + ($nextValid) + ' = false; ';
  218. var $currentErrorPath = it.errorPath,
  219. $currErrSchemaPath = $errSchemaPath,
  220. $missingProperty = it.util.escapeQuotes($propertyKey);
  221. if (it.opts._errorDataPathProperty) {
  222. it.errorPath = it.util.getPath($currentErrorPath, $propertyKey, it.opts.jsonPointers);
  223. }
  224. $errSchemaPath = it.errSchemaPath + '/required';
  225. var $$outStack = $$outStack || [];
  226. $$outStack.push(out);
  227. out = ''; /* istanbul ignore else */
  228. if (it.createErrors !== false) {
  229. out += ' { keyword: \'' + ('required') + '\' , dataPath: (dataPath || \'\') + ' + (it.errorPath) + ' , schemaPath: ' + (it.util.toQuotedString($errSchemaPath)) + ' , params: { missingProperty: \'' + ($missingProperty) + '\' } ';
  230. if (it.opts.messages !== false) {
  231. out += ' , message: \'';
  232. if (it.opts._errorDataPathProperty) {
  233. out += 'is a required property';
  234. } else {
  235. out += 'should have required property \\\'' + ($missingProperty) + '\\\'';
  236. }
  237. out += '\' ';
  238. }
  239. if (it.opts.verbose) {
  240. out += ' , schema: validate.schema' + ($schemaPath) + ' , parentSchema: validate.schema' + (it.schemaPath) + ' , data: ' + ($data) + ' ';
  241. }
  242. out += ' } ';
  243. } else {
  244. out += ' {} ';
  245. }
  246. var __err = out;
  247. out = $$outStack.pop();
  248. if (!it.compositeRule && $breakOnError) {
  249. /* istanbul ignore if */
  250. if (it.async) {
  251. out += ' throw new ValidationError([' + (__err) + ']); ';
  252. } else {
  253. out += ' validate.errors = [' + (__err) + ']; return false; ';
  254. }
  255. } else {
  256. out += ' var err = ' + (__err) + '; if (vErrors === null) vErrors = [err]; else vErrors.push(err); errors++; ';
  257. }
  258. $errSchemaPath = $currErrSchemaPath;
  259. it.errorPath = $currentErrorPath;
  260. out += ' } else { ';
  261. } else {
  262. if ($breakOnError) {
  263. out += ' if ( ' + ($useData) + ' === undefined ';
  264. if ($ownProperties) {
  265. out += ' || ! Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') ';
  266. }
  267. out += ') { ' + ($nextValid) + ' = true; } else { ';
  268. } else {
  269. out += ' if (' + ($useData) + ' !== undefined ';
  270. if ($ownProperties) {
  271. out += ' && Object.prototype.hasOwnProperty.call(' + ($data) + ', \'' + (it.util.escapeQuotes($propertyKey)) + '\') ';
  272. }
  273. out += ' ) { ';
  274. }
  275. }
  276. out += ' ' + ($code) + ' } ';
  277. }
  278. }
  279. if ($breakOnError) {
  280. out += ' if (' + ($nextValid) + ') { ';
  281. $closingBraces += '}';
  282. }
  283. }
  284. }
  285. }
  286. if ($pPropertyKeys.length) {
  287. var arr4 = $pPropertyKeys;
  288. if (arr4) {
  289. var $pProperty, i4 = -1,
  290. l4 = arr4.length - 1;
  291. while (i4 < l4) {
  292. $pProperty = arr4[i4 += 1];
  293. var $sch = $pProperties[$pProperty];
  294. if ((it.opts.strictKeywords ? (typeof $sch == 'object' && Object.keys($sch).length > 0) || $sch === false : it.util.schemaHasRules($sch, it.RULES.all))) {
  295. $it.schema = $sch;
  296. $it.schemaPath = it.schemaPath + '.patternProperties' + it.util.getProperty($pProperty);
  297. $it.errSchemaPath = it.errSchemaPath + '/patternProperties/' + it.util.escapeFragment($pProperty);
  298. if ($ownProperties) {
  299. out += ' ' + ($dataProperties) + ' = ' + ($dataProperties) + ' || Object.keys(' + ($data) + '); for (var ' + ($idx) + '=0; ' + ($idx) + '<' + ($dataProperties) + '.length; ' + ($idx) + '++) { var ' + ($key) + ' = ' + ($dataProperties) + '[' + ($idx) + ']; ';
  300. } else {
  301. out += ' for (var ' + ($key) + ' in ' + ($data) + ') { ';
  302. }
  303. out += ' if (' + (it.usePattern($pProperty)) + '.test(' + ($key) + ')) { ';
  304. $it.errorPath = it.util.getPathExpr(it.errorPath, $key, it.opts.jsonPointers);
  305. var $passData = $data + '[' + $key + ']';
  306. $it.dataPathArr[$dataNxt] = $key;
  307. var $code = it.validate($it);
  308. $it.baseId = $currentBaseId;
  309. if (it.util.varOccurences($code, $nextData) < 2) {
  310. out += ' ' + (it.util.varReplace($code, $nextData, $passData)) + ' ';
  311. } else {
  312. out += ' var ' + ($nextData) + ' = ' + ($passData) + '; ' + ($code) + ' ';
  313. }
  314. if ($breakOnError) {
  315. out += ' if (!' + ($nextValid) + ') break; ';
  316. }
  317. out += ' } ';
  318. if ($breakOnError) {
  319. out += ' else ' + ($nextValid) + ' = true; ';
  320. }
  321. out += ' } ';
  322. if ($breakOnError) {
  323. out += ' if (' + ($nextValid) + ') { ';
  324. $closingBraces += '}';
  325. }
  326. }
  327. }
  328. }
  329. }
  330. if ($breakOnError) {
  331. out += ' ' + ($closingBraces) + ' if (' + ($errs) + ' == errors) {';
  332. }
  333. return out;
  334. }