Clearscript: Are scopes supported?

Created on 18 Feb 2019  Â·  12Comments  Â·  Source: microsoft/ClearScript

I think I know the answer to this, but worth a shot.

With V8, it's possible to define a objects that act like scopes. You can add variables to them, and control how they can be accessed and when they get destroyed. Is that possible with ClearScript?

I'm going to guess not because it's a V8-specific thing but thought I'd ask.

Thanks

question

Most helpful comment

Some general information that might be helpful:

An _isolate_ is an independent copy of the V8 runtime. It's a heavyweight object with its own heap and garbage collector. An isolate can execute script code on one thread at a time, and can't share data with other isolates except via facilities provided by the host.

An isolate can contain multiple relatively lightweight _contexts_, each with its own global object and its own set of JavaScript built-ins. Contexts parented to the same isolate are semi-independent in that they can share data efficiently, but they can't execute script code simultaneously.

The mapping between these entities and ClearScript objects is described above. Please let us know if you need additional information.

All 12 comments

Hi @JohnLudlow,

As far as we can tell, the V8 API uses the term _scope_ to refer to any of a group of simple RAII-style classes whose public interfaces are generally limited to their constructors and destructors.

This is a common C++ pattern that isn't specific to V8 or scripting. The nearest .NET equivalent would probably be a disposable class that performs the destructor action in IDisposable::Dispose.

ClearScript uses this pattern internally (you can see a generic scope implementation here), but as it has nothing in particular to do with scripting, it isn't part of the public API.

Cheers!

@ClearScriptLib, That was kind of what I thought.

Today we have (without getting too specific about our application) a global ClearScript engine and its variable space, and we can kick off commands that create variables and do (hopefully) intelligent things. But if we do it twice in a row, the second thing's space is polluted by the first thing not cleaning up after itself.

V8 does allow you to create something (isolate? scope? context?) which can be destroyed and will then remove those variables it knows about. We can probably do something to remember the names of variables and remove them at the right time, but just wanted to confirm that ClearScript didn't itself provide that.

Obviously, you wouldn't expose the V8-specific things because you support other engines.

Hi @JohnLudlow,

we can kick off commands that create variables and do (hopefully) intelligent things. But if we do it twice in a row, the second thing's space is polluted by the first thing not cleaning up after itself.

This suggests that you're running externally authored scripts whose behavior you can't easily regulate. Is that correct?

Hi, @ClearScriptLib

That is true in that you can run a script in our application to make it do useful stuff, but it's a little more complex than that.

We also define lots of commands (buttons you can press, widgets you can mess with, etc) which can run snippets of JavaScript to do stuff like validation or default value evaluation. In some cases, they might be interested in something you did earlier, such that command A might modify a variable, and command B might check that variable. But once those two commands are done, that variable should be cleaned up.

We could do this with an object that tracks variables you add, then removes them when the object is destroyed. A little clunky, not really a proper scope, but would serve our needs.

V8 has stuff to make proper scopes, but you probably can't expose that while maintaining your engine independence (and engine independence is a good thing to maintain).

Now that I think of it, perhaps what we really want to do is not have these variables in the first place. Perhaps we should be storing those things in the application and making functions which allow you to talk to them. This would fundamentally alter our scripting API and mean a lot of these commands need to be updated, but it's not impossible. I might discuss that with our team.

Hi @JohnLudlow,

Perhaps we should be storing those things in the application and making functions which allow you to talk to them.

If your scripts can be trusted to create and access this data only through a central facility, then there's no real issue, and that facility could easily be implemented in JavaScript or managed code.

Your concern about _pollution_, however, indicates that you can't really trust your scripts to be so well-behaved. In a JavaScript environment that runs independently developed scripts, this is always a valid concern, as the language lets malicious scripts overwrite global variables, blow away built-ins, and monkey patch anything and everything.

V8 has stuff to make proper scopes, but you probably can't expose that while maintaining your engine independence (and engine independence is a good thing to maintain).

Although we aim to keep ClearScript's API engine-agnostic, some engines have features (or APIs that enable features) that override that goal; e.g., V8ScriptEngine.Compile.

However, we're not aware of any V8 feature that could provide the kind of script-based scope semantics you're looking for. If you know of such a feature, can you point us at it?

To deal with the pollution issue, V8 does provide an efficient way to create a pristine new _context_ (V8ScriptEngine) within an existing _isolate_ (V8Runtime), and ClearScript supports that, but we can't say without knowing more whether that's an option for you.

Good luck!

You've mentioned V8Runtime before, and I did mean to look at it further.

I think contexts are what I'm thinking of.

And no I don't trust even our scripts to be well-behaved. There's enough of them that someone could easily forget to do the necessary cleanup.

Thanks for your help

A V8 execution environment consists of two entities – an _isolate_, which is an independent copy of the V8 runtime, complete with its own garbage-collected heap – and a _context_, which consists of a discrete global object along with its own set of standard JavaScript built-ins.

Many script engines don’t partition the execution environment in this manner, but V8’s approach allows a single instance of the runtime to power multiple semi-independent contexts.

In ClearScript the isolate and context correspond to V8Runtime and V8ScriptEngine respectively. Invoking the V8ScriptEngine constructor gives you a context within its own dedicated isolate, which is equivalent to what you get with other script engines.

On the other hand, instantiating V8Runtime gives you an isolate that you can then use to create multiple contexts via V8Runtime.CreateScriptEngine.

Thanks - I never really got the difference between isolates and contexts. The documentation seems to indicate isolates can't share any information (e.g you can't have an isolate then a "child isolate") while I think contexts can?

Some general information that might be helpful:

An _isolate_ is an independent copy of the V8 runtime. It's a heavyweight object with its own heap and garbage collector. An isolate can execute script code on one thread at a time, and can't share data with other isolates except via facilities provided by the host.

An isolate can contain multiple relatively lightweight _contexts_, each with its own global object and its own set of JavaScript built-ins. Contexts parented to the same isolate are semi-independent in that they can share data efficiently, but they can't execute script code simultaneously.

The mapping between these entities and ClearScript objects is described above. Please let us know if you need additional information.

Is it possible to create multiple contexts in clear script and use them on the same isolate?
Well, it seems like you can with V8Runtime.CreateScriptEngine, but is there a way to chain them together, so you can have nested contexts. Could also be by the means of resolver semantics, where you look up unknown values in the parent contexts.

Hi @Ellested,

With the host's help, you can pass script objects between different engine instances, but ClearScript's support for this is limited.

Specifically, all cross-engine object access is always mediated by ClearScript, and therefore quite slow, despite the fact that V8 contexts sharing an isolate could theoretically access each other's objects directly.

Good luck!

Hi @Ellested,

With the host's help, you can pass script objects between different engine instances, but ClearScript's support for this is limited.

Specifically, all cross-engine object access is always mediated by ClearScript, and therefore quite slow, despite the fact that V8 contexts sharing an isolate could theoretically access each other's objects directly.

Good luck!

Thanks, and thanks for a very prompt reply, didn't expect that :-)

Just downloaded everything and got it working, though LinqPad had some trouble finding the native libraries in the Nuget package.

Anyway, it actually seems pretty cool, so I will start playing around and get to know it better.

Was this page helpful?
0 / 5 - 0 ratings