p5.js-web-editor icon indicating copy to clipboard operation
p5.js-web-editor copied to clipboard

Cannot console.log objects having circular references

Open dipamsen opened this issue 1 year ago • 5 comments

p5.js version

1.9.4

What is your operating system?

Windows

Web browser and version

Chrome 126.0.6478.127

Actual Behavior

Printing a p5.Image object breaks the console.

Expected Behavior

p5.Image should be printable.

Steps to reproduce

Steps:

  1. Copy the following code in a sketch
  2. Running the code prints nothing on the console
  3. Commenting out the third line prints "Hi".

Snippet:

let img = createImage(20, 20);
console.log("Hi");
console.log(img);

dipamsen avatar Jun 30 '24 21:06 dipamsen

More information: The source of this issue seems to be that recursive data structures cannot be logged in the console. (This limitation is not present in the latest version of console-feed)

Example:

let obj = {};
obj.a = obj;
console.log(obj); // breaks console, "maximum call stack exceeded"

Other objects which have a recursive structure and thus break the console:

  • All custom p5 class instances, as they have a obj._pInst.renderer._pInst. ... recursive definition
  • Window / globalThis
  • Any object/class instance which stores one of the above in a field

dipamsen avatar Jul 01 '24 07:07 dipamsen

Thanks for raising this and looking into it!

raclim avatar Jul 03 '24 15:07 raclim

@dipamsen hello there, i just looked into this issue. I am trying to understand it more in depth to came out with a solution. I want to know what expected behavior we want when we encounter this type of circular loop data structure ? What output should be logged out so user know he has done a mistake.

geekaryan avatar Oct 18 '24 05:10 geekaryan

@geekaryan I dont think it should be interpreted as a mistake. The library which is being used to render the "console" on the web editor (console-feed) is perfectly capable of logging such objects. (All major browsers also of course support logging of these objects).

The error we are hitting seems to be from immer/redux (?) which is unable to serialise these infinitely recursive objects. (not sure if this is correct).

dipamsen avatar Oct 18 '24 09:10 dipamsen

@dipamsen got your point let me try to run this locally on my system and try to regenerate this issue. Thank you

geekaryan avatar Oct 18 '24 15:10 geekaryan

Similar failure trying to display image variables in the console entry area from this sketch: https://editor.p5js.org/jht9629-nyu/sketches/N1xP0mzu- Enter img1 in the console entry area and you get this error in the browser console: Uncaught RangeError: Maximum call stack size exceeded at immer.esm.mjs:1:912 at Array.forEach () at ht (immer.esm.mjs:1:904) at Bt (immer.esm.mjs:1:2716) at It (immer.esm.mjs:1:3259) at immer.esm.mjs:1:2742 at immer.esm.mjs:1:948 at Array.forEach () at ht (immer.esm.mjs:1:904) at Bt (immer.esm.mjs:1:2716

jht9629-nyu avatar Nov 07 '24 19:11 jht9629-nyu

Hi @dipamsen I have been working on this issue for the past few days i have attached a screenshot P5 Console Log issue Fix please let me know is this the expected behavior

adwaitanand avatar Nov 17 '24 09:11 adwaitanand

@adwaitanand Thats pretty good, however I am pretty sure earlier it was possible to actually print circular structures in the p5 console, i.e. you could infinitely click the _pixelsState property which would render the recursive subtree incrementally. This feature is indeed supported by console-feed.

As I understand it, the problem is in serialisation/deserialisation, so if it is not possible to recover the object in its entirity, then perhaps this is the next best option. I'll leave it to the project maintainers to decide.

dipamsen avatar Nov 17 '24 11:11 dipamsen

Thank you @dipamsen . Initially, I attempted to resolve the issue by allowing infinite clicks on the _pixelsState property, but I kept encountering the error: "Immer forbids circular reference." This led me to replace the circular reference object with a string.

P5 Immer Error

However, I’ll explore whether it’s possible to render the circular reference object directly in the console feed.

adwaitanand avatar Nov 17 '24 12:11 adwaitanand

@dipamsen and @raclim I found a way to render the objects for circular reference .

P5 Solution for Console Issue

I'm new to open source and need help with the PR for this issue. When I run npm run test in the Docker shell, some tests fail, for files I didn’t modify. I tried cloning a fresh project and running the tests without making any changes, but the same tests failed .

Can someone please guide me on what I might be doing wrong or the correct steps to proceed? test error

adwaitanand avatar Nov 19 '24 08:11 adwaitanand

@dipamsen @raclim Issue Explanation: The original issue was that console.log(img) attempted to log the entire image object, which contains circular references and is not fully viewable in the console, leading to confusion and potentially uninformative outputs.

