@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
@@ -1,5 +1,5 @@
1
1
  import invariant from 'invariant';
2
- import { MUtf8Decoder } from "mutf-8";
2
+ import { MUtf8Decoder } from 'mutf-8';
3
3
  import { createExactElementParser } from './exactElementParser.js';
4
4
  import { createExactSequenceParser } from './exactSequenceParser.js';
5
5
  import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
@@ -11,13 +11,13 @@ import { createTupleParser } from './tupleParser.js';
11
11
  import { createParserAccessorParser } from './parserAccessorParser.js';
12
12
  import { createSkipToParser } from './skipToParser.js';
13
13
  import { createLookaheadParser } from './lookaheadParser.js';
14
- import { getIsoTypedNumberArray, isoIndexIntoFieldIds, isoIndexIntoMethodIds, isoIndexIntoPrototypeIds, isoIndexIntoStringIds, isoIndexIntoTypeIds, isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler, isoOffsetToAnnotationItem, isoOffsetToAnnotationsDirectoryItem, isoOffsetToAnnotationSetItem, isoOffsetToAnnotationSetRefListItem, isoOffsetToClassDataItem, isoOffsetToCodeItem, isoOffsetToDebugInfoItem, isoOffsetToEncodedArrayItem, isoOffsetToStringDataItem, isoOffsetToTypeList } from './dalvikExecutableParser/typedNumbers.js';
14
+ import { getIsoTypedNumberArray, isoIndexIntoFieldIds, isoIndexIntoMethodIds, isoIndexIntoPrototypeIds, isoIndexIntoStringIds, isoIndexIntoTypeIds, isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler, isoOffsetToAnnotationItem, isoOffsetToAnnotationsDirectoryItem, isoOffsetToAnnotationSetItem, isoOffsetToAnnotationSetRefListItem, isoOffsetToClassDataItem, isoOffsetToCodeItem, isoOffsetToDebugInfoItem, isoOffsetToEncodedArrayItem, isoOffsetToStringDataItem, isoOffsetToTypeList, } from './dalvikExecutableParser/typedNumbers.js';
15
15
  import { sleb128NumberParser, uleb128NumberParser } from './leb128Parser.js';
16
16
  import { createDisjunctionParser } from './disjunctionParser.js';
17
17
  import { createElementTerminatedSequenceParser } from './elementTerminatedSequenceParser.js';
18
18
  import { createElementTerminatedArrayParserUnsafe } from './elementTerminatedArrayParser.js';
19
- import { createDalvikBytecodeParser, resolveDalvikBytecodeOperation } from './dalvikBytecodeParser.js';
20
- import { ubyteParser, uintParser, uleb128p1NumberParser, ushortParser } from './dalvikExecutableParser/typeParsers.js';
19
+ import { createDalvikBytecodeParser, resolveDalvikBytecodeOperation, } from './dalvikBytecodeParser.js';
20
+ import { byteParser, ubyteParser, uintParser, uleb128p1NumberParser, ushortParser, } from './dalvikExecutableParser/typeParsers.js';
21
21
  // https://source.android.com/docs/core/runtime/dex-format
22
22
  const createByteAlignParser = (byteAlignment) => async (parserContext) => {
23
23
  const toSkip = (byteAlignment - (parserContext.position % byteAlignment)) % byteAlignment;
@@ -71,7 +71,7 @@ const dalvikExecutableHeaderItemParser = promiseCompose(createTupleParser([
71
71
  classDefinitions,
72
72
  data,
73
73
  }));
74
- const dalvikExecutableStringIdItemParser = promiseCompose(cloneParser(uintParser), (offset) => isoOffsetToStringDataItem.wrap(offset));
74
+ const dalvikExecutableStringIdItemParser = promiseCompose(cloneParser(uintParser), offset => isoOffsetToStringDataItem.wrap(offset));
75
75
  const isoDalvikExecutableStringIdItems = getIsoTypedNumberArray();
76
76
  const createSkipToThenStringIdItemsParser = ({ size, offset }) => (size === 0
77
77
  ? (() => isoDalvikExecutableStringIdItems.wrap([]))
@@ -79,7 +79,7 @@ const createSkipToThenStringIdItemsParser = ({ size, offset }) => (size === 0
79
79
  createSkipToParser(offset),
80
80
  createQuantifierParser(dalvikExecutableStringIdItemParser, size),
81
81
  ]), ([_, stringIds]) => isoDalvikExecutableStringIdItems.wrap(stringIds)));
82
- const dalvikExecutableTypeIdItemParser = promiseCompose(cloneParser(uintParser), (index) => isoIndexIntoStringIds.wrap(index));
82
+ const dalvikExecutableTypeIdItemParser = promiseCompose(cloneParser(uintParser), index => isoIndexIntoStringIds.wrap(index));
83
83
  const isoDalvikExecutableTypeIdItems = getIsoTypedNumberArray();
84
84
  const createSkipToThenTypeIdItemsParser = ({ size, offset }) => (size === 0
85
85
  ? (() => isoDalvikExecutableTypeIdItems.wrap([]))
@@ -156,49 +156,45 @@ const createSkipToThenMethodIdItemsParser = ({ size, offset }) => (size === 0
156
156
  createSkipToParser(offset),
157
157
  createQuantifierParser(dalvikExecutableMethodIdItemParser, size),
158
158
  ]), ([_, methodIds]) => isoDalvikExecutableMethodIdItems.wrap(methodIds)));
159
- const uintAccessFlagsParser = promiseCompose(uintParser, (flags) => ({
160
- public: Boolean(flags & 0b00000001),
161
- private: Boolean(flags & 0b00000010),
162
- protected: Boolean(flags & 0b00000100),
163
- static: Boolean(flags & 0b00001000),
164
- final: Boolean(flags & 0b00010000),
165
- synchronized: Boolean(flags & 0b00100000),
166
- volatile: Boolean(flags & 0b01000000),
167
- bridge: Boolean(flags & 0b01000000),
168
- transient: Boolean(flags & 0b10000000),
169
- varargs: Boolean(flags & 0b10000000),
170
- native: false,
171
- interface: false,
172
- abstract: false,
173
- strict: false,
174
- synthetic: false,
175
- annotation: false,
176
- enum: false,
177
- constructor: false,
178
- declaredSynchronized: false,
179
- }));
180
- const uleb128AccessFlagsParser = promiseCompose(uleb128NumberParser, flags => ({
181
- public: Boolean(flags & 0b00000001),
182
- private: Boolean(flags & 0b00000010),
183
- protected: Boolean(flags & 0b00000100),
184
- static: Boolean(flags & 0b00001000),
185
- final: Boolean(flags & 0b00010000),
186
- synchronized: Boolean(flags & 0b00100000),
187
- volatile: Boolean(flags & 0b01000000),
188
- bridge: Boolean(flags & 0b01000000),
189
- transient: Boolean(flags & 0b10000000),
190
- varargs: Boolean(flags & 0b10000000),
191
- native: Boolean(flags & 0b00000001_00000000),
192
- interface: Boolean(flags & 0b00000010_00000000),
193
- abstract: Boolean(flags & 0b00000100_00000000),
194
- strict: Boolean(flags & 0b00001000_00000000),
195
- synthetic: Boolean(flags & 0b00010000_00000000),
196
- annotation: Boolean(flags & 0b00100000_00000000),
197
- enum: Boolean(flags & 0b01000000_00000000),
198
- constructor: Boolean(flags & 0b00000001_00000000_00000000),
199
- declaredSynchronized: Boolean(flags & 0b00000010_00000000_00000000),
200
- }));
201
- const DEX_CLASS_DEFINITION_ITEM_SOURCE_FILE_NO_INDEX = 0xffffffff;
159
+ const parseAccessFlagsCommon = (flags) => ({
160
+ public: Boolean(flags & 0b0000_0001),
161
+ private: Boolean(flags & 0b0000_0010),
162
+ protected: Boolean(flags & 0b0000_0100),
163
+ static: Boolean(flags & 0b0000_1000),
164
+ final: Boolean(flags & 0b0001_0000),
165
+ synchronized: Boolean(flags & 0b0010_0000),
166
+ volatile: false,
167
+ bridge: false,
168
+ transient: Boolean(flags & 0b1000_0000),
169
+ varargs: Boolean(flags & 0b1000_0000),
170
+ native: Boolean(flags & 0b0000_0001_0000_0000),
171
+ interface: Boolean(flags & 0b0000_0010_0000_0000),
172
+ abstract: Boolean(flags & 0b0000_0100_0000_0000),
173
+ strict: Boolean(flags & 0b0000_1000_0000_0000),
174
+ synthetic: Boolean(flags & 0b0001_0000_0000_0000),
175
+ annotation: Boolean(flags & 0b0010_0000_0000_0000),
176
+ enum: Boolean(flags & 0b0100_0000_0000_0000),
177
+ constructor: Boolean(flags & 0b0000_0001_0000_0000_0000_0000),
178
+ declaredSynchronized: Boolean(flags & 0b0000_0010_0000_0000_0000_0000),
179
+ });
180
+ const parseAccessFlags = (flags) => parseAccessFlagsCommon(flags);
181
+ const parseFieldAccessFlags = (flags) => ({
182
+ ...parseAccessFlagsCommon(flags),
183
+ volatile: Boolean(flags & 0b0100_0000),
184
+ varargs: false, // Varargs is only for methods, not fields
185
+ bridge: false,
186
+ });
187
+ const parseMethodAccessFlags = (flags) => ({
188
+ ...parseAccessFlagsCommon(flags),
189
+ volatile: false,
190
+ transient: false, // Transient is only for fields, not methods
191
+ bridge: Boolean(flags & 0b0100_0000),
192
+ });
193
+ const uintAccessFlagsParser = promiseCompose(uintParser, parseAccessFlags);
194
+ const uleb128AccessFlagsParser = promiseCompose(uleb128NumberParser, parseAccessFlags);
195
+ const uleb128FieldAccessFlagsParser = promiseCompose(uleb128NumberParser, parseFieldAccessFlags);
196
+ const uleb128MethodAccessFlagsParser = promiseCompose(uleb128NumberParser, parseMethodAccessFlags);
197
+ const DEX_CLASS_DEFINITION_ITEM_SOURCE_FILE_NO_INDEX = 0xFF_FF_FF_FF;
202
198
  const createSkipToThenClassDefinitionItemsParser = ({ size, offset }) => (size === 0
203
199
  ? (() => [])
204
200
  : promiseCompose(createTupleParser([
@@ -251,12 +247,12 @@ const createSkipToThenStringsParser = (sizeOffset) => createSkipToThenItemByOffs
251
247
  isoOffset: isoOffsetToStringDataItem,
252
248
  parserName: 'skipToThenStringsParser',
253
249
  });
254
- const dalvikExecutableTypeItemParser = promiseCompose(cloneParser(ushortParser), (index) => isoIndexIntoTypeIds.wrap(index));
250
+ const dalvikExecutableTypeItemParser = promiseCompose(cloneParser(ushortParser), index => isoIndexIntoTypeIds.wrap(index));
255
251
  const isoDalvikExecutableTypeList = getIsoTypedNumberArray();
256
252
  const dalvikExecutableTypeListParser = parserCreatorCompose(() => createTupleParser([
257
253
  byteAlign4Parser,
258
254
  uintParser,
259
- ]), ([_, size]) => promiseCompose(createQuantifierParser(dalvikExecutableTypeItemParser, size), (typeItems) => isoDalvikExecutableTypeList.wrap(typeItems)))();
255
+ ]), ([_, size]) => promiseCompose(createQuantifierParser(dalvikExecutableTypeItemParser, size), typeItems => isoDalvikExecutableTypeList.wrap(typeItems)))();
260
256
  const createSkipToThenTypeListByOffsetParser = (sizeOffset) => createSkipToThenItemByOffsetParser({
261
257
  sizeOffset,
262
258
  itemParser: dalvikExecutableTypeListParser,
@@ -314,9 +310,9 @@ const createSkipToThenAnnotationsDirectoryItemsParser = (sizeOffset) => createSk
314
310
  });
