You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Why Closing in Application Code is Cleaner (Recommended)
When you write the code that opens a resource, you should also write the code that closes it. This guarantees resource integrity and simplifies error handling.
Guaranteed Closure (Robustness) | Using a try...finally block in your application code ensures the FileHandle is closed no matter what happens (success, crash, or error during parsing). This is the gold standard for resource management.
Clear Ownership | The application code owns the handle. The library (exifr) is merely a consumer of that open handle. The responsibility for closing is clear, avoiding the ambiguous "auto-close" logic that was failing internally in exifr.
Better Error Handling | If exifr.parse() throws an exception, your application's finally block still executes, preventing a catastrophic leak. If exifr managed the close internally, a crash could occur before its internal closure logic runs.
Preserves Library Intent | You preserve exifr's design as a stateless parser while fixing your leak.
PR Review by Gemini:
This is an excellent and comprehensive set of changes that implements the "auto-closing" fix cleanly. It addresses the leak, preserves the chunked reading, and uses the existing public API.
This is a good diff for a Pull Request (PR).
Here is a breakdown of why the changes are correct and what they achieve:
Analysis of the Diff
The diff contains three distinct, necessary patches that implement the auto-close fix:
1. src/core.mjs (The Auto-Closure Logic)
diff --git a/src/core.mjs b/src/core.mjs
index ea4810b..3f0fe02 100644
--- a/src/core.mjs+++ b/src/core.mjs@@ -12,6 +12,12 @@ import {Exifr} from './Exifr.mjs'
export async function parse(input, options) {
let exr = new Exifr(options)
- await exr.read(input)- return exr.parse()+ try {+ await exr.read(input)+ return await exr.parse()+ } finally {+ if (exr.file && exr.file.close) {+ await exr.file.close()+ }+ }
}
Goal Achieved: This is the core fix for the leak. It wraps the entire reading and parsing process in a try...finally block.
Safety: The finally block guarantees that exr.file.close() is called, whether the parsing succeeds or throws an error.
Cleanliness: It relies on the Exifr instance (exr) storing the reader object (exr.file), which has a close() method, maintaining the object-oriented structure.
diff --git a/src/file-readers/FsReader.mjs b/src/file-readers/FsReader.mjs
...
@@ -24,11 +24,19 @@ export class FsReader extends ChunkedReader {
async open() {
if (this.fh === undefined) {
- this.fh = await this.fs.open(this.input, 'r')- this.size = (await this.fh.stat(this.input)).size+ // Added logic to check for and use a pre-opened FileHandle+ if (this.input && typeof this.input === 'object' && typeof this.input.close === 'function' && typeof this.input.read === 'function') {+ this.fh = this.input+ } else {+ // Input is a string path, open it normally+ this.fh = await this.fs.open(this.input, 'r')+ }++ // Note: Use .stat() without arguments on the FileHandle+ this.size = (await this.fh.stat()).size
}
}
Goal Achieved: This allows advanced users to pass a pre-opened FileHandle object (the "Application-Level Closure" method we discussed). Although the core.mjs patch solves your immediate problem, adding this flexibility makes the library much more robust for various Node.js use cases.
Correctness: It correctly checks for the FileHandle structure and falls back to opening the file path if it's not present.
Goal Achieved: This is the necessary step to route the FileHandle input (added in the FsReader patch) to the correct reader class ('fs'). Without this change, passing a FileHandle would hit the throwError(INVALID_INPUT) line.
Conclusion for PR
The combination of these three changes is excellent. It not only fixes the automatic resource leak (via core.mjs), but also improves the library's utility by allowing external FileHandle objects (via FsReader.mjs and reader.mjs).
This is a well-structured and comprehensive fix for the resource leak issue.
evrial
changed the title
Fix memory leakage - Implement the Asynchronous Disposable Pattern to allow automatic cleanup
Fix memory leakage - Implement the FileHandle as input for resource safety and closing in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the FileHandle as input for resource safety and closing in application code
Fix memory leakage - Implement the FileHandle as input for IO resource safety and closing in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the FileHandle as input for IO resource safety and closing in application code
Fix memory leakage - Implement the FileHandle as input for IO resource safety and open/closing in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the FileHandle as input for IO resource safety and open/closing in application code
Fix memory leakage - Implement the FileHandle as input for IO resource safety and opening/closing in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the FileHandle as input for IO resource safety and opening/closing in application code
Fix memory leakage - Implement the FileHandle as input for IO safety and opening/closing in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the FileHandle as input for IO safety and opening/closing in application code
Fix memory leakage - Implement the FileHandle as input for IO safety and resource ownership in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the FileHandle as input for IO safety and resource ownership in application code
Fix memory leakage - Implement the FileHandle as input for IO safety and complete resource ownership in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the FileHandle as input for IO safety and complete resource ownership in application code
Fix memory leakage - Implement the pre-opened FileHandle as input for IO safety and complete resource ownership in application code
Dec 1, 2025
evrial
changed the title
Fix memory leakage - Implement the pre-opened FileHandle as input for IO safety and complete resource ownership in application code
Fix memory leakage - Implement the pre-opened FileHandle as input for IO safety and complete resource ownership in Node application code
Dec 1, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why Closing in Application Code is Cleaner (Recommended)
When you write the code that opens a resource, you should also write the code that closes it. This guarantees resource integrity and simplifies error handling.
Guaranteed Closure (Robustness) | Using a try...finally block in your application code ensures the FileHandle is closed no matter what happens (success, crash, or error during parsing). This is the gold standard for resource management.
Clear Ownership | The application code owns the handle. The library (exifr) is merely a consumer of that open handle. The responsibility for closing is clear, avoiding the ambiguous "auto-close" logic that was failing internally in exifr.
Better Error Handling | If exifr.parse() throws an exception, your application's finally block still executes, preventing a catastrophic leak. If exifr managed the close internally, a crash could occur before its internal closure logic runs.
Preserves Library Intent | You preserve exifr's design as a stateless parser while fixing your leak.
PR Review by Gemini:
This is an excellent and comprehensive set of changes that implements the "auto-closing" fix cleanly. It addresses the leak, preserves the chunked reading, and uses the existing public API.
This is a good diff for a Pull Request (PR).
Here is a breakdown of why the changes are correct and what they achieve:
Analysis of the Diff
The diff contains three distinct, necessary patches that implement the auto-close fix:
1.
src/core.mjs(The Auto-Closure Logic)try...finallyblock.finallyblock guarantees thatexr.file.close()is called, whether the parsing succeeds or throws an error.Exifrinstance (exr) storing the reader object (exr.file), which has aclose()method, maintaining the object-oriented structure.2.
src/file-readers/FsReader.mjs(To AcceptFileHandle)FileHandleobject (the "Application-Level Closure" method we discussed). Although thecore.mjspatch solves your immediate problem, adding this flexibility makes the library much more robust for various Node.js use cases.FileHandlestructure and falls back to opening the file path if it's not present.3.
src/reader.mjs(To RouteFileHandle)FileHandleinput (added in theFsReaderpatch) to the correct reader class ('fs'). Without this change, passing aFileHandlewould hit thethrowError(INVALID_INPUT)line.Conclusion for PR
The combination of these three changes is excellent. It not only fixes the automatic resource leak (via
core.mjs), but also improves the library's utility by allowing externalFileHandleobjects (viaFsReader.mjsandreader.mjs).This is a well-structured and comprehensive fix for the resource leak issue.