Probably not a one-sentence answer, is there any documentation on how marshalling between the runtimes works so that I don't do something really terrible?

​
Unfortunately there isn't much documentation on ClearScript internals other than the code itself.

Generally speaking, each exposed .NET object or type is wrapped in an instance of the internal class
HostItem, which is then referenced by a JavaScript proxy object on the V8 side. Conversely, when a script returns a reference to a native JavaScript object, ClearScript wraps it in an instance of the internal class
ScriptItem, which subclasses DynamicObject to support .NET's dynamic infrastructure.

These cross-runtime references prevent their targets from being garbage-collected, so care should be taken to avoid cross-runtime
circular references that leak memory. You can
dispose a script object to release its managed reference, but an exposed .NET reference can only be released when its V8-side proxy is collected, and V8 is
extremely leisurely when it comes to garbage collection.
​

Are there any related recommended best practices?

​
Here are a few that come to mind:

Try not to compile the same script code more than once. Instead, reuse the output of the
Compile() method, or hold references to compiled script functions for repeated execution.

Minimize your use of cross-runtime calls. Consider whether an expression such as
a.b.c.d() can be simplified by caching a direct reference to a nested object. This is relevant in both host-to-script and script-to-host scenarios.

Control your use of .NET's dynamic machinery. Instead of declaring a variable as
dynamic, consider casting it to dynamic where necessary. Otherwise the compiler may emit expensive dynamic operations in inconspicuous places.

Remember that direct access is convenient but relatively expensive. It may be cheaper to transfer a complex object in one step (via JSON or something similar) than to access its properties and nested objects one by one from the other side.

Use V8ScriptEngineFlags.DisableGlobalMembers in performance-critical applications.

Note that these are optimization ideas, not rules. ClearScript aims to combine ease of use with reasonable performance in most cases.
​

What is the relative cost of adding host types?

​
Exposing a host type is very similar to exposing a host object; it just provides access to a different set of members - constructors, static methods, nested types, etc. If the host type is a class that defines extension methods, then exposing it adds overhead
to the method binding process for all exposed objects.
​

What happens when "Compile" occurs? What costs does this mitigate?

​
The Compile() method returns an opaque script representation that can be executed multiple times without recompilation. Sorry about the recursive explanation, but the details of V8's compiled script representation are not well documented. Presumably
compilation involves at least parsing the script source code into a syntax tree of some sort.
​

Do you see this as something that could be used enterprise-scale or more of a utility?

​
ClearScript started life as a tool for automated testing, initially supporting only JScript and VBScript. In theory, V8 support should make it more suitable for server-side work, but to be honest, enterprise-level scalability has not been a priority for us
so far. However, if you choose to evaluate ClearScript in that capacity, we'd love to get your feedback!