315
311
  const encodedFieldParser = promiseCompose(createTupleParser([
316
312
  uleb128NumberParser,
317
- uleb128AccessFlagsParser,
313
+ uleb128FieldAccessFlagsParser,
318
314
  ]), ([fieldIndexDiff, accessFlags]) => ({ fieldIndexDiff, accessFlags }));
319
- const createEncodedFieldsParser = (fieldsSize) => promiseCompose(createQuantifierParser(encodedFieldParser, fieldsSize), (encodedFields) => {
315
+ const createEncodedFieldsParser = (fieldsSize) => promiseCompose(createQuantifierParser(encodedFieldParser, fieldsSize), encodedFields => {
320
316
  let previousFieldIndex = 0;
321
317
  return encodedFields.map(({ fieldIndexDiff, accessFlags }) => {
322
318
  previousFieldIndex += fieldIndexDiff;
@@ -328,14 +324,14 @@ const createEncodedFieldsParser = (fieldsSize) => promiseCompose(createQuantifie
328
324
  });
329
325
  const encodedMethodParser = promiseCompose(createTupleParser([
330
326
  uleb128NumberParser,
331
- uleb128AccessFlagsParser,
327
+ uleb128MethodAccessFlagsParser,
332
328
  uleb128NumberParser,
333
329
  ]), ([methodIndexDiff, accessFlags, codeOffset,]) => ({
334
330
  methodIndexDiff,
335
331
  accessFlags,
336
332
  codeOffset: isoOffsetToCodeItem.wrap(codeOffset),
337
333
  }));
338
- const createEncodedMethodsParser = (methodsSize) => promiseCompose(createQuantifierParser(encodedMethodParser, methodsSize), (encodedMethods) => {
334
+ const createEncodedMethodsParser = (methodsSize) => promiseCompose(createQuantifierParser(encodedMethodParser, methodsSize), encodedMethods => {
339
335
  let previousMethodIndex = 0;
340
336
  return encodedMethods.map(({ methodIndexDiff, accessFlags, codeOffset }) => {
341
337
  previousMethodIndex += methodIndexDiff;
@@ -372,326 +368,374 @@ const createSkipToThenClassDataItemsParser = (sizeOffset) => createSkipToThenIte
372
368
  const createByteWith5LeastSignificantBitsEqualParser = (leastSignificant5) => {
373
369
  const byteWith5LeastSignificantBitsEqualParser = async (parserContext) => {
374
370
  const byte = await parserContext.read(0);
375
- parserContext.invariant((byte & 0b00011111) === leastSignificant5, 'Expected byte with 5 least significant bits equal to %s, but got %s', leastSignificant5.toString(2).padStart(8, '0'), byte.toString(2).padStart(8, '0'));
371
+ parserContext.invariant((byte & 0b0001_1111) === leastSignificant5, 'Expected byte with 5 least significant bits equal to %s, but got %s', leastSignificant5.toString(2).padStart(8, '0'), byte.toString(2).padStart(8, '0'));
376
372
  return byte;
377
373
  };
378
374
  setParserName(byteWith5LeastSignificantBitsEqualParser, `createByteWith5LeastSignificantBitsEqualParser(${leastSignificant5.toString(2).padStart(5, '0')})`);
379
375
  return byteWith5LeastSignificantBitsEqualParser;
380
376
  };
381
- const createEncodedValueArgParser = (valueType) => promiseCompose(createByteWith5LeastSignificantBitsEqualParser(valueType), (byte) => byte >> 5);
377
+ const createEncodedValueArgParser = (valueType) => promiseCompose(createByteWith5LeastSignificantBitsEqualParser(valueType), byte => byte >> 5);
382
378
  const encodedValueByteParser = promiseCompose(createTupleParser([
383
379
  createExactElementParser(0),
384
- ubyteParser,
385
- ]), ([_, value]) => value);
380
+ byteParser,
381
+ ]), ([_, value]) => ({ type: 'byte', value }));
386
382
  setParserName(encodedValueByteParser, 'encodedValueByteParser');
387
383
  const encodedValueShortParser = parserCreatorCompose(() => createEncodedValueArgParser(0x02), sizeSubOne => {
388
384
  const size = sizeSubOne + 1;
389
385
  if (size === 1) {
390
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
386
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
391
387
  const buffer = Buffer.from(uint8Array);
392
- return buffer.readInt8(0);
388
+ return { type: 'short', value: buffer.readInt8(0) };
393
389
  });
394
390
  }
395
391
  invariant(size === 2, '(encodedValueShortParser) Unexpected size: %s', size);
396
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
392
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
397
393
  const buffer = Buffer.from(uint8Array);
398
- return buffer.readInt16LE(0);
394
+ return { type: 'short', value: buffer.readInt16LE(0) };
399
395
  });
400
396
  })();
401
397
  setParserName(encodedValueShortParser, 'encodedValueShortParser');
402
398
  const encodedValueCharParser = parserCreatorCompose(() => createEncodedValueArgParser(0x03), sizeSubOne => {
403
399
  const size = sizeSubOne + 1;
404
400
  if (size == 1) {
405
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
406
- const buffer = Buffer.from([0, ...uint8Array]);
407
- return buffer.readUInt16LE(0);
401
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
402
+ const buffer = Buffer.from([...uint8Array, 0]);
403
+ return { type: 'char', value: buffer.readUInt16LE(0) };
408
404
  });
409
405
  }
410
406
  invariant(size === 2, '(encodedValueCharParser) Unexpected size: %s', size);
411
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
407
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
412
408
  const buffer = Buffer.from(uint8Array);
413
- return buffer.readUInt16LE(0);
409
+ return { type: 'char', value: buffer.readUInt16LE(0) };
414
410
  });
415
411
  })();
416
412
  setParserName(encodedValueCharParser, 'encodedValueCharParser');
417
413
  const encodedValueIntParser = parserCreatorCompose(() => createEncodedValueArgParser(0x04), sizeSubOne => {
418
414
  const size = sizeSubOne + 1;
419
415
  if (size === 1) {
420
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
416
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
421
417
  const buffer = Buffer.from(uint8Array);
422
- return buffer.readInt8(0);
418
+ return { type: 'int', value: buffer.readInt8(0) };
423
419
  });
424
420
  }
425
421
  if (size === 2) {
426
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
422
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
427
423
  const buffer = Buffer.from(uint8Array);
428
- return buffer.readInt16LE(0);
424
+ return { type: 'int', value: buffer.readInt16LE(0) };
429
425
  });
430
426
  }
431
427
  if (size === 3) {
432
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
433
- const firstByte = uint8Array[0];
434
- const firstBit = (firstByte & 0b10000000) >> 7;
435
- const extensionByte = firstBit === 1 ? 0xff : 0x00;
436
- const buffer = Buffer.from([extensionByte, ...uint8Array]);
437
- return buffer.readInt32LE(0);
428
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
429
+ const lastByte = uint8Array[uint8Array.length - 1];
430
+ const signBit = (lastByte & 0b1000_0000) >> 7;
431
+ const extensionByte = signBit === 1 ? 0xFF : 0x00;
432
+ const buffer = Buffer.from([...uint8Array, extensionByte]);
433
+ return { type: 'int', value: buffer.readInt32LE(0) };
438
434
  });
439
435
  }
440
436
  invariant(size === 4, '(encodedValueIntParser) Unexpected size: %s', size);
441
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
437
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
442
438
  const buffer = Buffer.from(uint8Array);
443
- return buffer.readInt32LE(0);
439
+ return { type: 'int', value: buffer.readInt32LE(0) };
444
440
  });
445
441
  })();
446
442
  setParserName(encodedValueIntParser, 'encodedValueIntParser');
447
443
  const encodedValueLongParser = parserCreatorCompose(() => createEncodedValueArgParser(0x06), sizeSubOne => {
448
444
  const size = sizeSubOne + 1;
449
445
  if (size === 1) {
450
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
446
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
451
447
  const buffer = Buffer.from(uint8Array);
452
- return BigInt(buffer.readInt8(0));
448
+ return { type: 'long', value: BigInt(buffer.readInt8(0)) };
453
449
  });
454
450
  }
455
451
  if (size === 2) {
456
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
452
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
457
453
  const buffer = Buffer.from(uint8Array);
458
- return BigInt(buffer.readInt16LE(0));
454
+ return { type: 'long', value: BigInt(buffer.readInt16LE(0)) };
459
455
  });
460
456
  }
461
457
  if (size === 3) {
462
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
463
- const firstByte = uint8Array[0];
464
- const firstBit = (firstByte & 0b10000000) >> 7;
465
- const extensionByte = firstBit === 1 ? 0xff : 0x00;
466
- const buffer = Buffer.from([extensionByte, ...uint8Array]);
467
- return BigInt(buffer.readInt32LE(0));
458
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
459
+ const lastByte = uint8Array[size - 1];
460
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
461
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
462
+ const buffer = Buffer.from([...uint8Array, extensionByte]);
463
+ return { type: 'long', value: BigInt(buffer.readInt32LE(0)) };
468
464
  });
469
465
  }
470
466
  if (size === 4) {
471
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
467
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
472
468
  const buffer = Buffer.from(uint8Array);
473
- return BigInt(buffer.readInt32LE(0));
469
+ return { type: 'long', value: BigInt(buffer.readInt32LE(0)) };
474
470
  });
475
471
  }
476
472
  if (size === 5) {
477
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
478
- const firstByte = uint8Array[0];
479
- const firstBit = (firstByte & 0b10000000) >> 7;
480
- const extensionByte = firstBit === 1 ? 0xff : 0x00;
481
- const buffer = Buffer.from([extensionByte, extensionByte, extensionByte, ...uint8Array]);
482
- return BigInt(buffer.readBigInt64LE(0));
473
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
474
+ const lastByte = uint8Array[size - 1];
475
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
476
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
477
+ const buffer = Buffer.from([...uint8Array, extensionByte, extensionByte, extensionByte]);
478
+ return { type: 'long', value: BigInt(buffer.readBigInt64LE(0)) };
479
+ });
480
+ }
481
+ if (size === 6) {
482
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
483
+ const lastByte = uint8Array[size - 1];
484
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
485
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
486
+ const buffer = Buffer.from([...uint8Array, extensionByte, extensionByte]);
487
+ return { type: 'long', value: BigInt(buffer.readBigInt64LE(0)) };
488
+ });
489
+ }
490
+ if (size === 7) {
491
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
492
+ const lastByte = uint8Array[size - 1];
493
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
494
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
495
+ const buffer = Buffer.from([...uint8Array, extensionByte]);
496
+ return { type: 'long', value: BigInt(buffer.readBigInt64LE(0)) };
483
497
  });
