Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable 'for...in' my NativeJavaObject within Rhino?

I am newbie in rhino.

Currently, I am using Rhino 1.7R framework thru .NET 4 and IKVM.NET. I exposed several wrapped classes implementing NativeJavaObject using setWrapFractory() API.

public class InterceptNativeObject : NativeJavaObject
{
    public InterceptNativeObject()
    {

    }

    public override Object get(String name, Scriptable start)
    {
        Object res = base.get(name, start);
        if (res is NativeJavaMethod)
        {
            NativeJavaMethod method = (NativeJavaMethod)res;
            return new RhinoMethodWrapFunction(method);
        }
        if (res == org.mozilla.javascript.UniqueTag.NOT_FOUND &&
            base.javaObject is IPropertBox && base.javaObject != null)
        {
            object ret = ((IPropertBox)base.javaObject)._x__GetPropertyValue(name);

            return Utils.ConvertCLRValueToJavaValue(ret);
        }
        return res;
     }

     .....
}

Now, I can access all .NET methods and properties as I wanted.

My current problem is to support 'for...in' my NativeJavaObject classes. When I evaluate

     'for(var prop in myClass){printf(prop);};' ,

it returns 'no 'in' call for non-object' error.

It seems the 'get' attempting to searching an object of ' _iterator_', but it resulted in 'not found' at get() function. So, it ends up with exception. So far, I tried

  • added java.util.iterator
  • return this.getIds().GetEnumrator();

None of works.

How can i allow property enumrate access for my Wrapped NativeJavaObject? What is Rhino's expected return value of ' _iterator_' to enable 'for...in'?

Thanks in advance!

like image 265
ultra mother hacker Avatar asked Nov 03 '22 08:11

ultra mother hacker


1 Answers

__iterator__ is part of a Mozilla specific language extension. That link explains that the __iterator__ method returns an object with a next method that throws StopIteration when the iterator is exhausted.

You have to opt in to iterators and generators though:

To enable JavaScript 1.7 support, you must set the version as 170 using the Context.setLanguageVersion() API call. If you are using the Rhino shell, you can specify -version 170 on the command line or call version(170) in code executed by the shell.

You can write JS in rhino that will wrap a Java iterator to present it as a JS iterator:

function javaIteratorToJsIterator(javaIterator) {
  return {
    next: function () {
      if (!javaIterator.hasNext()) { throw StopIteration; }
      return javaIterator.next();
    }
  };
}

Alternatively, you can use Mozilla style generators but I think you need to create the Rhino interpreter with an option to enable them.

While custom iterators are a useful tool, their creation requires careful programming due to the need to explicitly maintain their internal state. Generators provide a powerful alternative: they allow you to define an iterative algorithm by writing a single function which can maintain its own state.

A generator is a special type of function that works as a factory for iterators. A function becomes a generator if it contains one or more yield expressions.

like image 117
Mike Samuel Avatar answered Nov 12 '22 15:11

Mike Samuel