JavaScript to Python Translator & JavaScript interpreter written in 100% pure Python🚀

Overview

Build Status Downloads

Pure Python JavaScript Translator/Interpreter

Everything is done in 100% pure Python so it's extremely easy to install and use. Supports Python 2 & 3. Full support for ECMAScript 5.1, ECMA 6 support is still experimental.


Simple Example:

>> add = js2py.eval_js('function add(a, b) {return a + b}') >>> add(1, 2) + 3 6 >>> add.constructor function Function() { [python code] } >>> js2py.require('underscore') 'function _(obj) { [python code] }'">
    >>> import js2py
    >>> js2py.eval_js('console.log( "Hello World!" )')
    'Hello World!'
    >>> add = js2py.eval_js('function add(a, b) {return a + b}')
    >>> add(1, 2) + 3
    6
    >>> add.constructor
    function Function() { [python code] }
    >>> js2py.require('underscore')
    'function _(obj) { [python code] }'

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}]

Now also supports JavaScript 6 (still experimental):

    >>> js2py.eval_js6('let a = () => 11; a()')
    11

JavaScript 6 support was achieved by using Js2Py to translate javascript library called Babel. Babel translates JS 6 to JS 5 and afterwards Js2Py translates JS 5 to Python. The only downside is that translated babel.js has about 4 MB and importing such a long Python file takes about 15 seconds!


Translating a JavaScript file:

    # this will translate example.js to example.py
    >>> js2py.translate_file('example.js', 'example.py')
    # example.py can be now imported and used!
    >>> from example import example
    >>> example.someFunction()
    ...

Every feature of ECMA 5.1 is implemented (except of 'with' statement):

>>> js2py.eval_js("Object.prototype.toString.call(Function('s', 'return s+arguments[1]')(new Date(), 7).__proto__)")
[object String]

Unfortunately even though Js2Py can be generally used to translate huge Js files (over 50k lines long), in rare cases you may encounter some unexpected problems (like javascript calling a function with 300 arguments - python allows only 255). These problems are very hard to fix with current translation approach. I will try to implement an interpreter in near future which will hopefully fix all the edge cases.

Installation

pip install js2py

More advanced usage example

It is possible to access all the variables from JS scope using EvalJs. Moreover, you can use Python objects from your JavaScript code if you add them to the scope. In this example we will be using Python built-in sum function to sum elements in JS array. It will stand under python_sum.

# Adding Python built-in sum to the JS context:
>>> context = js2py.EvalJs({'python_sum': sum})  
>>> js_code = '''
var a = 10
function f(x) {return x*x}
'''
>>> context.execute(js_code)
# Get value of variable a:
>>> context.a
10
# context.f behaves just like js function so you can supply more than 1 argument. '9'*'9' in javascript is 81.
>>> context.f('9', 0)  
81    
# context.f has all attributes of normal JavaScript object
>>> context.f.toString()
u'function f(x) { [python code] }'
>>> context.f.bind
function bind(thisArg) { [python code] }
# You can also add variables to the context:
>>> context.foo = [1,2,3]  # context.foo is now Js Array object and behaves just like javascript array!
>>> context.foo.push(4)  
4
>>> context.foo.to_list() # convert to python list
[1, 2, 3, 4]
# You can use Python objects that you put inside the context!
>>> context.eval('python_sum(new Array(1, 2, 3))')
6

You can also enable require support in JavaScript like this:

>>> context = js2py.EvalJs(enable_require=True)
>>> context.eval("require('esprima').parse('var a = 1')")

JavaScript 'VirtualMachine' in Python

As a fun experimental project I have also implemented a VM-based JavaScript (yes - there are 2 separate JS implementations in this repo). It is feature complete and faster than the translation based version. Below you can see a demo with a nice debug view (bytecode + execution sequence):

>>> from js2py.internals import seval
>>> seval.eval_js_vm("try {throw 3+3} catch (e) {console.log(e)}", debug=True)
[LOAD_UNDEFINED(),
 JUMP(4,),
 LABEL(1,),
 LOAD_UNDEFINED(),
 POP(),
 LOAD_NUMBER(3.0,),
 LOAD_NUMBER(3.0,),
 BINARY_OP('+',),
 THROW(),
 NOP(),
 LABEL(2,),
 LOAD_UNDEFINED(),
 POP(),
 LOAD('console',),
 LOAD('e',),
 LOAD_N_TUPLE(1,),
 CALL_METHOD_DOT('log',),
 NOP(),
 LABEL(3,),
 LOAD_UNDEFINED(),
 NOP(),
 LABEL(4,),
 TRY_CATCH_FINALLY(1, 2, 'e', 3, False, 4)]

