### Install PyMiniRacer Source: https://context7.com/bpcreech/pyminiracer/llms.txt Install the library using pip. No additional setup is required. ```bash pip install mini-racer ``` -------------------------------- ### Install MiniRacer Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Install the MiniRacer library using pip. ```sh $ pip install mini-racer ``` -------------------------------- ### Installation Source: https://context7.com/bpcreech/pyminiracer/llms.txt Install PyMiniRacer using pip. ```APIDOC ## Installation Install MiniRacer from PyPI using pip. ```bash pip install mini-racer ``` ``` -------------------------------- ### Local Development Setup and Commands Source: https://github.com/bpcreech/pyminiracer/blob/main/CONTRIBUTING.md Commands for setting up a local clone, building v8 and uv, running tests, and fixing/linting code. Building v8 and uv can take several hours. ```shell # Set up a local clone of your fork: $ git clone git@github.com:your_name_here/PyMiniRacer.git $ cd PyMiniRacer/ # build v8 and uv (this may take hours depending on your system!) $ just build # alternatively, to only build v8 and skip making the Python package: $ uv run --no-project builder/v8_build.py # will install a DLL into src/py_mini_racer # test stuff: $ uv run pytest test # fix and lint any changes you make: $ just fix $ just lint ``` ```shell # automatically fix any trivial linting issues: $ just fix # check for remaining linting issues: $ just lint # if you changed C++ code, lint it (this takes a long time): $ just clang-tidy # look at the docs if you changed them: $ just serve-docs # build v8, and your change (this takes a long time): $ just build # test: $ just test $ just test-matrix ``` ```shell $ git add . $ git commit -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature ``` -------------------------------- ### Installing Async Python Callbacks from JavaScript Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Shows how to install and use async Python functions as callbacks from JavaScript. Requires PyMiniRacer v0.12.0 or later. Note that this may degrade security. ```python from py_mini_racer import mini_racer import asyncio async def read_file(fn): with open(fn) as f: # (or aiofiles would be even better here) return f.read() with mini_racer() as ctx: async with ctx.wrap_py_function(read_file) as jsfunc: # "Install" our (async) JS function on the global "this" object: ctx.eval('this')['read_file'] = jsfunc d = await ctx.eval('read_file("/usr/share/dict/words")') print(d.split()[0:10]) ``` -------------------------------- ### Installing Async Python Callbacks from JavaScript Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/index.md Install async Python functions as JavaScript functions on the global `this` object using `wrap_py_function`. Ensure the Python function is `async`. ```python % python -m asyncio >>> from py_mini_racer import mini_racer >>> async def read_file(fn): ... with open(fn) as f: # (or aiofiles would be even better here) ... return f.read() ... >>> with mini_racer() as ctx: ... async with ctx.wrap_py_function(read_file) as jsfunc: ... # "Install" our (async) JS function on the global "this" object: ... ctx.eval('this')['read_file'] = jsfunc ... d = await ctx.eval('read_file("/usr/share/dict/words")') ... print(d.split()[0:10]) ['A', 'AA', 'AAA', "AA's", 'AB', 'ABC', "ABC's", 'ABCs', 'ABM', "ABM's"] ``` -------------------------------- ### ECMA Intl API Example Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Demonstrates the usage of the ECMA `Intl` API for internationalization, specifically formatting dates in Indonesian. ```python ctx.eval('Intl.DateTimeFormat(["ban", "id"]).format(new Date())') ``` -------------------------------- ### Handle JS Promises in Python Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/history.md PyMiniRacer can now convert JavaScript Promises returned from `eval` into Python objects. These objects support both a blocking `get()` method and can be `await`ed in async Python functions. ```python promise.get() ``` -------------------------------- ### Build and Test PyMiniRacer Locally Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/contributing.md Commands to set up a local development environment, build the project, and run tests. Building v8 and the Python package can take a significant amount of time. ```sh # Set up a local clone of your fork: $ git clone git@github.com:your_name_here/PyMiniRacer.git $ cd PyMiniRacer/ # build v8 and uv (this may take hours depending on your system!) $ just build # alternatively, to only build v8 and skip making the Python package: $ uv run --no-project builder/v8_build.py # will install a DLL into src/py_mini_racer # test stuff: $ uv run pytest test # fix and lint any changes you make: $ just fix $ just lint ``` -------------------------------- ### Create and Push Release Branch Source: https://github.com/bpcreech/pyminiracer/blob/main/CONTRIBUTING.md Checkout the main branch, pull the latest changes, define the next release tag, create a new release branch, and push it to the origin. ```sh git checkout main git pull NEXT_RELEASE=the next tag, starting with the letter v. E.g., "v0.12.1". git checkout -b "release/${NEXT_RELEASE}" git push --set-upstream origin "release/${NEXT_RELEASE}" ``` -------------------------------- ### Creating a MiniRacer Context Source: https://context7.com/bpcreech/pyminiracer/llms.txt Demonstrates how to create and use a MiniRacer context for executing JavaScript code. ```APIDOC ## Creating a MiniRacer Context Create a MiniRacer instance to evaluate JavaScript code. The context persists variables between evaluations and supports the context manager protocol for deterministic cleanup. ```python from py_mini_racer import MiniRacer, mini_racer # Basic instantiation ctx = MiniRacer() result = ctx.eval("1 + 1") print(result) # Output: 2 # Using context manager (recommended for deterministic cleanup) with MiniRacer() as ctx: ctx.eval("var x = 10") result = ctx.eval("x * 2") print(result) # Output: 20 # Alternative context manager syntax with mini_racer() as ctx: result = ctx.eval("Array.from('hello').reverse().join('')") print(result) # Output: olleh ``` ``` -------------------------------- ### Interactive Python REPL with PyMiniRacer Source: https://github.com/bpcreech/pyminiracer/blob/main/CONTRIBUTING.md Demonstrates how to use PyMiniRacer in an interactive Python REPL after setting up the development environment. Requires `uv` to run. ```shell $ uv run python >>> from py_mini_racer import MiniRacer >>> mr = MiniRacer() >>> mr.eval('6*7') 42 >>> exit() $ exit ``` -------------------------------- ### Run Linting and Testing Commands Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/contributing.md Commands to ensure code quality and correctness before committing changes. Includes fixing linting issues, checking for remaining issues, linting C++ code, serving documentation, building, and running tests. ```sh # automatically fix any trivial linting issues: $ just fix # check for remaining linting issues: $ just lint # if you changed C++ code, lint it (this takes a long time): $ just clang-tidy # look at the docs if you changed them: $ just serve-docs # build v8, and your change (this takes a long time): $ just build # test: $ just test $ just test-matrix ``` -------------------------------- ### Execute WebAssembly Modules with py_mini_racer Source: https://context7.com/bpcreech/pyminiracer/llms.txt Execute WebAssembly modules within the V8 context. Load the WASM binary into a `SharedArrayBuffer` and instantiate it. ```python from pathlib import Path from py_mini_racer import MiniRacer ctx = MiniRacer() # Load WASM module (example: a simple add function) wasm_path = Path("add.wasm") wasm_size = wasm_path.stat().st_size # Allocate a SharedArrayBuffer to hold the WASM binary buffer = ctx.eval(f" const wasmBuffer = new SharedArrayBuffer({wasm_size}); wasmBuffer ") # Read WASM binary into the buffer with open(wasm_path, "rb") as f: f.readinto(buffer) # Instantiate the WASM module ctx.eval(""" var wasmInstance = null; WebAssembly.instantiate(new Uint8Array(wasmBuffer)) .then(result => { wasmInstance = result.instance; }) .catch(err => { wasmInstance = err.message; }); """ ) # Wait for instantiation while ctx.eval("wasmInstance") is None: pass # Call WASM function result = ctx.eval("wasmInstance.exports.addTwo(40, 2)") print(result) # Output: 42 ``` -------------------------------- ### Create and Use MiniRacer Context Source: https://context7.com/bpcreech/pyminiracer/llms.txt Instantiate MiniRacer to evaluate JavaScript. Using the context manager is recommended for deterministic cleanup. ```python from py_mini_racer import MiniRacer, mini_racer # Basic instantiation ctx = MiniRacer() result = ctx.eval("1 + 1") print(result) # Output: 2 # Using context manager (recommended for deterministic cleanup) with MiniRacer() as ctx: ctx.eval("var x = 10") result = ctx.eval("x * 2") print(result) # Output: 20 # Alternative context manager syntax with mini_racer() as ctx: result = ctx.eval("Array.from('hello').reverse().join('')") print(result) # Output: olleh ``` -------------------------------- ### Context Manager for Resource Management Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Use the `mini_racer()` context manager for deterministic cleanup of MiniRacer resources. ```python >>> from py_mini_racer import mini_racer >>> with mini_racer() as ctx: ... print(ctx.eval("Array.from('foobar').reverse().join('')")) raboof ``` -------------------------------- ### Basic JavaScript Evaluation Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/index.md Initialize MiniRacer and evaluate simple JavaScript expressions. ```python $ python3 >>> from py_mini_racer import MiniRacer >>> ctx = MiniRacer() >>> ctx.eval("1+1") 2 >>> ctx.eval("var x = {company: 'Sqreen'}; x.company") 'Sqreen' >>> print(ctx.eval("'❤'")) ❤ >>> ctx.eval("var fun = () => ({ foo: 1 });") ``` -------------------------------- ### Commit and Push Changes Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/contributing.md Standard Git commands to stage all changes, commit them with a descriptive message, and push the branch to your GitHub fork. Ensure your commit message clearly explains the changes. ```sh $ git add . $ git commit -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature ``` -------------------------------- ### Create Isolated JavaScript Contexts with PyMiniRacer Source: https://context7.com/bpcreech/pyminiracer/llms.txt Demonstrates creating multiple independent MiniRacer instances to achieve isolated JavaScript execution environments. Variables and functions defined in one context are not accessible in others, ensuring true sandboxing. ```python from py_mini_racer import MiniRacer # Create separate isolated contexts ctx1 = MiniRacer() ctx2 = MiniRacer() ctx3 = MiniRacer() # Variables are isolated between contexts ctx1.eval("var x = 1") ctx2.eval("var x = 2") ctx3.eval("var x = 3") print(ctx1.eval("x")) # Output: 1 print(ctx2.eval("x")) # Output: 2 print(ctx3.eval("x")) # Output: 3 # Functions defined in one context are not available in others ctx1.eval("function greet() { return 'Hello from ctx1'; }") print(ctx1.eval("greet()")) # Output: Hello from ctx1 try: ctx2.eval("greet()") # Raises JSEvalException except Exception as e: print("greet() not defined in ctx2") # Clean up ctx1.close() ctx2.close() ctx3.close() ``` -------------------------------- ### Branching for Local Development Source: https://github.com/bpcreech/pyminiracer/blob/main/CONTRIBUTING.md Commands to create a new branch for local development, either for a feature or a fix. ```shell $ git checkout -b feature/name-of-feature # or: $ git checkout -b fix/name-of-fix ``` -------------------------------- ### Fetch and List Remote Tags Source: https://github.com/bpcreech/pyminiracer/blob/main/CONTRIBUTING.md Fetch remote references and list available release tags to determine the next revision number. ```sh git fetch git ls-remote origin | grep refs/heads/release # observe the next available release version ``` -------------------------------- ### V8 Heap Information Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/index.md Retrieve V8 heap statistics for memory usage analysis. ```python >>> ctx.heap_stats() {'total_physical_size': 1613896, 'used_heap_size': 1512520, 'total_heap_size': 3997696, 'total_heap_size_executable': 3145728, 'heap_size_limit': 1501560832} ``` -------------------------------- ### Async Evaluation with Timeout Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Demonstrates how to handle timeouts in async JavaScript evaluation using `asyncio.wait_for` with `eval_cancelable` or by upgrading a function to be cancelable. ```python from py_mini_racer import mini_racer import asyncio with mini_racer() as ctx: # Use eval_cancelable(...), which has async semantics: await asyncio.wait_for(ctx.eval_cancelable('while (true) {}'), timeout=2) ``` ```python from py_mini_racer import mini_racer import asyncio with mini_racer() as ctx: func = ctx.eval('() => {while (true) {}}") # Upgrade func using .cancelable(), which introduces async semantics: cancelable_func = func.cancelable() await asyncio.wait_for(cancelable_func(), timeout=2) ``` -------------------------------- ### V8 Heap Information Retrieval Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Shows how to retrieve V8 JavaScript engine heap statistics using the `heap_stats()` method. ```python ctx.heap_stats() ``` -------------------------------- ### Hypothetical Value Handling API in C++ Source: https://github.com/bpcreech/pyminiracer/blob/main/ARCHITECTURE.md This illustrates a potential API for handling values via IDs, which is not currently used by PyMiniRacer. It involves mapping value IDs to Value objects and using specific functions to retrieve value types and data. ```c++ 1. C++ generates a numeric `value_id` and stores a Value in a `std::unordered_map>`. 1. C++ gives Python that `value_id` to Python. 1. To get any data Python has to call APIs like `mr_value_type(context_id, value_id)`, `mr_value_as_bool(context_id, value_id)`, `mr_value_as_string_len(context_id, value_id)`, `mr_value_as_string(context_id, value_id, buf, buflen)`, ... 1. Eventually Python calls `mr_value_free(context_id, value_id)` which wipes out the map entry, thus freeing the `Value`. ``` -------------------------------- ### Format Dates and Numbers with Locales in JavaScript Source: https://context7.com/bpcreech/pyminiracer/llms.txt Demonstrates using JavaScript's Intl.DateTimeFormat and Intl.NumberFormat within PyMiniRacer to format dates and numbers according to specified locales. Ensure the JavaScript environment supports these Intl APIs. ```python us_date = ctx.eval('new Intl.DateTimeFormat("en-US").format(new Date("2024-03-15"))') print(us_date) # Output: 3/15/2024 de_date = ctx.eval('new Intl.DateTimeFormat("de-DE").format(new Date("2024-03-15"))') print(de_date) # Output: 15.3.2024 us_num = ctx.eval('new Intl.NumberFormat("en-US").format(1234567.89)') print(us_num) # Output: 1,234,567.89 de_num = ctx.eval('new Intl.NumberFormat("de-DE").format(1234567.89)') print(de_num) # Output: 1.234.567,89 ``` ```javascript new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(99.99) ``` ```javascript ["Émile", "emil", "Emma"].sort( new Intl.Collator("fr", {sensitivity: "base"}).compare ) ``` -------------------------------- ### Asynchronous Execution with Promises Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md MiniRacer supports JavaScript Promises. Use `promise.get()` to block and retrieve the resolved value. ```python >>> promise = ctx.eval( ... "new Promise((res, rej) => setTimeout(() => res(42), 10000))") >>> promise.get() # blocks for 10 seconds, and then: 42 ``` -------------------------------- ### Basic JavaScript Evaluation Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Evaluate simple JavaScript expressions and access object properties within a MiniRacer context. ```python >>> from py_mini_racer import MiniRacer >>> ctx = MiniRacer() >>> ctx.eval("1+1") 2 ``` ```python >>> ctx.eval("var x = {company: 'Sqreen'}; x.company") 'Sqreen' ``` ```python >>> print(ctx.eval("'❤'")) ❤ ``` ```python >>> ctx.eval("var fun = () => ({ foo: 1 });") ``` ```python >>> ctx.eval("x.company") 'Sqreen' ``` -------------------------------- ### Create Hotfix Release Branch Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/contributing.md Checkout a base release branch, pull changes, and create a new hotfix release branch. ```sh BASE_RELEASE=the release you are hotfixing, starting with the letter v. E.g., "v0.12.0". NEXT_RELEASE=the next tag, starting with the letter v. E.g., "v0.12.1". git checkout "release/${BASE_RELEASE}" git pull git checkout -b "release/${NEXT_RELEASE}" ``` -------------------------------- ### Use setTimeout and clearTimeout Source: https://github.com/bpcreech/pyminiracer/blob/main/HISTORY.md Implement Web API standard functions setTimeout and clearTimeout for delayed execution and cancellation of JS code within PyMiniRacer. ```python mr.setTimeout(lambda: print('Hello'), 1000) ``` ```python timer_id = mr.setTimeout(lambda: print('Hello'), 1000) clearInterval(timer_id) ``` -------------------------------- ### Set Hard Memory Limit Source: https://github.com/bpcreech/pyminiracer/blob/main/HISTORY.md Configure a hard memory limit for JavaScript execution context-wide using the `max_memory` parameter. The `eval`-specific argument is maintained for backward compatibility. ```python mr = MiniRacer(max_memory=1024*1024) # 1MB limit ``` -------------------------------- ### Run Task on Isolate Message Loop Source: https://github.com/bpcreech/pyminiracer/blob/main/ARCHITECTURE.md Submit a task to the message loop to safely interact with the v8::Isolate. The callback receives a v8::Isolate* and can perform operations until it exits. ```cpp isolate_manager->Run([global]() { delete global; }) ``` -------------------------------- ### ES6 Capabilities Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md MiniRacer supports ES6 features, demonstrated here with the `includes` array method. ```python >>> ctx.execute("[1,2,3].includes(5)") False ``` -------------------------------- ### Event Loop Management Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md MiniRacer uses `asyncio` internally. It can launch its own event loop or use an existing one. The `mini_racer()` context manager reuses the running event loop in async contexts. ```python >>> from py_mini_racer import MiniRacer, mini_racer >>> ctx = MiniRacer() # launches a new event loop in a new thread >>> with mini_racer() as ctx: # same: launches a new event loop in a new thread ... pass ... >>> async def demo(): ... with mini_racer() as ctx: # reuses the running event loop ... pass ... >>> import asyncio >>> asyncio.run(demo()) ``` ```python >>> my_loop = asyncio.new_event_loop() >>> with mini_racer(my_loop) as ctx: # uses the specified event loop ... pass ``` -------------------------------- ### Expose Python Async Functions to JavaScript with wrap_py_function Source: https://context7.com/bpcreech/pyminiracer/llms.txt Expose Python async functions to JavaScript using `wrap_py_function`, enabling bidirectional communication. JavaScript calls return Promises. ```python import asyncio from py_mini_racer import mini_racer async def python_callback_example(): # Define a Python function to expose to JavaScript async def fetch_data(url): # Simulate async data fetching await asyncio.sleep(0.1) return {"url": url, "data": f"Content from {url}"} async def calculate(a, b, operation): if operation == "add": return a + b elif operation == "multiply": return a * b return None with mini_racer() as ctx: # Expose fetch_data to JavaScript async with ctx.wrap_py_function(fetch_data) as js_fetch: # Install on global object ctx.eval("this")["fetch_data"] = js_fetch # Call from JavaScript (returns a Promise) result = await ctx.eval('fetch_data("https://api.example.com")') print(result["url"]) print(result["data"]) # Expose calculator function async with ctx.wrap_py_function(calculate) as js_calc: ctx.eval("this")["calculate"] = js_calc sum_result = await ctx.eval('calculate(10, 20, "add")') print(sum_result) product = await ctx.eval('calculate(5, 6, "multiply")') print(product) asyncio.run(python_callback_example()) ``` -------------------------------- ### Awaiting Promises in Async Code Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/index.md When calling MiniRacer from asynchronous Python code, use `await` to handle Promises instead of `.get()`. ```python % python -m asyncio >>> from py_mini_racer import mini_racer >>> with mini_racer() as ctx: ... promise = ctx.eval( ... "new Promise((res, rej) => setTimeout(() => res(42), 10000))") ... print(await promise) # yields for 10 seconds, and then: ... 42 ``` -------------------------------- ### Checkout and Pull Base Release Branch Source: https://github.com/bpcreech/pyminiracer/blob/main/CONTRIBUTING.md Checkout the base release branch for a hotfix and pull the latest changes. ```sh BASE_RELEASE=the release you are hotfixing, starting with the letter v. E.g., "v0.12.0". NEXT_RELEASE=the next tag, starting with the letter v. E.g., "v0.12.1". git checkout "release/${BASE_RELEASE}" git pull ``` -------------------------------- ### Extract and Call JS Function from Python Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/history.md For optimizing repeated calls to the same JavaScript function, extract the function handle from the MiniRacer context and call it directly from Python. This is more efficient than repeatedly evaluating the function call. ```python mr.eval("myfunc")() ``` -------------------------------- ### Async Cancelable Execution with py_mini_racer Source: https://context7.com/bpcreech/pyminiracer/llms.txt Use `eval_cancelable()` for async contexts to enable cancellation via `asyncio.wait_for()` or task cancellation. The context remains usable after cancellation. ```python import asyncio from py_mini_racer import mini_racer async def cancelable_example(): with mini_racer() as ctx: # Use eval_cancelable with asyncio.wait_for for timeouts try: await asyncio.wait_for( ctx.eval_cancelable("while(true) {}"), timeout=2 ) except asyncio.TimeoutError: print("Execution was canceled due to timeout") # Context remains usable after cancellation result = ctx.eval("'Still working!'") print(result) # Output: Still working! # Cancelable function calls func = ctx.eval("() => { while(true) {} }") cancelable_func = func.cancelable() try: await asyncio.wait_for(cancelable_func(), timeout=1) except asyncio.TimeoutError: print("Function canceled") asyncio.run(cancelable_example()) ``` -------------------------------- ### Internationalization API (Intl) Support Source: https://context7.com/bpcreech/pyminiracer/llms.txt MiniRacer supports the ECMA Internationalization API (`Intl`) for locale-aware formatting of dates, numbers, and strings. ```python from py_mini_racer import MiniRacer ctx = MiniRacer() ``` -------------------------------- ### Evaluate JavaScript Code with eval() Source: https://context7.com/bpcreech/pyminiracer/llms.txt Use eval() to execute JavaScript expressions and retrieve results as Python types. Variables and functions defined persist within the context. ```python from py_mini_racer import MiniRacer ctx = MiniRacer() # Evaluate expressions and get results result = ctx.eval("42") print(result) # Output: 42 # Define and use variables (persisted in context) ctx.eval("var company = 'Acme Corp'") ctx.eval("var revenue = 1000000") name = ctx.eval("company") print(name) # Output: Acme Corp # Define and call functions ctx.eval("var multiply = (a, b) => a * b") result = ctx.eval("multiply(6, 7)") print(result) # Output: 42 # Unicode support emoji = ctx.eval("'Hello ' + '❤️' + ' World'") print(emoji) # Output: Hello ❤️ World # ES6+ features ctx.eval("[1, 2, 3, 4, 5].includes(3)") # Output: True ctx.eval("`Template literal: ${2 + 2}`") # Output: Template literal: 4 ``` -------------------------------- ### Await Task Completion with std::future Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/architecture.md When using MiniRacer::IsolateManager::Run, await the returned std::future to ensure the task is completed before destroying any objects bound into the closure. This prevents reference cycles and potential memory leaks or use-after-free bugs. ```cpp std::future future = isolate_manager->Run(xyz); // ... later ... future.get(); ``` -------------------------------- ### Handle JavaScript Exceptions in Python Source: https://context7.com/bpcreech/pyminiracer/llms.txt Shows how to catch various JavaScript exceptions (parse, eval, timeout, OOM, promise rejection) raised during PyMiniRacer execution and map them to specific Python exception types. Ensure proper try-except blocks are used for robust error handling. ```python from py_mini_racer import ( MiniRacer, JSParseException, JSEvalException, JSTimeoutException, JSOOMException, JSPromiseError, ) ctx = MiniRacer() # Syntax/parse errors try: ctx.eval("function invalid(") except JSParseException as e: print(f"Parse error: {e}") # Output includes: SyntaxError: Unexpected end of input # Runtime evaluation errors try: ctx.eval("undefinedVariable.property") except JSEvalException as e: print(f"Eval error: {e}") # Output includes: ReferenceError: undefinedVariable is not defined # Thrown exceptions from JavaScript try: ctx.eval("throw new Error('Custom error message')") except JSEvalException as e: print(f"JS threw: {e}") # Timeout exceptions try: ctx.eval("while(true){}", timeout_sec=0.5) except JSTimeoutException as e: print(f"Timeout: {e}") # Out of memory exceptions ctx.set_hard_memory_limit(10_000_000) try: ctx.eval("var arr = []; while(true) arr.push(new Array(100000))") except JSOOMException as e: print(f"OOM: {e}") # Promise rejection errors try: promise = ctx.eval("Promise.reject('Rejection reason')") promise.get() except JSPromiseError as e: print(f"Promise rejected with: {e.reason}") ``` -------------------------------- ### Monitor V8 Heap Usage with heap_stats Source: https://context7.com/bpcreech/pyminiracer/llms.txt Retrieve V8 isolate heap statistics using `heap_stats()` to monitor memory consumption. `low_memory_notification()` can be called to request garbage collection. ```python from py_mini_racer import MiniRacer ctx = MiniRacer() # Allocate some memory in JavaScript ctx.eval("var data = new Array(10000).fill('x'.repeat(100))") # Get heap statistics stats = ctx.heap_stats() print(f"Total heap size: {stats['total_heap_size'] / 1024 / 1024:.2f} MB") print(f"Used heap size: {stats['used_heap_size'] / 1024 / 1024:.2f} MB") print(f"Heap size limit: {stats['heap_size_limit'] / 1024 / 1024:.2f} MB") print(f"Total physical size: {stats['total_physical_size'] / 1024 / 1024:.2f} MB") # Request garbage collection ctx.low_memory_notification() # Check stats after GC stats_after = ctx.heap_stats() print(f"Used heap after GC: {stats_after['used_heap_size'] / 1024 / 1024:.2f} MB") ``` -------------------------------- ### Evaluate and Call JavaScript Functions Source: https://github.com/bpcreech/pyminiracer/blob/main/README.md Define a JavaScript function and call it from Python. The function object is returned and can be invoked like a Python function. ```python >>> square = ctx.eval("a => a*a") >>> square(4) 16 ``` -------------------------------- ### Handle Asynchronous JavaScript Promises Source: https://context7.com/bpcreech/pyminiracer/llms.txt Manage JavaScript Promises using either a blocking `.get()` method for synchronous retrieval or an `await` pattern for asynchronous code. Handle rejected promises with `JSPromiseError`. ```python import asyncio from py_mini_racer import MiniRacer, mini_racer, JSPromiseError # Synchronous promise handling with .get() ctx = MiniRacer() promise = ctx.eval("new Promise((resolve) => setTimeout(() => resolve(42), 100))") result = promise.get(timeout=5) print(result) # Output: 42 # Already-resolved promises resolved = ctx.eval("Promise.resolve('immediate')") print(resolved.get()) # Output: immediate # Handling rejected promises try: rejected = ctx.eval("Promise.reject(new Error('Something went wrong'))") rejected.get() except JSPromiseError as e: print(f"Promise rejected: {e.reason}") # Async/await pattern (recommended for async code) async def async_example(): with mini_racer() as ctx: promise = ctx.eval(""" new Promise((resolve) => { setTimeout(() => resolve({status: 'done', value: 100}), 100) }) """) result = await promise print(result["status"]) # Output: done print(result["value"]) # Output: 100 asyncio.run(async_example()) ``` -------------------------------- ### Await Task Completion with std::future Source: https://github.com/bpcreech/pyminiracer/blob/main/ARCHITECTURE.md Ensure a task submitted to MiniRacer::IsolateManager::Run has completed before destroying objects bound into its closure. This is commonly achieved by waiting on the returned std::future. ```cpp std::future future = isolate_manager->Run(xyz); // ... wait for future to settle before tearing down references ``` -------------------------------- ### Set JavaScript Execution Timeouts and Memory Limits Source: https://context7.com/bpcreech/pyminiracer/llms.txt Prevent runaway JavaScript execution by setting `timeout_sec` for `eval()` or function calls, and `hard_memory_limit` or `soft_memory_limit` for memory consumption. Check limit status with `was_hard_memory_limit_reached()` and `was_soft_memory_limit_reached()`. ```python from py_mini_racer import MiniRacer, JSTimeoutException, JSOOMException ctx = MiniRacer() # Set execution timeout (in seconds) try: ctx.eval("while(true) {}", timeout_sec=2) except JSTimeoutException as e: print(f"Execution timed out: {e}") # Output: Execution timed out: JavaScript was terminated by timeout # Timeout on function calls func = ctx.eval("() => { while(true) {} }") try: func(timeout_sec=1) except JSTimeoutException: print("Function call timed out") # Context still works after timeout print(ctx.eval("1 + 1")) # Output: 2 # Set hard memory limit (in bytes) ctx.set_hard_memory_limit(100_000_000) # 100 MB try: ctx.eval(""" let arr = []; while(true) { arr.push(new Array(1000000).fill(0)); } """) except JSOOMException as e: print(f"Out of memory: {e}") # Set soft memory limit (triggers aggressive GC) ctx.set_soft_memory_limit(50_000_000) # 50 MB # Check if limits were reached print(ctx.was_hard_memory_limit_reached()) # Output: True print(ctx.was_soft_memory_limit_reached()) # Output: True ``` -------------------------------- ### Accessing Variables in Context Source: https://github.com/bpcreech/pyminiracer/blob/main/docs/index.md Evaluate JavaScript expressions to access variables previously defined within the MiniRacer context. ```python >>> ctx.eval("x.company") 'Sqreen' ``` -------------------------------- ### call - Call JavaScript Functions with Arguments Source: https://context7.com/bpcreech/pyminiracer/llms.txt The `call()` method invokes a JavaScript function by name with arguments serialized via JSON. It returns complex types as Python objects. ```APIDOC ## call - Call JavaScript Functions with Arguments The `call()` method invokes a JavaScript function by name with arguments serialized via JSON. It returns complex types as Python objects. ```python from py_mini_racer import MiniRacer from datetime import datetime, timezone from json import JSONEncoder ctx = MiniRacer() # Define a function and call it with arguments ctx.eval("var add = (a, b) => a + b") result = ctx.call("add", 10, 20) print(result) # Output: 30 # Call with multiple arguments ctx.eval("var greet = (name, greeting) => `${greeting}, ${name}!`") message = ctx.call("greet", "Alice", "Hello") print(message) # Output: Hello, Alice! # Call with object arguments ctx.eval("var processUser = (user) => `${user.name} is ${user.age} years old`") result = ctx.call("processUser", {"name": "Bob", "age": 25}) print(result) # Output: Bob is 25 years old # Custom JSON encoder for non-serializable types class CustomEncoder(JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.isoformat() return super().default(obj) ctx.eval("var formatDate = (date) => `Date: ${date}`") now = datetime.now(tz=timezone.utc) result = ctx.call("formatDate", now, encoder=CustomEncoder) print(result) # Output: Date: 2024-01-15T10:30:00+00:00 ``` ```