Skip to content

API Reference

CancelableJSFunction

Bases: JSMappedObject

JavaScript function.

This type is returned by JSFunction.cancelable().

You can call this object from Python, passing in positional args to match what the JavaScript function expects. Calls on the Python side are async, regardless of whether the underlying JS function is async (so a call to an async JS function will return a JSPromise, requiring a "double await" in Python to get the result).

Source code in src/py_mini_racer/_types.py
class CancelableJSFunction(JSMappedObject):
    """JavaScript function.

    This type is returned by JSFunction.cancelable().

    You can call this object from Python, passing in positional args to match what the
    JavaScript function expects. Calls on the Python side are async, regardless of
    whether the underlying JS function is async (so a call to an async JS function will
    return a JSPromise, requiring a "double await" in Python to get the result).
    """

    async def __call__(
        self,
        *args: PythonJSConvertedTypes,
        this: JSObject | JSUndefinedType = JSUndefined,
    ) -> PythonJSConvertedTypes:
        raise NotImplementedError

JSArray

Bases: MutableSequence['PythonJSConvertedTypes'], JSObject

JavaScript array.

Has Pythonic MutableSequence methods (e.g., insert(), __getitem__(), ...).

Source code in src/py_mini_racer/_types.py
class JSArray(MutableSequence["PythonJSConvertedTypes"], JSObject):
    """JavaScript array.

    Has Pythonic MutableSequence methods (e.g., `insert()`, `__getitem__()`, ...).
    """

JSArrayIndexError

Bases: IndexError, MiniRacerBaseException

Invalid index into a JSArray.

Source code in src/py_mini_racer/_exc.py
class JSArrayIndexError(IndexError, MiniRacerBaseException):
    """Invalid index into a JSArray."""

    def __init__(self) -> None:
        super().__init__("JSArray deletion out of range")

JSEvalException

Bases: MiniRacerBaseException

JavaScript could not be executed.

Source code in src/py_mini_racer/_exc.py
class JSEvalException(MiniRacerBaseException):
    """JavaScript could not be executed."""

JSFunction

Bases: JSMappedObject

JavaScript function.

This type is returned by synchronous MiniRacer contexts.

You can call this object from Python, passing in positional args to match what the JavaScript function expects.

In synchronous code you may supply an additional keyword argument, timeout_sec.

If you are running in an async context in the same event loop as Miniracer, you must not supply a non-None value for timeout_sec. Instead call func.cancelable() to obtain a CancellableJSFunction, and use a construct like asyncio.wait_for(...) to apply a timeout.

Source code in src/py_mini_racer/_types.py
class JSFunction(JSMappedObject):
    """JavaScript function.

    This type is returned by synchronous MiniRacer contexts.

    You can call this object from Python, passing in positional args to match what the
    JavaScript function expects.

    In synchronous code you may supply an additional keyword argument, `timeout_sec`.

    If you are running in an async context in the same event loop as Miniracer, you must
    not supply a non-None value for timeout_sec. Instead call func.cancelable() to
    obtain a CancellableJSFunction, and use a construct like asyncio.wait_for(...) to
    apply a timeout.
    """

    def __call__(
        self,
        *args: PythonJSConvertedTypes,
        this: JSObject | JSUndefinedType = JSUndefined,
        timeout_sec: float | None = None,
    ) -> PythonJSConvertedTypes:
        raise NotImplementedError

    def cancelable(self) -> CancelableJSFunction:
        raise NotImplementedError

JSKeyError

Bases: JSEvalException, KeyError

No such key found.

Source code in src/py_mini_racer/_exc.py
class JSKeyError(JSEvalException, KeyError):
    """No such key found."""

JSMappedObject

Bases: MutableMapping['PythonJSConvertedTypes', 'PythonJSConvertedTypes'], JSObject

A JavaScript object with Pythonic MutableMapping methods (keys(), __getitem__(), etc).

keys() and __iter__() will return properties from any prototypes as well as this object, as if using a for-in statement in JavaScript.

Source code in src/py_mini_racer/_types.py
class JSMappedObject(
    MutableMapping["PythonJSConvertedTypes", "PythonJSConvertedTypes"], JSObject
):
    """A JavaScript object with Pythonic MutableMapping methods (`keys()`,
    `__getitem__()`, etc).

    `keys()` and `__iter__()` will return properties from any prototypes as well as this
    object, as if using a for-in statement in JavaScript.
    """

JSOOMException

Bases: JSEvalException

JavaScript execution ran out of memory.

Source code in src/py_mini_racer/_exc.py
class JSOOMException(JSEvalException):
    """JavaScript execution ran out of memory."""

JSObject

A JavaScript object.

Source code in src/py_mini_racer/_types.py
class JSObject:
    """A JavaScript object."""

JSParseException

Bases: JSEvalException

JavaScript could not be parsed.

Source code in src/py_mini_racer/_exc.py
class JSParseException(JSEvalException):
    """JavaScript could not be parsed."""

JSPromise

Bases: JSObject

JavaScript Promise.

To get a value, call promise.get() (which blocks) or await promise (in async code). Both operations will raise a Python exception if the JavaScript Promise is rejected.

Source code in src/py_mini_racer/_types.py
class JSPromise(JSObject):
    """JavaScript Promise.

    To get a value, call `promise.get()` (which blocks) or `await promise` (in async
    code). Both operations will raise a Python exception if the JavaScript Promise is
    rejected.
    """

    def get(self, *, timeout: float | None = None) -> PythonJSConvertedTypes:
        raise NotImplementedError

    def __await__(self) -> Generator[Any, None, Any]:
        raise NotImplementedError

JSPromiseError

Bases: MiniRacerBaseException

JavaScript rejected a promise.

Source code in src/py_mini_racer/_exc.py
class JSPromiseError(MiniRacerBaseException):
    """JavaScript rejected a promise."""

    def __init__(self, reason: PythonJSConvertedTypes) -> None:
        super().__init__(f"JavaScript rejected promise with reason: {reason}\n")
        self.reason = reason

JSSymbol

Bases: JSMappedObject

JavaScript symbol.

Source code in src/py_mini_racer/_types.py
class JSSymbol(JSMappedObject):
    """JavaScript symbol."""

JSTimeoutException

Bases: JSEvalException, TimeoutError

JavaScript execution timed out.

Source code in src/py_mini_racer/_exc.py
class JSTimeoutException(JSEvalException, TimeoutError):  # noqa: N818
    """JavaScript execution timed out."""

    def __init__(self) -> None:
        super().__init__("JavaScript was terminated by timeout")

JSUndefinedType

The JavaScript undefined type.

Where JavaScript null is represented as None, undefined is represented as this type.

Source code in src/py_mini_racer/_types.py
class JSUndefinedType:
    """The JavaScript undefined type.

    Where JavaScript null is represented as None, undefined is represented as this
    type."""

    def __bool__(self) -> bool:
        return False

    def __repr__(self) -> str:
        return "JSUndefined"

JSValueError

Bases: JSEvalException, ValueError

Bad value passed to JavaScript engine.

Source code in src/py_mini_racer/_exc.py
class JSValueError(JSEvalException, ValueError):
    """Bad value passed to JavaScript engine."""

LibAlreadyInitializedError

Bases: MiniRacerBaseException

MiniRacer-wrapped V8 build not found.

Source code in src/py_mini_racer/_dll.py
class LibAlreadyInitializedError(MiniRacerBaseException):
    """MiniRacer-wrapped V8 build not found."""

    def __init__(self) -> None:
        super().__init__(
            "MiniRacer was already initialized before the call to init_mini_racer"
        )

LibNotFoundError

Bases: MiniRacerBaseException

MiniRacer-wrapped V8 build not found.

Source code in src/py_mini_racer/_dll.py
class LibNotFoundError(MiniRacerBaseException):
    """MiniRacer-wrapped V8 build not found."""

    def __init__(self, path: Path) -> None:
        super().__init__(f"Native library or dependency not available at {path}")

