JsonParser.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const Parser = require("../Parser");
  7. const JsonExportsDependency = require("../dependencies/JsonExportsDependency");
  8. const parseJson = require("../util/parseJson");
  9. const JsonData = require("./JsonData");
  10. /** @typedef {import("../../declarations/plugins/JsonModulesPluginParser").JsonModulesPluginParserOptions} JsonModulesPluginParserOptions */
  11. /** @typedef {import("../Module").BuildInfo} BuildInfo */
  12. /** @typedef {import("../Module").BuildMeta} BuildMeta */
  13. /** @typedef {import("../Parser").ParserState} ParserState */
  14. /** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
  15. /** @typedef {import("../util/fs").JsonValue} JsonValue */
  16. /** @typedef {(input: string) => Buffer | JsonValue} ParseFn */
  17. /**
  18. * Defines the function returning type used by this module.
  19. * @template T
  20. * @typedef {import("../util/memoize").FunctionReturning<T>} FunctionReturning
  21. */
  22. class JsonParser extends Parser {
  23. /**
  24. * Creates an instance of JsonParser.
  25. * @param {JsonModulesPluginParserOptions} options parser options
  26. */
  27. constructor(options = {}) {
  28. super();
  29. /** @type {JsonModulesPluginParserOptions} */
  30. this.options = options;
  31. }
  32. /**
  33. * Parses the provided source and updates the parser state.
  34. * @param {string | Buffer | PreparsedAst} source the source to parse
  35. * @param {ParserState} state the parser state
  36. * @returns {ParserState} the parser state
  37. */
  38. parse(source, state) {
  39. if (Buffer.isBuffer(source)) {
  40. source = source.toString("utf8");
  41. }
  42. /** @type {typeof parseJson} */
  43. const parseFn =
  44. typeof this.options.parse === "function" ? this.options.parse : parseJson;
  45. /** @type {Buffer | JsonValue | undefined} */
  46. let data;
  47. try {
  48. data =
  49. typeof source === "object"
  50. ? source
  51. : parseFn(source[0] === "\uFEFF" ? source.slice(1) : source);
  52. } catch (err) {
  53. throw new Error(
  54. `Cannot parse JSON: ${/** @type {Error} */ (err).message}`,
  55. { cause: err }
  56. );
  57. }
  58. const jsonData = new JsonData(/** @type {Buffer | JsonValue} */ (data));
  59. const buildInfo = /** @type {BuildInfo} */ (state.module.buildInfo);
  60. buildInfo.jsonData = jsonData;
  61. buildInfo.strict = true;
  62. const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
  63. buildMeta.exportsType = "default";
  64. buildMeta.defaultObject =
  65. typeof data === "object"
  66. ? this.options.namedExports === false
  67. ? false
  68. : this.options.namedExports === true
  69. ? "redirect"
  70. : "redirect-warn"
  71. : false;
  72. state.module.addDependency(
  73. new JsonExportsDependency(
  74. jsonData,
  75. /** @type {number} */
  76. (this.options.exportsDepth)
  77. )
  78. );
  79. return state;
  80. }
  81. }
  82. module.exports = JsonParser;