"this" parameter for the global scope

Jan 14, 2012 at 11:58 AM

Hi,

Just trying to figure out how to make the script scope replicate a browser object model.  E.g "this" within a browser resolves to the window object.  If I supplied a window object to the script engine, is it possible to resolve as "this".  if this is not currently available, is there any pointers to modifying the code to enable this functionality.

example:

c#: engine.SetParameter("window", window);

script: (this == window)

 

Thanks,

 

James

Jan 15, 2012 at 11:32 AM
Edited Jan 15, 2012 at 11:35 AM

This is a great engine - Figured it out one way of getting close,

First, point window at this.script.global (which is the same as 'this')

((JsGlobal)this.script.Global)["window"] = (JsGlobal)this.script.Global;

Then expose the methods we are interested in

JsGlobal)this.script.Global)["alert"] = new JsFunctionWrapper ((i) => {

 

this .window.alert(i[0].Value.ToString());

return JsNull .Instance; }, ((JsGlobal)this .script.Global).FunctionClass.PrototypeProperty);

The following scripts is then work correctly:

 

window.obj = { test: 'Passes' }; window.alert(window.obj.test);
window.obj = { test: 'Passes' }; this.alert(this.obj.test);
window.obj = { test: 'Passes' }; alert(obj.test);
 

 

However this one does not work as required. 

 obj = { test: 'Passes' }; window.alert(window.obj.test);

Any help :)

 Thanks,

James

 

((

Jan 15, 2012 at 12:35 PM

I think we need to modify Jint to make our very own global 'this' object :)

Take a look at ExecutionVisitor.cs in Jint source.

 

public ExecutionVisitor(Options options) {
	typeResolver = CachedTypeResolver.Default;

	Global = new JsGlobal(this, options); // this one creates global 'this' object
	GlobalScope = new JsScope(Global as JsObject);

	EnterScope(GlobalScope);

	CallStack = new Stack<string>();
}

 

Jan 15, 2012 at 2:49 PM

Yea, I can see by modifying the JsGlobal reference by modifying its parameters, e.g ["window"] = xxx... or ["alert"] = function call I can get almost what I need.

e.g

this == window

But, the issue now is when a var is defined, in a browser it gets added to the window object, e.g

var obj = "test";
window.obj == obj; // not true
this.obj == obj; // not true
By defining a var "obj" It should be added to the global instance?

Thanks,
James
Jan 15, 2012 at 4:22 PM

Hacked it:

I found that I can not access var / or assignments from this if it is defined, e.g

 

var obj;

this.obj == obj;

So, to achieve what I need I have modified JsGlobal to also check the global scopes properties, if it does not contain the property:

 

public override bool TryGetProperty(string index, out JsInstance result)
        {
            if (!base.TryGetProperty(index, out result))
                return ((ExecutionVisitor)this.Visitor).GlobalScope.TryGetProperty(index, out result);
            else
                return true;
        }

This may not be the best fix, but it passes my tests and does not break any existing ones.  Any other thoughts?

 

Thanks,

James

Jan 27, 2012 at 5:21 AM

I've been trying various overrides in JsGlobal now myself, but without much luck.  I basically want to assign a "fallback" object to assist the existing global object.

e.g. Look at global for '$' or 'jQuery'.  Failing that, try window.$

Is this what you've accomplished?

Oct 9, 2013 at 8:36 PM
This will do it (assuming 'WindowHelper' is the object that provides a browser's "window" object):
            WindowHelper jsWindow = new WindowHelper(this, doc);

            NativeConstructor nc = new NativeConstructor(typeof(WindowHelper), Script.Global);
            JsObject global = Script.Global as JsObject;
            nc.PrototypeProperty = global;
            nc.InitPrototype(Script.Global);
            nc.SetupNativeProperties(global);
            global.Value = jsWindow;

Maybe somebody can clarify how this could be simplified...