n-riesco / ijavascript

IJavascript is a javascript kernel for the Jupyter notebook
Other
2.18k stars 187 forks source link

Cell Cleanup / Cell Indentifier? #244

Closed prothSFDC closed 2 years ago

prothSFDC commented 3 years ago

This is more of a question, but happy to discuss further.

Is there any way to run logic before a cell is re-evaluated? Or a way to tell which cell is currently running?

Similar to the invalidation from observablehq, I'm looking for some way I could detect that a cell was previously run - so I can clean up resources.

Ideally, it would be great if say Cell at position 2 could have something accessible whenever it executes (so I know its at position 2) so if I have to register pointers etc on the global scope - I know they need to be re-evaluated or cleaned up.

Right now I can just define a variable at the beginning of each cell, but that lead me to a problem this morning where they weren't unique and that took me a while to find.

Any thoughts or suggestions? I really appreciate the work you've done here.

prothSFDC commented 3 years ago

I'm working on a very simple library for myself using rxjs / $$.display() etc to implement an observable value, and then allowing for re-evaluation if those values change. (There is quite a bit of opportunity there, like for custom inputs, etc) and this would help to protect against memory leaks, and make cleanup much less manual.

n-riesco commented 3 years ago

Is there any way to run logic before a cell is re-evaluated?

Where would the logic run? At NEL level (i.e. the node.js session) or at jp-kernel level (i.e. what jp-babel does to transpile code before running it in the node.js session)?

At the moment, only the transpilation hook is exposed.

Or a way to tell which cell is currently running?

This needs to be done at jp-kernel level, as NEL knows nothing about the Jupyter messaging protocol. It'd also require that the frontend implements JEP-62.

Right now I can just define a variable at the beginning of each cell, but that lead me to a problem this morning where they weren't unique and that took me a while to find.

How about generating a hash using the cell code? (assuming no two cells run the same code).

I'm working on a very simple library for myself using rxjs / $$.display() etc to implement an observable value, and then allowing for re-evaluation if those values change.

As long as rxjs runs in the Node.js session (i.e. not in the frontend), this should be possible already.

(There is quite a bit of opportunity there, like for custom inputs, etc)

For custom inputs (running in the frontend), something like ipwidgets for IJavascript, I'd need to implement comm_* messages (see issue #100).

prothSFDC commented 3 years ago

2021-06-29_19-38-10

prothSFDC commented 3 years ago

Thank you for looking at this!

Is there any way to run logic before a cell is re-evaluated?

Where would the logic run? At NEL level (i.e. the node.js session) or at jp-kernel level (i.e. what jp-babel does to transpile code before running it in the node.js session)?

At the moment, only the transpilation hook is exposed.

I was planning on running it on the NEL level. As long as there is some way to have a reference to the cell (and the hash below would work) then the variables can register based on that and self clean / so all set.

Or a way to tell which cell is currently running?

This needs to be done at jp-kernel level, as NEL knows nothing about the Jupyter messaging protocol. It'd also require that the frontend implements JEP-62.

Ah I see. Ah well.

Right now I can just define a variable at the beginning of each cell, but that lead me to a problem this morning where they weren't unique and that took me a while to find.

How about generating a hash using the cell code? (assuming no two cells run the same code).

That would absolutely work

Might you have any suggestions how I could get the cell code? I saw I could do this within ipy, but I couldn't figure out a way to make that work within iJavascript since as you said - it runs within the nodejs backend.

I'm working on a very simple library for myself using rxjs / $$.display() etc to implement an observable value, and then allowing for re-evaluation if those values change.

As long as rxjs runs in the Node.js session (i.e. not in the frontend), this should be possible already.

Yepper. I just tried to make it a bit easier (see the video below). Currently though, it seems that the only way to have this happen is either re-evaluating or through $$.displays

(There is quite a bit of opportunity there, like for custom inputs, etc)

For custom inputs (running in the frontend), something like ipwidgets for IJavascript, I'd need to implement comm_* messages (see issue #100).

I see what you're saying because anything we have running on the front end - won't get passed to the back end without that change. (since one is running nodejs and the other is on the browser)

One thing I have been experimenting with though is that I can pass the values from nodejs to the browser (I just can't go the other way without that change)

n-riesco commented 3 years ago

Thank you for the video (it gave me the context I was missing).

Might you have any suggestions how I could get the cell code?

Perhaps the same approach used by magicpatch. See https://github.com/apowers313/magicpatch/blob/master/lib/interpreter.js You could patch global.vm.runInThisContext, so that it sets $$._code to the code being run. That should give you enough flexibility (compute a hash or do whatever magic you need to manage resources). Another idea: instead of setting $$._code, you could define $$._addExecutionListener to register a callback to be invoked before execution.

If you decide to define anything on $$, I recommend using names starting with _, to avoid clashing with future changes to $$ in IJavascript.