Skip to content

[p5.js 2.0+ Bug Report]: Removed sketches are never freed and red()/green()/blue()/alpha() use the wrong range #9299

Open

Description

@Akshats-git

Most appropriate sub-area of p5.js?

  • Color
  • Core/Environment/Rendering

p5.js version

2.3.2

Web browser and version

Chrome 152.0.7977.64

Operating system

Ubuntu 24.04.4 LTS

Steps to reproduce this

Hi @limzykenneth, as discussed on Discord here is the issue.

Every time a sketch is created, the presetup hook in src/color/p5.Color.js wraps 12 methods on the shared p5.Color.prototype. These are setRed, setGreen, setBlue, setAlpha and the getters _getRed to _getLightness. Each wrapper holds on to its sketch. Nothing removes it later. This causes two problems.

  1. Removed sketches stay in memory. The wrappers keep every instance alive after remove().
  2. Colors are read in the wrong range. The wrappers use the colorMaxes of the newest sketch. They should use the sketch or graphics that made the color. red(), green(), blue() and alpha() are affected.

1. Wrong range with createGraphics

One sketch is enough to see this.

function setup() {
  createCanvas(100, 100);
  const g = createGraphics(100, 100);
  g.colorMode(RGB, 1);
  const c = g.color(0.5, 0.25, 0.75);
  print(g.red(c), g.green(c), g.blue(c));
  // actual:   127.5 63.75 191.25
  // expected: 0.5 0.25 0.75
}

2. Removed sketches stay in memory

Open about:blank and the DevTools console. Run each step on its own and wait for it to finish.

Load p5:

window.p5 = (await import('https://cdn.jsdelivr.net/npm/p5@2.3.2/lib/p5.esm.js')).default;
p5.disableSketchChecker = true; // hides an unrelated error on about:blank

Create and remove 10 sketches:

const sleep = ms => new Promise(r => setTimeout(r, ms));
window.refs = [];
for (let i = 0; i < 10; i++) {
  let inst = new p5(p => { p.setup = () => p.createCanvas(100, 100); });
  await sleep(50);
  refs.push(new WeakRef(inst));
  await inst.remove();
  inst = null;
}

Open the Memory tab and click the trash can ("Collect garbage") a few times. Then count the sketches that are still alive:

refs.filter(r => r.deref()).length
// actual:   10
// expected: 0

If I restore the original p5.Color.prototype methods after each remove(), none are left. So the wrappers are the cause.

Possible fix

  • Pass explicit ranges in red(), green(), blue() and alpha(). Include use of relevant maxes in hue(), saturation(), brightness() and lightness() #8062 did this for hue() and the others.
  • Add the four setter wrappers once instead of once per sketch. They would read the range from the sketch that made the color through _pInst.
  • Add tests for the createGraphics range, two sketches with different colorMode and an unchanged prototype after a sketch is created.

Activity

  1. welcome commented on Oct 16, 2026

    @welcome

    Welcome! 👋 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, please make sure to fill out the inputs in the issue forms.

    For guidance on contributing, check out our contributing guidelines and other resources for contributors.
    💬 If you have questions or need support, feel free to join the Processing Foundation Forum or visit our Community page.
    📜 Please also review our Code of Conduct to understand our community standards.
    Thank You!

  2. changed the title [-][p5.js 2.0+ Bug Report]: Every new sketch re-wraps p5.Color.prototype, so removed sketches are never freed and red()/green()/blue()/alpha() use the wrong range[/-] [+][p5.js 2.0+ Bug Report]: Removed sketches are never freed and red()/green()/blue()/alpha() use the wrong range[/+] on Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions