Channel: ClearScript
Viewing all articles
Browse latest Browse all 2297

Commented Unassigned: for/in loop in JScript standards mode fails [94]

It appears that the for/in loop is not working when JScript engine is initialized with WindowsScriptEngineFlags.EnableStandardsMode flag.

I tried adding PropertyBag and ExpandoObject as host objects.

I noticed that there is a ScriptEngineException when executing for/in loop on either of the two objects which has HResult of 0x800a0005 (Invalid procedure call or argument).

Without WindowsScriptEngineFlags.EnableStandardsMode flag everything works without exceptions.

I am developing on Windows 10 with ClearScript 5.4.3

Here is the sample program:

static void Main(string[] args)
var engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
engine.AddHostType("Console", typeof(Console));

dynamic expandoObj = new ExpandoObject();
expandoObj.testProp = "expando testProp Text";
engine.AddHostObject("expandoObj", expandoObj);

var propertyBag = new PropertyBag();
propertyBag["testProp"] = "property bag testProp Text";
engine.AddHostObject("propertyBagObj", propertyBag);

engine.Execute(@"Console.WriteLine('expandoObj.testProp=' + expandoObj.testProp);");
engine.Execute(@"Console.WriteLine('propertyBagObj.testProp=' + propertyBagObj.testProp);");
engine.Execute(@"for (var item in propertyBagObj) Console.WriteLine('propertyBagObj[' + item + ']=' + propertyBagObj[item]);");
engine.Execute(@"for (var item in expandoObj) Console.WriteLine('expandoObj[' + item + ']=' + expandoObj[item]);");



Comments: Hi frolovm, You're absolutely right. The [for..in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) statement is broken for host objects in Standards Mode. Unfortunately this appears to be a JScript bug and therefore isn't likely to be fixed. Consider however that for..in support is really only useful for `IPropertyBag` instances. All other host objects include instance methods, extension methods, and other undesirable members in the enumeration. This is by design, as some script engines (including JScript) don't have enumeration options for host object members. There are several ways to enumerate host object members that work in Standards Mode and don't have the problem mentioned above. JScript's [`Enumerator`](https://msdn.microsoft.com/en-us/library/6ch9zb09%28v=vs.84%29.aspx) class is one possibility: ``` C# engine.Execute(@" for (var e = new Enumerator(expandoObj); !e.atEnd(); e.moveNext()) { var item = e.item(); Console.WriteLine('{0} = {1}', item.Key, item.Value); } "); ``` Unfortunately this currently doesn't work with `IPropertyBag`; that's a ClearScript bug that we'll fix in the next point release. Another possibility might be to expose a JavaScript-friendly way to use .NET enumeration: ``` C# public static class IEnumerableExtensions { public static void @foreach(this IEnumerable source, dynamic callback) { foreach (var item in source) { callback(item); } } } ``` and then: ``` C# engine.AddHostType(typeof(IEnumerableExtensions)); engine.Execute(@" expandoObj.foreach(function(item) { Console.WriteLine('{0} = {1}', item.Key, item.Value); }); "); ``` Finally, for scriptable name-value collections, you can always use native JavaScript objects instead of host objects: ``` C# dynamic someObj = engine.Evaluate("({})"); someObj.foo = 123; someObj.bar = 456; engine.Script.someObj = someObj; ``` Thanks for reporting this issue, and good luck!

Viewing all articles
Browse latest Browse all 2297