0
# JavaScript Evaluation
1
2
Core JavaScript execution functionality supporting both one-off evaluation and persistent interpreter contexts with variable passing, module loading, and Python function exports.
3
4
## Capabilities
5
6
### One-off JavaScript Execution
7
8
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.
9
10
```python { .api }
11
def evaljs(code, **kwargs):
12
"""
13
Evaluates the given code as JavaScript and returns the result.
14
15
Parameters:
16
- code: str or list of str - JavaScript code to execute
17
- **kwargs: Variables available in JavaScript as dukpy.varname
18
19
Returns:
20
JSON-serializable result of JavaScript execution
21
22
Raises:
23
JSRuntimeError: When JavaScript execution fails
24
"""
25
```
26
27
Usage example:
28
29
```python
30
import dukpy
31
32
# Simple expression evaluation
33
result = dukpy.evaljs("5 + 3") # Returns 8
34
35
# Using Python variables in JavaScript
36
result = dukpy.evaljs("dukpy.x * dukpy.y + 10", x=5, y=3) # Returns 25
37
38
# Multiple JavaScript statements
39
result = dukpy.evaljs([
40
"var obj = {count: 0}",
41
"obj.count += dukpy.increment",
42
"obj"
43
], increment=5) # Returns {'count': 5}
44
45
# Working with arrays and objects
46
data = [1, 2, 3, 4, 5]
47
result = dukpy.evaljs("dukpy.numbers.reduce((a, b) => a + b, 0)", numbers=data) # Returns 15
48
```
49
50
### Persistent JavaScript Interpreter
51
52
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.
53
54
```python { .api }
55
class JSInterpreter:
56
"""JavaScript Interpreter with persistent context"""
57
58
def __init__(self):
59
"""
60
Creates a new JavaScript interpreter instance.
61
Automatically initializes console logging and module system.
62
"""
63
64
def evaljs(self, code, **kwargs):
65
"""
66
Runs JavaScript code in the context of the interpreter.
67
68
Parameters:
69
- code: str or list of str - JavaScript code to execute
70
- **kwargs: Variables available in JavaScript as dukpy.varname
71
72
Returns:
73
JSON-serializable result of JavaScript execution
74
75
Raises:
76
JSRuntimeError: When JavaScript execution fails
77
"""
78
79
def export_function(self, name, func):
80
"""
81
Exports a Python function to the JavaScript layer.
82
83
Parameters:
84
- name: str - Function name in JavaScript
85
- func: callable - Python function to export
86
87
Note: Only JSON-serializable objects can be passed between JS and Python.
88
Objects are passed by copy, not by reference.
89
"""
90
91
@property
92
def loader(self):
93
"""
94
Access to JSModuleLoader instance for registering module search paths.
95
96
Returns:
97
JSModuleLoader: Module loader for require() support
98
"""
99
```
100
101
Usage example:
102
103
```python
104
import dukpy
105
106
# Create persistent interpreter
107
interpreter = dukpy.JSInterpreter()
108
109
# Maintain state between calls
110
interpreter.evaljs("var counter = 0")
111
count1 = interpreter.evaljs("++counter") # Returns 1
112
count2 = interpreter.evaljs("++counter") # Returns 2
113
114
# Export Python functions to JavaScript
115
def multiply(a, b):
116
return a * b
117
118
interpreter.export_function('multiply', multiply)
119
result = interpreter.evaljs("call_python('multiply', 6, 7)") # Returns 42
120
121
# Use require() to load modules
122
interpreter.loader.register_path('./js_modules')
123
result = interpreter.evaljs("var lodash = require('lodash'); lodash.isArray([1, 2, 3])")
124
```
125
126
### Module Loading System
127
128
CommonJS-compatible module loading system that enables JavaScript modules to be loaded and used within the interpreter context using standard `require()` syntax.
129
130
```python { .api }
131
class JSModuleLoader:
132
"""
133
Manages finding and loading JS modules in CommonJS format.
134
Supports standard Node.js module resolution patterns.
135
"""
136
137
def __init__(self):
138
"""
139
Creates module loader with default search paths:
140
- dukpy/jsmodules (built-in modules)
141
- current working directory
142
"""
143
144
def register_path(self, path):
145
"""
146
Registers a directory where to look for modules.
147
148
Parameters:
149
- path: str - Directory path to search for modules
150
151
Note: Paths are searched in reverse registration order (LIFO).
152
"""
153
154
def lookup(self, module_name):
155
"""
156
Searches for a file providing given module.
157
158
Parameters:
159
- module_name: str - Name of module to find
160
161
Returns:
162
tuple: (normalized_module_id, file_path) or (None, None) if not found
163
"""
164
165
def load(self, module_name):
166
"""
167
Returns source code and normalized module id of the given module.
168
169
Parameters:
170
- module_name: str - Name of module to load
171
172
Returns:
173
tuple: (module_id, source_code) or (None, None) if not found
174
175
Note: Only supports UTF-8 encoded source files.
176
"""
177
```
178
179
Usage example:
180
181
```python
182
import dukpy
183
184
# Create interpreter and register module paths
185
interpreter = dukpy.JSInterpreter()
186
interpreter.loader.register_path('./my_js_modules')
187
interpreter.loader.register_path('./node_modules')
188
189
# Use require() in JavaScript
190
result = interpreter.evaljs("""
191
var utils = require('utils');
192
var math = require('math-functions');
193
utils.processData(math.fibonacci(10))
194
""")
195
```
196
197
### Node.js Compatibility Layer
198
199
Specialized interpreter providing Node.js-like environment with filesystem access and built-in core modules for enhanced JavaScript compatibility.
200
201
```python { .api }
202
class NodeLikeInterpreter(JSInterpreter):
203
"""
204
A DukPy Interpreter that provides a minimal compatibility layer with NodeJS.
205
Inherits all JSInterpreter functionality with additional Node.js-like features.
206
"""
207
208
def __init__(self):
209
"""
210
Creates NodeLikeInterpreter with Node.js compatibility features:
211
- Registers jscore module path for built-in Node.js modules
212
- Exports file.exists and file.read functions to JavaScript
213
- Inherits all JSInterpreter capabilities
214
"""
215
```
216
217
Usage example:
218
219
```python
220
import dukpy
221
from dukpy.nodelike import NodeLikeInterpreter
222
223
# Create Node.js-like interpreter
224
interpreter = NodeLikeInterpreter()
225
226
# Access filesystem from JavaScript
227
result = interpreter.evaljs("""
228
var exists = call_python('file.exists', '/path/to/file.txt');
229
var content = '';
230
if (exists) {
231
content = call_python('file.read', '/path/to/file.txt', 'utf-8');
232
}
233
{exists: exists, content: content}
234
""")
235
236
# Use LESS compiler with Node.js compatibility
237
from dukpy import less_compile
238
css = less_compile("""
239
@primary-color: #333;
240
.header { color: @primary-color; }
241
""")
242
```
243
244
### Filesystem Utilities
245
246
Simplified filesystem operations available to JavaScript through the NodeLikeInterpreter.
247
248
```python { .api }
249
class FS:
250
"""
251
Provides oversimplified fs.js native functions for JavaScript.
252
Available as exported functions in NodeLikeInterpreter.
253
"""
254
255
@classmethod
256
def exists(cls, filepath):
257
"""
258
Checks if a file or directory exists.
259
260
Parameters:
261
- filepath: str - Path to check
262
263
Returns:
264
bool: True if path exists, False otherwise
265
"""
266
267
@classmethod
268
def read(cls, path, encoding):
269
"""
270
Reads file contents with optional encoding.
271
272
Parameters:
273
- path: str - File path to read
274
- encoding: str or None - Text encoding (e.g., 'utf-8') or None for binary
275
276
Returns:
277
str or bytes: File contents as string (if encoding) or bytes (if None)
278
279
Raises:
280
IOError: When file cannot be read
281
"""
282
```
283
284
## Error Handling
285
286
```python { .api }
287
class JSRuntimeError(Exception):
288
"""
289
Exception raised when JavaScript execution fails.
290
Provides details about JavaScript runtime errors including
291
syntax errors, reference errors, and other execution failures.
292
"""
293
```
294
295
Common error scenarios:
296
297
```python
298
import dukpy
299
300
try:
301
# Syntax error
302
result = dukpy.evaljs("var x = ;")
303
except dukpy.JSRuntimeError as e:
304
print(f"JavaScript error: {e}")
305
306
try:
307
# Reference error
308
result = dukpy.evaljs("undefinedVariable.property")
309
except dukpy.JSRuntimeError as e:
310
print(f"JavaScript error: {e}")
311
312
try:
313
# Type error
314
result = dukpy.evaljs("null.toString()")
315
except dukpy.JSRuntimeError as e:
316
print(f"JavaScript error: {e}")
317
```