0 LOAD_UNDEFINED()
1 JUMP(4,)
18 TRY_CATCH_FINALLY(1, 2, 'e', 3, False, 4)
  ctx entry (from:2, to:9)
  2 LOAD_UNDEFINED()
  3 POP()
  4 LOAD_NUMBER(3.0,)
  5 LOAD_NUMBER(3.0,)
  6 BINARY_OP('+',)
  7 THROW()
  ctx exit (js errors)
  ctx entry (from:9, to:16)
  9 LOAD_UNDEFINED()
  10 POP()
  11 LOAD('console',)
  12 LOAD('e',)
  13 LOAD_N_TUPLE(1,)
  14 CALL_METHOD_DOT('log',)
6
  15 NOP()
  ctx exit (normal)

This is just a curiosity and I do not recommend using VM in practice (requires more polishing).


Limitations

There are 3 main limitations:

  • "strict mode" is ignored
  • with statement is not supported
  • Indirect call to eval is treated as direct call to eval (hence always evals in local scope)

They are generally not a big issue in practice. In practice more problematic are minor edge cases that unfortunately sometimes do happen. Please report a bug if you find one.

Js2Py was able to successfully translate and run huge JS libraries like Babel (100k+ loc), esprima, crypto-js and more. You can try it yourself by importing any supported npm package via js2py.require('your_package').


Other Examples

In Js2Py all JavaScript objects are a subclass of PyJs object. For example JS Number is represented by PyJsNumber class. js2py.eval_js and js2py.EvalJs automatically tries to convert PyJs type to builtin python type. So for example if you execute:

>>> js2py.eval_js('var a = "hello"; a')

eval_js will return unicode type (u"hello"). However for complex types such conversion is impossible and JsObjectWrapper is returned. See the conversion table JsType -> PyType:

Boolean -> bool
String -> unicode (str in Python 3)
Number -> float (or int/long if whole number)
undefined -> None
null -> None
OTHER -> JsObjectWrapper

JsObjectWrapper supports: getitem, getattr, setitem, setattr, repr and call. Moreover it has to_list and to_dict methods if you want to convert it to builtin python type.

>>> js = js2py.eval_js('d = {a:1, b:2}')
>>> js
{a: 1, b: 2}  
>>> type(js)
<class 'js2py.base.JsObjectWrapper'>
>>> js.a
1
>>> js['a']
1
>>> js.b = 20
>>> js
{a: 1, b: 20}  
>>> js['c'] = 30
>>> js.to_dict()
{u'a': 1, 'c': 30, u'b': 20}

Also, of course you can use Js2Py to parse (tree is the same as in esprima.js) and translate JavaScript

Parsing:

>>> js2py.parse_js('var $ = 5')   
{
    "body": [
        {
            "declarations": [
                {
                    "id": {
                        "name": "$",
                        "type": "Identifier"
                    },
                    "init": {
                        "raw": "5",
                        "type": "Literal",
                        "value": 5
                    },
                    "type": "VariableDeclarator"
                }
            ],
            "kind": "var",
            "type": "VariableDeclaration"
        }
    ],
    "type": "Program"
}

Translating:

>>> print(js2py.translate_js('var $ = 5'))
from js2py.pyjs import *
# setting scope
var = Scope( JS_BUILTINS )
set_global_object(var)

# Code follows:
var.registers(['$'])
var.put('$', Js(5.0))

pyimport statement

Finally, Js2Py also supports importing any Python code from JavaScript using 'pyimport' statement:

>> js2py.eval_js(x) 18211 undefined">
>>> x = """pyimport urllib;
           var result = urllib.urlopen('https://www.google.com/').read();
           console.log(result.length)
        """
>>> js2py.eval_js(x)
18211
undefined
Aggregating gridded data (xarray) to polygons

A package to aggregate gridded data in xarray to polygons in geopandas using area-weighting from the relative area overlaps between pixels and polygons.

