Sharing values across languages

View Source

Popcorn converts values when they cross between JavaScript and BEAM. The two directions do not use the same conversion.

Do not assume that a value can make a lossless round trip.

JavaScript to BEAM

JavaScript valueBEAM value
StringUTF-8 binary
Booleantrue or false atom
Safe integerInteger
Other finite numberFloat
ArrayList
Plain objectMap with binary keys
null or undefinednil
atom("ok")Existing atom
tuple(a, b)Tuple

Buffers and typed-array views become binaries containing their visible bytes. BigInt becomes an integer. Date becomes a UTC Calendar.ISO DateTime with millisecond precision. Map becomes a native map. Set becomes MapSet. Symbols use their registry key or description to name existing atoms.

atom() also names an existing atom. Unknown atoms and unnamed symbols fail. Cycles, unsupported instances, functions, unsafe Numbers, and non-finite numbers also fail.

BEAM to JavaScript

BEAM valueJavaScript value
Valid UTF-8 binaryString
Other binaryUint8Array
IntegerNumber when safe, otherwise BigInt
FloatNumber
List or tupleArray
MapPlain object
DateTimeDate
MapSetSet
true or falseBoolean
nil or :nullnull
Other atomString
PIDOpaque process handle

Map keys must be atoms, UTF-8 binaries, or numbers with distinct string forms. Popcorn rejects keys that become equal after conversion. Set members that become equal can merge, such as 1 and 1n sent from JavaScript.

DateTimes must use Calendar.ISO and have whole-millisecond precision. Conversion does not preserve time-zone names, buffer types, object identity, or set order. PID handles are only usable in the VM instance and boot that created them.

Tracked JavaScript values

Some JavaScript values cannot become BEAM terms. Examples include DOM nodes, abort controllers, and library objects.

Return new TrackedValue(value, cleanup) from run to create an opaque handle. Keep the handle in BEAM state while you need the JavaScript value.

Popcorn runs cleanup after the handle is released or the virtual machine stops. Garbage collection does not provide prompt cleanup. Call an idempotent cleanup function directly when timing matters.