CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-dukpy

Simple JavaScript interpreter for Python built on top of duktape engine without any external dependencies

Pending
Overview
Eval results
Files

javascript-evaluation.mddocs/

JavaScript Evaluation

Core JavaScript execution functionality supporting both one-off evaluation and persistent interpreter contexts with variable passing, module loading, and Python function exports.

Capabilities

One-off JavaScript Execution

Executes JavaScript code in a fresh interpreter context, automatically handling variable serialization and cleanup. Variables passed as keyword arguments are available in JavaScript as properties of the dukpy global object.

def evaljs(code, **kwargs):
    """
    Evaluates the given code as JavaScript and returns the result.
    
    Parameters:
    - code: str or list of str - JavaScript code to execute
    - **kwargs: Variables available in JavaScript as dukpy.varname
    
    Returns:
    JSON-serializable result of JavaScript execution
    
    Raises:
    JSRuntimeError: When JavaScript execution fails
    """

Usage example:

import dukpy

# Simple expression evaluation
result = dukpy.evaljs("5 + 3")  # Returns 8

# Using Python variables in JavaScript
result = dukpy.evaljs("dukpy.x * dukpy.y + 10", x=5, y=3)  # Returns 25

# Multiple JavaScript statements
result = dukpy.evaljs([
    "var obj = {count: 0}",
    "obj.count += dukpy.increment", 
    "obj"
], increment=5)  # Returns {'count': 5}

# Working with arrays and objects
data = [1, 2, 3, 4, 5]
result = dukpy.evaljs("dukpy.numbers.reduce((a, b) => a + b, 0)", numbers=data)  # Returns 15

Persistent JavaScript Interpreter

Maintains JavaScript context between evaluations, enabling stateful execution, module loading, and bi-directional Python-JavaScript function calls. Ideal for applications requiring multiple JavaScript operations or module usage.

class JSInterpreter:
    """JavaScript Interpreter with persistent context"""
    
    def __init__(self):
        """
        Creates a new JavaScript interpreter instance.
        Automatically initializes console logging and module system.
        """
    
    def evaljs(self, code, **kwargs):
        """
        Runs JavaScript code in the context of the interpreter.
        
        Parameters:
        - code: str or list of str - JavaScript code to execute
        - **kwargs: Variables available in JavaScript as dukpy.varname
        
        Returns:
        JSON-serializable result of JavaScript execution
        
        Raises:
        JSRuntimeError: When JavaScript execution fails
        """
    
    def export_function(self, name, func):
        """
        Exports a Python function to the JavaScript layer.
        
        Parameters:
        - name: str - Function name in JavaScript
        - func: callable - Python function to export
        
        Note: Only JSON-serializable objects can be passed between JS and Python.
        Objects are passed by copy, not by reference.
        """
    
    @property
    def loader(self):
        """
        Access to JSModuleLoader instance for registering module search paths.
        
        Returns:
        JSModuleLoader: Module loader for require() support
        """

Usage example:

import dukpy

# Create persistent interpreter
interpreter = dukpy.JSInterpreter()

# Maintain state between calls
interpreter.evaljs("var counter = 0")
count1 = interpreter.evaljs("++counter")  # Returns 1
count2 = interpreter.evaljs("++counter")  # Returns 2

# Export Python functions to JavaScript
def multiply(a, b):
    return a * b

interpreter.export_function('multiply', multiply)
result = interpreter.evaljs("call_python('multiply', 6, 7)")  # Returns 42

# Use require() to load modules
interpreter.loader.register_path('./js_modules')
result = interpreter.evaljs("var lodash = require('lodash'); lodash.isArray([1, 2, 3])")

Module Loading System

CommonJS-compatible module loading system that enables JavaScript modules to be loaded and used within the interpreter context using standard require() syntax.

