< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java

Print this page

        

*** 50,63 **** --- 50,66 ---- import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.codegen.ApplySpecialization; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.ir.debug.JSONWriter; + import jdk.nashorn.internal.objects.AbstractIterator; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.objects.NativeObject; import jdk.nashorn.internal.parser.Lexer; import jdk.nashorn.internal.runtime.linker.Bootstrap; + import jdk.nashorn.internal.runtime.linker.InvokeByName; + import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; /** * Utilities to be called by JavaScript runtime API and generated classes. */
*** 101,110 **** --- 104,118 ---- * Return an appropriate iterator for the elements in a for-each construct */ public static final Call TO_VALUE_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toValueIterator", Iterator.class, Object.class); /** + * Return an appropriate iterator for the elements in a ES6 for-of loop + */ + public static final Call TO_ES6_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toES6Iterator", Iterator.class, Object.class); + + /** * Method handle for apply. Used from {@link ScriptFunction} for looking up calls to * call sites that are known to be megamorphic. Using an invoke dynamic here would * lead to the JVM deoptimizing itself to death */ public static final Call APPLY = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "apply", Object.class, ScriptFunction.class, Object.class, Object[].class);
*** 364,373 **** --- 372,452 ---- return Collections.emptyIterator(); } /** + * Returns an iterator over property values used in the {@code for ... of} statement. The iterator uses the + * Iterator interface defined in version 6 of the ECMAScript specification. + * + * @param obj object to iterate on. + * @return iterator based on the ECMA 6 Iterator interface. + */ + public static Iterator<?> toES6Iterator(final Object obj) { + final Global global = Global.instance(); + final Object iterator = AbstractIterator.getIterator(Global.toObject(obj), global); + + final InvokeByName nextInvoker = AbstractIterator.getNextInvoker(global); + final MethodHandle doneInvoker = AbstractIterator.getDoneInvoker(global); + final MethodHandle valueInvoker = AbstractIterator.getValueInvoker(global); + + return new Iterator<Object>() { + + private Object nextResult = nextResult(); + + private Object nextResult() { + try { + final Object next = nextInvoker.getGetter().invokeExact(iterator); + if (Bootstrap.isCallable(next)) { + return nextInvoker.getInvoker().invokeExact(next, iterator, (Object) null); + } + } catch (final RuntimeException r) { + throw r; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + return null; + } + + @Override + public boolean hasNext() { + if (nextResult == null) { + return false; + } + try { + final Object done = doneInvoker.invokeExact(nextResult); + return !JSType.toBoolean(done); + } catch (final RuntimeException r) { + throw r; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } + + @Override + public Object next() { + if (nextResult == null) { + return Undefined.getUndefined(); + } + try { + final Object result = nextResult; + nextResult = nextResult(); + return valueInvoker.invokeExact(result); + } catch (final RuntimeException r) { + throw r; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove"); + } + }; + } + + /** * Merge a scope into its prototype's map. * Merge a scope into its prototype. * * @param scope Scope to merge. * @return prototype object after merge
< prev index next >