MiniRacer

MiniRacer evaluates JavaScript code using a V8 isolate.

A MiniRacer instance can be explicitly closed using the close() method, or by using the MiniRacer as a context manager, i.e,:

with MiniRacer() as mr: ...

The MiniRacer instance will otherwise clean up the underlying V8 resources upon garbage collection.

Attributes:

Name Type Description
json_impl Any

JSON module used by helper methods default is json

Source code in src/py_mini_racer/_mini_racer.py
class MiniRacer:
    """
    MiniRacer evaluates JavaScript code using a V8 isolate.

    A MiniRacer instance can be explicitly closed using the close() method, or by using
    the MiniRacer as a context manager, i.e,:

    with MiniRacer() as mr:
        ...

    The MiniRacer instance will otherwise clean up the underlying V8 resources upon
    garbage collection.

    Attributes:
        json_impl: JSON module used by helper methods default is
            [json](https://docs.python.org/3/library/json.html)
    """

    json_impl: ClassVar[Any] = json

    def __init__(self, context: Context | None = None) -> None:
        if context is None:
            self._own_context_maker: AbstractContextManager[Context] | None = (
                _make_context()
            )
            self._ctx: Context | None = self._own_context_maker.__enter__()
        else:
            self._own_context_maker = None
            self._ctx = context

        self.eval(INSTALL_SET_TIMEOUT)

    def close(
        self,
        exc_type: type[BaseException] | None = None,
        exc_val: BaseException | None = None,
        exc_tb: TracebackType | None = None,
    ) -> None:
        """Close this MiniRacer instance.

        It is an error to use this MiniRacer instance or any JS objects returned by it
        after calling this method.
        """
        own_context_maker = self._own_context_maker
        self._own_context_maker = None
        self._ctx = None

        if own_context_maker is not None:
            own_context_maker.__exit__(exc_type, exc_val, exc_tb)

    def __del__(self) -> None:
        # Ignore ordering problems on process teardown.
        # (A user who wants consistent teardown should use `with MiniRacer() as ctx`
        # which makes the cleanup deterministic.)
        with suppress(Exception):
            self.close()

    def __enter__(self) -> Self:
        return self

    def __exit__(
        self,
        exc_type: type[BaseException] | None,
        exc_val: BaseException | None,
        exc_tb: TracebackType | None,
    ) -> None:
        self.close(exc_type, exc_val, exc_tb)

    @property
    def v8_version(self) -> str:
        """Return the V8 version string."""
        assert self._ctx is not None
        return self._ctx.v8_version()

    def eval(
        self,
        code: str,
        timeout: float | None = None,
        timeout_sec: float | None = None,
        max_memory: int | None = None,
    ) -> PythonJSConvertedTypes:
        """Evaluate JavaScript code in the V8 isolate.

        Side effects from the JavaScript evaluation is persisted inside a context
        (meaning variables set are kept for the next evaluation).

        The JavaScript value returned by the last expression in `code` is converted to
        a Python value and returned by this method. Only primitive types are supported
        (numbers, strings, buffers...). Use the
        [py_mini_racer.MiniRacer.execute][] method to return more complex
        types such as arrays or objects.

        The evaluation can be interrupted by an exception for several reasons: a limit
        was reached, the code could not be parsed, a returned value could not be
        converted to a Python value.

        Args:
            code: JavaScript code
            timeout: number of milliseconds after which the execution is interrupted.
                This is deprecated; use timeout_sec instead.
            timeout_sec: number of seconds after which the execution is interrupted
            max_memory: hard memory limit, in bytes, after which the execution is
                interrupted.
        """

        if max_memory is not None:
            self.set_hard_memory_limit(max_memory)

        if timeout:
            # PyMiniRacer unfortunately uses milliseconds while Python and
            # Système international d'unités use seconds.
            timeout_sec = timeout / 1000

        ctx = self._ctx
        assert ctx is not None

        if not ctx.are_we_running_on_the_mini_racer_event_loop():

            async def run() -> PythonJSConvertedTypes:
                try:
                    return await asyncio.wait_for(
                        ctx.eval_cancelable(code), timeout=timeout_sec
                    )
                except asyncio.TimeoutError as e:
                    raise JSTimeoutException from e

            return asyncio.run_coroutine_threadsafe(run(), ctx.event_loop).result()

        assert timeout_sec is None, (
            "To apply a timeout in an async context, use "
            "`await asyncio.wait_for(mr.eval_cancelable(your_params), "
            "timeout=your_timeout)`"
        )

        return ctx.eval(code)

    async def eval_cancelable(self, code: str) -> PythonJSConvertedTypes:
        """Evaluate JavaScript code in the V8 isolate.

        Similar to eval(), but runaway calls can be canceled by canceling the
        coroutine's task, e.g., using:

            await asyncio.wait_for(mr.eval_cancelable(...), timeout=some_timeout)

        """

        assert self._ctx is not None

        return await self._ctx.eval_cancelable(code)

    def execute(
        self,
        expr: str,
        timeout: float | None = None,
        timeout_sec: float | None = None,
        max_memory: int | None = None,
    ) -> Any:  # noqa: ANN401
        """Helper to evaluate a JavaScript expression and return composite types.

        Returned value is serialized to JSON inside the V8 isolate and deserialized
        using `json_impl`.

        Args:
            expr: JavaScript expression
            timeout: number of milliseconds after which the execution is interrupted.
                This is deprecated; use timeout_sec instead.
            timeout_sec: number of seconds after which the execution is interrupted
            max_memory: hard memory limit, in bytes, after which the execution is
                interrupted.
        """

        if timeout:
            # PyMiniRacer unfortunately uses milliseconds while Python and
            # Système international d'unités use seconds.
            timeout_sec = timeout / 1000

        wrapped_expr = f"JSON.stringify((function(){{return ({expr})}})())"
        ret = self.eval(wrapped_expr, timeout_sec=timeout_sec, max_memory=max_memory)
        if not isinstance(ret, str):
            raise WrongReturnTypeException(type(ret))
        return self.json_impl.loads(ret)

    def call(
        self,
        expr: str,
        *args: Any,  # noqa: ANN401
        encoder: type[JSONEncoder] | None = None,
        timeout: float | None = None,
        timeout_sec: float | None = None,
        max_memory: int | None = None,
    ) -> Any:  # noqa: ANN401
        """Helper to call a JavaScript function and return compositve types.

        The `expr` argument refers to a JavaScript function in the current V8
        isolate context. Further positional arguments are serialized using the JSON
        implementation `json_impl` and passed to the JavaScript function as arguments.

        Returned value is serialized to JSON inside the V8 isolate and deserialized
        using `json_impl`.

        Args:
            expr: JavaScript expression referring to a function
            encoder: Custom JSON encoder
            timeout: number of milliseconds after which the execution is
                interrupted.
            timeout_sec: number of seconds after which the execution is interrupted
            max_memory: hard memory limit, in bytes, after which the execution is
                interrupted
        """

        if timeout:
            # PyMiniRacer unfortunately uses milliseconds while Python and
            # Système international d'unités use seconds.
            timeout_sec = timeout / 1000

        json_args = self.json_impl.dumps(args, separators=(",", ":"), cls=encoder)
        js = f"{expr}.apply(this, {json_args})"
        return self.execute(js, timeout_sec=timeout_sec, max_memory=max_memory)

    @asynccontextmanager
    async def wrap_py_function(
        self, func: PyJsFunctionType
    ) -> AsyncGenerator[JSFunction, None]:
        """Wrap a Python function such that it can be called from JS.

        To be wrapped and exposed in JavaScript, a Python function should:

          1. Be async,
          2. Accept variable positional arguments each of type PythonJSConvertedTypes,
             and
          3. Return one value of type PythonJSConvertedTypes (a type union which
             includes None).

        The function is rendered on the JavaScript side as an async function (i.e., a
        function which returns a Promise).

        Returns:
            An async context manager which, when entered, yields a JS Function which
            can be passed into MiniRacer and called by JS code.
        """

        assert self._ctx is not None

        async with self._ctx.wrap_py_function_as_js_function(func) as js_func:
            yield js_func

    def set_hard_memory_limit(self, limit: int) -> None:
        """Set a hard memory limit on this V8 isolate.

        JavaScript execution will be terminated when this limit is reached.

        :param int limit: memory limit in bytes or 0 to reset the limit
        """

        assert self._ctx is not None
        self._ctx.set_hard_memory_limit(limit)

    def set_soft_memory_limit(self, limit: int) -> None:
        """Set a soft memory limit on this V8 isolate.

        The Garbage Collection will use a more aggressive strategy when
        the soft limit is reached but the execution will not be stopped.

        :param int limit: memory limit in bytes or 0 to reset the limit
        """

        assert self._ctx is not None
        self._ctx.set_soft_memory_limit(limit)

    def was_hard_memory_limit_reached(self) -> bool:
        """Return true if the hard memory limit was reached on the V8 isolate."""

        assert self._ctx is not None
        return self._ctx.was_hard_memory_limit_reached()

    def was_soft_memory_limit_reached(self) -> bool:
        """Return true if the soft memory limit was reached on the V8 isolate."""

        assert self._ctx is not None
        return self._ctx.was_soft_memory_limit_reached()

    def low_memory_notification(self) -> None:
        """Ask the V8 isolate to collect memory more aggressively."""

        assert self._ctx is not None
        self._ctx.low_memory_notification()

    def heap_stats(self) -> Any:  # noqa: ANN401
        """Return the V8 isolate heap statistics."""

        assert self._ctx is not None
        return self.json_impl.loads(self._ctx.heap_stats())

    def heap_snapshot(self) -> Any:  # noqa: ANN401
        """Return a snapshot of the V8 isolate heap."""

        assert self._ctx is not None
        return self.json_impl.loads(self._ctx.heap_snapshot())

