p5.js
p5.js copied to clipboard
print("content") outside of setup/draw invokes print dialog. possible to catch with FES?
Most appropriate sub-area of p5.js?
- [ ] Color
- [x] Core/Environment/Rendering
- [ ] Data
- [ ] Events
- [ ] Image
- [ ] IO
- [ ] Math
- [ ] Typography
- [ ] Utilities
- [ ] WebGL
- [ ] Other (specify if possible)
Details about the bug:
- p5.js version: 0.10.2
- Web browser and version: Firefox 72.0.2
- Operating System: MacOS 10.14 (Mojave)
- Steps to reproduce this:
The following code causes the print dialog to appear in Firefox (using editor.p5js.org).
print("Hello world!")
Welcome! š Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, be sure to follow the issue template if you haven't already.
Hm odd! I am not able to recreate on Mac 10.15.2 using the online editor and Firefox 72.0.2. This sketch just prints the text in the console for me:
function setup() {
print("Hello world!")
}
Ah, I'm realizing my mistake. I tried to use the print
function all by itself, outside of the setup
function. Coming from Java Processing, I expected this to work, and the reference examples for print
don't include a setup
or draw
function.
I realize my case is probably a bit unusual, but it might be worth updating the documentation?
I don't think this is something we can specifically document just for print()
as most functions in p5.js cannot be used outside of setup()
or draw()
before setup()
or draw()
is called. However, this behaviour should be caught by the friendly error system, not sure if it would be impossible to catch print()
though.
@limzykenneth Can I work on this issue?
@debajitdeb11 Sure, do have a look at it. I'm not sure how would the FES detect print("something")
is being used before initialization though as unlike the other functions, print()
exist on the global scope. Let us know what you find, thanks!
Where is the source code for the online editor is located in the source file?
The source code for the web editor is located in another repo but why do you need the source code for it for this issue?
i think this is a great place for FES. if someone is interested in working on it iām also happy to answer questions, code review, whatever!
@debajitdeb11 if you are still working on this maybe window.onbeforeprint
can help you? I am just guessing here but maybe using something like a check for _setupDone
or similar inside it to call report()
to trigger a friendly warning message?
@akshay-99 the thing with calling print(...args) outside setup or draw is that it gets called before the library is loaded and browser calls window.print() . So I think it's hard for FES to detect it. A better way to go around situation will be to have a static function p5.print() alongside this one.
p5.print('Hello World'); // logs Hello World into console.
print('Hello'); // opens print dialog box
function setup() {
// put setup code here
}
function draw() {
// put drawing code here
}
@outofambit what do you suggest about this? If there is way for it to be get detected by FES, I would like to work on it.
@DivyamAhuja I am sorry I didn't reply earlier. I must have missed this comment somehow. When we use global mode, all of p5's API functions get attached to the window object when p5 is initialised.
Also you are right that the call is made before the library initialises. And hence my mention of_setupDone
was wrong. But we can still use window.onbeforeprint
:smile:
The FES has helpForMisusedAtTopLevelCode
which currently handles many cases similar to this issue. helpForMisusedAtTopLevelCode
is built such that it can work even before p5 is initialised. The reason it does not handle print()
is due to the fact that print is already there in the window object and hence calling it does not produce an error.
But what if just before this line, we add this
window.onbeforeprint = () => {
helpForMisusedAtTopLevelCode(new ErrorEvent('print', {message:'print used'}));
}
The effect of this now is that if a print()
is called outside setup, onbeforeprint
triggers and calls helpForMisusedAtTopLevelCode, passing to it a new ErrorEvent
. The contents of this can be anything since it won't be put on the console. We just need to make sure that the message field has "print" somewhere in it so that the regex here can match it
It is interesting to note that there is another way to handle this, one that is not just limited to print
but can work for anything else in the window
object that may conflict with p5
We can simply redefine the function in the window
object to make it pass through the FES before it executes its original task.
Lets assume we have a function something
that is both defined in p5 and the window
object. We can catch the use of something
outside of setup
and draw
in the following way
let somethingBackup = window.something;
window.something = (params) => {
helpForMisusedAtTopLevelCode(new ErrorEvent('something', {message:'something used'}));
somethingBackup(params);
}
@debajitdeb11 @DivyamAhuja is anyone working on this?
@akshay-99 No, am not working on it. You can continue working on it if you want.
BTW calling print(); with no parameters invokes the browsers print dialog. Which is really bad when using an online IDE like https://jsitor.com/ with auto run on and you type print() before entering what to print in the draw loop.
Having a command to override the system print would be great, NoPrintDialog();
Could the sandbox flags be used to disable the window.print()? https://html.spec.whatwg.org/multipage/origin.html#sandbox-propagates-to-auxiliary-browsing-contexts-flag
Or could we just hijack window.print() https://stackoverflow.com/questions/32181838/override-window-print-for-all-windows-using-window-prototype
I think overriding default print function with this should work.
const _windowPrint = window.print;
window.print = function(...args){
if(args.length === 0){
_windowPrint();
}
else{
console.log(...args);
}
}
current implementation adds print function to p5 class while overriding window.print will be helpful I think. https://editor.p5js.org/DivyamAhuja/sketches/6zIHhzpg0
@DivyamAhuja ah that's interesting. I was talking about overriding it for catching its use for outside setup and draw to warn the user. But your idea of removing p5.prototype.print and overriding window directly is simpler.
One question I have in mind is instance mode, as this would leak p5's functionality to the global object even in instance mode. So hypothetically if the user is also using some other script that also overrides print, and using p5 in instance mode to avoid any clashes, this print functionality would still clash. Which means it would depend on the order of the import which script's print is used. But this is a very unlikely situation indeed.
@hellonearthis yeah I guess a command or a parameter which when called or set true, would map print to console.log even when called with 0 parameters would help in that case.
@akshay-99 Yeah, I didn't think of a case with multiple libraries. In this case overriding may really be flawed
I have had this print() problem when used inside a draw() loop.
p5 could treat print() as console.log('') to would prevent the browser print() to not popup but there might also be a case to use print() so made add a printerMode(CONSOLE|PRINTER) to let the user enable the printer as the default could be console.
Overriding outside of the p5 scope is problematic unless it could be address like p5.print('hi'); but not sure on that point.
This simple sketch is very easy for a novice user write. In auto-refresh mode get into loop with print dialog repeating opening. Must kill browser window/tab to stop.
I recommend print with no args call console.log.
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
print();
}
Thank you all for working on this. I'd like to bump up this issue for the upcoming 1.7.0 release with another print() related issue #2765. Since the issue was filed a while ago, what will be the good next steps to move this issue forward? @limzykenneth @davepagurek. Also adding GSoC FES contributor @Ayush23Dash and mentors @almchung @nbriz to this discussion.
With the suggested beforeprint
event it is possible to catch print being called outside of setup and draw to print a FES warning, this possibly can be implemented in helpForMisusedAtTopLevelCode
as a special case. It won't stop the print dialog from showing, nor should it really for instances of it being used outside of setup and draw. @Ayush23Dash if you need help with this do let us know.
For the more general case for print()
with no arguments opening print dialogs when used in draw()
we can focus discussions on #2765. I have a couple vague ideas how this may be solved but have not yet tried it out but if there's idea for solutions that can preserve both print("something")
and print()
behaviours, do leave a comment in #2765.