484
498
  }
485
499
  invariant(size === 8, '(encodedValueLongParser) Unexpected size: %s', size);
486
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
500
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
487
501
  const buffer = Buffer.from(uint8Array);
488
- return buffer.readBigInt64LE(0);
502
+ return { type: 'long', value: buffer.readBigInt64LE(0) };
489
503
  });
490
504
  })();
491
505
  setParserName(encodedValueLongParser, 'encodedValueLongParser');
492
506
  const encodedValueFloatParser = parserCreatorCompose(() => createEncodedValueArgParser(0x10), sizeSubOne => {
493
507
  const size = sizeSubOne + 1;
494
508
  if (size === 1) {
495
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
496
- const buffer = Buffer.from([...uint8Array, 0, 0, 0]);
497
- return buffer.readFloatLE(0);
509
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
510
+ const buffer = Buffer.from([0, 0, 0, ...uint8Array]);
511
+ return { type: 'float', value: buffer.readFloatLE(0) };
498
512
  });
499
513
  }
500
514
  if (size === 2) {
501
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
502
- const buffer = Buffer.from([...uint8Array, 0, 0]);
503
- return buffer.readFloatLE(0);
515
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
516
+ const buffer = Buffer.from([0, 0, ...uint8Array]);
517
+ return { type: 'float', value: buffer.readFloatLE(0) };
518
+ });
519
+ }
520
+ if (size === 3) {
521
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
522
+ const buffer = Buffer.from([0, ...uint8Array]);
523
+ return { type: 'float', value: buffer.readFloatLE(0) };
504
524
  });
505
525
  }
506
526
  invariant(size === 4, '(encodedValueFloatParser) Unexpected size: %s', size);
507
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
527
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
508
528
  const buffer = Buffer.from(uint8Array);
509
- return buffer.readFloatLE(0);
529
+ return { type: 'float', value: buffer.readFloatLE(0) };
510
530
  });
511
531
  })();
512
532
  setParserName(encodedValueFloatParser, 'encodedValueFloatParser');
513
533
  const encodedValueDoubleParser = parserCreatorCompose(() => createEncodedValueArgParser(0x11), sizeSubOne => {
514
534
  const size = sizeSubOne + 1;
515
535
  if (size === 1) {
516
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
517
- const buffer = Buffer.from([...uint8Array, 0, 0, 0, 0, 0, 0, 0]);
518
- return buffer.readDoubleLE(0);
536
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
537
+ const buffer = Buffer.from([0, 0, 0, 0, 0, 0, 0, ...uint8Array]);
538
+ return { type: 'double', value: buffer.readDoubleLE(0) };
519
539
  });
520
540
  }
521
541
  if (size === 2) {
522
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
523
- const buffer = Buffer.from([...uint8Array, 0, 0, 0, 0, 0, 0]);
524
- return buffer.readDoubleLE(0);
542
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
543
+ const buffer = Buffer.from([0, 0, 0, 0, 0, 0, ...uint8Array]);
544
+ return { type: 'double', value: buffer.readDoubleLE(0) };
545
+ });
546
+ }
547
+ if (size === 3) {
548
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
549
+ const buffer = Buffer.from([0, 0, 0, 0, 0, ...uint8Array]);
550
+ return { type: 'double', value: buffer.readDoubleLE(0) };
525
551
  });
526
552
  }
527
553
  if (size === 4) {
528
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
529
- const buffer = Buffer.from([...uint8Array, 0, 0, 0, 0]);
530
- return buffer.readDoubleLE(0);
554
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
555
+ const buffer = Buffer.from([0, 0, 0, 0, ...uint8Array]);
556
+ return { type: 'double', value: buffer.readDoubleLE(0) };
557
+ });
558
+ }
559
+ if (size === 5) {
560
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
561
+ const buffer = Buffer.from([0, 0, 0, ...uint8Array]);
562
+ return { type: 'double', value: buffer.readDoubleLE(0) };
563
+ });
564
+ }
565
+ if (size === 6) {
566
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
567
+ const buffer = Buffer.from([0, 0, ...uint8Array]);
568
+ return { type: 'double', value: buffer.readDoubleLE(0) };
569
+ });
570
+ }
571
+ if (size === 7) {
572
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
573
+ const buffer = Buffer.from([0, ...uint8Array]);
574
+ return { type: 'double', value: buffer.readDoubleLE(0) };
531
575
  });
532
576
  }
533
577
  invariant(size === 8, '(encodedValueDoubleParser) Unexpected size: %s', size);
534
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
578
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
535
579
  const buffer = Buffer.from(uint8Array);
536
- return buffer.readDoubleLE(0);
580
+ return { type: 'double', value: buffer.readDoubleLE(0) };
537
581
  });
538
582
  })();
539
583
  setParserName(encodedValueDoubleParser, 'encodedValueDoubleParser');
540
584
  const encodedValueMethodTypeParser = parserCreatorCompose(() => createEncodedValueArgParser(0x15), sizeSubOne => {
541
585
  const size = sizeSubOne + 1;
542
586
  if (size === 1) {
543
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
587
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
544
588
  const buffer = Buffer.from(uint8Array);
545
- return buffer.readUint8(0);
589
+ return { type: 'methodType', value: isoIndexIntoPrototypeIds.wrap(buffer.readUint8(0)) };
546
590
  });
547
591
  }
548
592
  if (size === 2) {
549
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
593
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
550
594
  const buffer = Buffer.from(uint8Array);
551
- return buffer.readUInt16LE(0);
595
+ return { type: 'methodType', value: isoIndexIntoPrototypeIds.wrap(buffer.readUInt16LE(0)) };
552
596
  });
553
597
  }
554
598
  invariant(size === 4, '(encodedValueMethodTypeParser) Unexpected size: %s', size);
555
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
599
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
556
600
  const buffer = Buffer.from(uint8Array);
557
- return buffer.readUInt32LE(0);
601
+ return { type: 'methodType', value: isoIndexIntoPrototypeIds.wrap(buffer.readUInt32LE(0)) };
558
602
  });
559
603
  })();
560
604
  setParserName(encodedValueMethodTypeParser, 'encodedValueMethodTypeParser');
561
605
  const encodedValueMethodHandleParser = parserCreatorCompose(() => createEncodedValueArgParser(0x16), sizeSubOne => {
562
606
  const size = sizeSubOne + 1;
563
607
  if (size === 1) {
564
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
608
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
565
609
  const buffer = Buffer.from(uint8Array);
566
- return buffer.readUInt8(0);
610
+ return { type: 'methodHandle', value: buffer.readUInt8(0) };
567
611
  });
568
612
  }
569
613
  if (size === 2) {
570
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
614
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
571
615
  const buffer = Buffer.from(uint8Array);
572
- return buffer.readUInt16LE(0);
616
+ return { type: 'methodHandle', value: buffer.readUInt16LE(0) };
573
617
  });
574
618
  }
575
619
  invariant(size === 4, '(encodedValueMethodHandleParser) Unexpected size: %s', size);
576
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
620
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
577
621
  const buffer = Buffer.from(uint8Array);
578
- return buffer.readUInt32LE(0);
622
+ return { type: 'methodHandle', value: buffer.readUInt32LE(0) };
579
623
  });
580
624
  })();
581
625
  setParserName(encodedValueMethodHandleParser, 'encodedValueMethodHandleParser');
582
626
  const encodedValueStringParser = parserCreatorCompose(() => createEncodedValueArgParser(0x17), sizeSubOne => {
583
627
  const size = sizeSubOne + 1;
584
628
  if (size === 1) {
585
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
629
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
586
630
  const buffer = Buffer.from(uint8Array);
587
- return buffer.readUInt8(0);
631
+ return { type: 'string', value: isoIndexIntoStringIds.wrap(buffer.readUInt8(0)) };
588
632
  });
589
633
  }
590
634
  if (size === 2) {
591
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
635
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
592
636
  const buffer = Buffer.from(uint8Array);
593
- return buffer.readUInt16LE(0);
637
+ return { type: 'string', value: isoIndexIntoStringIds.wrap(buffer.readUInt16LE(0)) };
594
638
  });
595
639
  }
596
640
  invariant(size === 4, '(encodedValueStringParser) Unexpected size: %s', size);
597
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
641
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
598
642
  const buffer = Buffer.from(uint8Array);
599
- return buffer.readUInt32LE(0);
643
+ return { type: 'string', value: isoIndexIntoStringIds.wrap(buffer.readUInt32LE(0)) };
600
644
  });
601
645
  })();
602
646
  setParserName(encodedValueStringParser, 'encodedValueStringParser');
603
647
  const encodedValueTypeParser = parserCreatorCompose(() => createEncodedValueArgParser(0x18), sizeSubOne => {
604
648
  const size = sizeSubOne + 1;
605
649
  if (size === 1) {
606
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
650
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
607
651
  const buffer = Buffer.from(uint8Array);
608
- return buffer.readUInt8(0);
652
+ return { type: 'type', value: isoIndexIntoTypeIds.wrap(buffer.readUInt8(0)) };
609
653
  });
610
654
  }
611
655
  if (size === 2) {
612
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
656
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
613
657
  const buffer = Buffer.from(uint8Array);
614
- return buffer.readUInt16LE(0);
658
+ return { type: 'type', value: isoIndexIntoTypeIds.wrap(buffer.readUInt16LE(0)) };
615
659
  });
616
660
  }
617
661
  invariant(size === 4, '(encodedValueTypeParser) Unexpected size: %s', size);
618
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
662
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
619
663
  const buffer = Buffer.from(uint8Array);
620
- return buffer.readUInt32LE(0);
664
+ return { type: 'type', value: isoIndexIntoTypeIds.wrap(buffer.readUInt32LE(0)) };
621
665
  });
622
666
  })();
623
667
  setParserName(encodedValueTypeParser, 'encodedValueTypeParser');
624
668
  const encodedValueFieldParser = parserCreatorCompose(() => createEncodedValueArgParser(0x19), sizeSubOne => {
625
669
  const size = sizeSubOne + 1;
626
670
  if (size === 1) {
627
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
671
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
628
672
  const buffer = Buffer.from(uint8Array);
629
- return buffer.readUInt8(0);
673
+ return { type: 'field', value: isoIndexIntoFieldIds.wrap(buffer.readUInt8(0)) };
630
674
  });
631
675
  }
632
676
  if (size === 2) {
633
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
677
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
634
678
  const buffer = Buffer.from(uint8Array);
635
- return buffer.readUInt16LE(0);
679
+ return { type: 'field', value: isoIndexIntoFieldIds.wrap(buffer.readUInt16LE(0)) };
636
680
  });
