@futpib/parser 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/.github/copilot-instructions.md +149 -0
  2. package/.github/workflows/copilot-setup-steps.yml +18 -0
  3. package/.github/workflows/main.yml +29 -8
  4. package/.yarn/releases/yarn-4.9.4.cjs +942 -0
  5. package/.yarnrc.yml +1 -1
  6. package/build/allSettledStream.js +1 -1
  7. package/build/allSettledStream.test.js +2 -2
  8. package/build/androidPackageParser.d.ts +1 -1
  9. package/build/androidPackageParser.js +5 -3
  10. package/build/androidPackageParser.test.js +7 -7
  11. package/build/androidPackageUnparser.d.ts +2 -2
  12. package/build/androidPackageUnparser.js +18 -14
  13. package/build/androidPackageUnparser.test.js +7 -7
  14. package/build/arbitrarilySlicedAsyncInterator.js +2 -1
  15. package/build/arbitraryDalvikBytecode.d.ts +4 -0
  16. package/build/arbitraryDalvikBytecode.js +640 -0
  17. package/build/arbitraryDalvikExecutable.d.ts +3 -0
  18. package/build/arbitraryDalvikExecutable.js +282 -0
  19. package/build/arbitraryDosDateTime.js +1 -0
  20. package/build/arbitraryZipStream.js +1 -1
  21. package/build/arrayParser.js +2 -2
  22. package/build/arrayUnparser.d.ts +1 -1
  23. package/build/backsmali.d.ts +3 -1
  24. package/build/backsmali.js +31 -3
  25. package/build/bash.d.ts +84 -0
  26. package/build/bash.js +1 -0
  27. package/build/bashParser.d.ts +6 -0
  28. package/build/bashParser.js +294 -0
  29. package/build/bashParser.test.d.ts +1 -0
  30. package/build/bashParser.test.js +181 -0
  31. package/build/customInvariant.d.ts +2 -1
  32. package/build/customInvariant.js +4 -6
  33. package/build/dalvikBytecodeParser/formatParsers.d.ts +76 -2
  34. package/build/dalvikBytecodeParser/formatParsers.js +146 -11
  35. package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
  36. package/build/dalvikBytecodeParser/formatSizes.js +34 -0
  37. package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
  38. package/build/dalvikBytecodeParser/operationFormats.js +225 -0
  39. package/build/dalvikBytecodeParser.d.ts +1105 -5
  40. package/build/dalvikBytecodeParser.js +658 -205
  41. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
  42. package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
  43. package/build/dalvikBytecodeUnparser.d.ts +3 -0
  44. package/build/dalvikBytecodeUnparser.js +642 -0
  45. package/build/dalvikBytecodeUnparser.test.d.ts +1 -0
  46. package/build/dalvikBytecodeUnparser.test.js +25 -0
  47. package/build/dalvikExecutable.d.ts +65 -8
  48. package/build/dalvikExecutable.js +36 -0
  49. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +1 -1
  50. package/build/dalvikExecutableParser/stringSyntaxParser.js +17 -17
  51. package/build/dalvikExecutableParser/typeParsers.d.ts +2 -1
  52. package/build/dalvikExecutableParser/typeParsers.js +16 -11
  53. package/build/dalvikExecutableParser/typedNumbers.d.ts +85 -69
  54. package/build/dalvikExecutableParser/typedNumbers.js +0 -1
  55. package/build/dalvikExecutableParser.d.ts +2 -2
  56. package/build/dalvikExecutableParser.js +655 -337
  57. package/build/dalvikExecutableParser.test.js +24 -22
  58. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +223 -246
  59. package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
  60. package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
  61. package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
  62. package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
  63. package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
  64. package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
  65. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
  66. package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
  67. package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
  68. package/build/dalvikExecutableUnparser/utils.js +108 -0
  69. package/build/dalvikExecutableUnparser.d.ts +4 -0
  70. package/build/dalvikExecutableUnparser.js +406 -0
  71. package/build/dalvikExecutableUnparser.test.d.ts +1 -0
  72. package/build/dalvikExecutableUnparser.test.js +31 -0
  73. package/build/debugLogInputParser.js +1 -1
  74. package/build/disjunctionParser.d.ts +2 -2
  75. package/build/disjunctionParser.js +2 -2
  76. package/build/elementTerminatedArrayParser.d.ts +2 -2
  77. package/build/elementTerminatedArrayParser.js +1 -1
  78. package/build/elementTerminatedArrayParser.test.js +5 -5
  79. package/build/elementTerminatedSequenceArrayParser.d.ts +2 -2
  80. package/build/elementTerminatedSequenceArrayParser.js +1 -1
  81. package/build/elementTerminatedSequenceArrayParser.test.js +2 -2
  82. package/build/elementTerminatedSequenceParser.d.ts +2 -2
  83. package/build/elementTerminatedSequenceParser.js +1 -1
  84. package/build/elementTerminatedSequenceParser.test.js +2 -2
  85. package/build/endOfInputParser.d.ts +1 -1
  86. package/build/exactElementSwitchParser.d.ts +3 -0
  87. package/build/exactElementSwitchParser.js +22 -0
  88. package/build/fetchCid.js +2 -6
  89. package/build/fetchCid.test.d.ts +1 -0
  90. package/build/fetchCid.test.js +16 -0
  91. package/build/fixedLengthSequenceParser.test.js +2 -2
  92. package/build/hasExecutable.js +2 -2
  93. package/build/highResolutionTimer.js +1 -1
  94. package/build/index.d.ts +24 -2
  95. package/build/index.js +22 -1
  96. package/build/inputReader.d.ts +1 -1
  97. package/build/inputReader.test.js +33 -45
  98. package/build/javaKeyStoreParser.test.js +6 -6
  99. package/build/jsonParser.js +8 -8
  100. package/build/lazyMessageError.d.ts +48 -0
  101. package/build/lazyMessageError.js +53 -0
  102. package/build/lazyMessageError.test.d.ts +1 -0
  103. package/build/lazyMessageError.test.js +15 -0
  104. package/build/leb128Parser.d.ts +1 -1
  105. package/build/leb128Parser.js +10 -10
  106. package/build/leb128Parser.test.js +7 -7
  107. package/build/negativeLookaheadParser.js +2 -2
  108. package/build/negativeLookaheadParser.test.js +4 -4
  109. package/build/noStackCaptureOverheadError.d.ts +4 -0
  110. package/build/noStackCaptureOverheadError.js +9 -0
  111. package/build/noStackCaptureOverheadError.test.d.ts +1 -0
  112. package/build/noStackCaptureOverheadError.test.js +15 -0
  113. package/build/nonEmptyArrayParser.js +2 -2
  114. package/build/nonEmptyArrayParser.test.js +2 -1
  115. package/build/optionalParser.js +2 -2
  116. package/build/parser.d.ts +2 -1
  117. package/build/parser.js +23 -8
  118. package/build/parser.test.js +78 -29
  119. package/build/parserConsumedSequenceParser.d.ts +1 -1
  120. package/build/parserConsumedSequenceParser.js +2 -2
  121. package/build/parserContext.d.ts +8 -6
  122. package/build/parserContext.js +60 -33
  123. package/build/parserContext.test.js +7 -3
  124. package/build/parserError.d.ts +603 -44
  125. package/build/parserError.js +98 -53
  126. package/build/parserImplementationInvariant.d.ts +1 -1
  127. package/build/parserImplementationInvariant.js +2 -2
  128. package/build/parserInputCompanion.js +2 -2
  129. package/build/promiseCompose.js +1 -2
  130. package/build/regexpParser.d.ts +2 -0
  131. package/build/regexpParser.js +71 -0
  132. package/build/regexpParser.test.d.ts +1 -0
  133. package/build/regexpParser.test.js +83 -0
  134. package/build/regularExpression.d.ts +63 -0
  135. package/build/regularExpression.js +1 -0
  136. package/build/regularExpressionParser.d.ts +3 -0
  137. package/build/regularExpressionParser.js +580 -0
  138. package/build/regularExpressionParser.test.d.ts +1 -0
  139. package/build/regularExpressionParser.test.js +89 -0
  140. package/build/separatedArrayParser.js +2 -2
  141. package/build/separatedNonEmptyArrayParser.d.ts +2 -0
  142. package/build/separatedNonEmptyArrayParser.js +40 -0
  143. package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
  144. package/build/separatedNonEmptyArrayParser.test.js +66 -0
  145. package/build/sequenceBuffer.js +1 -1
  146. package/build/sequenceTerminatedSequenceParser.d.ts +2 -2
  147. package/build/sequenceTerminatedSequenceParser.js +3 -3
  148. package/build/sequenceTerminatedSequenceParser.test.js +1 -1
  149. package/build/sequenceUnparser.d.ts +1 -1
  150. package/build/skipToParser.d.ts +1 -1
  151. package/build/skipToParser.js +2 -2
  152. package/build/sliceBoundedParser.test.js +4 -9
  153. package/build/smali.d.ts +1 -1
  154. package/build/smali.js +6 -2
  155. package/build/smaliParser.d.ts +62 -6
  156. package/build/smaliParser.js +1721 -296
  157. package/build/smaliParser.test.js +338 -43
  158. package/build/stringFromAsyncIterable.d.ts +1 -0
  159. package/build/stringFromAsyncIterable.js +7 -0
  160. package/build/terminatedArrayParser.js +4 -4
  161. package/build/terminatedArrayParser.test.js +7 -7
  162. package/build/toAsyncIterator.js +4 -4
  163. package/build/unionParser.d.ts +1 -1
  164. package/build/unionParser.js +2 -2
  165. package/build/unionParser.test.js +3 -3
  166. package/build/unparser.d.ts +3 -3
  167. package/build/unparser.js +6 -4
  168. package/build/unparser.test.js +7 -19
  169. package/build/unparserContext.d.ts +2 -2
  170. package/build/unparserContext.js +2 -3
  171. package/build/unparserError.d.ts +2 -1
  172. package/build/unparserError.js +2 -1
  173. package/build/unparserImplementationInvariant.d.ts +1 -1
  174. package/build/unparserOutputCompanion.d.ts +1 -1
  175. package/build/unparserOutputCompanion.js +1 -1
  176. package/build/zipParser.js +1 -1
  177. package/build/zipUnparser.d.ts +3 -3
  178. package/build/zipUnparser.js +9 -19
  179. package/build/zipUnparser.test.js +1 -1
  180. package/package.json +20 -26
  181. package/src/allSettledStream.test.ts +2 -2
  182. package/src/allSettledStream.ts +3 -3
  183. package/src/androidPackageParser.test.ts +17 -19
  184. package/src/androidPackageParser.ts +129 -171
  185. package/src/androidPackageUnparser.test.ts +19 -21
  186. package/src/androidPackageUnparser.ts +23 -17
  187. package/src/arbitrarilySlicedAsyncInterable.ts +1 -1
  188. package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
  189. package/src/arbitraryDalvikBytecode.ts +992 -0
  190. package/src/arbitraryDalvikExecutable.ts +434 -0
  191. package/src/arbitraryDosDateTime.ts +1 -0
  192. package/src/arbitraryZipStream.ts +1 -1
  193. package/src/arrayParser.ts +2 -2
  194. package/src/arrayUnparser.ts +2 -2
  195. package/src/backsmali.ts +48 -4
  196. package/src/bash.ts +120 -0
  197. package/src/bashParser.test.ts +332 -0
  198. package/src/bashParser.ts +461 -0
  199. package/src/bsonParser.test.ts +12 -14
  200. package/src/customInvariant.ts +8 -12
  201. package/src/dalvikBytecodeParser/formatParsers.ts +376 -17
  202. package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
  203. package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
  204. package/src/dalvikBytecodeParser.ts +1042 -243
  205. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
  206. package/src/dalvikBytecodeUnparser.test.ts +44 -0
  207. package/src/dalvikBytecodeUnparser.ts +758 -0
  208. package/src/dalvikExecutable.ts +110 -48
  209. package/src/dalvikExecutableParser/stringSyntaxParser.ts +33 -33
  210. package/src/dalvikExecutableParser/typeParsers.ts +23 -14
  211. package/src/dalvikExecutableParser/typedNumbers.ts +19 -19
  212. package/src/dalvikExecutableParser.test.ts +60 -60
  213. package/src/dalvikExecutableParser.test.ts.md +6 -6
  214. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  215. package/src/dalvikExecutableParser.ts +911 -434
  216. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +256 -239
  217. package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
  218. package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
  219. package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
  220. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
  221. package/src/dalvikExecutableUnparser/utils.ts +149 -0
  222. package/src/dalvikExecutableUnparser.test.ts +57 -0
  223. package/src/dalvikExecutableUnparser.ts +581 -0
  224. package/src/debugLogInputParser.ts +1 -1
  225. package/src/disjunctionParser.ts +5 -5
  226. package/src/elementTerminatedArrayParser.test.ts +8 -8
  227. package/src/elementTerminatedArrayParser.ts +2 -2
  228. package/src/elementTerminatedSequenceArrayParser.test.ts +4 -6
  229. package/src/elementTerminatedSequenceArrayParser.ts +2 -2
  230. package/src/elementTerminatedSequenceParser.test.ts +4 -6
  231. package/src/elementTerminatedSequenceParser.ts +2 -2
  232. package/src/endOfInputParser.ts +1 -1
  233. package/src/exactElementSwitchParser.ts +41 -0
  234. package/src/fetchCid.test.ts +20 -0
  235. package/src/fetchCid.ts +3 -7
  236. package/src/fixedLengthSequenceParser.test.ts +10 -12
  237. package/src/hasExecutable.ts +2 -2
  238. package/src/highResolutionTimer.ts +1 -1
  239. package/src/index.ts +113 -2
  240. package/src/inputReader.test.ts +39 -52
  241. package/src/inputReader.ts +2 -4
  242. package/src/inputReaderState.ts +1 -1
  243. package/src/inspect.ts +1 -1
  244. package/src/javaKeyStoreParser.test.ts +12 -14
  245. package/src/javaKeyStoreParser.ts +2 -6
  246. package/src/jsonParser.test.ts +2 -4
  247. package/src/jsonParser.ts +34 -38
  248. package/src/lazyMessageError.test.ts +21 -0
  249. package/src/lazyMessageError.ts +88 -0
  250. package/src/leb128Parser.test.ts +25 -23
  251. package/src/leb128Parser.ts +19 -19
  252. package/src/negativeLookaheadParser.test.ts +7 -11
  253. package/src/negativeLookaheadParser.ts +2 -2
  254. package/src/noStackCaptureOverheadError.test.ts +17 -0
  255. package/src/noStackCaptureOverheadError.ts +12 -0
  256. package/src/nonEmptyArrayParser.test.ts +3 -2
  257. package/src/nonEmptyArrayParser.ts +2 -2
  258. package/src/optionalParser.ts +2 -2
  259. package/src/parser.test.ts +96 -43
  260. package/src/parser.test.ts.md +13 -6
  261. package/src/parser.test.ts.snap +0 -0
  262. package/src/parser.ts +35 -12
  263. package/src/parserAccessorParser.ts +1 -1
  264. package/src/parserConsumedSequenceParser.ts +3 -3
  265. package/src/parserContext.test.ts +7 -3
  266. package/src/parserContext.ts +82 -48
  267. package/src/parserError.ts +143 -63
  268. package/src/parserImplementationInvariant.ts +3 -3
  269. package/src/parserInputCompanion.ts +2 -2
  270. package/src/promiseCompose.ts +2 -2
  271. package/src/regexpParser.test.ts +186 -0
  272. package/src/regexpParser.ts +94 -0
  273. package/src/regularExpression.ts +24 -0
  274. package/src/regularExpressionParser.test.ts +102 -0
  275. package/src/regularExpressionParser.ts +921 -0
  276. package/src/separatedArrayParser.ts +3 -3
  277. package/src/separatedNonEmptyArrayParser.test.ts +117 -0
  278. package/src/separatedNonEmptyArrayParser.ts +61 -0
  279. package/src/sequenceBuffer.test.ts +9 -9
  280. package/src/sequenceBuffer.ts +4 -4
  281. package/src/sequenceTerminatedSequenceParser.test.ts +3 -5
  282. package/src/sequenceTerminatedSequenceParser.ts +4 -4
  283. package/src/sequenceUnparser.ts +2 -2
  284. package/src/skipToParser.ts +2 -2
  285. package/src/sliceBoundedParser.test.ts +4 -12
  286. package/src/sliceBoundedParser.ts +2 -2
  287. package/src/smali.ts +8 -3
  288. package/src/smaliParser.test.ts +377 -66
  289. package/src/smaliParser.test.ts.md +1635 -48
  290. package/src/smaliParser.test.ts.snap +0 -0
  291. package/src/smaliParser.ts +2751 -569
  292. package/src/stringFromAsyncIterable.ts +9 -0
  293. package/src/terminatedArrayParser.test.ts +11 -11
  294. package/src/terminatedArrayParser.ts +5 -7
  295. package/src/toAsyncIterator.ts +8 -8
  296. package/src/uint8Array.ts +2 -3
  297. package/src/unionParser.test.ts +22 -23
  298. package/src/unionParser.ts +6 -8
  299. package/src/unparser.test.ts +18 -34
  300. package/src/unparser.ts +13 -9
  301. package/src/unparserContext.ts +9 -13
  302. package/src/unparserError.ts +2 -1
  303. package/src/unparserImplementationInvariant.ts +1 -1
  304. package/src/unparserOutputCompanion.ts +1 -1
  305. package/src/zip.ts +2 -6
  306. package/src/zipParser.ts +10 -18
  307. package/src/zipUnparser.test.ts +1 -1
  308. package/src/zipUnparser.ts +52 -64
  309. package/tsconfig.json +7 -1
  310. package/xo.config.ts +15 -0
  311. package/.yarn/releases/yarn-4.5.3.cjs +0 -934
