JS Interop Guide

When using the JS interop primitives in the web interpreter, certain values will automatically be converted between JS and Scheme.

Scheme Values Passed to JavaScript


Scheme Numbers support both arbitrarily-large integers and double-precision floating points, while JS only natively supports double-precision floating points. If a Scheme number can't be accurately represented as a JS number, it will be coerced, likely losing some accuracy in the process.


The interpreter uses Dart bools (compiled to JS booleans) directly, so these will be passed to JS unchanged.


Symbols are converted to strings when passed to JS. Because symbols are stored in lowercase form, they will be passed to JS as such.


Scheme Strings are just wrappers around Dart Strings, which are compiled as JS Strings, so the JS String that Scheme Strings wrap around will be passed to JS.

Lists and Vectors

Well-formed lists (including nil) and vectors will be converted to JS arrays.


Primitive and lambda Scheme procedures will be wrapped in JS functions when passed to JavaScript. Mu and macro procedures will also be wrapped, but due to the specifics of their implementation they will likely not work.

These wrapped procedures can be called from JavaScript like any other function, except that, since the entire Scheme interpreter runs asynchronously, any wrapped Scheme procedure will return a JS Promise when called from JavaScript.

JS Promises work a bit differently from Scheme's promises. They are more analogous to Dart's Futures. See this guide for more information about JS Promises (it's written assuming you already know at least some JS).

All current browser versions support promises, though some recent browsers, like all versions of IE and older versions of Safari may not. If run on these browsers, passing Scheme procedures to JS will likely cause an error.

Pairs, Promises, and Streams

Scheme promises, streams, and pairs which are not well-formed lists will be passed to JS, but they will not be converted any way, so JS will get the raw Dart object, which will likely be all but useless.

JavaScript Values Passed to Scheme

JS Numbers, Booleans, and Strings

These will be converted to the corresponding Scheme types as expected.

JS Arrays

JS Arrays are currently converted to Scheme lists (despite being more analogous to Scheme vectors).

JS Functions

If a JS function is actually a previously wrapped Scheme procedure, the native Scheme procedure will be passed back to Scheme.

Otherwise, JS functions will be wrapped as Scheme procedures that can be called like primitive procedures from Scheme. If this wrapped JS function is passed back to JavaScript, it will be unwrapped (rather than wrapping it in another JS function).

JS Interop Primitives

A formal reference of these primitives is available here.