v8_version property

Return the V8 version string.

call(expr, *args, encoder=None, timeout=None, timeout_sec=None, max_memory=None)

Helper to call a JavaScript function and return compositve types.

The expr argument refers to a JavaScript function in the current V8 isolate context. Further positional arguments are serialized using the JSON implementation json_impl and passed to the JavaScript function as arguments.

Returned value is serialized to JSON inside the V8 isolate and deserialized using json_impl.

Parameters:

Name Type Description Default
expr str

JavaScript expression referring to a function

required
encoder type[JSONEncoder] | None

Custom JSON encoder

None
timeout float | None

number of milliseconds after which the execution is interrupted.

None
timeout_sec float | None

number of seconds after which the execution is interrupted

None
max_memory int | None

hard memory limit, in bytes, after which the execution is interrupted

None
Source code in src/py_mini_racer/_mini_racer.py
def call(
    self,
    expr: str,
    *args: Any,  # noqa: ANN401
    encoder: type[JSONEncoder] | None = None,
    timeout: float | None = None,
    timeout_sec: float | None = None,
    max_memory: int | None = None,
) -> Any:  # noqa: ANN401
    """Helper to call a JavaScript function and return compositve types.

    The `expr` argument refers to a JavaScript function in the current V8
    isolate context. Further positional arguments are serialized using the JSON
    implementation `json_impl` and passed to the JavaScript function as arguments.

    Returned value is serialized to JSON inside the V8 isolate and deserialized
    using `json_impl`.

    Args:
        expr: JavaScript expression referring to a function
        encoder: Custom JSON encoder
        timeout: number of milliseconds after which the execution is
            interrupted.
        timeout_sec: number of seconds after which the execution is interrupted
        max_memory: hard memory limit, in bytes, after which the execution is
            interrupted
    """

    if timeout:
        # PyMiniRacer unfortunately uses milliseconds while Python and
        # Système international d'unités use seconds.
        timeout_sec = timeout / 1000

    json_args = self.json_impl.dumps(args, separators=(",", ":"), cls=encoder)
    js = f"{expr}.apply(this, {json_args})"
    return self.execute(js, timeout_sec=timeout_sec, max_memory=max_memory)

