Skip to content

Instantly share code, notes, and snippets.

@mrspeaker
Last active November 16, 2022 10:35
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrspeaker/c3b7b8d0b0b96b1a012d736b22d12b2e to your computer and use it in GitHub Desktop.
Save mrspeaker/c3b7b8d0b0b96b1a012d736b22d12b2e to your computer and use it in GitHub Desktop.
"require(...).print is not a function" fix for org-babel:js

Org-babel-js fix

When evaluating this code in an org-mode document:

const sq = x => x * x;
const cube = x => sq(sq(x));
return cube(4);

I was getting the error:

> require('sys').print(require('sys').inspect(function(){
>                ^
> TypeError: require(...).print is not a function

I tracked it down to a js function wrapper in `ob-js.el.gz`:

(defvar org-babel-js-function-wrapper
  "require('sys').print(require('sys').inspect(function(){\n%s\n}()));"
  "Javascript code to print value of body.")

The `sys` module is long deprecated, and I can’t even see evidence that `print` was ever a valid function… but it used to work, so it must have been there at some point! Looking at the (I think current) source code for ob-js.el it’s still using “sys.print”.

Anyhoo, because it’s a `defvar` I don’t think it’s customizeable (right?), so I just had to re-eval the function with a different wrapper string:

(defvar org-babel-js-function-wrapper
  "console.log(JSON.stringify(require('util').inspect(function(){\n%s\n}())));"
  "Javascript code to print value of body.")

Not sure if that’s equivalent, but it seems ok so far (I had to add JSON.stringify… which seems like it shouldn’t do anything after util.inspect - but fixes a bunch of output formatting wierdness).

const sq = x => x * x;
const cube = x => sq(sq(x));
return cube(4);

Shows:

> RESULTS:
> : 256
@mrspeaker
Copy link
Author

(I re-had this issue, and forgot I wrote this gist... found someone had submitted a patch : https://www.mail-archive.com/emacs-orgmode@gnu.org/msg127137.html)

@phuhl
Copy link

phuhl commented Jul 1, 2020

Hey there, if you really want it to work, replace the console.log with process.stdout.write! Console.log adds a newline to the end of the output and thus confuses org-mode. This results in org-mode not being able to produce tables and such. Here is my full snippet:

(setq org-babel-js-function-wrapper
      "process.stdout.write(require('util').inspect(function(){\n%s\n}(), { maxArrayLength: null, maxStringLength: null, breakLength: Infinity, compact: true }))")

With that snippet, the following works:

#+BEGIN_SRC js
return [1,2];
#+END_SRC

#+RESULTS:
| 1 | 2 |

@mrspeaker
Copy link
Author

Nice one @phuhl - I'm going to use that for sure! (I wonder if it's worth submitting it to the main repo, as it looks like the patch they accepted doesn't have the { compact: true, etc etc} stuff?)

@phuhl
Copy link

phuhl commented Jul 12, 2020

Well maybe. I am not sure what parts of that are necessary! I fiddled with it, to get everything to work but it turned out that console.log produced the issue. compact: true might be necessary though, as it might be possible, that the underlying lisp code does not understand line brakes when parsing. Can't confirm that, right now, though.

@jhhb
Copy link

jhhb commented Jul 29, 2020

I had the same issue -- thanks for posting these workarounds!

@concurrentz
Copy link

@phuhl Thanks for the solution. It works now

@sevillaarvin
Copy link

Thanks, I have GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.22, cairo version 1.17.3) of 2020-08-29 and copied

(setq org-babel-js-function-wrapper
      "process.stdout.write(require('util').inspect(function(){\n%s\n}(), { maxArrayLength: null, maxStringLength: null, breakLength: Infinity, compact: true }))")

to my ~/.emacs.d/init.el and js now works.

@wisetc
Copy link

wisetc commented Oct 23, 2021

@sevillaarvin It works for me too, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment