@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
@@ -0,0 +1,282 @@
1
+ import * as fc from 'fast-check';
2
+ // String generators for valid Dalvik identifiers and type descriptors
3
+ const arbitraryJavaIdentifier = fc.stringMatching(/^[a-zA-Z_][a-zA-Z0-9_]*$/);
4
+ const arbitraryPrimitiveType = fc.oneof(fc.constant('V'), // void
5
+ fc.constant('Z'), // boolean
6
+ fc.constant('B'), // byte
7
+ fc.constant('S'), // short
8
+ fc.constant('C'), // char
9
+ fc.constant('I'), // int
10
+ fc.constant('J'), // long
11
+ fc.constant('F'), // float
12
+ fc.constant('D'));
13
+ const arbitraryDalvikClassName = fc.tuple(fc.array(arbitraryJavaIdentifier, { minLength: 1, maxLength: 3 }), arbitraryJavaIdentifier).map(([packages, className]) => `L${packages.join('/')}/${className};`);
14
+ const arbitraryDalvikTypeName = fc.oneof(arbitraryPrimitiveType, arbitraryDalvikClassName, arbitraryPrimitiveType.map(p => `[${p}`), // array of primitive
15
+ arbitraryDalvikClassName.map(c => `[${c}`));
16
+ const arbitraryDalvikMethodName = fc.oneof(arbitraryJavaIdentifier, fc.constant('<init>'), fc.constant('<clinit>'));
17
+ const arbitraryDalvikFieldName = arbitraryJavaIdentifier;
18
+ // Access flags generator - common flags for all contexts
19
+ const arbitraryDalvikExecutableAccessFlagsCommon = fc.record({
20
+ public: fc.boolean(),
21
+ private: fc.boolean(),
22
+ protected: fc.boolean(),
23
+ static: fc.boolean(),
24
+ final: fc.boolean(),
25
+ synchronized: fc.boolean(),
26
+ volatile: fc.constant(false),
27
+ bridge: fc.constant(false),
28
+ transient: fc.constant(false),
29
+ varargs: fc.constant(false),
30
+ native: fc.boolean(),
31
+ interface: fc.boolean(),
32
+ abstract: fc.boolean(),
33
+ strict: fc.boolean(),
34
+ synthetic: fc.boolean(),
35
+ annotation: fc.boolean(),
36
+ enum: fc.boolean(),
37
+ constructor: fc.boolean(),
38
+ declaredSynchronized: fc.boolean(),
39
+ });
40
+ // Access flags for fields - volatile and transient are valid (0x40 and 0x80)
41
+ const arbitraryDalvikExecutableFieldAccessFlags = fc.record({
42
+ public: fc.boolean(),
43
+ private: fc.boolean(),
44
+ protected: fc.boolean(),
45
+ static: fc.boolean(),
46
+ final: fc.boolean(),
47
+ synchronized: fc.boolean(),
48
+ volatile: fc.boolean(),
49
+ bridge: fc.constant(false),
50
+ transient: fc.boolean(),
51
+ varargs: fc.constant(false),
52
+ native: fc.boolean(),
53
+ interface: fc.boolean(),
54
+ abstract: fc.boolean(),
55
+ strict: fc.boolean(),
56
+ synthetic: fc.boolean(),
57
+ annotation: fc.boolean(),
58
+ enum: fc.boolean(),
59
+ constructor: fc.boolean(),
60
+ declaredSynchronized: fc.boolean(),
61
+ });
62
+ // Access flags for methods - bridge and varargs are valid (0x40 and 0x80)
63
+ const arbitraryDalvikExecutableMethodAccessFlags = fc.record({
64
+ public: fc.boolean(),
65
+ private: fc.boolean(),
66
+ protected: fc.boolean(),
67
+ static: fc.boolean(),
68
+ final: fc.boolean(),
69
+ synchronized: fc.boolean(),
70
+ volatile: fc.constant(false),
71
+ bridge: fc.boolean(),
72
+ transient: fc.constant(false),
73
+ varargs: fc.boolean(),
74
+ native: fc.boolean(),
75
+ interface: fc.boolean(),
76
+ abstract: fc.boolean(),
77
+ strict: fc.boolean(),
78
+ synthetic: fc.boolean(),
79
+ annotation: fc.boolean(),
80
+ enum: fc.boolean(),
81
+ constructor: fc.boolean(),
82
+ declaredSynchronized: fc.boolean(),
83
+ });
84
+ // Generic access flags for class-level (uses common)
85
+ const arbitraryDalvikExecutableAccessFlags = arbitraryDalvikExecutableAccessFlagsCommon;
86
+ // Field generator
87
+ const arbitraryDalvikExecutableField = fc.record({
88
+ class: arbitraryDalvikClassName,
89
+ type: arbitraryDalvikTypeName,
90
+ name: arbitraryDalvikFieldName,
91
+ });
92
+ const arbitraryDalvikExecutableFieldWithAccess = fc.record({
93
+ field: arbitraryDalvikExecutableField,
94
+ accessFlags: arbitraryDalvikExecutableFieldAccessFlags,
95
+ });
96
+ // Prototype generator
97
+ const arbitraryShorty = fc.tuple(arbitraryPrimitiveType, // return type
98
+ fc.array(fc.oneof(fc.constant('L'), arbitraryPrimitiveType), { maxLength: 5 })).map(([returnType, params]) => returnType + params.join(''));
99
+ const arbitraryDalvikExecutablePrototype = arbitraryShorty.chain(shorty => {
100
+ const returnTypeChar = shorty[0];
101
+ const paramChars = shorty.slice(1).split('');
102
+ const returnType = returnTypeChar === 'L' ? arbitraryDalvikClassName : fc.constant(returnTypeChar);
103
+ const parameters = fc.tuple(...paramChars.map(char => char === 'L' ? arbitraryDalvikClassName : fc.constant(char)));
104
+ return fc.record({
105
+ shorty: fc.constant(shorty),
106
+ returnType,
107
+ parameters,
108
+ });
109
+ });
110
+ // Method generator
111
+ const arbitraryDalvikExecutableMethod = fc.record({
112
+ class: arbitraryDalvikClassName,
113
+ prototype: arbitraryDalvikExecutablePrototype,
114
+ name: arbitraryDalvikMethodName,
115
+ });
116
+ // Encoded value generator (recursive)
117
+ // DalvikExecutableEncodedValue is now a tagged union with type information
118
+ const arbitraryDalvikExecutableEncodedValue = fc.letrec(tie => ({
119
+ value: fc.oneof(fc.record({ type: fc.constant('byte'), value: fc.integer({ min: -128, max: 127 }) }), fc.record({ type: fc.constant('short'), value: fc.integer({ min: -32768, max: 32767 }) }), fc.record({ type: fc.constant('char'), value: fc.integer({ min: 0, max: 65535 }) }), fc.record({ type: fc.constant('int'), value: fc.integer({ min: -2147483648, max: 2147483647 }) }), fc.record({ type: fc.constant('long'), value: fc.bigInt({ min: -9223372036854775808n, max: 9223372036854775807n }) }), fc.record({ type: fc.constant('float'), value: fc.float() }), fc.record({ type: fc.constant('double'), value: fc.double() }), fc.record({ type: fc.constant('methodType'), value: arbitraryDalvikExecutablePrototype }), fc.record({ type: fc.constant('methodHandle'), value: fc.nat(255) }), fc.record({ type: fc.constant('string'), value: fc.string() }), fc.record({ type: fc.constant('type'), value: arbitraryDalvikClassName }), fc.record({ type: fc.constant('field'), value: arbitraryDalvikExecutableField }), fc.record({ type: fc.constant('method'), value: arbitraryDalvikExecutableMethod }), fc.record({ type: fc.constant('enum'), value: arbitraryDalvikExecutableField }), fc.record({ type: fc.constant('array'), value: fc.array(tie('value'), { maxLength: 3 }) }),
120
+ // Note: We skip 'annotation' type here to avoid deep recursion complexity
121
+ fc.record({ type: fc.constant('null'), value: fc.constant(null) }), fc.record({ type: fc.constant('boolean'), value: fc.boolean() })),
122
+ })).value;
123
+ // Annotation generators
124
+ const arbitraryAnnotationVisibility = fc.oneof(fc.constant('build'), fc.constant('runtime'), fc.constant('system'));
125
+ const arbitraryDalvikExecutableAnnotationElement = fc.record({
126
+ name: arbitraryJavaIdentifier,
127
+ value: arbitraryDalvikExecutableEncodedValue,
128
+ });
129
+ const arbitraryDalvikExecutableAnnotation = fc.record({
130
+ visibility: arbitraryAnnotationVisibility,
131
+ type: arbitraryDalvikClassName,
132
+ elements: fc.array(arbitraryDalvikExecutableAnnotationElement, { maxLength: 3 }),
133
+ });
134
+ // Debug info generators
135
+ const arbitraryDalvikExecutableDebugByteCodeValue = fc.oneof(fc.record({
136
+ type: fc.constant('advancePc'),
137
+ addressDiff: fc.nat({ max: 255 }),
138
+ }), fc.record({
139
+ type: fc.constant('advanceLine'),
140
+ lineDiff: fc.integer({ min: -128, max: 127 }),
141
+ }), fc.record({
142
+ type: fc.constant('startLocal'),
143
+ registerNum: fc.nat({ max: 255 }),
144
+ name: fc.option(arbitraryJavaIdentifier, { nil: undefined }),
145
+ type_: fc.option(arbitraryDalvikTypeName, { nil: undefined }),
146
+ }), fc.record({
147
+ type: fc.constant('startLocalExtended'),
148
+ registerNum: fc.nat({ max: 255 }),
149
+ name: fc.option(arbitraryJavaIdentifier, { nil: undefined }),
150
+ type_: fc.option(arbitraryDalvikTypeName, { nil: undefined }),
151
+ signature: fc.option(fc.string(), { nil: undefined }),
152
+ }), fc.record({
153
+ type: fc.constant('endLocal'),
154
+ registerNum: fc.nat({ max: 255 }),
155
+ }), fc.record({
156
+ type: fc.constant('restartLocal'),
157
+ registerNum: fc.nat({ max: 255 }),
158
+ }), fc.record({
159
+ type: fc.constant('setPrologueEnd'),
160
+ }), fc.record({
161
+ type: fc.constant('setEpilogueBegin'),
162
+ }), fc.record({
163
+ type: fc.constant('setFile'),
164
+ name: fc.option(fc.string(), { nil: undefined }),
165
+ }), fc.record({
166
+ type: fc.constant('special'),
167
+ // Special opcodes must be >= 0x0A (values 0x00-0x09 are specific debug opcodes)
168
+ value: fc.integer({ min: 0x0A, max: 255 }),
169
+ }));
170
+ const arbitraryDalvikExecutableDebugInfo = fc.record({
171
+ lineStart: fc.nat({ max: 65535 }),
172
+ parameterNames: fc.array(fc.option(arbitraryJavaIdentifier, { nil: undefined }), { maxLength: 5 }),
173
+ bytecode: fc.array(arbitraryDalvikExecutableDebugByteCodeValue, { maxLength: 10 }),
174
+ });
175
+ const arbitraryDalvikExecutableEncodedTypeAddressPair = fc.record({
176
+ type: arbitraryDalvikClassName,
177
+ address: fc.nat({ max: 65535 }),
178
+ });
179
+ const arbitraryDalvikExecutableEncodedCatchHandler = fc.record({
180
+ handlers: fc.array(arbitraryDalvikExecutableEncodedTypeAddressPair, { maxLength: 3 }),
181
+ catchAllAddress: fc.option(fc.nat({ max: 65535 }), { nil: undefined }),
182
+ }).filter(handler => {
183
+ // A handler must have at least one typed handler OR a catch-all address
184
+ return handler.handlers.length > 0 || handler.catchAllAddress !== undefined;
185
+ });
186
+ const arbitraryDalvikExecutableTry = fc.record({
187
+ startAddress: fc.nat({ max: 65535 }),
188
+ instructionCount: fc.nat({ max: 255 }),
189
+ handler: arbitraryDalvikExecutableEncodedCatchHandler,
190
+ });
191
+ // Generic factory function for DalvikExecutable
192
+ export const createArbitraryDalvikExecutable = (arbitraryInstructions) => {
193
+ // Code generator using provided instructions arbitrary
194
+ const arbitraryDalvikExecutableCode = fc.record({
195
+ registersSize: fc.nat({ max: 65535 }),
196
+ insSize: fc.nat({ max: 255 }),
197
+ outsSize: fc.nat({ max: 255 }),
198
+ debugInfo: fc.option(arbitraryDalvikExecutableDebugInfo, { nil: undefined }),
199
+ instructions: arbitraryInstructions,
200
+ tries: fc.array(arbitraryDalvikExecutableTry, { maxLength: 2 }),
201
+ });
202
+ // Method with access and code
203
+ const arbitraryDalvikExecutableMethodWithAccess = fc.record({
204
+ method: arbitraryDalvikExecutableMethod,
205
+ accessFlags: arbitraryDalvikExecutableMethodAccessFlags,
206
+ code: fc.option(arbitraryDalvikExecutableCode, { nil: undefined }),
207
+ });
208
+ // Annotation collections
209
+ const arbitraryDalvikExecutableClassFieldAnnotation = fc.record({
210
+ field: arbitraryDalvikExecutableField,
211
+ annotations: fc.option(fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }), { nil: undefined }),
212
+ });
213
+ const arbitraryDalvikExecutableClassMethodAnnotation = fc.record({
214
+ method: arbitraryDalvikExecutableMethod,
215
+ annotations: fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }),
216
+ });
217
+ const arbitraryDalvikExecutableClassParameterAnnotation = fc.record({
218
+ method: arbitraryDalvikExecutableMethod,
219
+ annotations: fc.array(fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }), { maxLength: 3 }),
220
+ });
221
+ const arbitraryDalvikExecutableClassAnnotations = fc.record({
222
+ classAnnotations: fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }),
223
+ fieldAnnotations: fc.array(arbitraryDalvikExecutableClassFieldAnnotation, { maxLength: 2 }),
224
+ methodAnnotations: fc.array(arbitraryDalvikExecutableClassMethodAnnotation, { maxLength: 2 }),
225
+ parameterAnnotations: fc.array(arbitraryDalvikExecutableClassParameterAnnotation, { maxLength: 2 }),
226
+ }).map(annotations => ({
227
+ ...annotations,
228
+ // Filter out field/method/parameter annotations with undefined or empty annotations array
229
+ // In DEX format, fields/methods/parameters with no annotations should not appear in the annotations directory at all
230
+ fieldAnnotations: annotations.fieldAnnotations.filter(fa => fa.annotations !== undefined && fa.annotations.length > 0),
231
+ methodAnnotations: annotations.methodAnnotations.filter(ma => ma.annotations.length > 0),
232
+ parameterAnnotations: annotations.parameterAnnotations.filter(pa => pa.annotations.length > 0 && pa.annotations.some(paramAnnots => paramAnnots.length > 0)),
233
+ }));
234
+ // Class data
235
+ const arbitraryDalvikExecutableClassData = fc.record({
236
+ staticFields: fc.array(arbitraryDalvikExecutableFieldWithAccess, { maxLength: 3 }),
237
+ instanceFields: fc.array(arbitraryDalvikExecutableFieldWithAccess, { maxLength: 3 }),
238
+ directMethods: fc.array(arbitraryDalvikExecutableMethodWithAccess, { maxLength: 3 }),
239
+ virtualMethods: fc.array(arbitraryDalvikExecutableMethodWithAccess, { maxLength: 3 }),
240
+ }).filter(classData =>
241
+ // Filter out empty classData (all arrays empty) as it's semantically equivalent to undefined
242
+ classData.staticFields.length > 0 ||
243
+ classData.instanceFields.length > 0 ||
244
+ classData.directMethods.length > 0 ||
245
+ classData.virtualMethods.length > 0);
246
+ // Class definition
247
+ const arbitraryDalvikExecutableClassDefinition = fc.record({
248
+ class: arbitraryDalvikClassName,
249
+ accessFlags: arbitraryDalvikExecutableAccessFlags,
250
+ superclass: arbitraryDalvikClassName,
251
+ interfaces: fc.array(arbitraryDalvikClassName, { maxLength: 3 }),
252
+ sourceFile: fc.option(fc.stringMatching(/^[a-zA-Z0-9_]+\.java$/), { nil: undefined }),
253
+ annotations: fc.option(arbitraryDalvikExecutableClassAnnotations, { nil: undefined }),
254
+ staticValues: fc.array(arbitraryDalvikExecutableEncodedValue, { maxLength: 3 }),
255
+ classData: fc.option(arbitraryDalvikExecutableClassData, { nil: undefined }),
256
+ }).map(classDef => {
257
+ // Match parser logic: if all members are synthetic, set class synthetic to true
258
+ const allMembers = [
259
+ ...classDef.classData?.staticFields ?? [],
260
+ ...classDef.classData?.instanceFields ?? [],
261
+ ...classDef.classData?.directMethods ?? [],
262
+ // Note: virtualMethods are not included to match parser behavior
263
+ ];
264
+ const allMembersAreSynthetic = (allMembers.every(member => member.accessFlags.synthetic)
265
+ && allMembers.length > 0);
266
+ if (allMembersAreSynthetic) {
267
+ return {
268
+ ...classDef,
269
+ accessFlags: {
270
+ ...classDef.accessFlags,
271
+ synthetic: true,
272
+ },
273
+ };
274
+ }
275
+ return classDef;
276
+ });
277
+ // Root DalvikExecutable
278
+ return fc.record({
279
+ classDefinitions: fc.array(arbitraryDalvikExecutableClassDefinition, { minLength: 1, maxLength: 3 }),
280
+ link: fc.option(fc.uint8Array({ minLength: 1, maxLength: 10 }), { nil: undefined }),
281
+ });
282
+ };
@@ -2,6 +2,7 @@ import * as fc from 'fast-check';
2
2
  export const arbitraryDosDateTime = fc.date({
3
3
  min: new Date(Date.UTC(1980, 0, 1)),
4
4
  max: new Date(Date.UTC(2099, 11, 31)),
5
+ noInvalidDate: true,
5
6
  }).map(date => {
6
7
  date.setSeconds(0);
7
8
  date.setMilliseconds(0);
@@ -4,7 +4,7 @@ function addZipEntryToZip(zip, zipEntry) {
4
4
  const options = {
5
5
  comment: zipEntry.comment,
6
6
  date: zipEntry.date,
7
- // unixPermissions: zipEntry.permissions.type === 'unix' ? zipEntry.permissions.unixPermissions : undefined,
7
+ // UnixPermissions: zipEntry.permissions.type === 'unix' ? zipEntry.permissions.unixPermissions : undefined,
8
8
  // dosPermissions: zipEntry.permissions.type === 'dos' ? zipEntry.permissions.dosPermissions : undefined,
9
9
  };
10
10
  if (zipEntry.type === 'file') {
@@ -1,5 +1,5 @@
1
1
  import { getParserName, setParserName } from './parser.js';
2
- import { ParserParsingFailedError } from './parserError.js';
2
+ import { isParserParsingFailedError } from './parserError.js';
3
3
  export const createArrayParser = (elementParser) => {
4
4
  const arrayParser = async (parserContext) => {
5
5
  const elements = [];
@@ -15,7 +15,7 @@ export const createArrayParser = (elementParser) => {
15
15
  elementParserContext.unlookahead();
16
16
  }
17
17
  catch (error) {
18
- if (error instanceof ParserParsingFailedError) {
18
+ if (isParserParsingFailedError(error)) {
19
19
  return elements;
20
20
  }
21
21
  throw error;
@@ -1,2 +1,2 @@
1
- import { Unparser } from "./unparser.js";
1
+ import { type Unparser } from './unparser.js';
2
2
  export declare const createArrayUnparser: <ElementInput, Sequence>(elementUnparser: Unparser<ElementInput, Sequence>) => Unparser<ElementInput[], Sequence>;
@@ -1 +1,3 @@
1
- export declare function baksmaliClass(dexStream: AsyncIterable<Uint8Array>, smaliFilePath: string): Promise<string>;
1
+ export declare function baksmaliClass(dexStream: Uint8Array | AsyncIterable<Uint8Array>, smaliFilePath: string): Promise<string>;
2
+ export declare function backsmaliSmaliIsolateClass(dexStream: Uint8Array | AsyncIterable<Uint8Array>, smaliFilePath: string): Promise<Uint8Array>;
3
+ export declare function baksmaliListClasses(dexStream: Uint8Array | AsyncIterable<Uint8Array>): Promise<string[]>;
@@ -1,15 +1,18 @@
1
1
  import fs from 'node:fs/promises';
2
+ import path from 'node:path';
2
3
  import { execa } from 'execa';
3
4
  import { temporaryDirectory, temporaryFile } from 'tempy';
4
- import path from 'node:path';
5
+ import { smaliClass } from './smali.js';
5
6
  export async function baksmaliClass(dexStream, smaliFilePath) {
6
7
  const inputFilePath = temporaryFile();
7
8
  const outputDirectoryPath = temporaryDirectory();
8
9
  await fs.writeFile(inputFilePath, dexStream);
9
10
  await execa('baksmali', [
10
11
  'disassemble',
11
- '--classes', 'L' + smaliFilePath + ';',
12
- '--output', outputDirectoryPath,
12
+ '--classes',
13
+ 'L' + smaliFilePath + ';',
14
+ '--output',
15
+ outputDirectoryPath,
13
16
  inputFilePath,
14
17
  ]);
15
18
  await fs.unlink(inputFilePath);
@@ -20,3 +23,28 @@ export async function baksmaliClass(dexStream, smaliFilePath) {
20
23
  });
21
24
  return smali;
22
25
  }
26
+ export async function backsmaliSmaliIsolateClass(dexStream, smaliFilePath) {
27
+ const smali = await baksmaliClass(dexStream, smaliFilePath);
28
+ return smaliClass(smali);
29
+ }
30
+ export async function baksmaliListClasses(dexStream) {
31
+ const inputFilePath = temporaryFile();
32
+ await fs.writeFile(inputFilePath, dexStream);
33
+ const result = await execa('baksmali', [
34
+ 'list',
35
+ 'classes',
36
+ inputFilePath,
37
+ ]);
38
+ await fs.unlink(inputFilePath);
39
+ if (result.stderr) {
40
+ throw new Error(`baksmali error: ${result.stderr}`);
41
+ }
42
+ const classes = result.stdout
43
+ .split('\n')
44
+ .filter(line => line.trim())
45
+ .map(line => line.trim())
46
+ .map(class_ => (class_
47
+ .replace(/^L/, '')
48
+ .replace(/;$/, '')));
49
+ return classes;
50
+ }
@@ -0,0 +1,84 @@
1
+ export type BashWord = {
2
+ parts: BashWordPart[];
3
+ };
4
+ export type BashWordPart = BashWordPartLiteral | BashWordPartSingleQuoted | BashWordPartDoubleQuoted | BashWordPartVariable | BashWordPartVariableBraced | BashWordPartCommandSubstitution | BashWordPartBacktickSubstitution | BashWordPartArithmeticExpansion;
5
+ export type BashWordPartLiteral = {
6
+ type: 'literal';
7
+ value: string;
8
+ };
9
+ export type BashWordPartSingleQuoted = {
10
+ type: 'singleQuoted';
11
+ value: string;
12
+ };
13
+ export type BashWordPartDoubleQuoted = {
14
+ type: 'doubleQuoted';
15
+ parts: BashWordPart[];
16
+ };
17
+ export type BashWordPartVariable = {
18
+ type: 'variable';
19
+ name: string;
20
+ };
21
+ export type BashWordPartVariableBraced = {
22
+ type: 'variableBraced';
23
+ name: string;
24
+ operator?: string;
25
+ operand?: BashWord;
26
+ };
27
+ export type BashWordPartCommandSubstitution = {
28
+ type: 'commandSubstitution';
29
+ command: BashCommand;
30
+ };
31
+ export type BashWordPartBacktickSubstitution = {
32
+ type: 'backtickSubstitution';
33
+ command: BashCommand;
34
+ };
35
+ export type BashWordPartArithmeticExpansion = {
36
+ type: 'arithmeticExpansion';
37
+ expression: string;
38
+ };
39
+ export type BashRedirect = {
40
+ fd?: number;
41
+ operator: '>' | '>>' | '<' | '<<' | '<<<' | '>&' | '<&' | '>|';
42
+ target: BashWord | BashHereDoc;
43
+ };
44
+ export type BashHereDoc = {
45
+ type: 'hereDoc';
46
+ delimiter: string;
47
+ content: string;
48
+ quoted: boolean;
49
+ };
50
+ export type BashAssignment = {
51
+ name: string;
52
+ value?: BashWord;
53
+ };
54
+ export type BashSimpleCommand = {
55
+ type: 'simple';
56
+ name?: BashWord;
57
+ args: BashWord[];
58
+ redirects: BashRedirect[];
59
+ assignments: BashAssignment[];
60
+ };
61
+ export type BashSubshell = {
62
+ type: 'subshell';
63
+ body: BashCommand;
64
+ };
65
+ export type BashBraceGroup = {
66
+ type: 'braceGroup';
67
+ body: BashCommand;
68
+ };
69
+ export type BashCommandUnit = BashSimpleCommand | BashSubshell | BashBraceGroup;
70
+ export type BashPipeline = {
71
+ type: 'pipeline';
72
+ negated: boolean;
73
+ commands: BashCommandUnit[];
74
+ };
75
+ export type BashCommandListSeparator = '&&' | '||' | ';' | '&' | '\n';
76
+ export type BashCommandList = {
77
+ type: 'list';
78
+ entries: {
79
+ pipeline: BashPipeline;
80
+ separator?: BashCommandListSeparator;
81
+ }[];
82
+ };
83
+ export type BashCommand = BashCommandList;
84
+ export type BashScript = BashCommand;
package/build/bash.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { type Parser } from './parser.js';
2
+ import { type BashWord, type BashSimpleCommand, type BashCommand } from './bash.js';
3
+ export declare const bashWordParser: Parser<BashWord, string>;
4
+ export declare const bashSimpleCommandParser: Parser<BashSimpleCommand, string>;
5
+ export declare const bashCommandParser: Parser<BashCommand, string>;
6
+ export declare const bashScriptParser: Parser<BashCommand, string>;