More fun with scopes and ScriptObjectMirror

Tim Fox timvolpe at
Thu Dec 12 01:42:59 PST 2013

On 12/12/13 09:08, Attila Szegedi wrote:
> On Dec 12, 2013, at 10:02 AM, Tim Fox <timvolpe at 
> <mailto:timvolpe at>> wrote:
>> On 12/12/13 08:49, Attila Szegedi wrote:
>>> On Dec 12, 2013, at 8:00 AM, Tim Fox <timvolpe at 
>>> <mailto:timvolpe at>> wrote:
>>>> On 11/12/13 12:53, Attila Szegedi wrote:
>>>>> On Dec 11, 2013, at 1:13 PM, Tim Fox <timvolpe at 
>>>>> <mailto:timvolpe at>> wrote:
>>>>>> Confused...
>>>>>> I assumed that if two scripts where run with their own script 
>>>>>> context, then they would already have separate globals, i.e. if I do
>>>>>> myglobal = 1
>>>>>> in module 1 that won't be visible in module 2.
>>>>> That's true, but then you also end up with the need for 
>>>>> ScriptObjectMirrors between them, and that was what I suggested 
>>>>> you try to avoid.
>>>>>> So I'm not sure really what --global-per-engine really means, if 
>>>>>> the modules have their own globals anyway. I guess my 
>>>>>> understanding must be wrong somewhere.
>>>>> Well, it will mean that modules won't have their own globals… 
>>>>> --global-per-engine will make it so that the Global object is 
>>>>> specific to the ScriptEngine, and not to the ScriptContext, e.g. 
>>>>> even if you replace the ScriptContext of the engine, when scripts 
>>>>> are run, they'll still see the same global object as before the 
>>>>> replacement. The gist of it is:
>>>>> a) without --global-per-engine, the Global object is specific to a 
>>>>> ScriptContext, each ScriptContext has its own. ENGINE_SCOPE 
>>>>> Bindings object of the context is actually a mirror of its Global.
>>>>> b) with --global-per-engine, the Global object lives in the 
>>>>> ScriptEngine. ENGINE_SCOPE Bindings object of the context is just 
>>>>> a vanilla SimpleBindings (or whatever you set it to), and Global 
>>>>> will delegate property getters for non-existent properties to it 
>>>>> (but it'll still receive property setters, so new global variables 
>>>>> created by one script will be visible by another; no isolation there).
>>>> One more question on this. With --global-per-engine, and multiple 
>>>> ScriptContext instances - if all the ScriptContext instances share 
>>>> a single a single global, how is this different from just having a 
>>>> single ScriptContext in which you execute all JavaScript?
>>> Not much. Using separate ScriptContexts with single engine is pretty 
>>> much equivalent to modifying the initial ScriptContext of the 
>>> engine. When I thought you'll end up using Java code to implement 
>>> module loading, I suggested either using separate contexts, or at 
>>> least changing the ENGINE_SCOPE bindings of the original context to 
>>> contain "module", "exports", etc. but if you now implement those as 
>>> parameters of an anonymous function that you put around the module 
>>> source code and eval(), then you don't need even that.
>>> So, yeah, you can have a single context for all JavaScript. As I 
>>> said earlier, it'll be single-threaded, but JavaScript the language 
>>> is by nature single-threaded (that's why node.js is single-threaded 
>>> too). Probably the better way to say it is that JavaScript language 
>>> has no defined multithreaded semantics, and thus a JavaScript 
>>> execution environment is unsafe to use in a multithreaded manner.
>> Regarding thread safety... Unlike node, Vert.x is multi-threaded, 
>> however we guarantee that code in a particular Verticle is never 
>> executed concurrently by more than one thread.
>> In other words - we have a single engine which might contain many 
>> scripts, and may have many threads executing different scripts in it 
>> at any one time, but we guarantee that any particular script is never 
>> executed concurrently by more than one thread. So we don't need any 
>> multithreaded JS semantics.
>> This works well with Rhino and DynJS. So I assume it's ok for a 
>> single engine to be executed concurrently as long as those threads 
>> don't bump into each other, i.e. don't try and execute the same code 
>> concurrently?
> Code execution is not a concern, multiple threads executing same code 
> is okay. Concurrent mutation of shared data is a concern. If those 
> verticles also have data separation, and whatever data they share they 
> only use as read-only (talking about native JS objects, arrays, and 
> global vars here; you can obviously share threadsafe POJOs). Native JS 
> objects and arrays in Nashorn aren't threadsafe. That's a conscious 
> design decision; since the language doesn't have defined multithreaded 
> semantics, it doesn't make much sense to pay the price for it in terms 
> of code complexity and runtime cost.

+1. This fits the Vert.x model well... we don't share any mutable state 
between verticles, and I don't have any desire for the engine to support 
it. Vert.x has an "actor-like" approach to concurrency - where each 
verticle is like an actor (single threaded) and communicates with other 
verticles by passing immutable messages.

> Attila.

More information about the nashorn-dev mailing list