Popcorn. JS
(Popcorn v1.0.0)
View Source
Connects Elixir processes to JavaScript in the browser page.
Receiving messages
JavaScript calls to popcorn.send(target, payload) deliver {:wasm, payload} to the target process.
Use is_message/1 in guards to match it.
Use Popcorn.Proxy for GenServer calls and casts.
Values
Messages and run/3 arguments and results are converted between Elixir and JavaScript.
See Sharing values across languages for supported types and conversions.
Use a tracked_value/0 to keep a JavaScript value's identity.
Outside the browser
Use available?/0 to check if your code is running natively or in the browser.
On a native VM, JavaScript calls use a no-op mock so Popcorn applications can run in tests.
Summary
Types
A JavaScript message with a payload decoded into Elixir terms.
An opaque handle that keeps a JavaScript value alive.
Functions
Returns true if running in the browser.
Waits until the JavaScript Popcorn instance has finished booting.
Matches a message/0 sent from JavaScript.
Runs a JavaScript function on the page and waits for its result.
Sends a message to the JavaScript callbacks registered with popcorn.onEvent().
Types
@type message() :: {:wasm, payload :: term()}
A JavaScript message with a payload decoded into Elixir terms.
@type run_opts() :: [{:timeout, timeout()}]
@opaque tracked_value()
An opaque handle that keeps a JavaScript value alive.
Return new TrackedValue(value, cleanup) from a JavaScript function to create a handle.
The cleanup function has the signature () => void.
Pass the handle in run/3 arguments to access the original value.
The runtime calls the cleanup function after BEAM garbage collection releases the handle, or when the VM stops.
Note: Garbage collection does not guarantee prompt cleanup. For time-sensitive resources, call an idempotent cleanup function explicitly. This ensures you can call it yourself or it can be called by Popcorn.
Functions
@spec available?() :: boolean()
Returns true if running in the browser.
@spec await_ready(run_opts()) :: :ok | {:error, :timeout}
Waits until the JavaScript Popcorn instance has finished booting.
Use this only from asynchronous work whose process startup has already been
acknowledged, such as the body of a supervised Task:
children = [
{Task, &MyApp.API.run/0}
]
def run do
with :ok <- Popcorn.JS.await_ready(),
{:ok, _value} <- Popcorn.JS.run("() => initializeBrowser()") do
:ok
end
endOptions
:timeout- the reply timeout, or:infinity. Defaults to5_000ms.
Notes
- Do not call this function from
Application.start/2,GenServer.init/1, a childstart_linkpath that has not returned, or an OTP start phase — it will deadlock.
Matches a message/0 sent from JavaScript.
Runs a JavaScript function on the page and waits for its result.
code defines a function with the signature (args, {send, call, cast}) => result.
The bridge converts the args map to JavaScript values and awaits any returned promise.
It returns {:ok, value} with the result converted to Elixir terms or {:error, {:js, reason}}.
A timeout returns {:error, :timeout} and does not cancel JavaScript execution.
The page's Content Security Policy must permit JavaScript evaluation with unsafe-eval.
JS
The send helper sends a message to a BEAM process.
The call and cast helpers use Popcorn.Proxy to contact GenServers.
These helpers return values or reject on failure, like their JavaScript API counterparts.
Use trySend, tryCall, or tryCast to receive result objects for expected failures.
Notes:
- Calls during application startup run before
popcorn.boot()resolves. - Do not await a
callto the process that executesrun/3. It will cause deadlocks.
Options
:timeout- the reply timeout, or:infinity. Defaults to5_000ms.
Examples
Popcorn.JS.run("({n}) => n + 1", %{n: 1})
#=> {:ok, 2}Use a tracked_value/0 for values such as DOM elements:
{:ok, element} = Popcorn.JS.run("() => new TrackedValue(document.body)")
Popcorn.JS.run!("({element}) => { element.textContent = 'Ready'; }", %{element: element})
See run/3.
@spec send(term()) :: :ok
Sends a message to the JavaScript callbacks registered with popcorn.onEvent().