close(exc_type=None, exc_val=None, exc_tb=None)

Close this MiniRacer instance.

It is an error to use this MiniRacer instance or any JS objects returned by it after calling this method.

Source code in src/py_mini_racer/_mini_racer.py
def close(
    self,
    exc_type: type[BaseException] | None = None,
    exc_val: BaseException | None = None,
    exc_tb: TracebackType | None = None,
) -> None:
    """Close this MiniRacer instance.

    It is an error to use this MiniRacer instance or any JS objects returned by it
    after calling this method.
    """
    own_context_maker = self._own_context_maker
    self._own_context_maker = None
    self._ctx = None

    if own_context_maker is not None:
        own_context_maker.__exit__(exc_type, exc_val, exc_tb)

eval(code, timeout=None, timeout_sec=None, max_memory=None)

Evaluate JavaScript code in the V8 isolate.

Side effects from the JavaScript evaluation is persisted inside a context (meaning variables set are kept for the next evaluation).

The JavaScript value returned by the last expression in code is converted to a Python value and returned by this method. Only primitive types are supported (numbers, strings, buffers...). Use the py_mini_racer.MiniRacer.execute method to return more complex types such as arrays or objects.

The evaluation can be interrupted by an exception for several reasons: a limit was reached, the code could not be parsed, a returned value could not be converted to a Python value.

