@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.
- package/.github/copilot-instructions.md +149 -0
- package/.github/workflows/copilot-setup-steps.yml +18 -0
- package/.github/workflows/main.yml +29 -8
- package/.yarn/releases/yarn-4.9.4.cjs +942 -0
- package/.yarnrc.yml +1 -1
- package/build/allSettledStream.js +1 -1
- package/build/allSettledStream.test.js +2 -2
- package/build/androidPackageParser.d.ts +1 -1
- package/build/androidPackageParser.js +5 -3
- package/build/androidPackageParser.test.js +7 -7
- package/build/androidPackageUnparser.d.ts +2 -2
- package/build/androidPackageUnparser.js +18 -14
- package/build/androidPackageUnparser.test.js +7 -7
- package/build/arbitrarilySlicedAsyncInterator.js +2 -1
- package/build/arbitraryDalvikBytecode.d.ts +4 -0
- package/build/arbitraryDalvikBytecode.js +640 -0
- package/build/arbitraryDalvikExecutable.d.ts +3 -0
- package/build/arbitraryDalvikExecutable.js +282 -0
- package/build/arbitraryDosDateTime.js +1 -0
- package/build/arbitraryZipStream.js +1 -1
- package/build/arrayParser.js +2 -2
- package/build/arrayUnparser.d.ts +1 -1
- package/build/backsmali.d.ts +3 -1
- package/build/backsmali.js +31 -3
- package/build/bash.d.ts +84 -0
- package/build/bash.js +1 -0
- package/build/bashParser.d.ts +6 -0
- package/build/bashParser.js +294 -0
- package/build/bashParser.test.d.ts +1 -0
- package/build/bashParser.test.js +181 -0
- package/build/customInvariant.d.ts +2 -1
- package/build/customInvariant.js +4 -6
- package/build/dalvikBytecodeParser/formatParsers.d.ts +76 -2
- package/build/dalvikBytecodeParser/formatParsers.js +146 -11
- package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
- package/build/dalvikBytecodeParser/formatSizes.js +34 -0
- package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
- package/build/dalvikBytecodeParser/operationFormats.js +225 -0
- package/build/dalvikBytecodeParser.d.ts +1105 -5
- package/build/dalvikBytecodeParser.js +658 -205
- package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
- package/build/dalvikBytecodeUnparser.d.ts +3 -0
- package/build/dalvikBytecodeUnparser.js +642 -0
- package/build/dalvikBytecodeUnparser.test.d.ts +1 -0
- package/build/dalvikBytecodeUnparser.test.js +25 -0
- package/build/dalvikExecutable.d.ts +65 -8
- package/build/dalvikExecutable.js +36 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +1 -1
- package/build/dalvikExecutableParser/stringSyntaxParser.js +17 -17
- package/build/dalvikExecutableParser/typeParsers.d.ts +2 -1
- package/build/dalvikExecutableParser/typeParsers.js +16 -11
- package/build/dalvikExecutableParser/typedNumbers.d.ts +85 -69
- package/build/dalvikExecutableParser/typedNumbers.js +0 -1
- package/build/dalvikExecutableParser.d.ts +2 -2
- package/build/dalvikExecutableParser.js +655 -337
- package/build/dalvikExecutableParser.test.js +24 -22
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +223 -246
- package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
- package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
- package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
- package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
- package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
- package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
- package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
- package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
- package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
- package/build/dalvikExecutableUnparser/utils.js +108 -0
- package/build/dalvikExecutableUnparser.d.ts +4 -0
- package/build/dalvikExecutableUnparser.js +406 -0
- package/build/dalvikExecutableUnparser.test.d.ts +1 -0
- package/build/dalvikExecutableUnparser.test.js +31 -0
- package/build/debugLogInputParser.js +1 -1
- package/build/disjunctionParser.d.ts +2 -2
- package/build/disjunctionParser.js +2 -2
- package/build/elementTerminatedArrayParser.d.ts +2 -2
- package/build/elementTerminatedArrayParser.js +1 -1
- package/build/elementTerminatedArrayParser.test.js +5 -5
- package/build/elementTerminatedSequenceArrayParser.d.ts +2 -2
- package/build/elementTerminatedSequenceArrayParser.js +1 -1
- package/build/elementTerminatedSequenceArrayParser.test.js +2 -2
- package/build/elementTerminatedSequenceParser.d.ts +2 -2
- package/build/elementTerminatedSequenceParser.js +1 -1
- package/build/elementTerminatedSequenceParser.test.js +2 -2
- package/build/endOfInputParser.d.ts +1 -1
- package/build/exactElementSwitchParser.d.ts +3 -0
- package/build/exactElementSwitchParser.js +22 -0
- package/build/fetchCid.js +2 -6
- package/build/fetchCid.test.d.ts +1 -0
- package/build/fetchCid.test.js +16 -0
- package/build/fixedLengthSequenceParser.test.js +2 -2
- package/build/hasExecutable.js +2 -2
- package/build/highResolutionTimer.js +1 -1
- package/build/index.d.ts +24 -2
- package/build/index.js +22 -1
- package/build/inputReader.d.ts +1 -1
- package/build/inputReader.test.js +33 -45
- package/build/javaKeyStoreParser.test.js +6 -6
- package/build/jsonParser.js +8 -8
- package/build/lazyMessageError.d.ts +48 -0
- package/build/lazyMessageError.js +53 -0
- package/build/lazyMessageError.test.d.ts +1 -0
- package/build/lazyMessageError.test.js +15 -0
- package/build/leb128Parser.d.ts +1 -1
- package/build/leb128Parser.js +10 -10
- package/build/leb128Parser.test.js +7 -7
- package/build/negativeLookaheadParser.js +2 -2
- package/build/negativeLookaheadParser.test.js +4 -4
- package/build/noStackCaptureOverheadError.d.ts +4 -0
- package/build/noStackCaptureOverheadError.js +9 -0
- package/build/noStackCaptureOverheadError.test.d.ts +1 -0
- package/build/noStackCaptureOverheadError.test.js +15 -0
- package/build/nonEmptyArrayParser.js +2 -2
- package/build/nonEmptyArrayParser.test.js +2 -1
- package/build/optionalParser.js +2 -2
- package/build/parser.d.ts +2 -1
- package/build/parser.js +23 -8
- package/build/parser.test.js +78 -29
- package/build/parserConsumedSequenceParser.d.ts +1 -1
- package/build/parserConsumedSequenceParser.js +2 -2
- package/build/parserContext.d.ts +8 -6
- package/build/parserContext.js +60 -33
- package/build/parserContext.test.js +7 -3
- package/build/parserError.d.ts +603 -44
- package/build/parserError.js +98 -53
- package/build/parserImplementationInvariant.d.ts +1 -1
- package/build/parserImplementationInvariant.js +2 -2
- package/build/parserInputCompanion.js +2 -2
- package/build/promiseCompose.js +1 -2
- package/build/regexpParser.d.ts +2 -0
- package/build/regexpParser.js +71 -0
- package/build/regexpParser.test.d.ts +1 -0
- package/build/regexpParser.test.js +83 -0
- package/build/regularExpression.d.ts +63 -0
- package/build/regularExpression.js +1 -0
- package/build/regularExpressionParser.d.ts +3 -0
- package/build/regularExpressionParser.js +580 -0
- package/build/regularExpressionParser.test.d.ts +1 -0
- package/build/regularExpressionParser.test.js +89 -0
- package/build/separatedArrayParser.js +2 -2
- package/build/separatedNonEmptyArrayParser.d.ts +2 -0
- package/build/separatedNonEmptyArrayParser.js +40 -0
- package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
- package/build/separatedNonEmptyArrayParser.test.js +66 -0
- package/build/sequenceBuffer.js +1 -1
- package/build/sequenceTerminatedSequenceParser.d.ts +2 -2
- package/build/sequenceTerminatedSequenceParser.js +3 -3
- package/build/sequenceTerminatedSequenceParser.test.js +1 -1
- package/build/sequenceUnparser.d.ts +1 -1
- package/build/skipToParser.d.ts +1 -1
- package/build/skipToParser.js +2 -2
- package/build/sliceBoundedParser.test.js +4 -9
- package/build/smali.d.ts +1 -1
- package/build/smali.js +6 -2
- package/build/smaliParser.d.ts +62 -6
- package/build/smaliParser.js +1721 -296
- package/build/smaliParser.test.js +338 -43
- package/build/stringFromAsyncIterable.d.ts +1 -0
- package/build/stringFromAsyncIterable.js +7 -0
- package/build/terminatedArrayParser.js +4 -4
- package/build/terminatedArrayParser.test.js +7 -7
- package/build/toAsyncIterator.js +4 -4
- package/build/unionParser.d.ts +1 -1
- package/build/unionParser.js +2 -2
- package/build/unionParser.test.js +3 -3
- package/build/unparser.d.ts +3 -3
- package/build/unparser.js +6 -4
- package/build/unparser.test.js +7 -19
- package/build/unparserContext.d.ts +2 -2
- package/build/unparserContext.js +2 -3
- package/build/unparserError.d.ts +2 -1
- package/build/unparserError.js +2 -1
- package/build/unparserImplementationInvariant.d.ts +1 -1
- package/build/unparserOutputCompanion.d.ts +1 -1
- package/build/unparserOutputCompanion.js +1 -1
- package/build/zipParser.js +1 -1
- package/build/zipUnparser.d.ts +3 -3
- package/build/zipUnparser.js +9 -19
- package/build/zipUnparser.test.js +1 -1
- package/package.json +20 -26
- package/src/allSettledStream.test.ts +2 -2
- package/src/allSettledStream.ts +3 -3
- package/src/androidPackageParser.test.ts +17 -19
- package/src/androidPackageParser.ts +129 -171
- package/src/androidPackageUnparser.test.ts +19 -21
- package/src/androidPackageUnparser.ts +23 -17
- package/src/arbitrarilySlicedAsyncInterable.ts +1 -1
- package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
- package/src/arbitraryDalvikBytecode.ts +992 -0
- package/src/arbitraryDalvikExecutable.ts +434 -0
- package/src/arbitraryDosDateTime.ts +1 -0
- package/src/arbitraryZipStream.ts +1 -1
- package/src/arrayParser.ts +2 -2
- package/src/arrayUnparser.ts +2 -2
- package/src/backsmali.ts +48 -4
- package/src/bash.ts +120 -0
- package/src/bashParser.test.ts +332 -0
- package/src/bashParser.ts +461 -0
- package/src/bsonParser.test.ts +12 -14
- package/src/customInvariant.ts +8 -12
- package/src/dalvikBytecodeParser/formatParsers.ts +376 -17
- package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
- package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
- package/src/dalvikBytecodeParser.ts +1042 -243
- package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
- package/src/dalvikBytecodeUnparser.test.ts +44 -0
- package/src/dalvikBytecodeUnparser.ts +758 -0
- package/src/dalvikExecutable.ts +110 -48
- package/src/dalvikExecutableParser/stringSyntaxParser.ts +33 -33
- package/src/dalvikExecutableParser/typeParsers.ts +23 -14
- package/src/dalvikExecutableParser/typedNumbers.ts +19 -19
- package/src/dalvikExecutableParser.test.ts +60 -60
- package/src/dalvikExecutableParser.test.ts.md +6 -6
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +911 -434
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +256 -239
- package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
- package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
- package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
- package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
- package/src/dalvikExecutableUnparser/utils.ts +149 -0
- package/src/dalvikExecutableUnparser.test.ts +57 -0
- package/src/dalvikExecutableUnparser.ts +581 -0
- package/src/debugLogInputParser.ts +1 -1
- package/src/disjunctionParser.ts +5 -5
- package/src/elementTerminatedArrayParser.test.ts +8 -8
- package/src/elementTerminatedArrayParser.ts +2 -2
- package/src/elementTerminatedSequenceArrayParser.test.ts +4 -6
- package/src/elementTerminatedSequenceArrayParser.ts +2 -2
- package/src/elementTerminatedSequenceParser.test.ts +4 -6
- package/src/elementTerminatedSequenceParser.ts +2 -2
- package/src/endOfInputParser.ts +1 -1
- package/src/exactElementSwitchParser.ts +41 -0
- package/src/fetchCid.test.ts +20 -0
- package/src/fetchCid.ts +3 -7
- package/src/fixedLengthSequenceParser.test.ts +10 -12
- package/src/hasExecutable.ts +2 -2
- package/src/highResolutionTimer.ts +1 -1
- package/src/index.ts +113 -2
- package/src/inputReader.test.ts +39 -52
- package/src/inputReader.ts +2 -4
- package/src/inputReaderState.ts +1 -1
- package/src/inspect.ts +1 -1
- package/src/javaKeyStoreParser.test.ts +12 -14
- package/src/javaKeyStoreParser.ts +2 -6
- package/src/jsonParser.test.ts +2 -4
- package/src/jsonParser.ts +34 -38
- package/src/lazyMessageError.test.ts +21 -0
- package/src/lazyMessageError.ts +88 -0
- package/src/leb128Parser.test.ts +25 -23
- package/src/leb128Parser.ts +19 -19
- package/src/negativeLookaheadParser.test.ts +7 -11
- package/src/negativeLookaheadParser.ts +2 -2
- package/src/noStackCaptureOverheadError.test.ts +17 -0
- package/src/noStackCaptureOverheadError.ts +12 -0
- package/src/nonEmptyArrayParser.test.ts +3 -2
- package/src/nonEmptyArrayParser.ts +2 -2
- package/src/optionalParser.ts +2 -2
- package/src/parser.test.ts +96 -43
- package/src/parser.test.ts.md +13 -6
- package/src/parser.test.ts.snap +0 -0
- package/src/parser.ts +35 -12
- package/src/parserAccessorParser.ts +1 -1
- package/src/parserConsumedSequenceParser.ts +3 -3
- package/src/parserContext.test.ts +7 -3
- package/src/parserContext.ts +82 -48
- package/src/parserError.ts +143 -63
- package/src/parserImplementationInvariant.ts +3 -3
- package/src/parserInputCompanion.ts +2 -2
- package/src/promiseCompose.ts +2 -2
- package/src/regexpParser.test.ts +186 -0
- package/src/regexpParser.ts +94 -0
- package/src/regularExpression.ts +24 -0
- package/src/regularExpressionParser.test.ts +102 -0
- package/src/regularExpressionParser.ts +921 -0
- package/src/separatedArrayParser.ts +3 -3
- package/src/separatedNonEmptyArrayParser.test.ts +117 -0
- package/src/separatedNonEmptyArrayParser.ts +61 -0
- package/src/sequenceBuffer.test.ts +9 -9
- package/src/sequenceBuffer.ts +4 -4
- package/src/sequenceTerminatedSequenceParser.test.ts +3 -5
- package/src/sequenceTerminatedSequenceParser.ts +4 -4
- package/src/sequenceUnparser.ts +2 -2
- package/src/skipToParser.ts +2 -2
- package/src/sliceBoundedParser.test.ts +4 -12
- package/src/sliceBoundedParser.ts +2 -2
- package/src/smali.ts +8 -3
- package/src/smaliParser.test.ts +377 -66
- package/src/smaliParser.test.ts.md +1635 -48
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +2751 -569
- package/src/stringFromAsyncIterable.ts +9 -0
- package/src/terminatedArrayParser.test.ts +11 -11
- package/src/terminatedArrayParser.ts +5 -7
- package/src/toAsyncIterator.ts +8 -8
- package/src/uint8Array.ts +2 -3
- package/src/unionParser.test.ts +22 -23
- package/src/unionParser.ts +6 -8
- package/src/unparser.test.ts +18 -34
- package/src/unparser.ts +13 -9
- package/src/unparserContext.ts +9 -13
- package/src/unparserError.ts +2 -1
- package/src/unparserImplementationInvariant.ts +1 -1
- package/src/unparserOutputCompanion.ts +1 -1
- package/src/zip.ts +2 -6
- package/src/zipParser.ts +10 -18
- package/src/zipUnparser.test.ts +1 -1
- package/src/zipUnparser.ts +52 -64
- package/tsconfig.json +7 -1
- package/xo.config.ts +15 -0
- package/.yarn/releases/yarn-4.5.3.cjs +0 -934
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import invariant from 'invariant';
|
|
2
|
-
import { MUtf8Decoder } from
|
|
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),
|
|
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),
|
|
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
|
|
160
|
-
public: Boolean(flags &
|
|
161
|
-
private: Boolean(flags &
|
|
162
|
-
protected: Boolean(flags &
|
|
163
|
-
static: Boolean(flags &
|
|
164
|
-
final: Boolean(flags &
|
|
165
|
-
synchronized: Boolean(flags &
|
|
166
|
-
volatile:
|
|
167
|
-
bridge:
|
|
168
|
-
transient: Boolean(flags &
|
|
169
|
-
varargs: Boolean(flags &
|
|
170
|
-
native:
|
|
171
|
-
interface:
|
|
172
|
-
abstract:
|
|
173
|
-
strict:
|
|
174
|
-
synthetic:
|
|
175
|
-
annotation:
|
|
176
|
-
enum:
|
|
177
|
-
constructor:
|
|
178
|
-
declaredSynchronized:
|
|
179
|
-
})
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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),
|
|
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),
|
|
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
|
-
|
|
313
|
+
uleb128FieldAccessFlagsParser,
|
|
318
314
|
]), ([fieldIndexDiff, accessFlags]) => ({ fieldIndexDiff, accessFlags }));
|
|
319
|
-
const createEncodedFieldsParser = (fieldsSize) => promiseCompose(createQuantifierParser(encodedFieldParser, fieldsSize),
|
|
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
|
-
|
|
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),
|
|
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 &
|
|
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),
|
|
377
|
+
const createEncodedValueArgParser = (valueType) => promiseCompose(createByteWith5LeastSignificantBitsEqualParser(valueType), byte => byte >> 5);
|
|
382
378
|
const encodedValueByteParser = promiseCompose(createTupleParser([
|
|
383
379
|
createExactElementParser(0),
|
|
384
|
-
|
|
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),
|
|
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),
|
|
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),
|
|
406
|
-
const buffer = Buffer.from([
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
433
|
-
const
|
|
434
|
-
const
|
|
435
|
-
const extensionByte =
|
|
436
|
-
const buffer = Buffer.from([
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
463
|
-
const
|
|
464
|
-
const firstBit = (
|
|
465
|
-
const extensionByte = firstBit === 1 ?
|
|
466
|
-
const buffer = Buffer.from([
|
|
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),
|
|
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),
|
|
478
|
-
const
|
|
479
|
-
const firstBit = (
|
|
480
|
-
const extensionByte = firstBit === 1 ?
|
|
481
|
-
const buffer = Buffer.from([
|
|
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),
|
|
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),
|
|
496
|
-
const buffer = Buffer.from([
|
|
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),
|
|
502
|
-
const buffer = Buffer.from([
|
|
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),
|
|
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),
|
|
517
|
-
const buffer = Buffer.from([
|
|
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),
|
|
523
|
-
const buffer = Buffer.from([
|
|
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),
|
|
529
|
-
const buffer = Buffer.from([
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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),
|
|
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(
|
|
689
|
+
const encodedValueMethodParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1A), sizeSubOne => {
|
|
646
690
|
const size = sizeSubOne + 1;
|
|
647
691
|
if (size === 1) {
|
|
648
|
-
return promiseCompose(createFixedLengthSequenceParser(size),
|
|
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),
|
|
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),
|
|
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(
|
|
710
|
+
const encodedValueEnumParser = parserCreatorCompose(() => createEncodedValueArgParser(0x1B), sizeSubOne => {
|
|
667
711
|
const size = sizeSubOne + 1;
|
|
668
712
|
if (size === 1) {
|
|
669
|
-
return promiseCompose(createFixedLengthSequenceParser(size),
|
|
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),
|
|
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),
|
|
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,
|
|
731
|
+
const encodedArrayParser = parserCreatorCompose(() => uleb128NumberParser, size => createQuantifierParser(encodedValueParser, size))();
|
|
688
732
|
setParserName(encodedArrayParser, 'encodedArrayParser');
|
|
689
733
|
const encodedValueArrayParser = promiseCompose(createTupleParser([
|
|
690
|
-
parserCreatorCompose(() => createEncodedValueArgParser(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
(
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
(
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
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:
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
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,
|
|
955
|
+
const dalvikExecutableAnnotationItemVisibilityParser = promiseCompose(ubyteParser, visibility => {
|
|
896
956
|
switch (visibility) {
|
|
897
|
-
case 0x00:
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
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,
|
|
917
|
-
const dalvikExecutableAnnotationOffsetItemParser = promiseCompose(uintParser,
|
|
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),
|
|
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,
|
|
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),
|
|
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,
|
|
1011
|
+
const dalvikExecutableMapItemTypeParser = promiseCompose(ushortParser, type => {
|
|
944
1012
|
switch (type) {
|
|
945
|
-
case
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
case
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
case
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
case
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
case
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
case
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
case
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
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
|
-
|
|
1003
|
-
|
|
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
|
-
|
|
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(
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
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
|
-
//
|
|
1140
|
-
}
|
|
1141
|
-
const strings = stringIdItems.map(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
1327
|
+
bytecode: debugInfoItem.bytecode.map(value => {
|
|
1205
1328
|
switch (value.type) {
|
|
1206
|
-
case 'startLocal':
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
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
|
|
1365
|
+
debugInfo,
|
|
1235
1366
|
instructions: codeItem.instructions,
|
|
1236
|
-
tries: codeItem.tryItems.map(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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.
|
|
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
|
|
1385
|
-
invariant(isoOffsetToAnnotationSetItem.unwrap(fieldAnnotation.annotationsOffset) === 0 ||
|
|
1386
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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(
|
|
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
|
-
|
|
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
|
|
1416
|
-
invariant(
|
|
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
|
|
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,
|