Changes Made:

  1. Used img.loadPixels() : Ensured the pixel data could be accessed after creating the image.
  2. Selective Pixel Data Logging : Used Array.from(img.pixels).slice(0, 16) to print only a sample of the pixel data instead of the entire array, avoiding bloated outputs.
  3. Logged Image Dimensions : Added console logs for img.width and img.height for a more meaningful output.

Fixed Code :

function setup() { createCanvas(400, 400);

console.log("Hi");

let img = createImage(20, 20); img.loadPixels();

console.log("Pixels Data (Sample): ", Array.from(img.pixels).slice(0, 16)); console.log("Image Width: ", img.width); console.log("Image Height: ", img.height); }

Image

Harshit-7373 avatar Feb 10 '25 15:02 Harshit-7373

@adwaitanand @raclim

Apologies for the delayed response. The issue regarding the 15 test suites failing inside the docker while running npm run test is still not resolved, but I’ve been looking into it further and have come up with some potential solutions. I’ve shared my thoughts in the comments here : #3190 (ReferenceErrors when running tests in Docker)

Please take a look at the comments I’ve added and let me know your thoughts.

Harshit-7373 avatar Feb 10 '25 15:02 Harshit-7373

@adwaitanand Please share the specific issue related to your PR. I will help you out and guide you in correcting it.

Harshit-7373 avatar Feb 10 '25 15:02 Harshit-7373

@Harshit-7373 The issue here is not to change the user's code to not try to log the circular object. The issue to be resolved is that when an user tries to do so (log any object containing circular references), the web editor crashes without any errors shown.

Ideally though, the editor's console should be perfectly capable of logging such objects, just like the browser's console can do so. See above in one of my messages in this issue where I have linked a codepen which demonstrates that console-feed - the library used by the p5.js web editor to render the console - is capable of logging infinitely recursive structures.

Yet, the web editor crashes in this case, probably due to an issue with state management (redux) which cannot serialise these circular structures. Seemingly @adwaitanand was able to find a fix, but they seemed to have faced some issue in the tests.

dipamsen avatar Feb 10 '25 17:02 dipamsen

@dipamsen I understood the issue i will work on this. The issues which @adwaitanand is getting while running the tests are common issues. Even if you directly clone the project again , without changing any files u will recieve the issues in the test(15 failed).

I was working on solving these issues while running the tests inside the docker. I’ve been looking into it further and have come up with some potential solutions. I’ve shared my thoughts in the comments here : - #3190 (ReferenceErrors when running tests in Docker).

Please take a look at the comments I’ve added and let me know your thoughts.

Harshit-7373 avatar Feb 10 '25 18:02 Harshit-7373

Hi @adwaitanand , pinging you since you seemed to have solved this issue - do you have/recall the way you were able to get the circular object logs working? Did you use a custom json stringify replacer function with a maximum depth?

dipamsen avatar Mar 31 '25 13:03 dipamsen

I was thinking some more about this issue, and one idea worth discussion that I came up with is not using a redux store for handing console logs and errors. It seems on a surface level check that the console state is only used in the Console component. The only external interface with this state is for its actions - dispatchConsoleEvent() and clearConsole(). That makes me believe, that instead of making it a redux state, we could make it a local state/React Context object instead, which can expose these corresponding actions for external interfacing. React Context / local state has no problems with recursive substructures.

Of course, this requires a lot of refactoring of code related to the console, but I want to first verify this is indeed a valid solution. Is there any glaring issue I am missing which will cause this to not work?

dipamsen avatar Apr 07 '25 12:04 dipamsen

Thanks @dipamsen for taking the time to really delve into this and consider the options here! I think if the console state does seems to be isolated to just the Console component, I'm down to try working towards transitioning to using local state instead. We may also want to open a separate issue for this as well.

In terms of @Jatin24062005's PR, I'm down to implement it as a temporary solution for now, while working towards the longer term transition to local storage which probably might take a bit longer to work out. Would that seem like a viable solution for now?

raclim avatar Apr 29 '25 16:04 raclim

@raclim that seems like a good idea!

dipamsen avatar Apr 29 '25 16:04 dipamsen

Thanks @raclim! That makes a lot of sense—I’m glad the PR can serve as a temporary solution for now. I agree that transitioning to local state sounds like a cleaner long-term approach, and I’d be happy to help with that direction too if needed.

Jatin24062005 avatar Apr 29 '25 16:04 Jatin24062005

Sounds good! I just merged in the PR. Feel free to open a new issue regarding the longer-term solution—otherwise I'll try to open one up within the next week or so! Thanks so much again for your inputs on this!

raclim avatar May 01 '25 20:05 raclim