637
681
  }
638
682
  invariant(size === 4, '(encodedValueFieldParser) Unexpected size: %s', size);
639
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
683
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
640
684
  const buffer = Buffer.from(uint8Array);
641
- return buffer.readUInt32LE(0);
685
+ return { type: 'field', value: isoIndexIntoFieldIds.wrap(buffer.readUInt32LE(0)) };
642
686
  });
643
687
  })();
644
688
  setParserName(encodedValueFieldParser, 'encodedValueFieldParser');
645
- const encodedValueMethodParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1a), sizeSubOne => {
689
+ const encodedValueMethodParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1A), sizeSubOne => {
646
690
  const size = sizeSubOne + 1;
647
691
  if (size === 1) {
648
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
692
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
649
693
  const buffer = Buffer.from(uint8Array);
650
- return buffer.readUInt8(0);
694
+ return { type: 'method', value: isoIndexIntoMethodIds.wrap(buffer.readUInt8(0)) };
651
695
  });
652
696
  }
653
697
  if (size === 2) {
654
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
698
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
655
699
  const buffer = Buffer.from(uint8Array);
656
- return buffer.readUInt16LE(0);
700
+ return { type: 'method', value: isoIndexIntoMethodIds.wrap(buffer.readUInt16LE(0)) };
657
701
  });
658
702
  }
659
703
  invariant(size === 4, '(encodedValueMethodParser) Unexpected size: %s', size);
660
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
704
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
661
705
  const buffer = Buffer.from(uint8Array);
662
- return buffer.readUInt32LE(0);
706
+ return { type: 'method', value: isoIndexIntoMethodIds.wrap(buffer.readUInt32LE(0)) };
663
707
  });
664
708
  })();
665
709
  setParserName(encodedValueMethodParser, 'encodedValueMethodParser');
666
- const encodedValueEnumParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1b), sizeSubOne => {
710
+ const encodedValueEnumParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1B), sizeSubOne => {
667
711
  const size = sizeSubOne + 1;
668
712
  if (size === 1) {
669
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
713
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
670
714
  const buffer = Buffer.from(uint8Array);
671
- return buffer.readUInt8(0);
715
+ return { type: 'enum', value: isoIndexIntoFieldIds.wrap(buffer.readUInt8(0)) };
672
716
  });
673
717
  }
674
718
  if (size === 2) {
675
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
719
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
676
720
  const buffer = Buffer.from(uint8Array);
677
- return buffer.readUInt16LE(0);
721
+ return { type: 'enum', value: isoIndexIntoFieldIds.wrap(buffer.readUInt16LE(0)) };
678
722
  });
679
723
  }
680
724
  invariant(size === 4, '(encodedValueEnumParser) Unexpected size: %s', size);
681
- return promiseCompose(createFixedLengthSequenceParser(size), (uint8Array) => {
725
+ return promiseCompose(createFixedLengthSequenceParser(size), uint8Array => {
682
726
  const buffer = Buffer.from(uint8Array);
683
- return buffer.readUInt32LE(0);
727
+ return { type: 'enum', value: isoIndexIntoFieldIds.wrap(buffer.readUInt32LE(0)) };
684
728
  });
685
729
  })();
686
730
  setParserName(encodedValueEnumParser, 'encodedValueEnumParser');
687
- const encodedArrayParser = parserCreatorCompose(() => uleb128NumberParser, (size) => createQuantifierParser(encodedValueParser, size))();
731
+ const encodedArrayParser = parserCreatorCompose(() => uleb128NumberParser, size => createQuantifierParser(encodedValueParser, size))();
688
732
  setParserName(encodedArrayParser, 'encodedArrayParser');
689
733
  const encodedValueArrayParser = promiseCompose(createTupleParser([
690
- parserCreatorCompose(() => createEncodedValueArgParser(0x1c), valueArg => parserContext => {
734
+ parserCreatorCompose(() => createEncodedValueArgParser(0x1C), valueArg => parserContext => {
691
735
  parserContext.invariant(valueArg === 0, '(encodedValueArrayParser) valueArg: %s', valueArg);
692
736
  })(),
693
737
  encodedArrayParser,
694
- ]), ([_, array]) => array);
738
+ ]), ([_, array]) => ({ type: 'array', value: array }));
695
739
  setParserName(encodedValueArrayParser, 'encodedValueArrayParser');
696
740
  const annotationElementParser = promiseCompose(createTupleParser([
697
741
  uleb128NumberParser,
@@ -713,18 +757,18 @@ const encodedAnnotationParser = promiseCompose(parserCreatorCompose(() => create
713
757
  }));
714
758
  setParserName(encodedAnnotationParser, 'encodedAnnotationParser');
715
759
  const encodedValueAnnotationParser = promiseCompose(createTupleParser([
716
- parserCreatorCompose(() => createEncodedValueArgParser(0x1d), valueArg => parserContext => {
760
+ parserCreatorCompose(() => createEncodedValueArgParser(0x1D), valueArg => parserContext => {
717
761
  parserContext.invariant(valueArg === 0, '(encodedValueAnnotationParser) valueArg: %s', valueArg);
718
762
  })(),
719
763
  encodedAnnotationParser,
720
- ]), ([_, annotation]) => annotation);
764
+ ]), ([_, annotation]) => ({ type: 'annotation', value: annotation }));
721
765
  setParserName(encodedValueAnnotationParser, 'encodedValueAnnotationParser');
722
- const encodedValueNullParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1e), valueArg => parserContext => {
766
+ const encodedValueNullParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1E), valueArg => parserContext => {
723
767
  parserContext.invariant(valueArg === 0, '(encodedValueNullParser) valueArg: %s', valueArg);
724
- return null;
768
+ return ({ type: 'null', value: null });
725
769
  })();
726
770
  setParserName(encodedValueNullParser, 'encodedValueNullParser');
727
- const encodedValueBooleanParser = promiseCompose(createEncodedValueArgParser(0x1f), (value) => Boolean(value));
771
+ const encodedValueBooleanParser = promiseCompose(createEncodedValueArgParser(0x1F), valueArg => ({ type: 'boolean', value: Boolean(valueArg) }));
728
772
  setParserName(encodedValueBooleanParser, 'encodedValueBooleanParser');
729
773
  const encodedValueParser = createDisjunctionParser([
730
774
  encodedValueByteParser,
@@ -794,32 +838,28 @@ const createDalvikExecutableCodeItemParser = ({ createInstructionsParser, }) =>
794
838
  ushortParser,
795
839
  uintParser,
796
840
  uintParser,
797
- ]), ([_, registersSize, insSize, outsSize, triesSize, debugInfoOffset, instructionsSize,]) => {
798
- return promiseCompose(createTupleParser([
799
- createInstructionsParser(instructionsSize * 2),
800
- ((triesSize !== 0
801
- && instructionsSize % 2 === 1)
802
- ? byteAlign4Parser
803
- : () => undefined),
804
- (triesSize !== 0
805
- ? createQuantifierParser(tryItemParser, triesSize)
806
- : () => []),
807
- (triesSize !== 0
808
- ? encodedCatchHandlerListParser
809
- : () => new Map()),
810
- ]), ([instructions, _padding, tryItems, handlers,]) => {
811
- return {
812
- registersSize,
813
- insSize,
814
- outsSize,
815
- triesSize,
816
- debugInfoOffset: isoOffsetToDebugInfoItem.wrap(debugInfoOffset),
817
- instructions,
818
- tryItems,
819
- handlers,
820
- };
821
- });
822
- })();
841
+ ]), ([_, registersSize, insSize, outsSize, triesSize, debugInfoOffset, instructionsSize,]) => promiseCompose(createTupleParser([
842
+ createInstructionsParser(instructionsSize * 2),
843
+ ((triesSize !== 0
844
+ && instructionsSize % 2 === 1)
845
+ ? byteAlign4Parser
846
+ : () => undefined),
847
+ (triesSize === 0
848
+ ? () => []
849
+ : createQuantifierParser(tryItemParser, triesSize)),
850
+ (triesSize === 0
851
+ ? () => new Map()
852
+ : encodedCatchHandlerListParser),
853
+ ]), ([instructions, _padding, tryItems, handlers,]) => ({
854
+ registersSize,
855
+ insSize,
856
+ outsSize,
857
+ triesSize,
858
+ debugInfoOffset: isoOffsetToDebugInfoItem.wrap(debugInfoOffset),
859
+ instructions,
860
+ tryItems,
861
+ handlers,
862
+ })))();
823
863
  setParserName(dalvikExecutableCodeItemParser, 'dalvikExecutableCodeItemParser');
824
864
  return dalvikExecutableCodeItemParser;
825
865
  };
@@ -834,39 +874,59 @@ const createSkipToThenCodeItemsParser = ({ sizeOffset, createInstructionsParser,
834
874
  });
