Js2Py icon indicating copy to clipboard operation
Js2Py copied to clipboard

Js2Py throws 'ReferenceError: require is not defined'

Open Souvikray opened this issue 6 years ago • 10 comments

I am using js2py to run Javascript code inside my Python code and it works fine for basic function calls or console outputs.However when I try to use an npm library jsonata inside the Javascript code, it throws an error.

Traceback (most recent call last):
  File "/home/souvik/PycharmProjects/ServiceHandler/Testjs.py", line 67, in <module>
    data = js2py.eval_js(data)
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/evaljs.py", line 113, in eval_js
    return e.eval(js)
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/evaljs.py", line 182, in eval
    self.execute(code, use_compilation_plan=use_compilation_plan)
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/evaljs.py", line 177, in execute
    exec(compiled, self._context)
  File "<EvalJS snippet>", line 2, in <module>
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/base.py", line 899, in __call__
    return self.call(self.GlobalObject, args)
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/base.py", line 1344, in call
    return Js(self.code(*args))
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/host/jseval.py", line 42, in Eval
    executor(py_code)
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/host/jseval.py", line 49, in executor
    exec(code, globals())
  File "<string>", line 2, in <module>
  File "/home/souvik/utorapp/lib/python3.5/site-packages/js2py/base.py", line 1079, in get
    raise MakeError('ReferenceError', '%s is not defined' % prop)
js2py.internals.simplex.JsException: ReferenceError: require is not defined

Here is my code below

Testjs.py

import js2py

data = '''var jsonata = require("jsonata");

var data = {
  example: [
    {value: 4},
    {value: 7},
    {value: 13}
  ]
};
var expression = jsonata("$sum(example.value)");
var result = expression.evaluate(data);
console.log(result)
'''

data = js2py.eval_js(data)
print(data)

Note: I have npm, node.js and jsonata installed

The weird part is if I run just the Javascript code saved to a file in the command line, it works just fine

Testjs2.js

var jsonata = require("jsonata");

var data = {
  example: [
    {value: 4},
    {value: 7},
    {value: 14}
  ]
};
var expression = jsonata("$sum(example.value)");
var result = expression.evaluate(data);
console.log(result) 

In the command line node Testjs2.js --> gives me 25

I investigated for a while and found this in js2py documentation

You can also import a big number of node modules as if they were written in Python! For example, here we import a pure JS library crypto-js:

    >>> CryptoJS = js2py.require('crypto-js')
    >>> data = [{'id': 1}, {'id': 2}]
    >>> JSON = js2py.eval_js('JSON')
    >>> ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123')
    >>> bytes  = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123')
    >>> decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8)).to_list()
    >>> decryptedData
    [{u'id': 1}, {u'id': 2}]

So I even added this line js2py.require('node') to my Testjs.py file but then it started installing some 'Babel' related files and then threw the same error.How do I run this piece of Javascript code in my Python file?

Additional resources:

jsonata documentation

Souvikray avatar Mar 07 '18 08:03 Souvikray

I am also running into this issue, and believe it occurs any time require is used in the JS code. For instance, the CryptoJS example works just fine for me, and when I translate it into javascript code (saved as example.js -- see below for the code) I can run it just fine using node example.js. However, I then load up python and do the translation:

import js2py
js2py.translate_file('example.js', 'example.py')

Finally, when I run python example.py I get the following error:

Traceback (most recent call last):
  File "example.py", line 12, in <module>
  var.put(u'CryptoJS', var.get(u'require')(Js(u'crypto-js')))
  File "/usr/local/lib/python2.7/site-packages/js2py/base.py", line 1079, in get
  raise MakeError('ReferenceError', '%s is not defined' % prop)
  js2py.internals.simplex.JsException: ReferenceError: require is not defined

The code I used in example.js is:

CryptoJS = require('crypto-js')
data = [{'id': 1}, {'id': 2}]
ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123')
bytes  = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123')
decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8))
console.log(decryptedData)

kasmith avatar Mar 07 '18 18:03 kasmith

This is because require is not defined in the JS scope, its only defined on the Python level, hence the reference error.

PiotrDabkowski avatar Mar 07 '18 19:03 PiotrDabkowski

@Piotr any work around for this?

Souvikray avatar Mar 07 '18 19:03 Souvikray

Does anyone know the solution to this?

TriPham259 avatar May 27 '19 08:05 TriPham259

any news about this issue of 'require is not defined' following the translation from 'js' to 'py'?

LePassant19 avatar Dec 23 '19 10:12 LePassant19

>>> help(js2py.EvalJs)
...
You can enable JS require function via enable_require. With this feature enabled you can use js modules
        from npm, for example:
        >>> ctx = EvalJs(enable_require=True)
        >>> ctx.execute("var esprima = require('esprima');")
        >>> ctx.execute("esprima.parse('var a = 1')")
...

PiotrDabkowski avatar Dec 23 '19 14:12 PiotrDabkowski

I solved it by rolling up the JS files into one file with webpack, then there's no require anymore.

Akuukis avatar Sep 20 '20 12:09 Akuukis

I solved it by rolling up the JS files into one file with webpack, then there's no require anymore.

@Akuukis can you please explain what does that mean?

abhinav-mane avatar Mar 24 '21 14:03 abhinav-mane

He concatenated the dependencies and scripts together into a single script, so he could comment out the require command. Not very elegant imo.

worstperson avatar Mar 24 '21 16:03 worstperson

inside the translated file, right after it imports js2py you can add from js2py import require then for all the modules you want to import you put <module name> = require('<module name>') then you replace: var.put(u'<variable name>', var.get(u'require')(Js(u'<module name>'))) with: var.put(u'<variable name>', <module name>)

Inthenew avatar Jun 22 '21 18:06 Inthenew