< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/AbstractIterator.java

Print this page




  93     /**
  94      * ES6 25.1.1.2 The Iterator Interface
  95      *
  96      * @param arg argument
  97      * @return next iterator result
  98      */
  99     protected abstract IteratorResult next(final Object arg);
 100 
 101     /**
 102      * ES6 25.1.1.3 The IteratorResult Interface
 103      *
 104      * @param value result value
 105      * @param done result status
 106      * @param global the global object
 107      * @return result object
 108      */
 109     protected IteratorResult makeResult(final Object value, final Boolean done, final Global global) {
 110         return new IteratorResult(value, done, global);
 111     }
 112 



































 113     /**
 114      * ES6 7.4.1 GetIterator abstract operation
 115      *
 116      * @param iterable an object
 117      * @param global the global object
 118      * @return the iterator
 119      */
 120     public static Object getIterator(final Object iterable, final Global global) {
 121         final Object object = Global.toObject(iterable);
 122 
 123         if (object instanceof ScriptObject) {
 124             // TODO we need to implement fast property access for Symbol keys in order to use InvokeByName here.
 125             final Object getter = ((ScriptObject) object).get(NativeSymbol.iterator);
 126 
 127             if (Bootstrap.isCallable(getter)) {
 128                 try {
 129                     final MethodHandle invoker = global.getDynamicInvoker(ITERATOR_INVOKER_KEY,
 130                             () -> Bootstrap.createDynamicCallInvoker(Object.class, Object.class, Object.class));
 131 
 132                     final Object value = invoker.invokeExact(getter, iterable);
 133                     if (JSType.isPrimitive(value)) {
 134                         throw typeError("not.an.object", ScriptRuntime.safeToString(value));
 135                     }
 136                     return value;
 137 
 138                 } catch (final Throwable t) {
 139                     throw new RuntimeException(t);
 140                 }
 141             }
 142             throw typeError("not.a.function", ScriptRuntime.safeToString(getter));
 143         }
 144 
 145         throw typeError("cannot.get.iterator", ScriptRuntime.safeToString(iterable));
 146     }
 147 
 148     /**
 149      * Iterate over an iterable object, passing every value to {@code consumer}.
 150      *
 151      * @param iterable an iterable object
 152      * @param global the current global
 153      * @param consumer the value consumer
 154      */
 155     public static void iterate(final Object iterable, final Global global, final Consumer<Object> consumer) {
 156 
 157         final Object iterator = AbstractIterator.getIterator(Global.toObject(iterable), global);
 158 
 159         final InvokeByName nextInvoker = global.getInvokeByName(AbstractIterator.NEXT_INVOKER_KEY,
 160                 () -> new InvokeByName("next", Object.class, Object.class, Object.class));
 161         final MethodHandle doneInvoker = global.getDynamicInvoker(AbstractIterator.DONE_INVOKER_KEY,
 162                 () -> Bootstrap.createDynamicInvoker("done", NashornCallSiteDescriptor.GET_PROPERTY, Object.class, Object.class));
 163         final MethodHandle valueInvoker = global.getDynamicInvoker(AbstractIterator.VALUE_INVOKER_KEY,
 164                 () -> Bootstrap.createDynamicInvoker("value", NashornCallSiteDescriptor.GET_PROPERTY, Object.class, Object.class));
 165 
 166         try {
 167             do {
 168                 final Object next = nextInvoker.getGetter().invokeExact(iterator);
 169                 if (!Bootstrap.isCallable(next)) {
 170                     break;
 171                 }
 172 
 173                 final Object result = nextInvoker.getInvoker().invokeExact(next, iterator, (Object) null);
 174                 if (!(result instanceof ScriptObject)) {
 175                     break;
 176                 }
 177 
 178                 final Object done = doneInvoker.invokeExact(result);
 179                 if (JSType.toBoolean(done)) {
 180                     break;
 181                 }
 182 
 183                 consumer.accept(valueInvoker.invokeExact(result));
 184 


  93     /**
  94      * ES6 25.1.1.2 The Iterator Interface
  95      *
  96      * @param arg argument
  97      * @return next iterator result
  98      */
  99     protected abstract IteratorResult next(final Object arg);
 100 
 101     /**
 102      * ES6 25.1.1.3 The IteratorResult Interface
 103      *
 104      * @param value result value
 105      * @param done result status
 106      * @param global the global object
 107      * @return result object
 108      */
 109     protected IteratorResult makeResult(final Object value, final Boolean done, final Global global) {
 110         return new IteratorResult(value, done, global);
 111     }
 112 
 113     static MethodHandle getIteratorInvoker(final Global global) {
 114         return global.getDynamicInvoker(ITERATOR_INVOKER_KEY,
 115                 () -> Bootstrap.createDynamicCallInvoker(Object.class, Object.class, Object.class));
 116     }
 117 
 118     /**
 119      * Get the invoker for the ES6 iterator {@code next} method.
 120      * @param global the global object
 121      * @return the next invoker
 122      */
 123     public static InvokeByName getNextInvoker(final Global global) {
 124         return global.getInvokeByName(AbstractIterator.NEXT_INVOKER_KEY,
 125                 () -> new InvokeByName("next", Object.class, Object.class, Object.class));
 126     }
 127 
 128     /**
 129      * Get the invoker for the ES6 iterator result {@code done} property.
 130      * @param global the global object
 131      * @return the done invoker
 132      */
 133     public static MethodHandle getDoneInvoker(final Global global) {
 134         return global.getDynamicInvoker(AbstractIterator.DONE_INVOKER_KEY,
 135                 () -> Bootstrap.createDynamicInvoker("done", NashornCallSiteDescriptor.GET_PROPERTY, Object.class, Object.class));
 136     }
 137 
 138     /**
 139      * Get the invoker for the ES6 iterator result {@code value} property.
 140      * @param global the global object
 141      * @return the value invoker
 142      */
 143     public static MethodHandle getValueInvoker(final Global global) {
 144         return global.getDynamicInvoker(AbstractIterator.VALUE_INVOKER_KEY,
 145                 () -> Bootstrap.createDynamicInvoker("value", NashornCallSiteDescriptor.GET_PROPERTY, Object.class, Object.class));
 146     }
 147 
 148     /**
 149      * ES6 7.4.1 GetIterator abstract operation
 150      *
 151      * @param iterable an object
 152      * @param global the global object
 153      * @return the iterator
 154      */
 155     public static Object getIterator(final Object iterable, final Global global) {
 156         final Object object = Global.toObject(iterable);
 157 
 158         if (object instanceof ScriptObject) {
 159             // TODO we need to implement fast property access for Symbol keys in order to use InvokeByName here.
 160             final Object getter = ((ScriptObject) object).get(NativeSymbol.iterator);
 161 
 162             if (Bootstrap.isCallable(getter)) {
 163                 try {
 164                     final MethodHandle invoker = getIteratorInvoker(global);

 165 
 166                     final Object value = invoker.invokeExact(getter, iterable);
 167                     if (JSType.isPrimitive(value)) {
 168                         throw typeError("not.an.object", ScriptRuntime.safeToString(value));
 169                     }
 170                     return value;
 171 
 172                 } catch (final Throwable t) {
 173                     throw new RuntimeException(t);
 174                 }
 175             }
 176             throw typeError("not.a.function", ScriptRuntime.safeToString(getter));
 177         }
 178 
 179         throw typeError("cannot.get.iterator", ScriptRuntime.safeToString(iterable));
 180     }
 181 
 182     /**
 183      * Iterate over an iterable object, passing every value to {@code consumer}.
 184      *
 185      * @param iterable an iterable object
 186      * @param global the current global
 187      * @param consumer the value consumer
 188      */
 189     public static void iterate(final Object iterable, final Global global, final Consumer<Object> consumer) {
 190 
 191         final Object iterator = AbstractIterator.getIterator(Global.toObject(iterable), global);
 192 
 193         final InvokeByName nextInvoker = getNextInvoker(global);
 194         final MethodHandle doneInvoker = getDoneInvoker(global);
 195         final MethodHandle valueInvoker = getValueInvoker(global);



 196 
 197         try {
 198             do {
 199                 final Object next = nextInvoker.getGetter().invokeExact(iterator);
 200                 if (!Bootstrap.isCallable(next)) {
 201                     break;
 202                 }
 203 
 204                 final Object result = nextInvoker.getInvoker().invokeExact(next, iterator, (Object) null);
 205                 if (!(result instanceof ScriptObject)) {
 206                     break;
 207                 }
 208 
 209                 final Object done = doneInvoker.invokeExact(result);
 210                 if (JSType.toBoolean(done)) {
 211                     break;
 212                 }
 213 
 214                 consumer.accept(valueInvoker.invokeExact(result));
 215 
< prev index next >