Problem on a System.String using JScriptEngine

Oct 3, 2013 at 7:13 PM
I create a C# object like:

public class TestObject
    {
        public String StringProp { get; set; }
    }
I am able to get the ClearScript/JScriptEngine to evaluate:

"TestObject.StringProp"

but not

"TestObject.StringProp.PadLeft(8)"

Or any other method on StringProp.

scriptError.ErrorDetails = "Object doesn't support this property or method\n at JScript global code (Script Document [temp]:0:0) -> container.StringProp.PadLeft(8)\n"
Coordinator
Oct 3, 2013 at 8:18 PM
Edited Oct 3, 2013 at 8:21 PM
Greetings!

Strings and numbers are just about the only objects for which ClearScript performs automatic data conversion. In your example, the script engine receives the StringProp value in the form of a native script string, which of course doesn't have a PadLeft() method.

Here's one way to access .NET string members from script code:
// C#
engine.Script.host = new Microsoft.ClearScript.HostFunctions();
engine.Execute(@"
    String.prototype.toHost = function () {
        return host.newVar(this.valueOf());
    }
");
and then:
// JavaScript
var x = TestObject.StringProp.toHost().PadLeft(8);
Good luck!
Oct 3, 2013 at 9:16 PM
On that Execute, I get this with the JScript engine:

'String.prototype' is null or not an object
at JScript global code (Script Document:0:0) -> String.prototype.toHost = function () {
return host.newVar(this.valueOf());
}
Oct 3, 2013 at 9:28 PM
I had this elsewhere, so I suspect it caused a conflict:

engine.AddHostType("String", typeof(System.String));

I removed that, and that error went away.
Coordinator
Oct 3, 2013 at 9:37 PM
Did you overwrite the built-in JavaScript String function? The prototype property is documented here.
Coordinator
Oct 3, 2013 at 9:39 PM
Heh, looks like you've already resolved your issue. Remember that you can expose the .NET string class under a different name:
engine.AddHostType("CLRString", typeof(System.String));
Oct 3, 2013 at 10:01 PM
One more follow up: Is there a way to pass a CHAR param?

LeftPad(8) works fine, but this fails:
StringProp.toHost().PadLeft(8,'X')
I event tried:
StringProp.toHost().PadLeft(8,'X'.charAt(0))
In both cases, I got an exception in HostItem.InvokeMethod:
The best overloaded method match for 'string.PadLeft(int, char)' has some invalid arguments
Coordinator
Oct 3, 2013 at 10:19 PM
Yes. The problem is that both 'X' and 'X'.charAt(0) are strings. You might try 'X'.charCodeAt(0), but that would also fail because it would appear on the .NET side as an int, which cannot be converted implicitly to a char.

However, this should work:
StringProp.toHost().PadLeft(8, host.toChar('X'))
Please let us know if it doesn't!
Oct 3, 2013 at 10:26 PM
Yes that works great.

Thanks for your help.

My only (minor complaint is that my script now looks uglier and uglier).
var x = StringProp.toHost().PadLeft(8,host.toChar('X')).toHost().Replace('X','Y'); // For example
It would be nice if there were a way to force the engine to use CLR string type instead of jscript type. Since most of the objects I'm trying to automate have String properties.

For now, I will probably follow your pattern of adding a bunch of new methods to String.prototype (like replace, padLeft, etc), so it kinda acts like I want.

-- jorge.
Coordinator
Oct 3, 2013 at 10:45 PM
For now, I will probably follow your pattern of adding a bunch of new methods to String.prototype (like replace, padLeft, etc), so it kinda acts like I want.

That's a great idea. You could use additional String.prototype methods to eliminate .toHost(), streamline conversion to char, etc.