Parameters:

Name Type Description Default
code str

JavaScript code

required
timeout float | None

number of milliseconds after which the execution is interrupted. This is deprecated; use timeout_sec instead.

None
timeout_sec float | None

number of seconds after which the execution is interrupted

None
max_memory int | None

hard memory limit, in bytes, after which the execution is interrupted.

None
Source code in src/py_mini_racer/_mini_racer.py
def eval(
    self,
    code: str,
    timeout: float | None = None,
    timeout_sec: float | None = None,
    max_memory: int | None = None,
) -> PythonJSConvertedTypes:
    """Evaluate JavaScript code in the V8 isolate.

    Side effects from the JavaScript evaluation is persisted inside a context
    (meaning variables set are kept for the next evaluation).

    The JavaScript value returned by the last expression in `code` is converted to
    a Python value and returned by this method. Only primitive types are supported
    (numbers, strings, buffers...). Use the
    [py_mini_racer.MiniRacer.execute][] method to return more complex
    types such as arrays or objects.

    The evaluation can be interrupted by an exception for several reasons: a limit
    was reached, the code could not be parsed, a returned value could not be
    converted to a Python value.

    Args:
        code: JavaScript code
        timeout: number of milliseconds after which the execution is interrupted.
            This is deprecated; use timeout_sec instead.
        timeout_sec: number of seconds after which the execution is interrupted
        max_memory: hard memory limit, in bytes, after which the execution is
            interrupted.
    """

    if max_memory is not None:
        self.set_hard_memory_limit(max_memory)

    if timeout:
        # PyMiniRacer unfortunately uses milliseconds while Python and
        # Système international d'unités use seconds.
        timeout_sec = timeout / 1000

    ctx = self._ctx
    assert ctx is not None

    if not ctx.are_we_running_on_the_mini_racer_event_loop():

        async def run() -> PythonJSConvertedTypes:
            try:
                return await asyncio.wait_for(
                    ctx.eval_cancelable(code), timeout=timeout_sec
                )
            except asyncio.TimeoutError as e:
                raise JSTimeoutException from e

        return asyncio.run_coroutine_threadsafe(run(), ctx.event_loop).result()

    assert timeout_sec is None, (
        "To apply a timeout in an async context, use "
        "`await asyncio.wait_for(mr.eval_cancelable(your_params), "
        "timeout=your_timeout)`"
    )

    return ctx.eval(code)

eval_cancelable(code) async

Evaluate JavaScript code in the V8 isolate.

Similar to eval(), but runaway calls can be canceled by canceling the coroutine's task, e.g., using:

