Skip to content

fix: revoke Blob URLs created by p5.File - #9155

Merged
limzykenneth merged 10 commits into
processing:mainfrom
slash-init:fix/file-blob-url-lifecycle
Sep 28, 2026
Merged

limzykenneth merged 10 commits into
processing:mainfrom
slash-init:fix/file-blob-url-lifecycle

Conversation

@slash-init

@slash-init slash-init commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Resolves #9134

Changes:

  • Track media p5.File objects with Blob URLs on their owning p5 instance.
  • Automatically revoke tracked Blob URLs through the remove lifecycle hook.
  • Add p5.File.revoke() for explicitly releasing a file’s Blob URL.
  • Make p5.File.revoke() idempotent.
  • Track media files from both createFileInput() and Element.drop() without passing pInst through File._load().
  • Register the p5.File addon through p5.registerAddon().
  • Add behavior-focused unit tests covering automatic cleanup, manual revocation, duplicate cleanup prevention, instance isolation, and both file-loading entry points.
  • Preserve existing behavior for non-media files.

PR Checklist

@rk-3001

rk-3001 commented Sep 9, 2026

Copy link
Copy Markdown

Hi, I'd like to take this on.
Cause: p5.File._load() creates blob URLs for audio/video files via URL.createObjectURL() but never revokes them, so they leak for the page's lifetime instead of the sketch's.
Fix: track created URLs in a _blobUrls Set on the p5 instance (passed through from createFileInput/drop), revoke + clear them in p5.remove(), and add a file.revoke() method for early manual cleanup. I'll include unit tests.
I can work on this...

@slash-init

Copy link
Copy Markdown
Contributor Author

@rk-3001 i think you should read contributor guidelines first.

@Vaivaswat2244 Vaivaswat2244 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the pr @slash-init . Matches what we discussed on the issue, left a few comments.

Comment thread src/dom/p5.File.js Outdated
Comment thread test/js/mocks.js Outdated
@slash-init
slash-init force-pushed the fix/file-blob-url-lifecycle branch from de025d3 to 6cbdcea Compare September 16, 2026 12:05
Comment thread src/core/main.js Outdated
this._userNode = node;
this._curElement = null;
this._elements = [];
this._blobUrls = new Set();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be on the p5 instance? Can it not be fully handled by p5.File itself? For cleaning up when the sketch is removed, use the remove lifecycle hook which is designed for this kind of use.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@limzykenneth Thanks for the feedback! I looked through the lifecycle code and I think I understand the direction now: move the Blob URL cleanup into p5.File and use the existing remove lifecycle hook, rather than keeping _blobUrls on the p5 instance.
The one thing I'm still unsure about is how you'd like the File to keep track of which p5 instance it belongs to. Right now _load() gets pInst explicitly for that, but from your comment on dom.js, it sounds like you'd prefer not to pass it through like this.
I could move the cleanup into a single remove hook, but I don't want to introduce another registry or ownership mechanism if there's already a pattern in p5.js that I'm missing.
Is there a particular approach you had in mind for handling the per-instance cleanup here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit abstract for me to think about without actually writing the code so the explanation here may be a bit abstract as well. Passing pInst to File._load in this case could possibly work since it is a static function with no side effect. Another option if at all possible is to handle the object URL somewhere where this points to the p5 instance, that can be in lifecycle hooks or more likely a p5 function call such as createFileInput, eg.

const handleFileSelect = function (event) {
  for (const file of event.target.files) {
    File._load(file, trackObjectURL);
  }
};

// Deliberate arrow function to keep reference to `this`
const trackObjectURL = (callback) => (blob) => {
  if(blob instanceof Blob){
    this._blobURLs.push(blob);
  }
  callback(blob);
};

Hopefully that made sense, let me know if not and I can try to flesh out the idea more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@limzykenneth
Made the changes based on your feedback.
Moved the Blob URL cleanup into the remove lifecycle hook, removed the pInst plumbing from File._load(), and used the callback approach to track Blob-backed files per p5 instance. Also switched p5.File to p5.registerAddon().
Would love a feedback.

Comment thread src/dom/dom.js Outdated
Comment thread src/dom/p5.File.js
@p5-bot

p5-bot Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Continuous Release

CDN link

Published Packages

Commit hash: 5de459c

Previous deployments

cd057c7


This is an automated message.

@limzykenneth
limzykenneth merged commit 2ce359a into processing:main Sep 28, 2026
4 checks passed
@limzykenneth

Copy link
Copy Markdown
Member

Looks good. Thanks!

@slash-init
slash-init deleted the fix/file-blob-url-lifecycle branch September 29, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[p5.js 2.0+ Bug Report]: Blob URLs created by p5.File._load() for video/audio files are never revoked

4 participants