class JSModuleLoader:
    """
    Manages finding and loading JS modules in CommonJS format.
    Supports standard Node.js module resolution patterns.
    """
    
    def __init__(self):
        """
        Creates module loader with default search paths:
        - dukpy/jsmodules (built-in modules)
        - current working directory
        """
    
    def register_path(self, path):
        """
        Registers a directory where to look for modules.
        
        Parameters:
        - path: str - Directory path to search for modules
        
        Note: Paths are searched in reverse registration order (LIFO).
        """
    
    def lookup(self, module_name):
        """
        Searches for a file providing given module.
        
        Parameters:
        - module_name: str - Name of module to find
        
        Returns:
        tuple: (normalized_module_id, file_path) or (None, None) if not found
        """
    
    def load(self, module_name):
        """
        Returns source code and normalized module id of the given module.
        
        Parameters:
        - module_name: str - Name of module to load
        
        Returns:
        tuple: (module_id, source_code) or (None, None) if not found
        
        Note: Only supports UTF-8 encoded source files.
        """

Usage example:

import dukpy

# Create interpreter and register module paths
interpreter = dukpy.JSInterpreter()
interpreter.loader.register_path('./my_js_modules')
interpreter.loader.register_path('./node_modules')

# Use require() in JavaScript
result = interpreter.evaljs("""
    var utils = require('utils');
    var math = require('math-functions');
    utils.processData(math.fibonacci(10))
""")

Node.js Compatibility Layer

Specialized interpreter providing Node.js-like environment with filesystem access and built-in core modules for enhanced JavaScript compatibility.

class NodeLikeInterpreter(JSInterpreter):
    """
    A DukPy Interpreter that provides a minimal compatibility layer with NodeJS.
    Inherits all JSInterpreter functionality with additional Node.js-like features.
    """
    
    def __init__(self):
        """
        Creates NodeLikeInterpreter with Node.js compatibility features:
        - Registers jscore module path for built-in Node.js modules
        - Exports file.exists and file.read functions to JavaScript
        - Inherits all JSInterpreter capabilities
        """

Usage example:

import dukpy
from dukpy.nodelike import NodeLikeInterpreter

# Create Node.js-like interpreter
interpreter = NodeLikeInterpreter()

# Access filesystem from JavaScript
result = interpreter.evaljs("""
    var exists = call_python('file.exists', '/path/to/file.txt');
    var content = '';
    if (exists) {
        content = call_python('file.read', '/path/to/file.txt', 'utf-8');
    }
    {exists: exists, content: content}
""")

# Use LESS compiler with Node.js compatibility
from dukpy import less_compile
css = less_compile("""
    @primary-color: #333;
    .header { color: @primary-color; }
""")

Filesystem Utilities

Simplified filesystem operations available to JavaScript through the NodeLikeInterpreter.

class FS:
    """
    Provides oversimplified fs.js native functions for JavaScript.
    Available as exported functions in NodeLikeInterpreter.
    """
    
    @classmethod
    def exists(cls, filepath):
        """
        Checks if a file or directory exists.
        
        Parameters:
        - filepath: str - Path to check
        
        Returns:
        bool: True if path exists, False otherwise
        """
    
    @classmethod  
    def read(cls, path, encoding):
        """
        Reads file contents with optional encoding.
        
        Parameters:
        - path: str - File path to read
        - encoding: str or None - Text encoding (e.g., 'utf-8') or None for binary
        
        Returns:
        str or bytes: File contents as string (if encoding) or bytes (if None)
        
        Raises:
        IOError: When file cannot be read
        """

Error Handling

class JSRuntimeError(Exception):
    """
    Exception raised when JavaScript execution fails.
    Provides details about JavaScript runtime errors including
    syntax errors, reference errors, and other execution failures.
    """

Common error scenarios:

import dukpy

try:
    # Syntax error
    result = dukpy.evaljs("var x = ;")
except dukpy.JSRuntimeError as e:
    print(f"JavaScript error: {e}")

try:
    # Reference error
    result = dukpy.evaljs("undefinedVariable.property")
except dukpy.JSRuntimeError as e:
    print(f"JavaScript error: {e}")

try:
    # Type error
    result = dukpy.evaljs("null.toString()")
except dukpy.JSRuntimeError as e:
    print(f"JavaScript error: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-dukpy

docs

index.md

javascript-evaluation.md

package-management.md

transpilers.md

webassets.md

tile.json