await asyncio.wait_for(mr.eval_cancelable(...), timeout=some_timeout)
Source code in src/py_mini_racer/_mini_racer.py
async def eval_cancelable(self, code: str) -> PythonJSConvertedTypes:
    """Evaluate JavaScript code in the V8 isolate.

    Similar to eval(), but runaway calls can be canceled by canceling the
    coroutine's task, e.g., using:

        await asyncio.wait_for(mr.eval_cancelable(...), timeout=some_timeout)

    """

    assert self._ctx is not None

    return await self._ctx.eval_cancelable(code)

execute(expr, timeout=None, timeout_sec=None, max_memory=None)

Helper to evaluate a JavaScript expression and return composite types.

Returned value is serialized to JSON inside the V8 isolate and deserialized using json_impl.

Parameters:

Name Type Description Default
expr str

JavaScript expression

required
timeout float | None

number of milliseconds after which the execution is interrupted. This is deprecated; use timeout_sec instead.

None
timeout_sec float | None

number of seconds after which the execution is interrupted

None
max_memory int | None

hard memory limit, in bytes, after which the execution is interrupted.

None
Source code in src/py_mini_racer/_mini_racer.py
def execute(
    self,
    expr: str,
    timeout: float | None = None,
    timeout_sec: float | None = None,
    max_memory: int | None = None,
) -> Any:  # noqa: ANN401
    """Helper to evaluate a JavaScript expression and return composite types.

    Returned value is serialized to JSON inside the V8 isolate and deserialized
    using `json_impl`.

    Args:
        expr: JavaScript expression
        timeout: number of milliseconds after which the execution is interrupted.
            This is deprecated; use timeout_sec instead.
        timeout_sec: number of seconds after which the execution is interrupted
        max_memory: hard memory limit, in bytes, after which the execution is
            interrupted.
    """

    if timeout:
        # PyMiniRacer unfortunately uses milliseconds while Python and
        # Système international d'unités use seconds.
        timeout_sec = timeout / 1000

    wrapped_expr = f"JSON.stringify((function(){{return ({expr})}})())"
    ret = self.eval(wrapped_expr, timeout_sec=timeout_sec, max_memory=max_memory)
    if not isinstance(ret, str):
        raise WrongReturnTypeException(type(ret))
    return self.json_impl.loads(ret)

heap_snapshot()

Return a snapshot of the V8 isolate heap.

Source code in src/py_mini_racer/_mini_racer.py
def heap_snapshot(self) -> Any:  # noqa: ANN401
    """Return a snapshot of the V8 isolate heap."""

    assert self._ctx is not None
    return self.json_impl.loads(self._ctx.heap_snapshot())

heap_stats()

Return the V8 isolate heap statistics.

Source code in src/py_mini_racer/_mini_racer.py
def heap_stats(self) -> Any:  # noqa: ANN401
    """Return the V8 isolate heap statistics."""

    assert self._ctx is not None
    return self.json_impl.loads(self._ctx.heap_stats())

low_memory_notification()

Ask the V8 isolate to collect memory more aggressively.

Source code in src/py_mini_racer/_mini_racer.py
def low_memory_notification(self) -> None:
    """Ask the V8 isolate to collect memory more aggressively."""

    assert self._ctx is not None
    self._ctx.low_memory_notification()

set_hard_memory_limit(limit)

Set a hard memory limit on this V8 isolate.

JavaScript execution will be terminated when this limit is reached.

:param int limit: memory limit in bytes or 0 to reset the limit

Source code in src/py_mini_racer/_mini_racer.py
def set_hard_memory_limit(self, limit: int) -> None:
    """Set a hard memory limit on this V8 isolate.

    JavaScript execution will be terminated when this limit is reached.

    :param int limit: memory limit in bytes or 0 to reset the limit
    """

    assert self._ctx is not None
    self._ctx.set_hard_memory_limit(limit)

set_soft_memory_limit(limit)

Set a soft memory limit on this V8 isolate.

The Garbage Collection will use a more aggressive strategy when the soft limit is reached but the execution will not be stopped.

