Skip to content

Commit eb16abb

Browse files
committed
chore: update freeing behavior to reduce memory leaks
1 parent 2d5ae99 commit eb16abb

2 files changed

Lines changed: 28 additions & 15 deletions

File tree

src/libexif/ExifData.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ExifContent } from "./ExifContent.ts";
22
import { ExifEntry } from "./ExifEntry.ts";
33
import type { ExifLog } from "./ExifLog.ts";
4-
import type { ExifMem } from "./ExifMem.ts";
4+
import { ExifMem } from "./ExifMem.ts";
55
import { ExifMnoteData } from "./ExifMnoteData.ts";
66
import { POINTER_SIZE } from "../constants.ts";
77
import { ExifByteOrder, type ByteOrder } from "../enums/ExifByteOrder.ts";
@@ -66,15 +66,16 @@ class ExifData extends ExifDataStruct implements DisposableDataSegment {
6666
}
6767

6868
/**
69-
* Will update all ifd's .parent correctly.
69+
* Will update all ifd's .parent correctly. Note you will need to free the
70+
* previous ifds you set yourself. This is so that someone can do something like
71+
* exifData.ifd = exifData.ifd.with(0, newContent)
7072
*/
7173
set ifd(ifd: ExifContent[]) {
7274
if (ifd.length !== ExifIfd.COUNT) {
7375
throw new Error(
7476
`ExifData.ifd: Expected ${ExifIfd.COUNT} IFDs, got ${ifd.length}`,
7577
);
7678
}
77-
7879
this.ifdPtr = ifd.map((ifd) => ifd.byteOffset) as IfdPtr;
7980
ifd.forEach((exifContent) => {
8081
exifContent.parent = this;
@@ -86,10 +87,14 @@ class ExifData extends ExifDataStruct implements DisposableDataSegment {
8687
}
8788

8889
set data(data: Uint8Array) {
89-
const dataPtr = malloc(data.byteLength);
90-
HEAPU8.set(data, dataPtr);
91-
this.dataPtr = dataPtr;
90+
const prevDataPtr = this.dataPtr;
91+
const newDataPtr = malloc(data.byteLength);
92+
HEAPU8.set(data, newDataPtr);
93+
this.dataPtr = newDataPtr;
9294
this.size = data.byteLength;
95+
if (prevDataPtr !== 0) {
96+
free(prevDataPtr);
97+
}
9398
}
9499

95100
/**
@@ -198,7 +203,10 @@ class ExifData extends ExifDataStruct implements DisposableDataSegment {
198203
throw new Error("ExifData.saveData: Memory allocation failed");
199204
}
200205

201-
return HEAPU8.subarray(dataPtr, dataPtr + dataSize);
206+
const data = HEAPU8.subarray(dataPtr, dataPtr + dataSize);
207+
const exifMem = new ExifMem(dataPtr);
208+
exifMem.unref();
209+
return data;
202210
}
203211

204212
/**

src/libexif/ExifEntry.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,22 @@ class ExifEntry extends ExifEntryStruct implements DisposableDataSegment {
105105
* Running this setter will free .dataPtr beforehand
106106
*/
107107
set data(data: Uint8Array) {
108-
if (this.dataPtr !== 0) {
109-
free(this.dataPtr);
110-
}
111-
108+
const prevDataPtr = this.dataPtr;
112109
this.size = data.length;
113110
const dataPtr = malloc(data.byteLength);
114111
HEAPU8.set(data, dataPtr);
115112
this.dataPtr = dataPtr;
113+
114+
if (prevDataPtr !== 0) {
115+
free(prevDataPtr);
116+
}
116117
}
117118

118119
get parent() {
119120
return this.parentPtr !== 0 ? new ExifContent(this.parentPtr) : null;
120121
}
121122

123+
// Does not free parent
122124
set parent(parent: ExifContent | null) {
123125
this.parentPtr = parent?.byteOffset ?? 0;
124126
}
@@ -221,16 +223,19 @@ class ExifEntry extends ExifEntryStruct implements DisposableDataSegment {
221223
* Updates ExifEntry.data using a TypedArray
222224
*/
223225
fromTypedArray(typedArray: ValidTypedArray) {
224-
const prevPtr = this.dataPtr;
225-
const newPtr = setDataFromTypedArray(
226+
const prevDataPtr = this.dataPtr;
227+
const newDataPtr = setDataFromTypedArray(
226228
typedArray,
227229
this.format ?? "UNDEFINED",
228230
this.byteOrder,
229231
);
230-
this.dataPtr = newPtr;
232+
this.dataPtr = newDataPtr;
231233
this.components = typedArray.length;
232234
this.size = typedArray.byteLength;
233-
free(prevPtr);
235+
236+
if (prevDataPtr !== 0) {
237+
free(prevDataPtr);
238+
}
234239
}
235240

236241
toTypedArray(): ValidTypedArray {

0 commit comments

Comments
 (0)