jsilnet 0.1.0 → 0.2.0
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/README.md +25 -6
- package/REFERENCE.md +4 -0
- package/dist/browser/index.js +345 -0
- package/dist/browser/worker.js +42480 -0
- package/package.json +23 -4
- package/src/assembly/instruction-editing.js +165 -0
- package/src/assembly/method-removal.js +789 -0
- package/src/assembly/pointer-table-editing.js +506 -0
- package/src/assembly/portable-pdb-editing.js +441 -0
- package/src/browser/index.d.ts +123 -0
- package/src/browser/index.js +373 -0
- package/src/browser/worker-runtime.js +287 -0
- package/src/browser/worker.js +47 -0
- package/src/index.d.ts +267 -0
- package/src/index.js +107 -1574
- package/src/metadata/portable-pdb.js +2 -2
- package/src/metadata/strong-name.js +84 -83
- package/src/pe/headers.js +1 -1
- package/src/platform/bytes.js +21 -0
- package/src/platform/compression.js +24 -0
- package/src/platform/crypto.js +17 -0
- package/src/types/assembly/instruction-editing.d.ts +33 -0
- package/src/types/assembly/method-removal.d.ts +3 -0
- package/src/types/assembly/pointer-table-editing.d.ts +3 -0
- package/src/types/assembly/portable-pdb-editing.d.ts +23 -0
- package/src/types/binary/errors.d.ts +7 -0
- package/src/types/binary/reader.d.ts +30 -0
- package/src/types/il/body.d.ts +51 -0
- package/src/types/il/instructions.d.ts +33 -0
- package/src/types/il/opcodes.d.ts +2 -0
- package/src/types/il/rewrite.d.ts +38 -0
- package/src/types/index.d.ts +864 -0
- package/src/types/metadata/classic-pdb.d.ts +688 -0
- package/src/types/metadata/custom-attributes.d.ts +28 -0
- package/src/types/metadata/portable-pdb.d.ts +296 -0
- package/src/types/metadata/resources.d.ts +1 -0
- package/src/types/metadata/root-writer.d.ts +1 -0
- package/src/types/metadata/signatures.d.ts +5 -0
- package/src/types/metadata/streams.d.ts +26 -0
- package/src/types/metadata/strong-name.d.ts +11 -0
- package/src/types/metadata/tables.d.ts +25 -0
- package/src/types/metadata/writer.d.ts +16 -0
- package/src/types/pe/headers.d.ts +160 -0
- package/src/types/platform/bytes.d.ts +3 -0
- package/src/types/platform/compression.d.ts +2 -0
- package/src/types/platform/crypto.d.ts +4 -0
- package/src/types/resolution/module.d.ts +12 -0
- package/src/types/writer/patch.d.ts +4 -0
- package/src/types/writer/pe.d.ts +9 -0
- package/src/types/writer/structural.d.ts +4 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
import { FormatError, UnsupportedFormatError } from "../binary/errors.js";
|
|
2
|
+
import { parseEmbeddedPortablePdbData } from "../pe/headers.js";
|
|
3
|
+
import {
|
|
4
|
+
addEmbeddedPortablePdbDocument as addPortablePdbDocument,
|
|
5
|
+
insertEmbeddedPortablePdbDocument as insertPortablePdbDocument,
|
|
6
|
+
addEmbeddedPortablePdbTypeDefinitionDocuments as addPortablePdbTypeDefinitionDocuments,
|
|
7
|
+
removeEmbeddedPortablePdbDocument as removePortablePdbDocument,
|
|
8
|
+
replaceEmbeddedPortablePdbTypeDefinitionDocuments as replacePortablePdbTypeDefinitionDocuments,
|
|
9
|
+
replaceEmbeddedPortablePdbDocumentMetadata as replacePortablePdbDocumentMetadata,
|
|
10
|
+
replaceEmbeddedPortablePdbDocumentName as replacePortablePdbDocumentName,
|
|
11
|
+
replaceEmbeddedPortablePdbSequencePoints as replacePortablePdbSequencePoints,
|
|
12
|
+
replaceEmbeddedPortablePdbMethodDocument as replacePortablePdbMethodDocument,
|
|
13
|
+
replaceEmbeddedPortablePdbImportScope as replacePortablePdbImportScope,
|
|
14
|
+
replaceEmbeddedPortablePdbLocalScope as replacePortablePdbLocalScope,
|
|
15
|
+
replaceEmbeddedPortablePdbLocalVariable as replacePortablePdbLocalVariable,
|
|
16
|
+
replaceEmbeddedPortablePdbLocalConstant as replacePortablePdbLocalConstant,
|
|
17
|
+
replaceEmbeddedPortablePdbCustomDebugInformation as replacePortablePdbCustomDebugInformation,
|
|
18
|
+
replaceEmbeddedPortablePdbSource as replacePortablePdbSource,
|
|
19
|
+
addEmbeddedPortablePdbSource as addPortablePdbSource,
|
|
20
|
+
removeEmbeddedPortablePdbSource as removePortablePdbSource,
|
|
21
|
+
removeEmbeddedPortablePdbCustomDebugInformation as removePortablePdbCustomDebugInformation,
|
|
22
|
+
replaceEmbeddedPortablePdbSourceLink as replacePortablePdbSourceLink,
|
|
23
|
+
removeEmbeddedPortablePdbSourceLink as removePortablePdbSourceLink,
|
|
24
|
+
addEmbeddedPortablePdbSourceLink as addPortablePdbSourceLink
|
|
25
|
+
} from "../metadata/portable-pdb.js";
|
|
26
|
+
|
|
27
|
+
export function createPortablePdbEditor(hooks) {
|
|
28
|
+
return {
|
|
29
|
+
addEmbeddedPortablePdbDocument(debugEntryIndex, name, options) {
|
|
30
|
+
hooks.ensureEditable();
|
|
31
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
32
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
33
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
34
|
+
}
|
|
35
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
36
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
37
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
38
|
+
}
|
|
39
|
+
const data = addPortablePdbDocument(
|
|
40
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
41
|
+
name,
|
|
42
|
+
options
|
|
43
|
+
);
|
|
44
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
insertEmbeddedPortablePdbDocument(debugEntryIndex, options) {
|
|
48
|
+
hooks.ensureEditable();
|
|
49
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
50
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
51
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
52
|
+
}
|
|
53
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
54
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
55
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
56
|
+
}
|
|
57
|
+
const data = insertPortablePdbDocument(
|
|
58
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
59
|
+
options
|
|
60
|
+
);
|
|
61
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
addEmbeddedPortablePdbTypeDefinitionDocuments(
|
|
65
|
+
debugEntryIndex,
|
|
66
|
+
typeRid,
|
|
67
|
+
documentRids
|
|
68
|
+
) {
|
|
69
|
+
hooks.ensureEditable();
|
|
70
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
71
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
72
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
73
|
+
}
|
|
74
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
75
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
76
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
77
|
+
}
|
|
78
|
+
const data = addPortablePdbTypeDefinitionDocuments(
|
|
79
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
80
|
+
typeRid,
|
|
81
|
+
documentRids
|
|
82
|
+
);
|
|
83
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
removeEmbeddedPortablePdbDocument(debugEntryIndex, documentRid) {
|
|
87
|
+
hooks.ensureEditable();
|
|
88
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
89
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
90
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
91
|
+
}
|
|
92
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
93
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
94
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
95
|
+
}
|
|
96
|
+
const data = removePortablePdbDocument(
|
|
97
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
98
|
+
documentRid
|
|
99
|
+
);
|
|
100
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
replaceEmbeddedPortablePdbTypeDefinitionDocuments(
|
|
104
|
+
debugEntryIndex,
|
|
105
|
+
typeRid,
|
|
106
|
+
documentRids
|
|
107
|
+
) {
|
|
108
|
+
hooks.ensureEditable();
|
|
109
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
110
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
111
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
112
|
+
}
|
|
113
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
114
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
115
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
116
|
+
}
|
|
117
|
+
const data = replacePortablePdbTypeDefinitionDocuments(
|
|
118
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
119
|
+
typeRid,
|
|
120
|
+
documentRids
|
|
121
|
+
);
|
|
122
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
replaceEmbeddedPortablePdbDocumentMetadata(debugEntryIndex, documentRid, options) {
|
|
126
|
+
hooks.ensureEditable();
|
|
127
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
128
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
129
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
130
|
+
}
|
|
131
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
132
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
133
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
134
|
+
}
|
|
135
|
+
const data = replacePortablePdbDocumentMetadata(
|
|
136
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
137
|
+
documentRid,
|
|
138
|
+
options
|
|
139
|
+
);
|
|
140
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
replaceEmbeddedPortablePdbDocumentName(debugEntryIndex, documentRid, name, separator) {
|
|
144
|
+
hooks.ensureEditable();
|
|
145
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
146
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
147
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
148
|
+
}
|
|
149
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
150
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
151
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
152
|
+
}
|
|
153
|
+
const data = replacePortablePdbDocumentName(
|
|
154
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
155
|
+
documentRid,
|
|
156
|
+
name,
|
|
157
|
+
separator
|
|
158
|
+
);
|
|
159
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
replaceEmbeddedPortablePdbSequencePoints(debugEntryIndex, methodRid, sequencePoints) {
|
|
163
|
+
hooks.ensureEditable();
|
|
164
|
+
if (this._portablePdbOffsetBaselines.has(methodRid)) {
|
|
165
|
+
throw new UnsupportedFormatError(
|
|
166
|
+
"Portable PDB sequence points cannot be replaced after IL offset remapping has been staged"
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
170
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
171
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
172
|
+
}
|
|
173
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
174
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
175
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
176
|
+
}
|
|
177
|
+
const data = replacePortablePdbSequencePoints(
|
|
178
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
179
|
+
methodRid,
|
|
180
|
+
sequencePoints
|
|
181
|
+
);
|
|
182
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
replaceEmbeddedPortablePdbMethodDocument(debugEntryIndex, methodRid, documentRid) {
|
|
186
|
+
hooks.ensureEditable();
|
|
187
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
188
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
189
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
190
|
+
}
|
|
191
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
192
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
193
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
194
|
+
}
|
|
195
|
+
const data = replacePortablePdbMethodDocument(
|
|
196
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
197
|
+
methodRid,
|
|
198
|
+
documentRid
|
|
199
|
+
);
|
|
200
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
replaceEmbeddedPortablePdbImportScope(debugEntryIndex, importScopeRid, options) {
|
|
204
|
+
hooks.ensureEditable();
|
|
205
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
206
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
207
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
208
|
+
}
|
|
209
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
210
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
211
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
212
|
+
}
|
|
213
|
+
const data = replacePortablePdbImportScope(
|
|
214
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
215
|
+
importScopeRid,
|
|
216
|
+
options
|
|
217
|
+
);
|
|
218
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
replaceEmbeddedPortablePdbLocalScope(debugEntryIndex, localScopeRid, options) {
|
|
222
|
+
hooks.ensureEditable();
|
|
223
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
224
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
225
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
226
|
+
}
|
|
227
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
228
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
229
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
230
|
+
}
|
|
231
|
+
const pdb = hooks.getPortablePdbForEdit(debugEntryIndex, entry);
|
|
232
|
+
const localScope = pdb.tables.rows.get(50)?.[localScopeRid - 1];
|
|
233
|
+
if (!localScope || localScope.rid !== localScopeRid) {
|
|
234
|
+
throw new RangeError(`Invalid Portable PDB LocalScope row ID ${localScopeRid}`);
|
|
235
|
+
}
|
|
236
|
+
if (this._portablePdbOffsetBaselines.has(localScope.Method.rid)) {
|
|
237
|
+
throw new UnsupportedFormatError(
|
|
238
|
+
"Portable PDB LocalScope offsets cannot be replaced after IL offset remapping has been staged"
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
const data = replacePortablePdbLocalScope(pdb, localScopeRid, options);
|
|
242
|
+
const updatedPdb = parseEmbeddedPortablePdbData(data, 0, data.length);
|
|
243
|
+
const updatedScope = updatedPdb.tables.rows.get(50)?.[localScopeRid - 1];
|
|
244
|
+
const body = this.getMethodBody(localScope.Method.rid);
|
|
245
|
+
if (!updatedScope || !body) {
|
|
246
|
+
throw new FormatError(
|
|
247
|
+
`Portable PDB LocalScope row ${localScopeRid} does not resolve to a method body`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
const isBoundary = (offset) => offset === body.codeSize ||
|
|
251
|
+
body.instructions.some((instruction) => instruction.offset === offset);
|
|
252
|
+
const endOffset = updatedScope.StartOffset + updatedScope.Length;
|
|
253
|
+
if (!isBoundary(updatedScope.StartOffset) || !isBoundary(endOffset)) {
|
|
254
|
+
throw new FormatError(
|
|
255
|
+
`Portable PDB LocalScope row ${localScopeRid} does not align with MethodDef ${localScope.Method.rid} instruction boundaries`
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
replaceEmbeddedPortablePdbLocalVariable(debugEntryIndex, localVariableRid, options) {
|
|
262
|
+
hooks.ensureEditable();
|
|
263
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
264
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
265
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
266
|
+
}
|
|
267
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
268
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
269
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
270
|
+
}
|
|
271
|
+
const data = replacePortablePdbLocalVariable(
|
|
272
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
273
|
+
localVariableRid,
|
|
274
|
+
options
|
|
275
|
+
);
|
|
276
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
replaceEmbeddedPortablePdbLocalConstant(debugEntryIndex, localConstantRid, options) {
|
|
280
|
+
hooks.ensureEditable();
|
|
281
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
282
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
283
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
284
|
+
}
|
|
285
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
286
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
287
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
288
|
+
}
|
|
289
|
+
const data = replacePortablePdbLocalConstant(
|
|
290
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
291
|
+
localConstantRid,
|
|
292
|
+
options
|
|
293
|
+
);
|
|
294
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
replaceEmbeddedPortablePdbCustomDebugInformation(
|
|
298
|
+
debugEntryIndex,
|
|
299
|
+
customDebugInformationRid,
|
|
300
|
+
value
|
|
301
|
+
) {
|
|
302
|
+
hooks.ensureEditable();
|
|
303
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
304
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
305
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
306
|
+
}
|
|
307
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
308
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
309
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
310
|
+
}
|
|
311
|
+
const data = replacePortablePdbCustomDebugInformation(
|
|
312
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
313
|
+
customDebugInformationRid,
|
|
314
|
+
value
|
|
315
|
+
);
|
|
316
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
317
|
+
},
|
|
318
|
+
|
|
319
|
+
replaceEmbeddedPortablePdbSource(debugEntryIndex, documentRid, source, options) {
|
|
320
|
+
hooks.ensureEditable();
|
|
321
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
322
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
323
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
324
|
+
}
|
|
325
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
326
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
327
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
328
|
+
}
|
|
329
|
+
const data = replacePortablePdbSource(
|
|
330
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
331
|
+
documentRid,
|
|
332
|
+
source,
|
|
333
|
+
options
|
|
334
|
+
);
|
|
335
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
addEmbeddedPortablePdbSource(debugEntryIndex, documentRid, source, options) {
|
|
339
|
+
hooks.ensureEditable();
|
|
340
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
341
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
342
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
343
|
+
}
|
|
344
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
345
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
346
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
347
|
+
}
|
|
348
|
+
const data = addPortablePdbSource(
|
|
349
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
350
|
+
documentRid,
|
|
351
|
+
source,
|
|
352
|
+
options
|
|
353
|
+
);
|
|
354
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
removeEmbeddedPortablePdbSource(debugEntryIndex, documentRid) {
|
|
358
|
+
hooks.ensureEditable();
|
|
359
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
360
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
361
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
362
|
+
}
|
|
363
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
364
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
365
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
366
|
+
}
|
|
367
|
+
const data = removePortablePdbSource(
|
|
368
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
369
|
+
documentRid
|
|
370
|
+
);
|
|
371
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
removeEmbeddedPortablePdbCustomDebugInformation(debugEntryIndex, recordRid) {
|
|
375
|
+
hooks.ensureEditable();
|
|
376
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
377
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
378
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
379
|
+
}
|
|
380
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
381
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
382
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
383
|
+
}
|
|
384
|
+
const data = removePortablePdbCustomDebugInformation(
|
|
385
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
386
|
+
recordRid
|
|
387
|
+
);
|
|
388
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
389
|
+
},
|
|
390
|
+
|
|
391
|
+
replaceEmbeddedPortablePdbSourceLink(debugEntryIndex, sourceLink) {
|
|
392
|
+
hooks.ensureEditable();
|
|
393
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
394
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
395
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
396
|
+
}
|
|
397
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
398
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
399
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
400
|
+
}
|
|
401
|
+
const data = replacePortablePdbSourceLink(
|
|
402
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
403
|
+
sourceLink
|
|
404
|
+
);
|
|
405
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
406
|
+
},
|
|
407
|
+
|
|
408
|
+
removeEmbeddedPortablePdbSourceLink(debugEntryIndex) {
|
|
409
|
+
hooks.ensureEditable();
|
|
410
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
411
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
412
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
413
|
+
}
|
|
414
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
415
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
416
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
417
|
+
}
|
|
418
|
+
const data = removePortablePdbSourceLink(
|
|
419
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry)
|
|
420
|
+
);
|
|
421
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
422
|
+
},
|
|
423
|
+
|
|
424
|
+
addEmbeddedPortablePdbSourceLink(debugEntryIndex, sourceLink) {
|
|
425
|
+
hooks.ensureEditable();
|
|
426
|
+
if (!Number.isInteger(debugEntryIndex) || debugEntryIndex < 0 ||
|
|
427
|
+
debugEntryIndex >= this.pe.debugDirectoryEntries.length) {
|
|
428
|
+
throw new RangeError(`Invalid debug-directory entry index ${debugEntryIndex}`);
|
|
429
|
+
}
|
|
430
|
+
const entry = this.pe.debugDirectoryEntries[debugEntryIndex];
|
|
431
|
+
if (entry.type !== 17 || !entry.embeddedPortablePdb) {
|
|
432
|
+
throw new UnsupportedFormatError("Debug-directory entry is not an embedded Portable PDB");
|
|
433
|
+
}
|
|
434
|
+
const data = addPortablePdbSourceLink(
|
|
435
|
+
hooks.getPortablePdbForEdit(debugEntryIndex, entry),
|
|
436
|
+
sourceLink
|
|
437
|
+
);
|
|
438
|
+
return this.replaceEmbeddedPortablePdb(debugEntryIndex, data);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { Assembly as NodeAssembly } from "../index.js";
|
|
2
|
+
|
|
3
|
+
type Browserify<T> = T extends NodeAssembly
|
|
4
|
+
? BrowserAssembly
|
|
5
|
+
: T extends (...args: infer Args) => infer Result
|
|
6
|
+
? (...args: { [K in keyof Args]: Browserify<Args[K]> }) =>
|
|
7
|
+
Browserify<Result> | Promise<Browserify<Result>>
|
|
8
|
+
: T extends readonly unknown[]
|
|
9
|
+
? { [K in keyof T]: Browserify<T[K]> }
|
|
10
|
+
: T extends object
|
|
11
|
+
? { [K in keyof T]: Browserify<T[K]> }
|
|
12
|
+
: T;
|
|
13
|
+
|
|
14
|
+
type AsyncMethods<T> = {
|
|
15
|
+
[K in keyof T as T[K] extends (...args: infer _Args) => unknown ? K : never]:
|
|
16
|
+
T[K] extends (...args: infer Args) => infer Result
|
|
17
|
+
? (...args: { [I in keyof Args]: Browserify<Args[I]> }) => Promise<Browserify<Result>>
|
|
18
|
+
: never;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type ResolverMethodName =
|
|
22
|
+
| "parseCustomAttribute"
|
|
23
|
+
| "parseDeclSecurity"
|
|
24
|
+
| "replaceCustomAttribute"
|
|
25
|
+
| "addCustomAttribute"
|
|
26
|
+
| "insertCustomAttribute"
|
|
27
|
+
| "addDeclSecurity"
|
|
28
|
+
| "insertDeclSecurity"
|
|
29
|
+
| "replaceDeclSecurity";
|
|
30
|
+
|
|
31
|
+
type MethodResult<K extends keyof NodeAssembly> =
|
|
32
|
+
NodeAssembly[K] extends (...args: any[]) => infer Result
|
|
33
|
+
? Result extends NodeAssembly ? BrowserAssembly : Result
|
|
34
|
+
: unknown;
|
|
35
|
+
|
|
36
|
+
export interface BrowserTypeResolverContext {
|
|
37
|
+
assembly: BrowserAssembly;
|
|
38
|
+
reference: { table: number; rid: number } | null;
|
|
39
|
+
assemblyReference: unknown;
|
|
40
|
+
assemblyIdentity: string | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface BrowserResolverOptions {
|
|
44
|
+
resolveEnum?: (name: string) => number | undefined | Promise<number | undefined>;
|
|
45
|
+
resolveType?: (
|
|
46
|
+
name: string,
|
|
47
|
+
context: BrowserTypeResolverContext
|
|
48
|
+
) =>
|
|
49
|
+
| { assembly: BrowserAssembly; rid: number }
|
|
50
|
+
| null
|
|
51
|
+
| undefined
|
|
52
|
+
| Promise<{ assembly: BrowserAssembly; rid: number } | null | undefined>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface BrowserAssemblyState extends Readonly<Record<string, unknown>> {
|
|
56
|
+
bytes: Uint8Array;
|
|
57
|
+
modified: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type BrowserAssembly = Omit<AsyncMethods<NodeAssembly>, ResolverMethodName> & {
|
|
61
|
+
parseCustomAttribute(
|
|
62
|
+
rid: number,
|
|
63
|
+
options?: BrowserResolverOptions
|
|
64
|
+
): Promise<MethodResult<"parseCustomAttribute">>;
|
|
65
|
+
parseDeclSecurity(
|
|
66
|
+
rid: number,
|
|
67
|
+
options?: BrowserResolverOptions
|
|
68
|
+
): Promise<MethodResult<"parseDeclSecurity">>;
|
|
69
|
+
replaceCustomAttribute(
|
|
70
|
+
rid: number,
|
|
71
|
+
value: unknown,
|
|
72
|
+
options?: BrowserResolverOptions
|
|
73
|
+
): Promise<MethodResult<"replaceCustomAttribute">>;
|
|
74
|
+
addCustomAttribute(value: {
|
|
75
|
+
parent: unknown;
|
|
76
|
+
constructor: unknown;
|
|
77
|
+
value: unknown;
|
|
78
|
+
} & BrowserResolverOptions): Promise<MethodResult<"addCustomAttribute">>;
|
|
79
|
+
insertCustomAttribute(value: {
|
|
80
|
+
parent: unknown;
|
|
81
|
+
constructor: unknown;
|
|
82
|
+
value: unknown;
|
|
83
|
+
} & BrowserResolverOptions): Promise<MethodResult<"insertCustomAttribute">>;
|
|
84
|
+
addDeclSecurity(value: {
|
|
85
|
+
parent: unknown;
|
|
86
|
+
action: number;
|
|
87
|
+
permissionSet: unknown;
|
|
88
|
+
} & BrowserResolverOptions): Promise<MethodResult<"addDeclSecurity">>;
|
|
89
|
+
insertDeclSecurity(value: {
|
|
90
|
+
parent: unknown;
|
|
91
|
+
action: number;
|
|
92
|
+
permissionSet: unknown;
|
|
93
|
+
} & BrowserResolverOptions): Promise<MethodResult<"insertDeclSecurity">>;
|
|
94
|
+
replaceDeclSecurity(
|
|
95
|
+
rid: number,
|
|
96
|
+
value?: {
|
|
97
|
+
action?: number;
|
|
98
|
+
permissionSet?: unknown;
|
|
99
|
+
} & BrowserResolverOptions
|
|
100
|
+
): Promise<MethodResult<"replaceDeclSecurity">>;
|
|
101
|
+
getState(): Promise<BrowserAssemblyState>;
|
|
102
|
+
callUtility(name: string, ...args: unknown[]): Promise<unknown>;
|
|
103
|
+
dispose(): void;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export type Assembly = BrowserAssembly;
|
|
107
|
+
|
|
108
|
+
export declare const BrowserAssembly: {
|
|
109
|
+
from(
|
|
110
|
+
input: Uint8Array | ArrayBuffer | Blob,
|
|
111
|
+
options?: { workerFactory?: () => Worker; transferInput?: boolean }
|
|
112
|
+
): Promise<BrowserAssembly>;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export declare const Assembly: typeof BrowserAssembly;
|
|
116
|
+
|
|
117
|
+
export declare function parseAssembly(
|
|
118
|
+
input: Uint8Array | ArrayBuffer | Blob,
|
|
119
|
+
options?: { workerFactory?: () => Worker; transferInput?: boolean }
|
|
120
|
+
): Promise<BrowserAssembly>;
|
|
121
|
+
|
|
122
|
+
export declare function callUtility(name: string, ...args: unknown[]): Promise<unknown>;
|
|
123
|
+
export { FormatError, UnsupportedFormatError } from "../index.js";
|