:param int limit: memory limit in bytes or 0 to reset the limit

Source code in src/py_mini_racer/_mini_racer.py
def set_soft_memory_limit(self, limit: int) -> None:
    """Set a soft memory limit on this V8 isolate.

    The Garbage Collection will use a more aggressive strategy when
    the soft limit is reached but the execution will not be stopped.

    :param int limit: memory limit in bytes or 0 to reset the limit
    """

    assert self._ctx is not None
    self._ctx.set_soft_memory_limit(limit)

was_hard_memory_limit_reached()

Return true if the hard memory limit was reached on the V8 isolate.

Source code in src/py_mini_racer/_mini_racer.py
def was_hard_memory_limit_reached(self) -> bool:
    """Return true if the hard memory limit was reached on the V8 isolate."""

    assert self._ctx is not None
    return self._ctx.was_hard_memory_limit_reached()

was_soft_memory_limit_reached()

Return true if the soft memory limit was reached on the V8 isolate.

Source code in src/py_mini_racer/_mini_racer.py
def was_soft_memory_limit_reached(self) -> bool:
    """Return true if the soft memory limit was reached on the V8 isolate."""

    assert self._ctx is not None
    return self._ctx.was_soft_memory_limit_reached()

wrap_py_function(func) async

Wrap a Python function such that it can be called from JS.

To be wrapped and exposed in JavaScript, a Python function should:

  1. Be async,
  2. Accept variable positional arguments each of type PythonJSConvertedTypes, and
  3. Return one value of type PythonJSConvertedTypes (a type union which includes None).

The function is rendered on the JavaScript side as an async function (i.e., a function which returns a Promise).

Returns:

Type Description
AsyncGenerator[JSFunction, None]

An async context manager which, when entered, yields a JS Function which

AsyncGenerator[JSFunction, None]

can be passed into MiniRacer and called by JS code.

Source code in src/py_mini_racer/_mini_racer.py
@asynccontextmanager
async def wrap_py_function(
    self, func: PyJsFunctionType
) -> AsyncGenerator[JSFunction, None]:
    """Wrap a Python function such that it can be called from JS.

    To be wrapped and exposed in JavaScript, a Python function should:

      1. Be async,
      2. Accept variable positional arguments each of type PythonJSConvertedTypes,
         and
      3. Return one value of type PythonJSConvertedTypes (a type union which
         includes None).

    The function is rendered on the JavaScript side as an async function (i.e., a
    function which returns a Promise).

    Returns:
        An async context manager which, when entered, yields a JS Function which
        can be passed into MiniRacer and called by JS code.
    """

    assert self._ctx is not None

    async with self._ctx.wrap_py_function_as_js_function(func) as js_func:
        yield js_func

init_mini_racer(*, flags=DEFAULT_V8_FLAGS, ignore_duplicate_init=False)

Initialize py_mini_racer (and V8).

This function can optionally be used to set V8 flags. This function can be called at most once, before any instances of MiniRacer are initialized. Instances of MiniRacer will automatically call this function to initialize MiniRacer and V8.

Source code in src/py_mini_racer/_dll.py
def init_mini_racer(
    *, flags: Iterable[str] = DEFAULT_V8_FLAGS, ignore_duplicate_init: bool = False
) -> ctypes.CDLL:
    """Initialize py_mini_racer (and V8).

    This function can optionally be used to set V8 flags. This function can be called
    at most once, before any instances of MiniRacer are initialized. Instances of
    MiniRacer will automatically call this function to initialize MiniRacer and V8.
    """

    global _dll_handle_context_manager  # noqa: PLW0603
    global _dll_handle  # noqa: PLW0603

    with _init_lock:
        if _dll_handle is None:
            _dll_handle_context_manager = _open_dll(flags)
            _dll_handle = _dll_handle_context_manager.__enter__()
            # Note: we never call _dll_handle_context_manager.__exit__() because it's
            # designed as a singleton. But we could if we wanted to!
        elif not ignore_duplicate_init:
            raise LibAlreadyInitializedError

        return _dll_handle