835
875
  const dalvikExecutableDebugByteCodeValueParser = parserCreatorCompose(() => ubyteParser, (value) => {
836
876
  switch (value) {
837
- case 0x01: return promiseCompose(uleb128NumberParser, (addressDiff) => ({ type: 'advancePc', addressDiff }));
838
- case 0x02: return promiseCompose(sleb128NumberParser, (lineDiff) => ({ type: 'advanceLine', lineDiff }));
839
- case 0x03: return promiseCompose(createTupleParser([
840
- uleb128NumberParser,
841
- uleb128NumberParser,
842
- uleb128NumberParser,
843
- ]), ([registerNum, nameIndex, typeIndex]) => ({
844
- type: 'startLocal',
845
- registerNum,
846
- nameIndex: isoIndexIntoStringIds.wrap(nameIndex),
847
- typeIndex: isoIndexIntoTypeIds.wrap(typeIndex),
848
- }));
849
- case 0x04: return promiseCompose(createTupleParser([
850
- uleb128NumberParser,
851
- uleb128NumberParser,
852
- uleb128NumberParser,
853
- uleb128NumberParser,
854
- ]), ([registerNum, nameIndex, typeIndex, signatureIndex]) => ({
855
- type: 'startLocalExtended',
856
- registerNum,
857
- nameIndex: isoIndexIntoStringIds.wrap(nameIndex),
858
- typeIndex: isoIndexIntoTypeIds.wrap(typeIndex),
859
- signatureIndex: isoIndexIntoStringIds.wrap(signatureIndex),
860
- }));
861
- case 0x05: return promiseCompose(uleb128NumberParser, (registerNum) => ({ type: 'endLocal', registerNum }));
862
- case 0x06: return promiseCompose(uleb128NumberParser, (registerNum) => ({ type: 'restartLocal', registerNum }));
863
- case 0x07: return () => ({ type: 'setPrologueEnd' });
864
- case 0x08: return () => ({ type: 'setEpilogueBegin' });
865
- case 0x09: return promiseCompose(uleb128NumberParser, (nameIndex) => ({ type: 'setFile', nameIndex: isoIndexIntoStringIds.wrap(nameIndex) }));
866
- default: return parserContext => {
867
- parserContext.invariant(value >= 0x0a, 'Unexpected special value: %s', value);
868
- return { type: 'special', value };
869
- };
877
+ case 0x01: {
878
+ return promiseCompose(uleb128NumberParser, addressDiff => ({ type: 'advancePc', addressDiff }));
879
+ }
880
+ case 0x02: {
881
+ return promiseCompose(sleb128NumberParser, lineDiff => ({ type: 'advanceLine', lineDiff }));
882
+ }
883
+ case 0x03: {
884
+ return promiseCompose(createTupleParser([
885
+ uleb128NumberParser,
886
+ uleb128p1NumberParser,
887
+ uleb128p1NumberParser,
888
+ ]), ([registerNumber, nameIndex, typeIndex]) => ({
889
+ type: 'startLocal',
890
+ registerNum: registerNumber,
891
+ nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex),
892
+ typeIndex: typeIndex === -1 ? undefined : isoIndexIntoTypeIds.wrap(typeIndex),
893
+ }));
894
+ }
895
+ case 0x04: {
896
+ return promiseCompose(createTupleParser([
897
+ uleb128NumberParser,
898
+ uleb128p1NumberParser,
899
+ uleb128p1NumberParser,
900
+ uleb128p1NumberParser,
901
+ ]), ([registerNumber, nameIndex, typeIndex, signatureIndex]) => ({
902
+ type: 'startLocalExtended',
903
+ registerNum: registerNumber,
904
+ nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex),
905
+ typeIndex: typeIndex === -1 ? undefined : isoIndexIntoTypeIds.wrap(typeIndex),
906
+ signatureIndex: signatureIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(signatureIndex),
907
+ }));
908
+ }
909
+ case 0x05: {
910
+ return promiseCompose(uleb128NumberParser, registerNumber => ({ type: 'endLocal', registerNum: registerNumber }));
911
+ }
912
+ case 0x06: {
913
+ return promiseCompose(uleb128NumberParser, registerNumber => ({ type: 'restartLocal', registerNum: registerNumber }));
914
+ }
915
+ case 0x07: {
916
+ return () => ({ type: 'setPrologueEnd' });
917
+ }
918
+ case 0x08: {
919
+ return () => ({ type: 'setEpilogueBegin' });
920
+ }
921
+ case 0x09: {
922
+ return promiseCompose(uleb128p1NumberParser, nameIndex => ({ type: 'setFile', nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex) }));
923
+ }
924
+ default: {
925
+ return parserContext => {
926
+ parserContext.invariant(value >= 0x0A, 'Unexpected special value: %s', value);
927
+ return { type: 'special', value };
928
+ };
929
+ }
870
930
  }
871
931
  })();
872
932
  setParserName(dalvikExecutableDebugByteCodeValueParser, 'dalvikExecutableDebugByteCodeValueParser');
@@ -892,12 +952,20 @@ const createSkipToThenDebugInfoItemsParser = (sizeOffset) => createSkipToThenIte
892
952
  isoOffset: isoOffsetToDebugInfoItem,
893
953
  parserName: 'skipToThenDebugInfoItemsParser',
894
954
  });
895
- const dalvikExecutableAnnotationItemVisibilityParser = promiseCompose(ubyteParser, (visibility) => {
955
+ const dalvikExecutableAnnotationItemVisibilityParser = promiseCompose(ubyteParser, visibility => {
896
956
  switch (visibility) {
897
- case 0x00: return 'build';
898
- case 0x01: return 'runtime';
899
- case 0x02: return 'system';
900
- default: invariant(false, 'Unexpected visibility: %s', visibility);
957
+ case 0x00: {
958
+ return 'build';
959
+ }
960
+ case 0x01: {
961
+ return 'runtime';
962
+ }
963
+ case 0x02: {
964
+ return 'system';
965
+ }
966
+ default: {
967
+ invariant(false, 'Unexpected visibility: %s', visibility);
968
+ }
901
969
  }
902
970
  });
903
971
  setParserName(dalvikExecutableAnnotationItemVisibilityParser, 'dalvikExecutableAnnotationItemVisibilityParser');
@@ -913,14 +981,14 @@ const createSkipToThenAnnotationItemsParser = (sizeOffset) => createSkipToThenIt
913
981
  isoOffset: isoOffsetToAnnotationItem,
914
982
  parserName: 'skipToThenAnnotationItemsParser',
915
983
  });
916
- const dalvikExecutableHeaderAndMapParser = parserCreatorCompose(() => dalvikExecutableHeaderItemParser, (headerItem) => promiseCompose(createLookaheadParser(createDalvikExecutableMapListParser(headerItem.mapOffset)), (mapList) => ({ headerItem, mapList })))();
917
- const dalvikExecutableAnnotationOffsetItemParser = promiseCompose(uintParser, (annotationOffset) => ({
984
+ const dalvikExecutableHeaderAndMapParser = parserCreatorCompose(() => dalvikExecutableHeaderItemParser, headerItem => promiseCompose(createLookaheadParser(createDalvikExecutableMapListParser(headerItem.mapOffset)), mapList => ({ headerItem, mapList })))();
985
+ const dalvikExecutableAnnotationOffsetItemParser = promiseCompose(uintParser, annotationOffset => ({
918
986
  annotationOffset: isoOffsetToAnnotationItem.wrap(annotationOffset),
919
987
  }));
920
988
  const dalvikExecutableAnnotationSetItemParser = parserCreatorCompose(() => createTupleParser([
921
989
  byteAlign4Parser,
922
990
  uintParser,
923
- ]), ([_, size]) => promiseCompose(createQuantifierParser(dalvikExecutableAnnotationOffsetItemParser, size), (entries) => ({ entries })))();
991
+ ]), ([_, size]) => promiseCompose(createQuantifierParser(dalvikExecutableAnnotationOffsetItemParser, size), entries => ({ entries })))();
924
992
  const createSkipToThenAnnotationSetItemsParser = (sizeOffset) => createSkipToThenItemByOffsetParser({
925
993
  sizeOffset,
926
994
  itemParser: dalvikExecutableAnnotationSetItemParser,
@@ -928,11 +996,11 @@ const createSkipToThenAnnotationSetItemsParser = (sizeOffset) => createSkipToThe
928
996
  isoOffset: isoOffsetToAnnotationSetItem,
929
997
  parserName: 'skipToThenAnnotationSetItemsParser',
930
998
  });
931
- const dalvikExecutableAnnotationSetRefItemParser = promiseCompose(uintParser, (annotationsOffset) => isoOffsetToAnnotationSetItem.wrap(annotationsOffset));
999
+ const dalvikExecutableAnnotationSetRefItemParser = promiseCompose(uintParser, annotationsOffset => isoOffsetToAnnotationSetItem.wrap(annotationsOffset));
932
1000
  const dalvikExecutableAnnotationSetRefListParser = parserCreatorCompose(() => createTupleParser([
933
1001
  byteAlign4Parser,
934
1002
  uintParser,
935
- ]), ([_, size]) => promiseCompose(createQuantifierParser(dalvikExecutableAnnotationSetRefItemParser, size), (list) => ({ list })))();
1003
+ ]), ([_, size]) => promiseCompose(createQuantifierParser(dalvikExecutableAnnotationSetRefItemParser, size), list => ({ list })))();
936
1004
  const createSkipToThenAnnotationSetRefListsParser = (sizeOffset) => createSkipToThenItemByOffsetParser({
937
1005
  sizeOffset,
938
1006
  itemParser: dalvikExecutableAnnotationSetRefListParser,
@@ -940,30 +1008,74 @@ const createSkipToThenAnnotationSetRefListsParser = (sizeOffset) => createSkipTo
940
1008
  isoOffset: isoOffsetToAnnotationSetRefListItem,
941
1009
  parserName: 'skipToThenAnnotationSetRefListsParser',
942
1010
  });
