< prev index next >
src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java
Print this page
@@ -50,14 +50,17 @@
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,10 +104,15 @@
* 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,10 +372,81 @@
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|Error 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|Error 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|Error 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 >