Kevin Schwarzwald 42 Nov 09, 2022
Python @deprecat decorator to deprecate old python classes, functions or methods.

deprecat Decorator Python @deprecat decorator to deprecate old python classes, functions or methods. Installation pip install deprecat Usage To use th

12 Dec 12, 2022
one_click_kag_server is a program which tries to fully automate the creation of a King Arthur's Gold server.

one_click_kag_server is a program which tries to fully automate the creation of a King Arthur's Gold server.

Benjamin Gorman 4 Jan 05, 2022
Script to rename and resize folders of images

script to rename and resize folders of images

Tega Brain 2 Oct 29, 2021
The producer-consumer problem implemented with threads in Python

This was developed using a Python virtual environment, I would strongly recommend to do the same if you want to clone this repository. How to run this

Omar Beltran 1 Oct 30, 2021
A set of Python scripts to surpass human limits in accomplishing simple tasks.

Human benchmark fooler Summary A set of Python scripts with Selenium designed to surpass human limits in accomplishing simple tasks available on https

Bohdan Dudchenko 3 Feb 10, 2022
Shypan, a simple, easy to use, full-featured library written in Python.

Shypan, a simple, easy to use, full-featured library written in Python.

ShypanLib 4 Dec 08, 2021
A python tool give n number of inputs and parallelly you will get a output by separetely

http-status-finder Hello Everyone!! This is kavisurya, In this tool you can give n number of inputs and parallelly you will get a output by separetely

KAVISURYA V 3 Dec 05, 2021
Pampy: The Pattern Matching for Python you always dreamed of.

Pampy: Pattern Matching for Python Pampy is pretty small (150 lines), reasonably fast, and often makes your code more readable and hence easier to rea

Claudio Santini 3.5k Jan 06, 2023
A hashtag from string extract python module

A hashtag from string extract python module

Fayas Noushad 3 Aug 10, 2022
Python HTTP Agent Parser

Features Fast Detects OS and Browser. Does not aim to be a full featured agent parser Will not turn into django-httpagentparser ;) Usage import ht

Shekhar 213 Dec 06, 2022
A simple dork generator written in python that outputs dorks with the domain extensions you enter

Dork Gen A simple dork generator written in python that outputs dorks with the domain extensions you enter in a ".txt file". Usage The code is pretty

Z3NToX 4 Oct 30, 2022
A collection of resources/tools and analyses for the angr binary analysis framework.

Awesome angr A collection of resources/tools and analyses for the angr binary analysis framework. This page does not only collect links and external r

105 Jan 02, 2023
Helper script to bootstrap a Python environment with the tools required to build and install packages.

python-bootstrap Helper script to bootstrap a Python environment with the tools required to build and install packages. Usage $ python -m bootstrap.bu

Filipe Laíns 7 Oct 06, 2022
A simple gpsd client and python library.

gpsdclient A small and simple gpsd client and library Installation Needs Python 3 (no other dependencies). If you want to use the library, use pip: pi

Thomas Feldmann 33 Nov 24, 2022
A simulator for xkcd 2529's weirdly concrete problem

What is this? This is a quick hack implementation of a simulator for xkcd 2529's weirdly concrete problem. This is barely tested and I suck at computa

Reuben Steenekamp 6 Oct 27, 2021
Pyfunctools is a module that provides functions, methods and classes that help in the creation of projects in python

Pyfunctools Pyfunctools is a module that provides functions, methods and classes that help in the creation of projects in python, bringing functional

Natanael dos Santos Feitosa 5 Dec 22, 2022
API for obtaining results from the Beery-Bukenica test of the visomotor integration development (VMI) 4th edition.

VMI API API for obtaining results from the Beery-Bukenica test of the visomotor integration development (VMI) 4th edition. Install docker-compose up -

Victor Vargas Sandoval 1 Oct 26, 2021
A fixture that allows runtime xfail

pytest-runtime-xfail pytest plugin, providing a runtime_xfail fixture, which is callable as runtime_xfail(), to allow runtime decisions to mark a test

Brian Okken 4 Apr 06, 2022
PyResToolbox - A collection of Reservoir Engineering Utilities

pyrestoolbox A collection of Reservoir Engineering Utilities This set of functio

Mark W. Burgoyne 39 Oct 17, 2022