943
- const dalvikExecutableMapItemTypeParser = promiseCompose(ushortParser, (type) => {
1011
+ const dalvikExecutableMapItemTypeParser = promiseCompose(ushortParser, type => {
944
1012
  switch (type) {
945
- case 0x0000: return 'headerItem';
946
- case 0x0001: return 'stringIdItem';
947
- case 0x0002: return 'typeIdItem';
948
- case 0x0003: return 'prototypeIdItem';
949
- case 0x0004: return 'fieldIdItem';
950
- case 0x0005: return 'methodIdItem';
951
- case 0x0006: return 'classDefinitionItem';
952
- case 0x0007: return 'callSiteIdItem';
953
- case 0x0008: return 'methodHandleItem';
954
- case 0x1000: return 'mapList';
955
- case 0x1001: return 'typeList';
956
- case 0x1002: return 'annotationSetRefList';
957
- case 0x1003: return 'annotationSetItem';
958
- case 0x2000: return 'classDataItem';
959
- case 0x2001: return 'codeItem';
960
- case 0x2002: return 'stringDataItem';
961
- case 0x2003: return 'debugInfoItem';
962
- case 0x2004: return 'annotationItem';
963
- case 0x2005: return 'encodedArrayItem';
964
- case 0x2006: return 'annotationsDirectoryItem';
965
- case 0xF000: return 'hiddenApiClassDataItem';
966
- default: invariant(false, 'Unexpected map item type: %s', type);
1013
+ case 0x00_00: {
1014
+ return 'headerItem';
1015
+ }
1016
+ case 0x00_01: {
1017
+ return 'stringIdItem';
1018
+ }
1019
+ case 0x00_02: {
1020
+ return 'typeIdItem';
1021
+ }
1022
+ case 0x00_03: {
1023
+ return 'prototypeIdItem';
1024
+ }
1025
+ case 0x00_04: {
1026
+ return 'fieldIdItem';
1027
+ }
1028
+ case 0x00_05: {
1029
+ return 'methodIdItem';
1030
+ }
1031
+ case 0x00_06: {
1032
+ return 'classDefinitionItem';
1033
+ }
1034
+ case 0x00_07: {
1035
+ return 'callSiteIdItem';
1036
+ }
1037
+ case 0x00_08: {
1038
+ return 'methodHandleItem';
1039
+ }
1040
+ case 0x10_00: {
1041
+ return 'mapList';
1042
+ }
1043
+ case 0x10_01: {
1044
+ return 'typeList';
1045
+ }
1046
+ case 0x10_02: {
1047
+ return 'annotationSetRefList';
1048
+ }
1049
+ case 0x10_03: {
1050
+ return 'annotationSetItem';
1051
+ }
1052
+ case 0x20_00: {
1053
+ return 'classDataItem';
1054
+ }
1055
+ case 0x20_01: {
1056
+ return 'codeItem';
1057
+ }
1058
+ case 0x20_02: {
1059
+ return 'stringDataItem';
1060
+ }
1061
+ case 0x20_03: {
1062
+ return 'debugInfoItem';
1063
+ }
1064
+ case 0x20_04: {
1065
+ return 'annotationItem';
1066
+ }
1067
+ case 0x20_05: {
1068
+ return 'encodedArrayItem';
1069
+ }
1070
+ case 0x20_06: {
1071
+ return 'annotationsDirectoryItem';
1072
+ }
1073
+ case 0xF0_00: {
1074
+ return 'hiddenApiClassDataItem';
1075
+ }
1076
+ default: {
1077
+ invariant(false, 'Unexpected map item type: %s', type);
1078
+ }
967
1079
  }
968
1080
  });
969
1081
  const dalvikExecutableMapItemParser = promiseCompose(createTupleParser([
@@ -972,9 +1084,7 @@ const dalvikExecutableMapItemParser = promiseCompose(createTupleParser([
972
1084
  uintParser,
973
1085
  uintParser,
974
1086
  ]), ([type, _unused, size, offset]) => ({ type, size, offset }));
975
- const dalvikExecutableMapListParser = parserCreatorCompose(() => uintParser, size => {
976
- return createQuantifierParser(dalvikExecutableMapItemParser, size);
977
- })();
1087
+ const dalvikExecutableMapListParser = parserCreatorCompose(() => uintParser, size => createQuantifierParser(dalvikExecutableMapItemParser, size))();
978
1088
  setParserName(dalvikExecutableMapListParser, 'dalvikExecutableMapListParser');
979
1089
  const createDalvikExecutableMapListParser = (mapOffset) => {
980
1090
  const dalvikExecutableMapParser = promiseCompose(createTupleParser([
@@ -999,8 +1109,8 @@ const createDalvikExecutableDataParser = ({ headerItem, mapList, createInstructi
999
1109
  let fieldIdItems = isoDalvikExecutableFieldIdItems.wrap([]);
1000
1110
  let methodIdItems = isoDalvikExecutableMethodIdItems.wrap([]);
1001
1111
  let classDefinitionItems = [];
1002
- let callSiteIdItems = [];
1003
- let methodHandleItems = [];
1112
+ const callSiteIdItems = [];
1113
+ const methodHandleItems = [];
1004
1114
  let typeListByOffset = new Map();
1005
1115
  let annotationSetRefListItemByOffset = new Map();
1006
1116
  let annotationSetItemByOffset = new Map();
@@ -1011,8 +1121,17 @@ const createDalvikExecutableDataParser = ({ headerItem, mapList, createInstructi
1011
1121
  let annotationItemByOffset = new Map();
1012
1122
  let encodedArrayItemByOffset = new Map();
1013
1123
  let annotationsDirectoryItemByOffset = new Map();
1014
- let hiddenApiClassDataItems = [];
1124
+ const hiddenApiClassDataItems = [];
1125
+ // Track if link has been parsed
1126
+ let link = undefined;
1127
+ let linkParsed = false;
1015
1128
  for (const dexMapItem of mapList) {
1129
+ // Parse link data before any map item that comes after it in the file
1130
+ // Link data is not included in the map items, but is referenced in the header
1131
+ if (!linkParsed && headerItem.link.size > 0 && headerItem.link.offset < dexMapItem.offset) {
1132
+ link = await createRawDataParser(headerItem.link)(parserContext);
1133
+ linkParsed = true;
1134
+ }
1016
1135
  if (dexMapItem.type === 'headerItem') {
1017
1136
  continue;
1018
1137
  }
@@ -1047,6 +1166,7 @@ const createDalvikExecutableDataParser = ({ headerItem, mapList, createInstructi
1047
1166
  // TODO
1048
1167
  }
1049
1168
  if (dexMapItem.type === 'mapList') {
1169
+ // Re-parse the map itself to consume it from the input
1050
1170
  await createDalvikExecutableMapListParser(dexMapItem.offset)(parserContext);
1051
1171
  continue;
1052
1172
  }
@@ -1098,6 +1218,11 @@ const createDalvikExecutableDataParser = ({ headerItem, mapList, createInstructi
1098
1218
  }
1099
1219
  invariant(false, 'Unexpected map item type: %s', dexMapItem.type);
1100
1220
  }
1221
+ // Parse link data after the loop if it hasn't been parsed yet
1222
+ // This handles the case where link comes after all map items
1223
+ if (!linkParsed && headerItem.link.size > 0) {
1224
+ link = await createRawDataParser(headerItem.link)(parserContext);
1225
+ }
1101
1226
  return {
1102
1227
  headerItem,
1103
1228
  stringIdItems,
@@ -1120,31 +1245,29 @@ const createDalvikExecutableDataParser = ({ headerItem, mapList, createInstructi
1120
1245
  encodedArrayItemByOffset,
1121
1246
  annotationsDirectoryItemByOffset,
1122
1247
  hiddenApiClassDataItems,
1248
+ link,
1123
1249
  };
1124
1250
  };
1125
1251
  setParserName(dalvikExecutableDataParser, 'dalvikExecutableDataParser');
1126
1252
  return dalvikExecutableDataParser;
1127
1253
  };
1128
- const createDalvikExecutableParser = ({ createInstructionsParser, }) => parserCreatorCompose(() => dalvikExecutableHeaderAndMapParser, ({ headerItem, mapList, }) => promiseCompose(createTupleParser([
1129
- createDalvikExecutableDataParser({
1130
- headerItem,
1131
- mapList,
1132
- createInstructionsParser,
1133
- }),
1134
- createRawDataParser(headerItem.link),
1135
- ]), async ([{ headerItem: _headerItem, stringIdItems, typeIdItems, prototypeIdItems, fieldIdItems, methodIdItems, classDefinitionItems,
1136
- // callSiteIdItems,
1254
+ const createDalvikExecutableParser = ({ createInstructionsParser, }) => parserCreatorCompose(() => dalvikExecutableHeaderAndMapParser, ({ headerItem, mapList, }) => promiseCompose(createDalvikExecutableDataParser({
1255
+ headerItem,
1256
+ mapList,
1257
+ createInstructionsParser,
1258
+ }), async ({ headerItem: _headerItem, stringIdItems, typeIdItems, prototypeIdItems, fieldIdItems, methodIdItems, classDefinitionItems,
1259
+ // CallSiteIdItems,
1137
1260
  // methodHandleItems,
1138
- mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotationSetItemByOffset, classDataItemByOffset, codeItemByOffset, stringDataItemStringByOffset, debugInfoItemByOffset, annotationItemByOffset, encodedArrayItemByOffset, annotationsDirectoryItemByOffset,
1139
- // hiddenApiClassDataItems,
1140
- }, link,]) => {
1141
- const strings = stringIdItems.map((stringId) => {
1261
+ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotationSetItemByOffset, classDataItemByOffset, codeItemByOffset, stringDataItemStringByOffset, debugInfoItemByOffset, annotationItemByOffset, encodedArrayItemByOffset, annotationsDirectoryItemByOffset,
1262
+ // HiddenApiClassDataItems,
1263
+ link, }) => {
1264
+ const strings = stringIdItems.map(stringId => {
1142
1265
  const stringOffset = stringId;
1143
1266
  const string = stringDataItemStringByOffset.get(stringOffset);
1144
1267
  invariant(string !== undefined, 'String must be there. String offset: %s', stringOffset);
1145
1268
  return string;
1146
1269
  });
1147
- const types = typeIdItems.map((typeId) => {
1270
+ const types = typeIdItems.map(typeId => {
1148
1271
  const type = strings.at(typeId);
1149
1272
  invariant(type, 'Type string must be there. Type id: %s', typeId);
1150
1273
  return type;
@@ -1153,14 +1276,14 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1153
1276
  [isoOffsetToTypeList.wrap(0), []],
1154
1277
  ]);
1155
1278
  for (const [offset, typeIndexes] of typeListByOffset) {
1156
- const typeNames = isoDalvikExecutableTypeList.unwrap(typeIndexes).map((typeIndex) => {
1279
+ const typeNames = isoDalvikExecutableTypeList.unwrap(typeIndexes).map(typeIndex => {
1157
1280
  const type = types.at(typeIndex);
1158
1281
  invariant(type, 'Type must be there. Type id: %s', typeIndex);
1159
1282
  return type;
1160
1283
  });
1161
1284
  resolvedTypeListByOffset.set(offset, typeNames);
1162
1285
  }
1163
- const prototypes = prototypeIdItems.map((prototypeId) => {
1286
+ const prototypes = prototypeIdItems.map(prototypeId => {
1164
1287
  const shorty = strings.at(prototypeId.shortyIndex);
1165
1288
  invariant(shorty, 'Shorty must be there. Shorty id: %s', prototypeId.shortyIndex);
1166
1289
  const returnType = types.at(prototypeId.returnTypeIndex);
@@ -1169,7 +1292,7 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1169
1292
  invariant(parameters !== undefined, 'Parameters must be there. Parameters offset: %s', prototypeId.parametersOffset);
1170
1293
  return { shorty, returnType, parameters };
1171
1294
  });
1172
- const fields = fieldIdItems.map((fieldId) => {
1295
+ const fields = fieldIdItems.map(fieldId => {
1173
1296
  const class_ = types.at(fieldId.classIndex);
1174
1297
  invariant(class_, 'Class must be there. Class id: %s', fieldId.classIndex);
1175
1298
  const type = types.at(fieldId.typeIndex);
@@ -1178,7 +1301,7 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1178
1301
  invariant(name, 'Name string must be there. String offset: %s', fieldId.nameIndex);
1179
1302
  return { class: class_, type, name };
1180
1303
  });
1181
- const methods = methodIdItems.map((methodId) => {
1304
+ const methods = methodIdItems.map(methodId => {
1182
1305
  const class_ = types.at(methodId.classIndex);
1183
1306
  invariant(class_, 'Class must be there. Class id: %s', methodId.classIndex);
1184
1307
  const prototype = prototypes.at(methodId.prototypeIndex);
@@ -1193,7 +1316,7 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1193
1316
  for (const [offset, debugInfoItem] of debugInfoItemByOffset) {
1194
1317
  debugInfoByOffset.set(offset, {
1195
1318
  lineStart: debugInfoItem.lineStart,
1196
- parameterNames: debugInfoItem.parameterNames.map((index) => {
1319
+ parameterNames: debugInfoItem.parameterNames.map(index => {
1197
1320
  if (index === undefined) {
1198
1321
  return undefined;
1199
1322
  }
@@ -1201,23 +1324,31 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1201
1324
  invariant(string !== undefined, 'String must be there. String id: %s', index);
1202
1325
  return string;
1203
1326
  }),
1204
- bytecode: debugInfoItem.bytecode.map((value) => {
1327
+ bytecode: debugInfoItem.bytecode.map(value => {
1205
1328
  switch (value.type) {
1206
- case 'startLocal': return {
1207
- type: 'startLocal',
1208
- registerNum: value.registerNum,
1209
- name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
1210
- type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
1211
- };
1212
- case 'startLocalExtended': return {
1213
- type: 'startLocalExtended',
1214
- registerNum: value.registerNum,
1215
- name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
1216
- type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
1217
- signature: value.signatureIndex === undefined ? undefined : strings.at(value.signatureIndex),
1218
- };
1219
- case 'setFile': return { type: 'setFile', name: strings.at(value.nameIndex) };
1220
- default: return value;
1329
+ case 'startLocal': {
1330
+ return {
1331
+ type: 'startLocal',
1332
+ registerNum: value.registerNum,
1333
+ name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
1334
+ type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
1335
+ };
1336
+ }
1337
+ case 'startLocalExtended': {
1338
+ return {
1339
+ type: 'startLocalExtended',
1340
+ registerNum: value.registerNum,
1341
+ name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
1342
+ type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
1343
+ signature: value.signatureIndex === undefined ? undefined : strings.at(value.signatureIndex),
1344
+ };
1345
+ }
1346
+ case 'setFile': {
1347
+ return { type: 'setFile', name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex) };
1348
+ }
1349
+ default: {
1350
+ return value;
1351
+ }
1221
1352
  }
1222
1353
  }),
1223
1354
  });
@@ -1231,14 +1362,13 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1231
1362
  registersSize: codeItem.registersSize,
1232
1363
  insSize: codeItem.insSize,
1233
1364
  outsSize: codeItem.outsSize,
1234
- debugInfo: debugInfo,
1365
+ debugInfo,
1235
1366
  instructions: codeItem.instructions,
1236
- tries: codeItem.tryItems.map((tryItem) => {
1367
+ tries: codeItem.tryItems.map(tryItem => {
1237
1368
  const handler_ = codeItem.handlers.get(tryItem.handlerOffset);
1238
1369
  invariant(handler_, 'Handler must be there. Handler offset: %s', tryItem.handlerOffset);
1239
1370
  const handler = {
1240
- ...handler_,
1241
- handlers: handler_.handlers.map((encodedHandler) => {
1371
+ handlers: handler_.handlers.map(encodedHandler => {
1242
1372
  const type = types.at(encodedHandler.typeIndex);
1243
1373
  invariant(type, 'Type must be there. Type id: %s', encodedHandler.typeIndex);
1244
1374
  return {
@@ -1246,6 +1376,7 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1246
1376
  address: encodedHandler.address,
1247
1377
  };
1248
1378
  }),
1379
+ catchAllAddress: handler_.catchAllAddress,
1249
1380
  };
1250
1381
  return {
1251
1382
  startAddress: tryItem.startAddress,
@@ -1261,22 +1392,22 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1261
1392
  const resolvers = {
1262
1393
  resolveIndexIntoStringIds(indexIntoStringIds) {
1263
1394
  const string = strings.at(indexIntoStringIds);
1264
- invariant(string, 'String must be there. String id: %s', indexIntoStringIds);
1395
+ invariant(string !== undefined, 'String must be there. String id: %s', indexIntoStringIds);
1265
1396
  return string;
1266
1397
  },
1267
1398
  resolveIndexIntoTypeIds(indexIntoTypeIds) {
1268
1399
  const type = types.at(indexIntoTypeIds);
1269
- invariant(type, 'Type must be there. Type id: %s', indexIntoTypeIds);
1400
+ invariant(type !== undefined, 'Type must be there. Type id: %s', indexIntoTypeIds);
1270
1401
  return type;
1271
1402
  },
1272
1403
  resolveIndexIntoMethodIds(indexIntoMethodIds) {
1273
1404
  const method = methods.at(indexIntoMethodIds);
1274
- invariant(method, 'Method must be there. Method id: %s', indexIntoMethodIds);
1405
+ invariant(method !== undefined, 'Method must be there. Method id: %s', indexIntoMethodIds);
1275
1406
  return method;
1276
1407
  },
1277
1408
  resolveIndexIntoFieldIds(indexIntoFieldIds) {
1278
1409
  const field = fields.at(indexIntoFieldIds);
1279
- invariant(field, 'Field must be there. Field id: %s', indexIntoFieldIds);
1410
+ invariant(field !== undefined, 'Field must be there. Field id: %s', indexIntoFieldIds);
1280
1411
  return field;
1281
1412
  },
1282
1413
  };
@@ -1290,14 +1421,12 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1290
1421
  }
1291
1422
  return {
1292
1423
  ...rest,
1293
- instructions: instructions.map((instruction) => {
1294
- return resolveDalvikBytecodeOperation(instruction, resolvers);
1295
- }),
1424
+ instructions: instructions.map((instruction) => resolveDalvikBytecodeOperation(instruction, resolvers)),
1296
1425
  };
1297
1426
  }
1298
1427
  for (const [offset, classDataItem] of classDataItemByOffset) {
1299
1428
  classDataByOffset.set(offset, {
1300
- staticFields: classDataItem.staticFields.map((encodedField) => {
1429
+ staticFields: classDataItem.staticFields.map(encodedField => {
1301
1430
  const field = fields.at(encodedField.fieldIndex);
1302
1431
  invariant(field, 'Field must be there. Field id: %s', encodedField.fieldIndex);
1303
1432
  return {
@@ -1305,7 +1434,7 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1305
1434
  accessFlags: encodedField.accessFlags,
1306
1435
  };
1307
1436
  }),
1308
- instanceFields: classDataItem.instanceFields.map((encodedField) => {
1437
+ instanceFields: classDataItem.instanceFields.map(encodedField => {
1309
1438
  const field = fields.at(encodedField.fieldIndex);
1310
1439
  invariant(field, 'Field must be there. Field id: %s', encodedField.fieldIndex);
1311
1440
  return {
@@ -1313,7 +1442,7 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1313
1442
  accessFlags: encodedField.accessFlags,
1314
1443
  };
1315
1444
  }),
1316
- directMethods: classDataItem.directMethods.map((method) => {
1445
+ directMethods: classDataItem.directMethods.map(method => {
1317
1446
  const method_ = methods.at(method.methodIndex);
1318
1447
  invariant(method_, 'Method must be there. Method id: %s', method.methodIndex);
1319
1448
  const code = codeByOffset.get(method.codeOffset);
@@ -1324,7 +1453,7 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1324
1453
  code: resolveCode(code),
1325
1454
  };
1326
1455
  }),
1327
- virtualMethods: classDataItem.virtualMethods.map((method) => {
1456
+ virtualMethods: classDataItem.virtualMethods.map(method => {
1328
1457
  const method_ = methods.at(method.methodIndex);
1329
1458
  invariant(method_, 'Method must be there. Method id: %s', method.methodIndex);
1330
1459
  const code = codeByOffset.get(method.codeOffset);
@@ -1337,17 +1466,155 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1337
1466
  }),
1338
1467
  });
1339
1468
  }
1469
+ // Resolve TaggedEncodedValue to DalvikExecutableEncodedValue for static values
1470
+ // Resolves internal index types to actual values while preserving type tags
1471
+ function resolveTaggedEncodedValueForStaticValues(taggedValue) {
1472
+ const { type, value } = taggedValue;
1473
+ // For primitive types, keep the type tag and value
1474
+ if (type === 'byte'
1475
+ || type === 'short'
1476
+ || type === 'char'
1477
+ || type === 'int'
1478
+ || type === 'float'
1479
+ || type === 'double'
1480
+ || type === 'long'
1481
+ || type === 'boolean'
1482
+ || type === 'null'
1483
+ || type === 'methodHandle') {
1484
+ return { type, value };
1485
+ }
1486
+ // For types that reference the pool, resolve the index to the actual value
1487
+ if (type === 'methodType') {
1488
+ const prototype = prototypes.at(value);
1489
+ invariant(prototype, 'Prototype must be there. Prototype id: %s', isoIndexIntoPrototypeIds.unwrap(value));
1490
+ return { type, value: prototype };
1491
+ }
1492
+ if (type === 'string') {
1493
+ const string = strings.at(value);
1494
+ invariant(string !== undefined, 'String must be there. String id: %s', isoIndexIntoStringIds.unwrap(value));
1495
+ return { type, value: string };
1496
+ }
1497
+ if (type === 'type') {
1498
+ const typeString = types.at(value);
1499
+ invariant(typeString !== undefined, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value));
1500
+ return { type, value: typeString };
1501
+ }
1502
+ if (type === 'field' || type === 'enum') {
1503
+ const field = fields.at(value);
1504
+ invariant(field, 'Field must be there. Field id: %s', isoIndexIntoFieldIds.unwrap(value));
1505
+ return { type, value: field };
1506
+ }
1507
+ if (type === 'method') {
1508
+ const method = methods.at(value);
1509
+ invariant(method, 'Method must be there. Method id: %s', isoIndexIntoMethodIds.unwrap(value));
1510
+ return { type, value: method };
1511
+ }
1512
+ if (type === 'array') {
1513
+ return { type, value: value.map(resolveTaggedEncodedValueForStaticValues) };
1514
+ }
1515
+ if (type === 'annotation') {
1516
+ // Resolve the encoded annotation
1517
+ const annotationType = types.at(value.typeIndex);
1518
+ invariant(annotationType, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value.typeIndex));
1519
+ const resolvedElements = value.elements.map(element => {
1520
+ const name = strings.at(element.nameIndex);
1521
+ invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
1522
+ return {
1523
+ name,
1524
+ value: resolveTaggedEncodedValueForAnnotations(element.value),
1525
+ };
1526
+ });
1527
+ const annotation = {
1528
+ visibility: 'build', // Default visibility for embedded annotations
1529
+ type: annotationType,
1530
+ elements: resolvedElements,
1531
+ };
1532
+ return { type, value: annotation };
1533
+ }
1534
+ // This should never happen
1535
+ throw new Error(`Unknown encoded value type: ${type}`);
1536
+ }
1537
+ // Resolve TaggedEncodedValue to DalvikExecutableEncodedValue for annotation elements
1538
+ // Resolves internal index types to actual values while preserving type tags
1539
+ function resolveTaggedEncodedValueForAnnotations(taggedValue) {
1540
+ const { type, value } = taggedValue;
1541
+ // For primitive types, keep the type tag and value
1542
+ if (type === 'byte'
1543
+ || type === 'short'
1544
+ || type === 'char'
1545
+ || type === 'int'
1546
+ || type === 'float'
1547
+ || type === 'double'
1548
+ || type === 'long'
1549
+ || type === 'boolean'
1550
+ || type === 'null'
1551
+ || type === 'methodHandle') {
1552
+ return { type, value };
1553
+ }
1554
+ // For types that reference the pool, resolve the index to the actual value
1555
+ if (type === 'methodType') {
1556
+ const prototype = prototypes.at(value);
1557
+ invariant(prototype, 'Prototype must be there. Prototype id: %s', isoIndexIntoPrototypeIds.unwrap(value));
1558
+ return { type, value: prototype };
1559
+ }
1560
+ if (type === 'string') {
1561
+ const string = strings.at(value);
1562
+ invariant(string !== undefined, 'String must be there. String id: %s', isoIndexIntoStringIds.unwrap(value));
1563
+ return { type, value: string };
1564
+ }
1565
+ if (type === 'type') {
1566
+ const typeString = types.at(value);
1567
+ invariant(typeString !== undefined, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value));
1568
+ return { type, value: typeString };
1569
+ }
1570
+ if (type === 'field' || type === 'enum') {
1571
+ const field = fields.at(value);
1572
+ invariant(field, 'Field must be there. Field id: %s', isoIndexIntoFieldIds.unwrap(value));
1573
+ return { type, value: field };
1574
+ }
1575
+ if (type === 'method') {
1576
+ const method = methods.at(value);
1577
+ invariant(method, 'Method must be there. Method id: %s', isoIndexIntoMethodIds.unwrap(value));
1578
+ return { type, value: method };
1579
+ }
1580
+ // For arrays, recursively resolve elements
1581
+ if (type === 'array') {
1582
+ return { type, value: value.map(resolveTaggedEncodedValueForAnnotations) };
1583
+ }
1584
+ // For annotations
1585
+ if (type === 'annotation') {
1586
+ // Resolve the encoded annotation (subannotation)
1587
+ const annotationType = types.at(value.typeIndex);
1588
+ invariant(annotationType, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value.typeIndex));
1589
+ const resolvedElements = value.elements.map(element => {
1590
+ const name = strings.at(element.nameIndex);
1591
+ invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
1592
+ return {
1593
+ name,
1594
+ value: resolveTaggedEncodedValueForAnnotations(element.value),
1595
+ };
1596
+ });
1597
+ const annotation = {
1598
+ visibility: 'build', // Default visibility for embedded annotations
1599
+ type: annotationType,
1600
+ elements: resolvedElements,
1601
+ };
1602
+ return { type, value: annotation };
1603
+ }
1604
+ // This should never happen
1605
+ throw new Error(`Unknown encoded value type: ${type}`);
1606
+ }
1340
1607
  function resolveAnnotationOffsetItem({ annotationOffset }) {
1341
1608
  const annotationItem = annotationItemByOffset.get(annotationOffset);
1342
1609
  invariant(annotationItem, 'Annotation must be there. Annotation offset: %s', annotationOffset);
1343
1610
  const type = types.at(annotationItem.encodedAnnotation.typeIndex);
1344
1611
  invariant(type, 'Type must be there. Type id: %s', annotationItem.encodedAnnotation.typeIndex);
1345
- const elements = annotationItem.encodedAnnotation.elements.map((element) => {
1612
+ const elements = annotationItem.encodedAnnotation.elements.map(element => {
1346
1613
  const name = strings.at(element.nameIndex);
1347
1614
  invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
1348
1615
  return {
1349
1616
  name,
1350
- value: element.value,
1617
+ value: resolveTaggedEncodedValueForAnnotations(element.value),
1351
1618
  };
1352
1619
  });
1353
1620
  return {
@@ -1357,9 +1624,16 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1357
1624
  };
1358
1625
  }
1359
1626
  function resolveAnnotationSetItem(annotationSetItem) {
1360
- return annotationSetItem?.entries.map(resolveAnnotationOffsetItem);
1627
+ if (!annotationSetItem) {
1628
+ return undefined;
1629
+ }
1630
+ const annotationSet = annotationSetItem.entries.map(resolveAnnotationOffsetItem);
1631
+ if (!annotationSet.length) {
1632
+ return [];
1633
+ }
1634
+ return annotationSet;
1361
1635
  }
1362
- const classDefinitions = classDefinitionItems.map((classDefinitionItem) => {
1636
+ const classDefinitions = classDefinitionItems.map(classDefinitionItem => {
1363
1637
  const class_ = types.at(classDefinitionItem.classIndex);
1364
1638
  invariant(class_, 'Class must be there. Class id: %s', classDefinitionItem.classIndex);
1365
1639
  const superclass = types.at(classDefinitionItem.superclassIndex);
@@ -1377,31 +1651,48 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1377
1651
  invariant(isoOffsetToAnnotationSetItem.unwrap(annotationsDirectoryItem.classAnnotationsOffset) === 0 || classAnnotationSetItem, 'Class annotations must be there. Class annotations offset: %s', annotationsDirectoryItem.classAnnotationsOffset);
1378
1652
  const classAnnotations = (classAnnotationSetItem
1379
1653
  ? resolveAnnotationSetItem(classAnnotationSetItem)
1380
- : undefined);
1381
- const fieldAnnotations = annotationsDirectoryItem.fieldAnnotations.map((fieldAnnotation) => {
1654
+ : undefined) ?? [];
1655
+ const fieldAnnotations = annotationsDirectoryItem.fieldAnnotations.flatMap(fieldAnnotation => {
1382
1656
  const field = fields.at(fieldAnnotation.fieldIndex);
1383
1657
  invariant(field, 'Field must be there. Field id: %s', fieldAnnotation.fieldIndex);
1384
- const annotations = annotationSetItemByOffset.get(fieldAnnotation.annotationsOffset);
1385
- invariant(isoOffsetToAnnotationSetItem.unwrap(fieldAnnotation.annotationsOffset) === 0 || annotations, 'Annotations must be there. Annotations offset: %s', fieldAnnotation.annotationsOffset);
1386
- return { field, annotations: annotations?.entries.map(resolveAnnotationOffsetItem) };
1658
+ const annotationSetItem = annotationSetItemByOffset.get(fieldAnnotation.annotationsOffset);
1659
+ invariant(isoOffsetToAnnotationSetItem.unwrap(fieldAnnotation.annotationsOffset) === 0 || annotationSetItem, 'Annotations must be there. Annotations offset: %s', fieldAnnotation.annotationsOffset);
1660
+ const annotations = resolveAnnotationSetItem(annotationSetItem);
1661
+ // Skip fields with no annotations (undefined or empty array)
1662
+ if (!annotations || annotations.length === 0) {
1663
+ return [];
1664
+ }
1665
+ return [{
1666
+ field,
1667
+ annotations,
1668
+ }];
1387
1669
  });
1388
- const methodAnnotations = annotationsDirectoryItem.methodAnnotations.map((methodAnnotation) => {
1670
+ const methodAnnotations = annotationsDirectoryItem.methodAnnotations.flatMap(methodAnnotation => {
1389
1671
  const method = methods.at(methodAnnotation.methodIndex);
1390
1672
  invariant(method, 'Method must be there. Method id: %s', methodAnnotation.methodIndex);
1391
1673
  const annotationSetItem = annotationSetItemByOffset.get(methodAnnotation.annotationsOffset);
1392
1674
  invariant(isoOffsetToAnnotationSetItem.unwrap(methodAnnotation.annotationsOffset) === 0 || annotationSetItem, 'Annotations must be there. Annotations offset: %s', methodAnnotation.annotationsOffset);
1393
- return { method, annotations: resolveAnnotationSetItem(annotationSetItem) };
1675
+ const annotations = resolveAnnotationSetItem(annotationSetItem) ?? [];
1676
+ // Skip methods with no annotations
1677
+ if (annotations.length === 0) {
1678
+ return [];
1679
+ }
1680
+ return [{
1681
+ method,
1682
+ annotations,
1683
+ }];
1394
1684
  });
1395
- const parameterAnnotations = annotationsDirectoryItem.parameterAnnotations.map((parameterAnnotation) => {
1685
+ const parameterAnnotations = annotationsDirectoryItem.parameterAnnotations.flatMap(parameterAnnotation => {
1396
1686
  const method = methods.at(parameterAnnotation.methodIndex);
1397
1687
  invariant(method, 'Method must be there. Method id: %s', parameterAnnotation.methodIndex);
1398
1688
  const annotationSetRefList = annotationSetRefListItemByOffset.get(parameterAnnotation.annotationsOffset);
1399
1689
  invariant(isoOffsetToAnnotationSetRefListItem.unwrap(parameterAnnotation.annotationsOffset) === 0 || annotationSetRefList, 'Annotations must be there. Annotations offset: %s', parameterAnnotation.annotationsOffset);
1400
- const annotations = annotationSetRefList?.list.map((annotationSetRefItem) => {
1690
+ const annotations = annotationSetRefList?.list.map(annotationSetRefItem => {
1401
1691
  const annotationSetItem = annotationSetItemByOffset.get(annotationSetRefItem);
1402
1692
  invariant(isoOffsetToAnnotationSetItem.unwrap(annotationSetRefItem) === 0 || annotationSetItem, 'Annotations must be there. Annotations offset: %s', annotationSetRefItem);
1403
- return resolveAnnotationSetItem(annotationSetItem);
1404
- });
1693
+ const annotationSet = resolveAnnotationSetItem(annotationSetItem);
1694
+ return annotationSet ?? [];
1695
+ }) ?? [];
1405
1696
  return { method, annotations };
1406
1697
  });
1407
1698
  return {
@@ -1412,11 +1703,25 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1412
1703
  };
1413
1704
  })();
1414
1705
  const classData = classDataByOffset.get(classDefinitionItem.classDataOffset);
1415
- const staticValues = isoOffsetToEncodedArrayItem.unwrap(classDefinitionItem.staticValuesOffset) === 0 ? [] : encodedArrayItemByOffset.get(classDefinitionItem.staticValuesOffset);
1416
- invariant(staticValues, 'Static values must be there. Static values offset: %s', classDefinitionItem.staticValuesOffset);
1706
+ const staticValuesTagged = isoOffsetToEncodedArrayItem.unwrap(classDefinitionItem.staticValuesOffset) === 0 ? [] : encodedArrayItemByOffset.get(classDefinitionItem.staticValuesOffset);
1707
+ invariant(staticValuesTagged, 'Static values must be there. Static values offset: %s', classDefinitionItem.staticValuesOffset);
1708
+ const staticValues = staticValuesTagged.map(resolveTaggedEncodedValueForStaticValues);
1709
+ const allMembers = [
1710
+ ...classData?.staticFields ?? [],
1711
+ ...classData?.instanceFields ?? [],
1712
+ ...classData?.directMethods ?? [],
1713
+ // ...classData?.virtualMethods ?? [], // TODO?
1714
+ ];
1715
+ const allMembersAreSynthetic = (allMembers.every(member => member.accessFlags.synthetic)
1716
+ && allMembers.length > 0);
1717
+ const accessFlags = {
1718
+ ...classDefinitionItem.accessFlags,
1719
+ // Use the synthetic flag from the class definition, or compute it from members if not set
1720
+ synthetic: classDefinitionItem.accessFlags.synthetic || allMembersAreSynthetic,
1721
+ };
1417
1722
  return {
1418
1723
  class: class_,
1419
- accessFlags: classDefinitionItem.accessFlags,
1724
+ accessFlags,
1420
1725
  superclass,
1421
1726
  interfaces,
1422
1727
  sourceFile,
@@ -1425,6 +1730,19 @@ mapList: _mapList, typeListByOffset, annotationSetRefListItemByOffset, annotatio
1425
1730
  staticValues,
1426
1731
  };
1427
1732
  });
1733
+ // Sort parameter annotations in each class by method index in classData
1734
+ for (const classDef of classDefinitions) {
1735
+ if (classDef.annotations?.parameterAnnotations && classDef.classData) {
1736
+ const allMethods = [...(classDef.classData.directMethods ?? []), ...(classDef.classData.virtualMethods ?? [])];
1737
+ classDef.annotations.parameterAnnotations.sort((a, b) => {
1738
+ const indexA = allMethods.findIndex(m => m.method.name === a.method.name &&
1739
+ m.method.prototype.shorty === a.method.prototype.shorty);
1740
+ const indexB = allMethods.findIndex(m => m.method.name === b.method.name &&
1741
+ m.method.prototype.shorty === b.method.prototype.shorty);
1742
+ return indexA - indexB;
1743
+ });
1744
+ }
1745
+ }
1428
1746
  return {
1429
1747
  classDefinitions,
1430
1748
  link,