index.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.getData = exports.KeywordCxt = exports.validateFunctionCode = void 0;
  4. const boolSchema_1 = require("./boolSchema");
  5. const dataType_1 = require("./dataType");
  6. const applicability_1 = require("./applicability");
  7. const dataType_2 = require("./dataType");
  8. const defaults_1 = require("./defaults");
  9. const keyword_1 = require("./keyword");
  10. const subschema_1 = require("./subschema");
  11. const codegen_1 = require("../codegen");
  12. const names_1 = require("../names");
  13. const resolve_1 = require("../resolve");
  14. const util_1 = require("../util");
  15. const errors_1 = require("../errors");
  16. // schema compilation - generates validation function, subschemaCode (below) is used for subschemas
  17. function validateFunctionCode(it) {
  18. if (isSchemaObj(it)) {
  19. checkKeywords(it);
  20. if (schemaCxtHasRules(it)) {
  21. topSchemaObjCode(it);
  22. return;
  23. }
  24. }
  25. validateFunction(it, () => (0, boolSchema_1.topBoolOrEmptySchema)(it));
  26. }
  27. exports.validateFunctionCode = validateFunctionCode;
  28. function validateFunction({ gen, validateName, schema, schemaEnv, opts }, body) {
  29. if (opts.code.es5) {
  30. gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${names_1.default.valCxt}`, schemaEnv.$async, () => {
  31. gen.code((0, codegen_1._) `"use strict"; ${funcSourceUrl(schema, opts)}`);
  32. destructureValCxtES5(gen, opts);
  33. gen.code(body);
  34. });
  35. }
  36. else {
  37. gen.func(validateName, (0, codegen_1._) `${names_1.default.data}, ${destructureValCxt(opts)}`, schemaEnv.$async, () => gen.code(funcSourceUrl(schema, opts)).code(body));
  38. }
  39. }
  40. function destructureValCxt(opts) {
  41. return (0, codegen_1._) `{${names_1.default.instancePath}="", ${names_1.default.parentData}, ${names_1.default.parentDataProperty}, ${names_1.default.rootData}=${names_1.default.data}${opts.dynamicRef ? (0, codegen_1._) `, ${names_1.default.dynamicAnchors}={}` : codegen_1.nil}}={}`;
  42. }
  43. function destructureValCxtES5(gen, opts) {
  44. gen.if(names_1.default.valCxt, () => {
  45. gen.var(names_1.default.instancePath, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.instancePath}`);
  46. gen.var(names_1.default.parentData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentData}`);
  47. gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.parentDataProperty}`);
  48. gen.var(names_1.default.rootData, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.rootData}`);
  49. if (opts.dynamicRef)
  50. gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `${names_1.default.valCxt}.${names_1.default.dynamicAnchors}`);
  51. }, () => {
  52. gen.var(names_1.default.instancePath, (0, codegen_1._) `""`);
  53. gen.var(names_1.default.parentData, (0, codegen_1._) `undefined`);
  54. gen.var(names_1.default.parentDataProperty, (0, codegen_1._) `undefined`);
  55. gen.var(names_1.default.rootData, names_1.default.data);
  56. if (opts.dynamicRef)
  57. gen.var(names_1.default.dynamicAnchors, (0, codegen_1._) `{}`);
  58. });
  59. }
  60. function topSchemaObjCode(it) {
  61. const { schema, opts, gen } = it;
  62. validateFunction(it, () => {
  63. if (opts.$comment && schema.$comment)
  64. commentKeyword(it);
  65. checkNoDefault(it);
  66. gen.let(names_1.default.vErrors, null);
  67. gen.let(names_1.default.errors, 0);
  68. if (opts.unevaluated)
  69. resetEvaluated(it);
  70. typeAndKeywords(it);
  71. returnResults(it);
  72. });
  73. return;
  74. }
  75. function resetEvaluated(it) {
  76. // TODO maybe some hook to execute it in the end to check whether props/items are Name, as in assignEvaluated
  77. const { gen, validateName } = it;
  78. it.evaluated = gen.const("evaluated", (0, codegen_1._) `${validateName}.evaluated`);
  79. gen.if((0, codegen_1._) `${it.evaluated}.dynamicProps`, () => gen.assign((0, codegen_1._) `${it.evaluated}.props`, (0, codegen_1._) `undefined`));
  80. gen.if((0, codegen_1._) `${it.evaluated}.dynamicItems`, () => gen.assign((0, codegen_1._) `${it.evaluated}.items`, (0, codegen_1._) `undefined`));
  81. }
  82. function funcSourceUrl(schema, opts) {
  83. const schId = typeof schema == "object" && schema[opts.schemaId];
  84. return schId && (opts.code.source || opts.code.process) ? (0, codegen_1._) `/*# sourceURL=${schId} */` : codegen_1.nil;
  85. }
  86. // schema compilation - this function is used recursively to generate code for sub-schemas
  87. function subschemaCode(it, valid) {
  88. if (isSchemaObj(it)) {
  89. checkKeywords(it);
  90. if (schemaCxtHasRules(it)) {
  91. subSchemaObjCode(it, valid);
  92. return;
  93. }
  94. }
  95. (0, boolSchema_1.boolOrEmptySchema)(it, valid);
  96. }
  97. function schemaCxtHasRules({ schema, self }) {
  98. if (typeof schema == "boolean")
  99. return !schema;
  100. for (const key in schema)
  101. if (self.RULES.all[key])
  102. return true;
  103. return false;
  104. }
  105. function isSchemaObj(it) {
  106. return typeof it.schema != "boolean";
  107. }
  108. function subSchemaObjCode(it, valid) {
  109. const { schema, gen, opts } = it;
  110. if (opts.$comment && schema.$comment)
  111. commentKeyword(it);
  112. updateContext(it);
  113. checkAsyncSchema(it);
  114. const errsCount = gen.const("_errs", names_1.default.errors);
  115. typeAndKeywords(it, errsCount);
  116. // TODO var
  117. gen.var(valid, (0, codegen_1._) `${errsCount} === ${names_1.default.errors}`);
  118. }
  119. function checkKeywords(it) {
  120. (0, util_1.checkUnknownRules)(it);
  121. checkRefsAndKeywords(it);
  122. }
  123. function typeAndKeywords(it, errsCount) {
  124. if (it.opts.jtd)
  125. return schemaKeywords(it, [], false, errsCount);
  126. const types = (0, dataType_1.getSchemaTypes)(it.schema);
  127. const checkedTypes = (0, dataType_1.coerceAndCheckDataType)(it, types);
  128. schemaKeywords(it, types, !checkedTypes, errsCount);
  129. }
  130. function checkRefsAndKeywords(it) {
  131. const { schema, errSchemaPath, opts, self } = it;
  132. if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self.RULES)) {
  133. self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
  134. }
  135. }
  136. function checkNoDefault(it) {
  137. const { schema, opts } = it;
  138. if (schema.default !== undefined && opts.useDefaults && opts.strictSchema) {
  139. (0, util_1.checkStrictMode)(it, "default is ignored in the schema root");
  140. }
  141. }
  142. function updateContext(it) {
  143. const schId = it.schema[it.opts.schemaId];
  144. if (schId)
  145. it.baseId = (0, resolve_1.resolveUrl)(it.opts.uriResolver, it.baseId, schId);
  146. }
  147. function checkAsyncSchema(it) {
  148. if (it.schema.$async && !it.schemaEnv.$async)
  149. throw new Error("async schema in sync schema");
  150. }
  151. function commentKeyword({ gen, schemaEnv, schema, errSchemaPath, opts }) {
  152. const msg = schema.$comment;
  153. if (opts.$comment === true) {
  154. gen.code((0, codegen_1._) `${names_1.default.self}.logger.log(${msg})`);
  155. }
  156. else if (typeof opts.$comment == "function") {
  157. const schemaPath = (0, codegen_1.str) `${errSchemaPath}/$comment`;
  158. const rootName = gen.scopeValue("root", { ref: schemaEnv.root });
  159. gen.code((0, codegen_1._) `${names_1.default.self}.opts.$comment(${msg}, ${schemaPath}, ${rootName}.schema)`);
  160. }
  161. }
  162. function returnResults(it) {
  163. const { gen, schemaEnv, validateName, ValidationError, opts } = it;
  164. if (schemaEnv.$async) {
  165. // TODO assign unevaluated
  166. gen.if((0, codegen_1._) `${names_1.default.errors} === 0`, () => gen.return(names_1.default.data), () => gen.throw((0, codegen_1._) `new ${ValidationError}(${names_1.default.vErrors})`));
  167. }
  168. else {
  169. gen.assign((0, codegen_1._) `${validateName}.errors`, names_1.default.vErrors);
  170. if (opts.unevaluated)
  171. assignEvaluated(it);
  172. gen.return((0, codegen_1._) `${names_1.default.errors} === 0`);
  173. }
  174. }
  175. function assignEvaluated({ gen, evaluated, props, items }) {
  176. if (props instanceof codegen_1.Name)
  177. gen.assign((0, codegen_1._) `${evaluated}.props`, props);
  178. if (items instanceof codegen_1.Name)
  179. gen.assign((0, codegen_1._) `${evaluated}.items`, items);
  180. }
  181. function schemaKeywords(it, types, typeErrors, errsCount) {
  182. const { gen, schema, data, allErrors, opts, self } = it;
  183. const { RULES } = self;
  184. if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
  185. gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition)); // TODO typecast
  186. return;
  187. }
  188. if (!opts.jtd)
  189. checkStrictTypes(it, types);
  190. gen.block(() => {
  191. for (const group of RULES.rules)
  192. groupKeywords(group);
  193. groupKeywords(RULES.post);
  194. });
  195. function groupKeywords(group) {
  196. if (!(0, applicability_1.shouldUseGroup)(schema, group))
  197. return;
  198. if (group.type) {
  199. gen.if((0, dataType_2.checkDataType)(group.type, data, opts.strictNumbers));
  200. iterateKeywords(it, group);
  201. if (types.length === 1 && types[0] === group.type && typeErrors) {
  202. gen.else();
  203. (0, dataType_2.reportTypeError)(it);
  204. }
  205. gen.endIf();
  206. }
  207. else {
  208. iterateKeywords(it, group);
  209. }
  210. // TODO make it "ok" call?
  211. if (!allErrors)
  212. gen.if((0, codegen_1._) `${names_1.default.errors} === ${errsCount || 0}`);
  213. }
  214. }
  215. function iterateKeywords(it, group) {
  216. const { gen, schema, opts: { useDefaults }, } = it;
  217. if (useDefaults)
  218. (0, defaults_1.assignDefaults)(it, group.type);
  219. gen.block(() => {
  220. for (const rule of group.rules) {
  221. if ((0, applicability_1.shouldUseRule)(schema, rule)) {
  222. keywordCode(it, rule.keyword, rule.definition, group.type);
  223. }
  224. }
  225. });
  226. }
  227. function checkStrictTypes(it, types) {
  228. if (it.schemaEnv.meta || !it.opts.strictTypes)
  229. return;
  230. checkContextTypes(it, types);
  231. if (!it.opts.allowUnionTypes)
  232. checkMultipleTypes(it, types);
  233. checkKeywordTypes(it, it.dataTypes);
  234. }
  235. function checkContextTypes(it, types) {
  236. if (!types.length)
  237. return;
  238. if (!it.dataTypes.length) {
  239. it.dataTypes = types;
  240. return;
  241. }
  242. types.forEach((t) => {
  243. if (!includesType(it.dataTypes, t)) {
  244. strictTypesError(it, `type "${t}" not allowed by context "${it.dataTypes.join(",")}"`);
  245. }
  246. });
  247. narrowSchemaTypes(it, types);
  248. }
  249. function checkMultipleTypes(it, ts) {
  250. if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) {
  251. strictTypesError(it, "use allowUnionTypes to allow union type keyword");
  252. }
  253. }
  254. function checkKeywordTypes(it, ts) {
  255. const rules = it.self.RULES.all;
  256. for (const keyword in rules) {
  257. const rule = rules[keyword];
  258. if (typeof rule == "object" && (0, applicability_1.shouldUseRule)(it.schema, rule)) {
  259. const { type } = rule.definition;
  260. if (type.length && !type.some((t) => hasApplicableType(ts, t))) {
  261. strictTypesError(it, `missing type "${type.join(",")}" for keyword "${keyword}"`);
  262. }
  263. }
  264. }
  265. }
  266. function hasApplicableType(schTs, kwdT) {
  267. return schTs.includes(kwdT) || (kwdT === "number" && schTs.includes("integer"));
  268. }
  269. function includesType(ts, t) {
  270. return ts.includes(t) || (t === "integer" && ts.includes("number"));
  271. }
  272. function narrowSchemaTypes(it, withTypes) {
  273. const ts = [];
  274. for (const t of it.dataTypes) {
  275. if (includesType(withTypes, t))
  276. ts.push(t);
  277. else if (withTypes.includes("integer") && t === "number")
  278. ts.push("integer");
  279. }
  280. it.dataTypes = ts;
  281. }
  282. function strictTypesError(it, msg) {
  283. const schemaPath = it.schemaEnv.baseId + it.errSchemaPath;
  284. msg += ` at "${schemaPath}" (strictTypes)`;
  285. (0, util_1.checkStrictMode)(it, msg, it.opts.strictTypes);
  286. }
  287. class KeywordCxt {
  288. constructor(it, def, keyword) {
  289. (0, keyword_1.validateKeywordUsage)(it, def, keyword);
  290. this.gen = it.gen;
  291. this.allErrors = it.allErrors;
  292. this.keyword = keyword;
  293. this.data = it.data;
  294. this.schema = it.schema[keyword];
  295. this.$data = def.$data && it.opts.$data && this.schema && this.schema.$data;
  296. this.schemaValue = (0, util_1.schemaRefOrVal)(it, this.schema, keyword, this.$data);
  297. this.schemaType = def.schemaType;
  298. this.parentSchema = it.schema;
  299. this.params = {};
  300. this.it = it;
  301. this.def = def;
  302. if (this.$data) {
  303. this.schemaCode = it.gen.const("vSchema", getData(this.$data, it));
  304. }
  305. else {
  306. this.schemaCode = this.schemaValue;
  307. if (!(0, keyword_1.validSchemaType)(this.schema, def.schemaType, def.allowUndefined)) {
  308. throw new Error(`${keyword} value must be ${JSON.stringify(def.schemaType)}`);
  309. }
  310. }
  311. if ("code" in def ? def.trackErrors : def.errors !== false) {
  312. this.errsCount = it.gen.const("_errs", names_1.default.errors);
  313. }
  314. }
  315. result(condition, successAction, failAction) {
  316. this.failResult((0, codegen_1.not)(condition), successAction, failAction);
  317. }
  318. failResult(condition, successAction, failAction) {
  319. this.gen.if(condition);
  320. if (failAction)
  321. failAction();
  322. else
  323. this.error();
  324. if (successAction) {
  325. this.gen.else();
  326. successAction();
  327. if (this.allErrors)
  328. this.gen.endIf();
  329. }
  330. else {
  331. if (this.allErrors)
  332. this.gen.endIf();
  333. else
  334. this.gen.else();
  335. }
  336. }
  337. pass(condition, failAction) {
  338. this.failResult((0, codegen_1.not)(condition), undefined, failAction);
  339. }
  340. fail(condition) {
  341. if (condition === undefined) {
  342. this.error();
  343. if (!this.allErrors)
  344. this.gen.if(false); // this branch will be removed by gen.optimize
  345. return;
  346. }
  347. this.gen.if(condition);
  348. this.error();
  349. if (this.allErrors)
  350. this.gen.endIf();
  351. else
  352. this.gen.else();
  353. }
  354. fail$data(condition) {
  355. if (!this.$data)
  356. return this.fail(condition);
  357. const { schemaCode } = this;
  358. this.fail((0, codegen_1._) `${schemaCode} !== undefined && (${(0, codegen_1.or)(this.invalid$data(), condition)})`);
  359. }
  360. error(append, errorParams, errorPaths) {
  361. if (errorParams) {
  362. this.setParams(errorParams);
  363. this._error(append, errorPaths);
  364. this.setParams({});
  365. return;
  366. }
  367. this._error(append, errorPaths);
  368. }
  369. _error(append, errorPaths) {
  370. ;
  371. (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error, errorPaths);
  372. }
  373. $dataError() {
  374. (0, errors_1.reportError)(this, this.def.$dataError || errors_1.keyword$DataError);
  375. }
  376. reset() {
  377. if (this.errsCount === undefined)
  378. throw new Error('add "trackErrors" to keyword definition');
  379. (0, errors_1.resetErrorsCount)(this.gen, this.errsCount);
  380. }
  381. ok(cond) {
  382. if (!this.allErrors)
  383. this.gen.if(cond);
  384. }
  385. setParams(obj, assign) {
  386. if (assign)
  387. Object.assign(this.params, obj);
  388. else
  389. this.params = obj;
  390. }
  391. block$data(valid, codeBlock, $dataValid = codegen_1.nil) {
  392. this.gen.block(() => {
  393. this.check$data(valid, $dataValid);
  394. codeBlock();
  395. });
  396. }
  397. check$data(valid = codegen_1.nil, $dataValid = codegen_1.nil) {
  398. if (!this.$data)
  399. return;
  400. const { gen, schemaCode, schemaType, def } = this;
  401. gen.if((0, codegen_1.or)((0, codegen_1._) `${schemaCode} === undefined`, $dataValid));
  402. if (valid !== codegen_1.nil)
  403. gen.assign(valid, true);
  404. if (schemaType.length || def.validateSchema) {
  405. gen.elseIf(this.invalid$data());
  406. this.$dataError();
  407. if (valid !== codegen_1.nil)
  408. gen.assign(valid, false);
  409. }
  410. gen.else();
  411. }
  412. invalid$data() {
  413. const { gen, schemaCode, schemaType, def, it } = this;
  414. return (0, codegen_1.or)(wrong$DataType(), invalid$DataSchema());
  415. function wrong$DataType() {
  416. if (schemaType.length) {
  417. /* istanbul ignore if */
  418. if (!(schemaCode instanceof codegen_1.Name))
  419. throw new Error("ajv implementation error");
  420. const st = Array.isArray(schemaType) ? schemaType : [schemaType];
  421. return (0, codegen_1._) `${(0, dataType_2.checkDataTypes)(st, schemaCode, it.opts.strictNumbers, dataType_2.DataType.Wrong)}`;
  422. }
  423. return codegen_1.nil;
  424. }
  425. function invalid$DataSchema() {
  426. if (def.validateSchema) {
  427. const validateSchemaRef = gen.scopeValue("validate$data", { ref: def.validateSchema }); // TODO value.code for standalone
  428. return (0, codegen_1._) `!${validateSchemaRef}(${schemaCode})`;
  429. }
  430. return codegen_1.nil;
  431. }
  432. }
  433. subschema(appl, valid) {
  434. const subschema = (0, subschema_1.getSubschema)(this.it, appl);
  435. (0, subschema_1.extendSubschemaData)(subschema, this.it, appl);
  436. (0, subschema_1.extendSubschemaMode)(subschema, appl);
  437. const nextContext = { ...this.it, ...subschema, items: undefined, props: undefined };
  438. subschemaCode(nextContext, valid);
  439. return nextContext;
  440. }
  441. mergeEvaluated(schemaCxt, toName) {
  442. const { it, gen } = this;
  443. if (!it.opts.unevaluated)
  444. return;
  445. if (it.props !== true && schemaCxt.props !== undefined) {
  446. it.props = util_1.mergeEvaluated.props(gen, schemaCxt.props, it.props, toName);
  447. }
  448. if (it.items !== true && schemaCxt.items !== undefined) {
  449. it.items = util_1.mergeEvaluated.items(gen, schemaCxt.items, it.items, toName);
  450. }
  451. }
  452. mergeValidEvaluated(schemaCxt, valid) {
  453. const { it, gen } = this;
  454. if (it.opts.unevaluated && (it.props !== true || it.items !== true)) {
  455. gen.if(valid, () => this.mergeEvaluated(schemaCxt, codegen_1.Name));
  456. return true;
  457. }
  458. }
  459. }
  460. exports.KeywordCxt = KeywordCxt;
  461. function keywordCode(it, keyword, def, ruleType) {
  462. const cxt = new KeywordCxt(it, def, keyword);
  463. if ("code" in def) {
  464. def.code(cxt, ruleType);
  465. }
  466. else if (cxt.$data && def.validate) {
  467. (0, keyword_1.funcKeywordCode)(cxt, def);
  468. }
  469. else if ("macro" in def) {
  470. (0, keyword_1.macroKeywordCode)(cxt, def);
  471. }
  472. else if (def.compile || def.validate) {
  473. (0, keyword_1.funcKeywordCode)(cxt, def);
  474. }
  475. }
  476. const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/;
  477. const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/;
  478. function getData($data, { dataLevel, dataNames, dataPathArr }) {
  479. let jsonPointer;
  480. let data;
  481. if ($data === "")
  482. return names_1.default.rootData;
  483. if ($data[0] === "/") {
  484. if (!JSON_POINTER.test($data))
  485. throw new Error(`Invalid JSON-pointer: ${$data}`);
  486. jsonPointer = $data;
  487. data = names_1.default.rootData;
  488. }
  489. else {
  490. const matches = RELATIVE_JSON_POINTER.exec($data);
  491. if (!matches)
  492. throw new Error(`Invalid JSON-pointer: ${$data}`);
  493. const up = +matches[1];
  494. jsonPointer = matches[2];
  495. if (jsonPointer === "#") {
  496. if (up >= dataLevel)
  497. throw new Error(errorMsg("property/index", up));
  498. return dataPathArr[dataLevel - up];
  499. }
  500. if (up > dataLevel)
  501. throw new Error(errorMsg("data", up));
  502. data = dataNames[dataLevel - up];
  503. if (!jsonPointer)
  504. return data;
  505. }
  506. let expr = data;
  507. const segments = jsonPointer.split("/");
  508. for (const segment of segments) {
  509. if (segment) {
  510. data = (0, codegen_1._) `${data}${(0, codegen_1.getProperty)((0, util_1.unescapeJsonPointer)(segment))}`;
  511. expr = (0, codegen_1._) `${expr} && ${data}`;
  512. }
  513. }
  514. return expr;
  515. function errorMsg(pointerType, up) {
  516. return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`;
  517. }
  518. }
  519. exports.getData = getData;
  520. //# sourceMappingURL=index.js.map