JsonParser.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 memoize = require("../util/memoize");
  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. const getParseJson = memoize(() => require("json-parse-even-better-errors"));
  18. class JsonParser extends Parser {
  19. /**
  20. * @param {JsonModulesPluginParserOptions} options parser options
  21. */
  22. constructor(options) {
  23. super();
  24. this.options = options || {};
  25. }
  26. /**
  27. * @param {string | Buffer | PreparsedAst} source the source to parse
  28. * @param {ParserState} state the parser state
  29. * @returns {ParserState} the parser state
  30. */
  31. parse(source, state) {
  32. if (Buffer.isBuffer(source)) {
  33. source = source.toString("utf8");
  34. }
  35. /** @type {ParseFn} */
  36. const parseFn =
  37. typeof this.options.parse === "function"
  38. ? this.options.parse
  39. : getParseJson();
  40. /** @type {Buffer | JsonValue | undefined} */
  41. let data;
  42. try {
  43. data =
  44. typeof source === "object"
  45. ? source
  46. : parseFn(source[0] === "\uFEFF" ? source.slice(1) : source);
  47. } catch (err) {
  48. throw new Error(
  49. `Cannot parse JSON: ${/** @type {Error} */ (err).message}`,
  50. { cause: err }
  51. );
  52. }
  53. const jsonData = new JsonData(/** @type {Buffer | JsonValue} */ (data));
  54. const buildInfo = /** @type {BuildInfo} */ (state.module.buildInfo);
  55. buildInfo.jsonData = jsonData;
  56. buildInfo.strict = true;
  57. const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
  58. buildMeta.exportsType = "default";
  59. buildMeta.defaultObject =
  60. typeof data === "object"
  61. ? this.options.namedExports === false
  62. ? false
  63. : this.options.namedExports === true
  64. ? "redirect"
  65. : "redirect-warn"
  66. : false;
  67. state.module.addDependency(
  68. new JsonExportsDependency(
  69. jsonData,
  70. /** @type {number} */
  71. (this.options.exportsDepth)
  72. )
  73. );
  74. return state;
  75. }
  76. }
  77. module.exports = JsonParser;