This project has moved. For the latest updates, please go here.

Global Object problem

Nov 18, 2011 at 8:40 AM

Hi

I want to create a Global Object such as WindowObject(InternalClassName "window") and set to ScriptEngine

then I can invoke "window.alert('test')", I also want to invoke "alert('test')" directly (No add "window" prefix).

now GloalObject can invoke method like "isFinite(123)" (don't need add InternalClassName)

Mozilla rhino can implement it by   

ScriptableObject.putConstProperty(glob_, "window", jswindowObject);

spidemonkey can use by   

JS_SetPrivate(cx_, glob_, (void *) window);

  JS_SetContextPrivate(cx_,window);

can Jurassic invoke "alert('test')" directly?

Now I use

ScriptEngine engine_ = new ScriptEngine();

engine_.SetGlobalValue("window", new JSWindowValue(engine_));

 "window.alert('test')" work well, "alert('test')" can't work.

Thank you.

Coordinator
Nov 18, 2011 at 9:49 AM
Edited Nov 18, 2011 at 9:44 PM

Try this:

engine_.SetGlobalFunction("alert", new Action<string>(str => Console.WriteLine(str)));

(Replace Console.WriteLine with whatever you need the alert to do)

Nov 18, 2011 at 6:37 PM
I must say that this do not answer to his question. I've also wanted to do something like this for a while (without the use of a "window" variable), and my question is, and as far as I can see his is too, can you in a simple way extend the Global with your own class? You should be able to subcass the Global in Jurassic and create a Engine with your own subclass as the Global object. That way you could do myGlobal["window"] = myGlobal and every function and object that's reachable without a prefix would also be reachable with the "window"-prefix. This can be somewhat important as "window.noExistingObject" gives you "undefined" while "noExistingObject" throws you an exception.

Personally I wouldn't want to name the global loopback-var to "window", but something else, but that shouldn't really matter.
Coordinator
Nov 18, 2011 at 9:53 PM

You can already do "engine.Global["window"] = engine.Global", which aliases window to the global object ("window = this" in javascript).  Or you can create your own window class and set the prototype to the global object (pass it to the ObjectInstance constructor) - effectively subclassing the global object.  That way you can add additonal properties to "window" that don't exist in the global object.

Nov 19, 2011 at 12:30 AM
I knew the first one was posible, that's only logical, but I never thought about setting the prototype for Global. That's pretty smart, and I will do this from now.
Nov 19, 2011 at 6:59 AM
Edited Nov 19, 2011 at 1:26 PM

Thank you for all your help.

I use the second way.(oh , the other way :-)  )

ScriptEngine.cs add method

        public void populateGlobalFunctions(Type type) {       

this.globalObject.PopulateFunctions(type); 

}

and add JSWindowValue class like this

ScriptEngine engine_ = new ScriptEngine();

        JSWindowValue windowValue = new JSWindowValue(engine_);           

engine_.SetGlobalValue("window", windowValue);           

engine_.populateGlobalFunctions(windowValue.GetType());

Now It works well.

Coordinator
Nov 19, 2011 at 12:34 PM

That's not what I suggested at all - but if you're happy I'm happy :-)

Nov 19, 2011 at 1:23 PM
Edited Nov 19, 2011 at 1:29 PM
paulbartrum wrote:

That's not what I suggested at all - but if you're happy I'm happy :-)

oh, sorry.

Can you explain with example exactly?^_^

Coordinator
Nov 20, 2011 at 10:10 AM

I meant something like this:

public class WindowObject : ObjectInstance
{
  public WindowObject(ScriptEngine engine)
    : base(engine.Global)
  {
    this.PopulateFunctions();
  }

  // your methods here
}

// Elsewhere...

var engine = new ScriptEngine();
engine.SetGlobalValue("window", new WindowObject());


Aug 31, 2012 at 12:30 PM

I have a similar (I think) requirement to this. Suppose I've created a class that inherits ObjectInstance and just overrides GetMissingPropertyValue, so the "content" of the object is completely dynamically determined.

For example, the object could represent a directory on disk. When asked for a property "MyDocuments", it returns another ObjectInstance bound to that directory. If the requested name resolves to a file, it returns a string containing the contents of the file. This is just an example - it could be registry keys, or whatever. The point being that it is not necessary to recurse the whole file system to build the object instance - instead just grab whatever is asked for on demand.

Then for a particular kind of script I'd like this dynamic namespace to be the global namespace. So I create one of these ObjectInstances bound to a root directory, and then I'd like to assign it to ScriptEngine.Globals, but that has no setter.

Is there an official/better way of achieving this?