Subj : Re: named scope To : Stuart From : Igor Bukanov Date : Sun Aug 22 2004 09:49 pm Stuart wrote: > Hi, > > I having some difficulty understanding how to correctly use scopes (I'm new > to ECMAScript and Rhino so some help getting over this initial hurdle would > be much appreciated). > > I am implementing something similar to a HTML browser in which variables > fall into different scopes (session, document etc...). > > I understand how to create the initial scope: > > ecmaContext = Context.enter(); > ecmaScope = ecmaContext.initStandardObjects(); > > And from this scope I can use newObject, setPrototype and setParentScope to > create 'child scopes' (Looking at the example from the 'Scopes and Contexts > document'). > > My main question is: > > (1) How can the scopes be named so that variables can be found in the > correct scope e.g document.var or session.var? There is no notion of named scope in Rhino. It would be better if you give an example of JS code and its desire behavior regarding the name lookup. > > If you have time please could you also answer the following questions (I > feel these may be a little dummer than the 1st question): > > (2) The 'Scopes and Contexts document' sets the parent scope to null but for > my purpose I would need to explicitly set the parent (shared) scope. Is > this correct? Does this also mean I would not call the setPrototype method? > > (3) To add variables to my scope I just need to call defineProperty on the > object. Is this correct? If the name of the variable was abc and the scope > was document would I name the property abc or document.abc on the document > scope? > > (4) When calling evaluateString on the context with a particular scope. The > script which I am evaluating may define variables and functions. Will these > variables and functions get added to the supplied scope? Consider the following script: var x; x = y; z = y; function f() { } When you pass the script to cx.evaluateString(scope, ...), then the script will first compiled to an internal form to produce Script object which does not depend on scope or an other objects. Then the compiled script is executed against the supplied scope and the following steps are be taken: 1. All variable declared in var statements and function declarations are added to the supplied scope object as properties as if using ScriptableObject.defineProperty methods. In the example case it means that the scope passed to evaluateString will get property f containg the function object and property x initialized initially to undefined. 2. The rest of code is executed using the given scope to lookup for property names. In the example the runtime first evaluates "x = y". Since x is declared with "var", the runtime uses the current scope to update the property x there with the value of y. To get y the runtime first looks for property defined in the scope and its prototype chain, then it looks in scope.getParentScope and its prototype chain etc. If no y property will ever be found you get an error. Then the runtime evaluates "z = y". First it tries to see which scope contains z since z is not declared as a variable. There are two cases. In the first case there is property z in the scope or its parent scopes. In this case the head of prototype chain containg y is be updated with the value of y. In the second case when z is not found, it is be created in the topmost parent scope of the current scope and filled with the value of y. Due to this second case in general Context.evaluateString or Script.eval should only be used with top scopes (getParentScope() should be null) unless you now presizely what you are doing and have full control of the supplied scripts. In this way "z = y" and "var z = y" will behave in the same way. For a particular setup of the top scope and its prototype chain for a browser-like environment see http://groups.google.com/groups?selm=40C71743.6060103%40fastmail.fm Regards, Igor .