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.
Files changed (50) hide show
  1. package/README.md +25 -6
  2. package/REFERENCE.md +4 -0
  3. package/dist/browser/index.js +345 -0
  4. package/dist/browser/worker.js +42480 -0
  5. package/package.json +23 -4
  6. package/src/assembly/instruction-editing.js +165 -0
  7. package/src/assembly/method-removal.js +789 -0
  8. package/src/assembly/pointer-table-editing.js +506 -0
  9. package/src/assembly/portable-pdb-editing.js +441 -0
  10. package/src/browser/index.d.ts +123 -0
  11. package/src/browser/index.js +373 -0
  12. package/src/browser/worker-runtime.js +287 -0
  13. package/src/browser/worker.js +47 -0
  14. package/src/index.d.ts +267 -0
  15. package/src/index.js +107 -1574
  16. package/src/metadata/portable-pdb.js +2 -2
  17. package/src/metadata/strong-name.js +84 -83
  18. package/src/pe/headers.js +1 -1
  19. package/src/platform/bytes.js +21 -0
  20. package/src/platform/compression.js +24 -0
  21. package/src/platform/crypto.js +17 -0
  22. package/src/types/assembly/instruction-editing.d.ts +33 -0
  23. package/src/types/assembly/method-removal.d.ts +3 -0
  24. package/src/types/assembly/pointer-table-editing.d.ts +3 -0
  25. package/src/types/assembly/portable-pdb-editing.d.ts +23 -0
  26. package/src/types/binary/errors.d.ts +7 -0
  27. package/src/types/binary/reader.d.ts +30 -0
  28. package/src/types/il/body.d.ts +51 -0
  29. package/src/types/il/instructions.d.ts +33 -0
  30. package/src/types/il/opcodes.d.ts +2 -0
  31. package/src/types/il/rewrite.d.ts +38 -0
  32. package/src/types/index.d.ts +864 -0
  33. package/src/types/metadata/classic-pdb.d.ts +688 -0
  34. package/src/types/metadata/custom-attributes.d.ts +28 -0
  35. package/src/types/metadata/portable-pdb.d.ts +296 -0
  36. package/src/types/metadata/resources.d.ts +1 -0
  37. package/src/types/metadata/root-writer.d.ts +1 -0
  38. package/src/types/metadata/signatures.d.ts +5 -0
  39. package/src/types/metadata/streams.d.ts +26 -0
  40. package/src/types/metadata/strong-name.d.ts +11 -0
  41. package/src/types/metadata/tables.d.ts +25 -0
  42. package/src/types/metadata/writer.d.ts +16 -0
  43. package/src/types/pe/headers.d.ts +160 -0
  44. package/src/types/platform/bytes.d.ts +3 -0
  45. package/src/types/platform/compression.d.ts +2 -0
  46. package/src/types/platform/crypto.d.ts +4 -0
  47. package/src/types/resolution/module.d.ts +12 -0
  48. package/src/types/writer/patch.d.ts +4 -0
  49. package/src/types/writer/pe.d.ts +9 -0
  50. 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";