@@ -5,7 +5,8 @@ import { stringParserInputCompanion } from './parserInputCompanion.js';
5
5
  import { createExactElementParser } from './exactElementParser.js';
6
6
  test('empty array does not match', async (t) => {
7
7
  const parser = createNonEmptyArrayParser(createExactElementParser('0'));
8
- await t.throwsAsync(() => runParser(parser, '', stringParserInputCompanion), {
8
+ await t.throwsAsync(async () => runParser(parser, '', stringParserInputCompanion), {
9
+ any: true,
9
10
  message: /Expected .* to match at least once/,
10
11
  });
11
12
  });
@@ -1,5 +1,5 @@
1
1
  import { getParserName, setParserName } from './parser.js';
2
- import { ParserParsingFailedError } from './parserError.js';
2
+ import { isParserParsingFailedError } from './parserError.js';
3
3
  export const createOptionalParser = (childParser) => {
4
4
  const optionalParser = async (parserContext) => {
5
5
  const childParserContext = parserContext.lookahead();
@@ -9,7 +9,7 @@ export const createOptionalParser = (childParser) => {
9
9
  return value;
10
10
  }
11
11
  catch (error) {
12
- if (error instanceof ParserParsingFailedError) {
12
+ if (isParserParsingFailedError(error)) {
13
13
  return undefined;
14
14
  }
15
15
  throw error;
package/build/parser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Class } from 'type-fest';
1
+ import { type Class } from 'type-fest';
2
2
  import { type ParserInputCompanion } from './parserInputCompanion.js';
3
3
  import { type ParserContext } from './parserContext.js';
4
4
  import { type DeriveSequenceElement } from './sequence.js';
@@ -8,6 +8,7 @@ export declare function setParserName<Output, Sequence, Element = DeriveSequence
8
8
  export declare function cloneParser<Output, Sequence, Element = DeriveSequenceElement<Sequence>>(parser: Parser<Output, Sequence, Element>): Parser<Output, Sequence, Element>;
9
9
  export type RunParserOptions<Output, Sequence, Element = DeriveSequenceElement<Sequence>> = {
10
10
  errorJoinMode?: 'none' | 'deepest' | 'furthest' | 'all';
11
+ errorStack?: boolean;
11
12
  parserContextClass?: Class<ParserContext<Sequence, Element>>;
12
13
  };
13
14
  export type RunParserWithRemainingInputResult<Output, Sequence, Element = DeriveSequenceElement<Sequence>> = {
package/build/parser.js CHANGED
@@ -1,8 +1,12 @@
1
1
  import { InputReaderImplementation } from './inputReader.js';
2
2
  import { ParserContextImplementation } from './parserContext.js';
3
- import { ParserError, ParserUnexpectedRemainingInputError } from './parserError.js';
4
3
  import { toAsyncIterator } from './toAsyncIterator.js';
5
4
  import { inputReaderStateCompanion } from './inputReaderState.js';
5
+ import { isLazyMessageError } from './lazyMessageError.js';
6
+ import { isParserError, normalParserErrorModule, noStackCaptureOverheadParserErrorModule } from './parserError.js';
7
+ import { NoStackCaptureOverheadError } from './noStackCaptureOverheadError.js';
8
+ import invariant from 'invariant';
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
10
  export function getParserName(parser, default_ = 'anonymous') {
7
11
  return parser.name || default_;
8
12
  }
@@ -12,12 +16,11 @@ export function setParserName(parser, name) {
12
16
  });
13
17
  return parser;
14
18
  }
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
20
  const originalParserByClone = new WeakMap();
16
21
  export function cloneParser(parser) {
17
22
  const originalParser = originalParserByClone.get(parser) ?? parser;
18
- const clone = (parserContext) => {
19
- return originalParser(parserContext);
20
- };
23
+ const clone = parserContext => originalParser(parserContext);
21
24
  setParserName(clone, getParserName(parser));
22
25
  originalParserByClone.set(clone, originalParser);
23
26
  return clone;
@@ -27,7 +30,18 @@ async function withEnrichedParserError(parserContext, inputReader, f) {
27
30
  return await f();
28
31
  }
29
32
  catch (error) {
30
- if (error instanceof ParserError) {
33
+ if (error instanceof NoStackCaptureOverheadError) {
34
+ invariant(error.name in normalParserErrorModule, 'NoStackCaptureOverheadError with unknown name encountered during parser execution: %s', error.name);
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ const normalError = new (normalParserErrorModule[error.name])(error.message);
37
+ Object.assign(normalError, error);
38
+ normalError.stack = normalError.stack + '\nIf you need a useful stack trace, pass `errorStack: true` to `runParser`, trading off some performance.';
39
+ error = normalError;
40
+ }
41
+ if (isLazyMessageError(error)) {
42
+ error.computeMessage();
43
+ }
44
+ if (isParserError(error)) {
31
45
  if (error.position === undefined) {
32
46
  error.position = parserContext.position;
33
47
  }
@@ -44,6 +58,7 @@ function runParserInternal(parser, input, parserInputCompanion, options = {}) {
44
58
  const ParserContext = options.parserContextClass ?? ParserContextImplementation;
45
59
  const parserContext = new ParserContext(parserInputCompanion, inputReader, undefined, {
46
60
  ...options,
61
+ errorsModule: options.errorStack ? normalParserErrorModule : noStackCaptureOverheadParserErrorModule,
47
62
  debugName: 'root',
48
63
  });
49
64
  const outputPromise = (async () => {
@@ -62,7 +77,7 @@ function runParserInternal(parser, input, parserInputCompanion, options = {}) {
62
77
  }
63
78
  export async function runParserWithRemainingInput(parser, input, parserInputCompanion, options = {}) {
64
79
  const { outputPromise, parserContext, inputReader, } = runParserInternal(parser, input, parserInputCompanion, options);
65
- return await withEnrichedParserError(parserContext, inputReader, async () => {
80
+ return withEnrichedParserError(parserContext, inputReader, async () => {
66
81
  const output = await outputPromise;
67
82
  const inputReaderState = inputReader.toInputReaderState();
68
83
  const remainingInput = (inputReaderStateCompanion.isDone(inputReaderState)
@@ -77,11 +92,11 @@ export async function runParserWithRemainingInput(parser, input, parserInputComp
77
92
  }
78
93
  export async function runParser(parser, input, parserInputCompanion, options = {}) {
79
94
  const { outputPromise, parserContext, inputReader, } = runParserInternal(parser, input, parserInputCompanion, options);
80
- return await withEnrichedParserError(parserContext, inputReader, async () => {
95
+ return withEnrichedParserError(parserContext, inputReader, async () => {
81
96
  const output = await outputPromise;
82
97
  const inputReaderState = inputReader.toInputReaderState();
83
98
  if (!inputReaderStateCompanion.isDone(inputReaderState)) {
84
- throw new ParserUnexpectedRemainingInputError('Unexpected remaining input', 0, parserContext.position);
99
+ throw new normalParserErrorModule.ParserUnexpectedRemainingInputError('Unexpected remaining input', 0, parserContext.position);
85
100
  }
86
101
  return output;
87
102
  });
@@ -3,7 +3,7 @@ import invariant from 'invariant';
3
3
  import { createUnionParser } from './unionParser.js';
4
4
  import { runParser, runParserWithRemainingInput } from './parser.js';
5
5
  import { stringParserInputCompanion, uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
6
- import { ParserError, ParserParsingInvariantError, ParserParsingJoinAllError, ParserParsingJoinDeepestError, ParserParsingJoinError, ParserParsingJoinFurthestError, ParserParsingJoinNoneError, ParserUnexpectedRemainingInputError, } from './parserError.js';
6
+ import { isParserParsingJoinError, normalParserErrorModule, } from './parserError.js';
7
7
  import { createTupleParser } from './tupleParser.js';
8
8
  import { promiseCompose } from './promiseCompose.js';
9
9
  import { createDisjunctionParser } from './disjunctionParser.js';
@@ -11,6 +11,7 @@ import { createExactSequenceNaiveParser } from './exactSequenceParser.js';
11
11
  import { createArrayParser } from './arrayParser.js';
12
12
  import { createElementParser } from './elementParser.js';
13
13
  import { toAsyncIterable } from './toAsyncIterable.js';
14
+ import { stringFromAsyncIterable } from './stringFromAsyncIterable.js';
14
15
  const aUnionParser = createUnionParser([
15
16
  createExactSequenceNaiveParser('1'),
16
17
  createExactSequenceNaiveParser('aa'),
@@ -36,29 +37,23 @@ const sampleParser = promiseCompose(createTupleParser([
36
37
  async function* asyncIteratorFromString(string) {
37
38
  yield string;
38
39
  }
39
- async function stringFromAsyncIterable(asyncIterable) {
40
- let string = '';
41
- for await (const chunk of asyncIterable) {
42
- string += chunk;
43
- }
44
- return string;
45
- }
46
40
  function sortChildErrors(error) {
47
41
  error.childErrors.sort((a, b) => a.message.localeCompare(b.message));
48
42
  for (const childError of error.childErrors) {
49
- if (childError instanceof ParserParsingJoinError) {
43
+ if (isParserParsingJoinError(childError)) {
50
44
  sortChildErrors(childError);
51
45
  }
52
46
  }
53
47
  }
54
48
  function removeStackLocations(errorStack) {
55
- return errorStack.replaceAll(/((at [^\n]+)[\s\n]+)+(at [^\n]+)/g, 'at [LOCATIONS]');
49
+ return errorStack?.replaceAll(/((at [^\n]+)[\s\n]+)+(at [^\n]+)/g, 'at [LOCATIONS]');
56
50
  }
57
51
  test('errorJoinMode: none', async (t) => {
58
52
  const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringParserInputCompanion, {
59
53
  errorJoinMode: 'none',
54
+ errorStack: true,
60
55
  }), {
61
- instanceOf: ParserParsingJoinNoneError,
56
+ instanceOf: normalParserErrorModule.ParserParsingJoinNoneError,
62
57
  });
63
58
  t.is(error.position, 12);
64
59
  t.deepEqual(error.childErrors, []);
@@ -67,61 +62,112 @@ test('errorJoinMode: none', async (t) => {
67
62
  test('errorJoinMode: all', async (t) => {
68
63
  const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringParserInputCompanion, {
69
64
  errorJoinMode: 'all',
65
+ errorStack: true,
70
66
  }), {
71
- instanceOf: ParserParsingJoinAllError,
67
+ instanceOf: normalParserErrorModule.ParserParsingJoinAllError,
72
68
  });
73
69
  sortChildErrors(error);
74
70
  t.snapshot(removeStackLocations(error.stack));
75
71
  t.is(error.position, 12, 'error.position');
76
72
  t.is(error.childErrors.length, 4);
77
73
  const error1 = error.childErrors.at(-1);
78
- invariant(error1 instanceof ParserParsingJoinAllError, 'error1 instanceof ParserParsingJoinAllError');
74
+ invariant(isParserParsingJoinError(error1), 'error1 instanceof ParserParsingJoinAllError');
79
75
  t.is(error1.position, 3, 'error1.position');
80
76
  t.is(error1.childErrors.length, 4);
81
77
  const error2 = error1.childErrors.at(-1);
82
- invariant(error2 instanceof ParserParsingJoinAllError, 'error2 instanceof ParserParsingJoinAllError');
78
+ invariant(isParserParsingJoinError(error2), 'error2 instanceof ParserParsingJoinAllError');
83
79
  t.is(error2.position, 4, 'error2.position');
84
80
  t.is(error2.childErrors.length, 3);
85
81
  const error3 = error2.childErrors.at(-1);
86
- invariant(error3 instanceof ParserParsingInvariantError, 'error3 instanceof ParserParsingInvariantError');
82
+ invariant(error3.name === 'ParserParsingInvariantError', 'error3 instanceof ParserParsingInvariantError');
87
83
  t.is(error3.position, 4, 'error3.position');
88
84
  });
89
85
  test('errorJoinMode: deepest', async (t) => {
90
86
  const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringParserInputCompanion, {
91
87
  errorJoinMode: 'deepest',
88
+ errorStack: true,
92
89
  }), {
93
- instanceOf: ParserParsingJoinDeepestError,
90
+ instanceOf: normalParserErrorModule.ParserParsingJoinDeepestError,
94
91
  });
95
92
  sortChildErrors(error);
96
93
  t.snapshot(removeStackLocations(error.stack));
97
94
  t.is(error.position, 12);
98
95
  t.is(error.childErrors.length, 1);
99
96
  const error1 = error.childErrors.at(-1);
100
- invariant(error1 instanceof ParserParsingJoinDeepestError, 'error1 instanceof ParserParsingJoinDeepestError');
97
+ invariant(isParserParsingJoinError(error1), 'error1 instanceof ParserParsingJoinDeepestError');
101
98
  t.is(error1.position, 3);
102
99
  t.is(error1.childErrors.length, 1);
103
100
  const error2 = error1.childErrors.at(-1);
104
- invariant(error2 instanceof ParserParsingJoinDeepestError, 'error2 instanceof ParserParsingJoinDeepestError');
101
+ invariant(isParserParsingJoinError(error2), 'error2 instanceof ParserParsingJoinDeepestError');
105
102
  t.is(error2.position, 4);
106
103
  t.is(error2.childErrors.length, 3);
107
104
  const error3 = error2.childErrors.at(-1);
108
- invariant(error3 instanceof ParserParsingInvariantError, 'error3 instanceof ParserParsingInvariantError');
105
+ invariant(error3.name === 'ParserParsingInvariantError', 'error3 instanceof ParserParsingInvariantError');
109
106
  t.is(error3.position, 4);
110
107
  });
111
108
  test('errorJoinMode: furthest', async (t) => {
112
109
  const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringParserInputCompanion, {
113
110
  errorJoinMode: 'furthest',
111
+ errorStack: true,
114
112
  }), {
115
- instanceOf: ParserParsingJoinFurthestError,
113
+ instanceOf: normalParserErrorModule.ParserParsingJoinFurthestError,
116
114
  });
117
115
  sortChildErrors(error);
118
116
  t.snapshot(removeStackLocations(error.stack));
119
117
  t.is(error.position, 12);
120
118
  t.is(error.childErrors.length, 1);
121
119
  const error1 = error.childErrors.at(-1);
122
- invariant(error1 instanceof ParserParsingInvariantError, 'error1 instanceof ParserParsingInvariantError');
120
+ invariant(error1.name === 'ParserParsingInvariantError', 'error1 instanceof ParserParsingInvariantError');
123
121
  t.is(error1.position, 12);
124
122
  });
123
+ test('errorStack: false', async (t) => {
124
+ const error = await t.throwsAsync(runParser(sampleParser, 'nothing like what sampleParser expects', stringParserInputCompanion, {
125
+ errorJoinMode: 'all',
126
+ }), {
127
+ instanceOf: normalParserErrorModule.ParserParsingJoinAllError,
128
+ });
129
+ t.regex(error.stack, /intentionally left blank/);
130
+ t.regex(error.stack, /errorStack: true/);
131
+ });
132
+ test('errorStack: true', async (t) => {
133
+ const error = await t.throwsAsync(runParser(sampleParser, 'nothing like what sampleParser expects', stringParserInputCompanion, {
134
+ errorJoinMode: 'all',
135
+ errorStack: true,
136
+ }), {
137
+ instanceOf: normalParserErrorModule.ParserParsingJoinAllError,
138
+ });
139
+ t.regex(error.stack, /exactSequenceParser/);
140
+ });
141
+ test('errorJoinMode: none, errorStack: false', async (t) => {
142
+ const error = await t.throwsAsync(runParser(sampleParser, asyncIteratorFromString('1bbfinal_CC!'), stringParserInputCompanion, {
143
+ errorJoinMode: 'none',
144
+ errorStack: false,
145
+ }), {
146
+ instanceOf: normalParserErrorModule.ParserParsingJoinNoneError,
147
+ });
148
+ t.is(error.position, 12);
149
+ t.deepEqual(error.childErrors, []);
150
+ t.snapshot(removeStackLocations(error.stack));
151
+ });
152
+ test('retrows normal errors untouched', async (t) => {
153
+ class CustomError extends Error {
154
+ }
155
+ ;
156
+ const originalCustomError1 = new CustomError('This is a custom error');
157
+ const originalCustomError2 = new Error('This is a normal error');
158
+ const error1 = await t.throwsAsync(runParser(() => {
159
+ throw originalCustomError1;
160
+ }, 'foo', stringParserInputCompanion), {
161
+ instanceOf: CustomError,
162
+ });
163
+ t.is(error1, originalCustomError1);
164
+ const error2 = await t.throwsAsync(runParser(() => {
165
+ throw originalCustomError2;
166
+ }, 'foo', stringParserInputCompanion), {
167
+ instanceOf: Error,
168
+ });
169
+ t.is(error2, originalCustomError2);
170
+ });
125
171
  test('throws on parserInputCompanion type mismatch', async (t) => {
126
172
  const anythingParser = createArrayParser(createElementParser());
127
173
  await runParser(anythingParser, asyncIteratorFromString('anything'), stringParserInputCompanion);
@@ -140,8 +186,10 @@ test('thrown error has input reader state', async (t) => {
140
186
  yield 'foo';
141
187
  yield 'qux';
142
188
  yield 'bar';
143
- })(), stringParserInputCompanion), {
144
- instanceOf: ParserError,
189
+ })(), stringParserInputCompanion, {
190
+ errorStack: true,
191
+ }), {
192
+ instanceOf: normalParserErrorModule.ParserParsingInvariantError,
145
193
  });
146
194
  t.is(error.position, 4);
147
195
  invariant(error.inputReaderSate, 'error.inputReaderSate');
@@ -160,8 +208,9 @@ test('thrown error has input reader state', async (t) => {
160
208
  });
161
209
  test('runParser throws with remaining input', async (t) => {
162
210
  const parser = createExactSequenceNaiveParser('foo');
163
- const error = await t.throwsAsync(() => runParser(parser, 'foobar', stringParserInputCompanion), {
164
- instanceOf: ParserUnexpectedRemainingInputError,
211
+ const error = await t.throwsAsync(async () => runParser(parser, 'foobar', stringParserInputCompanion), {
212
+ any: true,
213
+ name: 'ParserUnexpectedRemainingInputError',
165
214
  message: /remaining input/,
166
215
  });
167
216
  t.is(error.position, 3);
@@ -175,19 +224,19 @@ test('runParser throws with remaining input', async (t) => {
175
224
  test('runParser does not throw without remaining input', async (t) => {
176
225
  const parser = createExactSequenceNaiveParser('foo');
177
226
  const output = await runParser(parser, 'foo', stringParserInputCompanion);
178
- t.deepEqual(output, 'foo');
227
+ t.is(output, 'foo');
179
228
  });
180
229
  test('runParserWithRemainingInput with remaining input', async (t) => {
181
230
  const parser = createExactSequenceNaiveParser('foo');
182
231
  const { output, remainingInput, position, ...resultRest } = await runParserWithRemainingInput(parser, 'foobar', stringParserInputCompanion);
183
232
  t.deepEqual(resultRest, {});
184
- t.deepEqual(output, 'foo');
185
- t.deepEqual(await stringFromAsyncIterable(remainingInput), 'bar');
233
+ t.is(output, 'foo');
234
+ t.is(await stringFromAsyncIterable(remainingInput), 'bar');
186
235
  t.is(position, 3);
187
236
  });
188
237
  test('runParserWithRemainingInput without remaining input', async (t) => {
189
238
  const parser = createExactSequenceNaiveParser('foo');
190
239
  const { output, remainingInput } = await runParserWithRemainingInput(parser, 'foo', stringParserInputCompanion);
191
- t.deepEqual(output, 'foo');
240
+ t.is(output, 'foo');
192
241
  t.is(remainingInput, undefined);
193
242
  });
@@ -1,2 +1,2 @@
1
- import { Parser } from "./parser.js";
1
+ import { type Parser } from './parser.js';
2
2
  export declare const createParserConsumedSequenceParser: <Output, Sequence>(childParser: Parser<Output, Sequence>) => Parser<[Output, Sequence], Sequence>;
@@ -1,5 +1,5 @@
1
- import { createFixedLengthSequenceParser } from "./fixedLengthSequenceParser.js";
2
- import { getParserName, setParserName } from "./parser.js";
1
+ import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
2
+ import { getParserName, setParserName } from './parser.js';
3
3
  export const createParserConsumedSequenceParser = (childParser) => {
4
4
  const parserConsumedSequenceParser = async (parserContext) => {
5
5
  const initialPosition = parserContext.position;
@@ -1,13 +1,15 @@
1
1
  import { type ParserInputCompanion } from './parserInputCompanion.js';
2
2
  import { type InputReader } from './inputReader.js';
3
- import { type ParserParsingFailedError } from './parserError.js';
3
+ import { normalParserErrorModule, noStackCaptureOverheadParserErrorModule, ParserParsingFailedError } from './parserError.js';
4
4
  import { type RunParserOptions } from './parser.js';
5
5
  import { type Falsy, type ValueOrAccessor } from './customInvariant.js';
6
6
  type LookaheadOptions = {
7
7
  debugName?: string;
8
8
  sliceEnd?: number;
9
9
  };
10
- type ParserContextOptions<Sequence, Element> = RunParserOptions<unknown, Sequence, Element> & LookaheadOptions;
10
+ type ParserContextOptions<Sequence, Element> = RunParserOptions<unknown, Sequence, Element> & LookaheadOptions & {
11
+ errorsModule: typeof normalParserErrorModule | typeof noStackCaptureOverheadParserErrorModule;
12
+ };
11
13
  export type ParserContext<Sequence, Element> = {
12
14
  from(elements: Element[]): Sequence;
13
15
  concat(sequences: Sequence[]): Sequence;
@@ -26,8 +28,8 @@ export type ParserContext<Sequence, Element> = {
26
28
  lookahead(options?: LookaheadOptions): ParserContext<Sequence, Element>;
27
29
  unlookahead(): void;
28
30
  dispose(): void;
29
- invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
30
- invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
31
+ invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: unknown[]): Exclude<T, Falsy>;
32
+ invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: unknown[]): Exclude<T, Falsy>;
31
33
  };
32
34
  export declare class ParserContextImplementation<Sequence, Element> implements ParserContext<Sequence, Element> {
33
35
  private readonly _parserInputCompanion;
@@ -56,7 +58,7 @@ export declare class ParserContextImplementation<Sequence, Element> implements P
56
58
  lookahead(options?: LookaheadOptions): ParserContext<Sequence, Element>;
57
59
  unlookahead(): void;
58
60
  dispose(): void;
59
- invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
60
- invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: any[]): Exclude<T, Falsy>;
61
+ invariant<T>(value: T, format: ValueOrAccessor<string | string[]>, ...formatArguments: unknown[]): Exclude<T, Falsy>;
62
+ invariantJoin<T>(value: T, childErrors: ParserParsingFailedError[], format: ValueOrAccessor<string | string[]>, ...formatArguments: unknown[]): Exclude<T, Falsy>;
61
63
  }
62
64
  export {};
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable prefer-arrow-callback */
2
- import { ParserUnexpectedEndOfInputError, ParserParsingInvariantError, ParserParsingJoinNoneError, ParserParsingJoinAllError, ParserParsingJoinDeepestError, ParserParsingJoinFurthestError, } from './parserError.js';
3
2
  import { customInvariant } from './customInvariant.js';
4
3
  import { parserImplementationInvariant } from './parserImplementationInvariant.js';
4
+ import { formatLazyMessage, isLazyMessageError } from './lazyMessageError.js';
5
5
  let parserContextId = 0;
6
6
  export class ParserContextImplementation {
7
7
  _parserInputCompanion;
@@ -81,7 +81,7 @@ export class ParserContextImplementation {
81
81
  async read(offset) {
82
82
  const element = await this.peek(offset);
83
83
  if (element === undefined) {
84
- throw new ParserUnexpectedEndOfInputError('', this._depth, this.position);
84
+ throw new this._options.errorsModule.ParserUnexpectedEndOfInputError('', this._depth, this.position);
85
85
  }
86
86
  this.skip(offset + 1);
87
87
  return element;
@@ -89,7 +89,7 @@ export class ParserContextImplementation {
89
89
  async readSequence(start, end) {
90
90
  const sequence = await this.peekSequence(start, end);
91
91
  if (sequence === undefined) {
92
- throw new ParserUnexpectedEndOfInputError('', this._depth, this.position);
92
+ throw new this._options.errorsModule.ParserUnexpectedEndOfInputError('', this._depth, this.position);
93
93
  }
94
94
  this.skip(end);
95
95
  return sequence;
@@ -121,7 +121,7 @@ export class ParserContextImplementation {
121
121
  'this: %s',
122
122
  'parent: %s',
123
123
  'parent.exclusiveChild: %s',
124
- ].join('\n'), this.toString(), parentParserContext.toString(), parentParserContext._exclusiveChildParserContext?.toString());
124
+ ], () => this.toString(), () => parentParserContext.toString(), () => parentParserContext._exclusiveChildParserContext?.toString());
125
125
  parserImplementationInvariant(parentParserContext.position <= this.position, 'unlookahead this._parentParserContext.position (%s) <= this.position (%s)', parentParserContext.position, this.position);
126
126
  const offset = this._inputReader.position - parentParserContext._inputReader.position;
127
127
  parentParserContext.skip(offset);
@@ -140,14 +140,14 @@ export class ParserContextImplementation {
140
140
  'this: %s',
141
141
  'parent: %s',
142
142
  'parent.exclusiveChild: %s',
143
- ].join('\n'), this.toString(), parentParserContext.toString(), parentParserContext._exclusiveChildParserContext?.toString());
143
+ ], () => this.toString(), () => parentParserContext.toString(), () => parentParserContext._exclusiveChildParserContext?.toString());
144
144
  parentParserContext._exclusiveChildParserContext = undefined;
145
145
  this._parentParserContext = undefined;
146
146
  }
147
147
  invariant(value, format, ...formatArguments) {
148
148
  const parserContext = this;
149
- return customInvariant(function (message) {
150
- return new ParserParsingInvariantError(message, parserContext._depth, parserContext.position);
149
+ return customInvariant(function (lazyMessage) {
150
+ return new parserContext._options.errorsModule.ParserParsingInvariantError(lazyMessage, parserContext._depth, parserContext.position);
151
151
  }, value, format, ...formatArguments);
152
152
  }
153
153
  invariantJoin(value, childErrors, format, ...formatArguments) {
@@ -155,12 +155,12 @@ export class ParserContextImplementation {
155
155
  const errorJoinMode = this._options.errorJoinMode ?? 'none';
156
156
  const parserContext = this;
157
157
  if (errorJoinMode === 'none') {
158
- return customInvariant(function (message) {
159
- return new ParserParsingJoinNoneError(message, parserContext._depth, parserContext.position);
158
+ return customInvariant(function (lazyMessage) {
159
+ return new parserContext._options.errorsModule.ParserParsingJoinNoneError(lazyMessage, parserContext._depth, parserContext.position);
160
160
  }, value, format, ...formatArguments);
161
161
  }
162
162
  if (errorJoinMode === 'furthest') {
163
- return customInvariant(function (message) {
163
+ return customInvariant(function (userLazyMessage) {
164
164
  let furthestPosition = 0;
165
165
  let furthestChildErrors = [];
166
166
  for (const childError of childErrors) {
@@ -174,20 +174,31 @@ export class ParserContextImplementation {
174
174
  }
175
175
  furthestChildErrors.push(childError);
176
176
  }
177
- message += [
178
- '',
179
- 'Furthest child error stacks, indented:',
180
- ...furthestChildErrors.flatMap(furthestChildError => furthestChildError.stack?.split('\n').map(line => ' ' + line)),
181
- 'End of furthest child error stacks',
182
- ].join('\n');
183
- return new ParserParsingJoinFurthestError(message, parserContext._depth, furthestPosition, furthestChildErrors);
177
+ return new parserContext._options.errorsModule.ParserParsingJoinFurthestError([
178
+ [
179
+ '%s',
180
+ 'Furthest child error stacks, indented:',
181
+ '%s',
182
+ 'End of furthest child error stacks',
183
+ ],
184
+ () => formatLazyMessage(userLazyMessage),
185
+ () => furthestChildErrors.flatMap(furthestChildError => {
186
+ if (isLazyMessageError(furthestChildError)) {
187
+ furthestChildError.computeMessage();
188
+ }
189
+ return furthestChildError.stack?.split('\n').map(line => ' ' + line);
190
+ }).join('\n'),
191
+ ], parserContext._depth, furthestPosition, furthestChildErrors);
184
192
  }, value, format, ...formatArguments);
185
193
  }
186
194
  if (errorJoinMode === 'deepest') {
187
- return customInvariant(function (message) {
195
+ return customInvariant(function (userLazyMessage) {
188
196
  let deepestDepth = 0;
189
197
  let deepestChildErrors = [];
190
198
  for (const childError of childErrors) {
199
+ if (isLazyMessageError(childError)) {
200
+ childError.computeMessage();
201
+ }
191
202
  if (childError.depth < deepestDepth) {
192
203
  continue;
193
204
  }
@@ -198,24 +209,40 @@ export class ParserContextImplementation {
198
209
  }
199
210
  deepestChildErrors.push(childError);
200
211
  }
201
- message += [
202
- '',
203
- 'Deepest child error stacks, indented:',
204
- ...deepestChildErrors.flatMap(deepestChildError => deepestChildError.stack?.split('\n').map(line => ' ' + line)),
205
- 'End of deepest child error stacks',
206
- ].join('\n');
207
- return new ParserParsingJoinDeepestError(message, deepestDepth, parserContext.position, deepestChildErrors);
212
+ return new parserContext._options.errorsModule.ParserParsingJoinDeepestError([
213
+ [
214
+ '%s',
215
+ 'Deepest child error stacks, indented:',
216
+ '%s',
217
+ 'End of deepest child error stacks',
218
+ ],
219
+ () => formatLazyMessage(userLazyMessage),
220
+ () => deepestChildErrors.flatMap(deepestChildError => {
221
+ if (isLazyMessageError(deepestChildError)) {
222
+ deepestChildError.computeMessage();
223
+ }
224
+ return deepestChildError.stack?.split('\n').map(line => ' ' + line);
225
+ }).join('\n'),
226
+ ], deepestDepth, parserContext.position, deepestChildErrors);
208
227
  }, value, format, ...formatArguments);
209
228
  }
210
229
  if (errorJoinMode === 'all') {
211
- return customInvariant(function (message) {
212
- message += [
213
- '',
214
- 'Child error stacks, indented:',
215
- ...childErrors.flatMap(childError => childError.stack?.split('\n').map(line => ' ' + line)),
216
- 'End of child error stacks',
217
- ].join('\n');
218
- return new ParserParsingJoinAllError(message, parserContext._depth, parserContext.position, childErrors);
230
+ return customInvariant(function (userLazyMessage) {
231
+ return new parserContext._options.errorsModule.ParserParsingJoinAllError([
232
+ [
233
+ '%s',
234
+ 'All child error stacks, indented:',
235
+ '%s',
236
+ 'End of all child error stacks',
237
+ ],
238
+ () => formatLazyMessage(userLazyMessage),
239
+ () => childErrors.flatMap(childError => {
240
+ if (isLazyMessageError(childError)) {
241
+ childError.computeMessage();
242
+ }
243
+ return childError.stack?.split('\n').map(line => ' ' + line);
244
+ }).join('\n'),
245
+ ], parserContext._depth, parserContext.position, childErrors);
219
246
  }, value, format, ...formatArguments);
220
247
  }
221
248
  return parserImplementationInvariant(false, 'Unsupported errorJoinMode: %s', errorJoinMode);
@@ -2,12 +2,14 @@ import test from 'ava';
2
2
  import { ParserContextImplementation } from './parserContext.js';
3
3
  import { stringParserInputCompanion } from './parserInputCompanion.js';
4
4
  import { InputReaderImplementation } from './inputReader.js';
5
- import { ParserUnexpectedEndOfInputError } from './parserError.js';
5
+ import { noStackCaptureOverheadParserErrorModule } from './parserError.js';
6
6
  const commonParserContextArguments = [
7
7
  undefined,
8
8
  {
9
9
  debugName: 'root',
10
10
  errorJoinMode: 'all',
11
+ errorStack: false,
12
+ errorsModule: noStackCaptureOverheadParserErrorModule,
11
13
  },
12
14
  ];
13
15
  test('parserContext.read', async (t) => {
@@ -22,7 +24,8 @@ test('parserContext.read', async (t) => {
22
24
  t.is(await parserContext.read(0), 'b');
23
25
  t.is(await parserContext.read(5), 'h');
24
26
  await t.throwsAsync(async () => parserContext.read(0), {
25
- instanceOf: ParserUnexpectedEndOfInputError,
27
+ any: true,
28
+ name: 'ParserUnexpectedEndOfInputError',
26
29
  });
27
30
  });
28
31
  test('parserContext.readSequence', async (t) => {
@@ -42,7 +45,8 @@ test('parserContext.readSequence', async (t) => {
42
45
  t.is(await parserContext.readSequence(1, 1), '');
43
46
  t.is(await parserContext.readSequence(0, 0), '');
44
47
  await t.throwsAsync(async () => parserContext.readSequence(0, 1), {
45
- instanceOf: ParserUnexpectedEndOfInputError,
48
+ any: true,
49
+ name: 'ParserUnexpectedEndOfInputError',
46
50
  });
47
51
  });
48
52
  test('parserContext.lookahead', async (t) => {