Popcorn.Wasm (Popcorn v0.1.0)

View Source

Functions for JS side communication.

Summary

Types

Message received from JS side with binary data.

Parsed raw message with data transformed to terms.

Functions

Takes a list of tracked objects and returns a list of terms coresponding to them.

Deserializes raw message and calls handler with it. If the message was a :wasm_call, settles the promise with a value. Returns handler result.

Deserializes message received from JS side.

Notifies JS that Elixir side finished initializing. Can be called only once.

Registers event listener for element with given selector. Events will be sent to the process registered under target name. To get event data, specify needed keys in event_keys list.

Runs JS code in the WASM iframe context. Takes a JS function as a string. Returns list of TrackedObject (or values directly, see return) for each value in an array returned from JS function.

Types

handler_result()

@type handler_result() ::
  {:resolve, promise_reply :: term(), result :: term()}
  | {:reject, promise_reply :: term(), result :: term()}
  | term()

See handle_message!/2 docs.

js_function()

@type js_function() :: String.t()

See run_js/2 docs.

message_handler()

@type message_handler() :: (wasm_message() -> handler_result())

See handle_message!/2 docs.

promise()

@type promise() :: term()

raw_message()

@type raw_message() ::
  {:emscripten, {:call, promise(), data :: binary()}}
  | {:emscripten, {:cast, data :: binary()}}

Message received from JS side with binary data.

register_event_listener_opts()

@type register_event_listener_opts() :: [
  event_keys: [atom()],
  target_node: Popcorn.TrackedObject.t(),
  receiver_name: String.t(),
  custom_data: term()
]

result(t)

@type result(t) :: {:ok, t} | {:error, term()}

run_js_opts()

@type run_js_opts() :: [return: :ref | :value, args: map()]

run_js_return()

@type run_js_return() :: Popcorn.TrackedObject.t() | term()

wasm_message()

@type wasm_message() ::
  {:wasm_call, data :: term(), promise()} | {:wasm_cast, data :: term()}

Parsed raw message with data transformed to terms.

Functions

get_tracked_values(refs)

@spec get_tracked_values([Popcorn.TrackedObject.t()]) :: [
  error: :not_found,
  error: :unserializable,
  ok: String.t()
]

Takes a list of tracked objects and returns a list of terms coresponding to them.

This function has an overhead coming from the need of serialization and deserialization. For variant that assumes success, see get_tracked_values!/1.

get_tracked_values!(refs)

@spec get_tracked_values!([Popcorn.TrackedObject.t()]) :: [String.t()]

Raises on error. See get_tracked_values/1.

handle_message!(raw_msg, handler)

@spec handle_message!(raw_message(), message_handler()) :: term()

Deserializes raw message and calls handler with it. If the message was a :wasm_call, settles the promise with a value. Returns handler result.

is_wasm_message(msg)

(macro)

parse_message!(arg)

@spec parse_message!(raw_message()) :: wasm_message()

Deserializes message received from JS side.

register(main_process_name)

Notifies JS that Elixir side finished initializing. Can be called only once.

register_event_listener(event_name, opts)

@spec register_event_listener(atom(), register_event_listener_opts()) ::
  result(run_js_return())

Registers event listener for element with given selector. Events will be sent to the process registered under target name. To get event data, specify needed keys in event_keys list.

To unregister listener, use returned ref with unregister_event_listener/1

reject(term, promise)

@spec reject(term(), promise()) :: :ok

resolve(term, promise)

@spec resolve(term(), promise()) :: :ok

run_js(function, args \\ %{}, opts \\ [])

@spec run_js(js_function(), map(), run_js_opts()) :: result(run_js_return())

Runs JS code in the WASM iframe context. Takes a JS function as a string. Returns list of TrackedObject (or values directly, see return) for each value in an array returned from JS function.

Options

  • return: an atom controlling if run_js should return tracked objects list or deserialized return value. Possible values: :ref, refs, :value, :values. Default: :ref

Passing args and returning values introduces overhead related to serializing and deserializing.

JS function

The JS function takes an object with following keys:

  • args: the arguments passed from Elixir and deserialized for JS.
  • wasm: the wasm module used underneath. See "Notes" section.
  • iframeWindow: original iframe window object. See "Notes" section.

Passed function should return an array of tracked values. Their lifetime is tied to returned TrackedObjects refs. Value stops being tracked after Elixir VM garbage collects the TrackedObject.

Notes

wasm argument passed to JS function is a emscripten's instantiated wasm module. It does not have same crash and timeout resiliency as Popcorn object. This matters when calling wasm.call() which may hang the runtime if used improperly.

run_js executes code in iframe context which normally would use window (implicitly and explicitly) from iframe. Typically, window is used to interact with main browser window context. Popcorn shadows window variable for that reason.

Example

Popcorn.Wasm.run_js("""
({ args }) => {
  const n = args.n;
  return [n-1, n, n-1];
}
""", %{n: 5})

#=> {:ok, [%TrackedObject{}, %TrackedObject{}, %TrackedObject{}]}

run_js!(function, args \\ %{}, opts \\ [])

@spec run_js!(js_function(), map(), run_js_opts()) :: result(run_js_return())

unregister_event_listener(ref)

Unregister event listener. See register_event_listener/2.