<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.javascript.tests;

import junit.framework.TestCase;
import org.mozilla.javascript.Context;
import static org.mozilla.javascript.Context.VERSION_ES6;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Symbol;
import org.mozilla.javascript.SymbolKey;
import org.mozilla.javascript.SymbolScriptable;
import org.mozilla.javascript.TopLevel;
import org.mozilla.javascript.Undefined;

/**
 * Tests for host objects implementing the iterable protocol.
 *
 * See https://github.com/mozilla/rhino/pull/599
 *
 * @author <NAME>
 */
public class IterableTest extends TestCase {

    //Explicitly not a ScriptableObject
    public static final class FooWithArrayIterator implements Scriptable, SymbolScriptable {

        private final Scriptable scope;

        public FooWithArrayIterator(final Scriptable scope) {
            this.scope = scope;
        }

        @Override
        public String getClassName() {
            return this.getClass().getSimpleName();
        }

        @Override
        public Object get(String name, Scriptable start) {
            switch (name) {
                case "length":
                    return 1;
            }
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object get(int index, Scriptable start) {
            switch (index) {
                case 0:
                    return 123;
                default:
                    return Undefined.instance;
            }
        }

        @Override
        public boolean has(String name, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public boolean has(int index, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void put(String name, Scriptable start, Object value) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void put(int index, Scriptable start, Object value) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void delete(String name) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void delete(int index) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Scriptable getPrototype() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void setPrototype(Scriptable prototype) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Scriptable getParentScope() {
            return scope;
        }

        @Override
        public void setParentScope(Scriptable parent) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object[] getIds() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object getDefaultValue(Class<?> hint) {
            if(String.class == hint) {
                return "[object Object]";
            }
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public boolean hasInstance(Scriptable instance) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object get(Symbol key, Scriptable start) {
            if (SymbolKey.ITERATOR.equals(key)) {
                return ScriptableObject.getProperty(
                        TopLevel.getArrayPrototype(scope),
                        SymbolKey.ITERATOR
                );
            }
            throw new IllegalStateException();
        }

        @Override
        public boolean has(Symbol key, Scriptable start) {
            return SymbolKey.ITERATOR.equals(key);
        }

        @Override
        public void put(Symbol key, Scriptable start, Object value) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void delete(Symbol key) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

    }

    /**
     * Test for a host object to be able to supply an iterator, specifically
     * Array.prototype[Symbol.iterator], for a for-of loop.
     */
    public void testForOfUsingArrayIterator() {

        Context cx = Context.enter();
        cx.setLanguageVersion(VERSION_ES6);

        final Scriptable top = cx.initSafeStandardObjects();

        Scriptable foo = new FooWithArrayIterator(top);

        ScriptableObject.putProperty(top, "foo", foo);

        assertEquals(
                true,
                cx.evaluateString(top, "foo[Symbol.iterator] === Array.prototype[Symbol.iterator]", "<eval>", 0, null)
        );

        assertEquals(
                123,
                cx.evaluateString(top, "(function(){for(x of foo) { return x; }})()", "<eval>", 0, null)
        );
    }

}<commit_msg>Added more tests to IterableTest.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.javascript.tests;

import junit.framework.TestCase;
import org.mozilla.javascript.Context;
import static org.mozilla.javascript.Context.VERSION_ES6;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.EcmaError;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.Symbol;
import org.mozilla.javascript.SymbolKey;
import org.mozilla.javascript.SymbolScriptable;
import org.mozilla.javascript.TopLevel;
import org.mozilla.javascript.Undefined;

/**
 * Tests for host objects implementing the iterable protocol.
 *
 * See https://github.com/mozilla/rhino/pull/599
 *
 * @author <NAME>
 */
public class IterableTest extends TestCase {

    public static final class FooWithoutSymbols extends FooBoilerplate {

        public FooWithoutSymbols(final Scriptable scope) {
            super(scope);
        }

    }

    public static final class FooWithSymbols extends SymbolFooBoilerplate {

        public FooWithSymbols(final Scriptable scope) {
            super(scope);
        }

        @Override
        public boolean has(Symbol key, Scriptable start) {
            return false;
        }

    }

    public static final class FooWithArrayIterator extends SymbolFooBoilerplate {

        public FooWithArrayIterator(final Scriptable scope) {
            super(scope);
        }

        @Override
        public Object get(String name, Scriptable start) {
            switch (name) {
                case "length":
                    return 1;
            }
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object get(int index, Scriptable start) {
            switch (index) {
                case 0:
                    return 123;
                default:
                    return Undefined.instance;
            }
        }

        @Override
        public Object get(Symbol key, Scriptable start) {
            if (SymbolKey.ITERATOR.equals(key)) {
                return ScriptableObject.getProperty(
                        TopLevel.getArrayPrototype(scope),
                        SymbolKey.ITERATOR
                );
            }
            throw new IllegalStateException();
        }

        @Override
        public boolean has(Symbol key, Scriptable start) {
            return SymbolKey.ITERATOR.equals(key);
        }

    }

    private final Scriptable top;

    static {
        ContextFactory.initGlobal(new ContextFactory() {
            @Override
            protected Context makeContext() {
                return new Context(this) {
                    {
                        this.setLanguageVersion(VERSION_ES6);
                    }
                };
            }
        });
    }

    public IterableTest() {
        Context cx = Context.enter();
        try {
            top = cx.initSafeStandardObjects();
        } finally {
            Context.exit();
        }
    }

    /**
     * Regression test for a Scriptable not implementing SymbolScriptable, used
     * in for a for-of loop.
     *
     * Note: no spec is (knowingly) being adhered to with the "expected" in this
     * test, merely the situation as-is being "noted".
     */
    public void testForOfUsingNonSymbolScriptable() {

        Context cx = Context.enter();
        try {
            Scriptable foo = new FooWithoutSymbols(top);
            ScriptableObject.putProperty(top, "foo", foo);

            try {
                cx.evaluateString(top, "(function(){for(x of foo) { return x; }})();", "<eval>", 0, null);

            } catch (Throwable t) {
                assertEquals(t.getClass(), EcmaError.class);
                assertEquals(t.getMessage(), "TypeError: [object Object] is not iterable");
            }
        } finally {
            Context.exit();
        }
    }

    /**
     * Regression test for a Scriptable implementing SymbolScriptable that
     * doesn't implement the iterable protocol, used in for a for-of loop.
     *
     * Note: no spec is (knowingly) being adhered to with the "expected" in this
     * test, merely the situation as-is being "noted".
     */
    public void testForOfUsingNonIterable() {
        Context cx = Context.enter();
        try {
            Scriptable foo = new FooWithSymbols(top);
            ScriptableObject.putProperty(top, "foo", foo);

            try {
                cx.evaluateString(top, "(function(){for(x of foo) { return x; }})();", "<eval>", 0, null);
            } catch (Throwable t) {
                assertEquals(t.getClass(), EcmaError.class);
                assertEquals(t.getMessage(), "TypeError: [object Object] is not iterable");
            }
        } finally {
            Context.exit();
        }
    }

    /**
     * Test for a host object to be able to supply an iterator, specifically
     * Array.prototype[Symbol.iterator], for a for-of loop.
     */
    public void testForOfUsingArrayIterator() {
        Context cx = Context.enter();
        try {
            Scriptable foo = new FooWithArrayIterator(top);
            ScriptableObject.putProperty(top, "foo", foo);

            assertEquals(
                    true,
                    cx.evaluateString(top, "foo[Symbol.iterator] === Array.prototype[Symbol.iterator]", "<eval>", 0, null)
            );

            assertEquals(
                    123,
                    cx.evaluateString(top, "(function(){for(x of foo) { return x; }})();", "<eval>", 0, null)
            );
        } finally {
            Context.exit();
        }
    }

    //Explicitly not a ScriptableObject
    public static class FooBoilerplate implements Scriptable {

        protected final Scriptable scope;

        public FooBoilerplate(final Scriptable scope) {
            this.scope = scope;
        }

        @Override
        public String getClassName() {
            return this.getClass().getSimpleName();
        }

        @Override
        public Scriptable getParentScope() {
            return scope;
        }

        @Override
        public Object getDefaultValue(Class<?> hint) {
            if (String.class == hint) {
                return "[object Object]";
            }
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Scriptable getPrototype() {
            return TopLevel.getBuiltinPrototype(scope, TopLevel.Builtins.Object);
        }

        @Override
        public Object get(String name, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object get(int index, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public boolean has(String name, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public boolean has(int index, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void put(String name, Scriptable start, Object value) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void put(int index, Scriptable start, Object value) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void delete(String name) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void delete(int index) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void setPrototype(Scriptable prototype) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public void setParentScope(Scriptable parent) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public Object[] getIds() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        @Override
        public boolean hasInstance(Scriptable instance) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

    }

    public static class SymbolFooBoilerplate extends FooBoilerplate implements SymbolScriptable {

        public SymbolFooBoilerplate(final Scriptable scope) {
            super(scope);
        }

        @Override
        public Object get(Symbol key, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public boolean has(Symbol key, Scriptable start) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public void put(Symbol key, Scriptable start, Object value) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public void delete(Symbol key) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

    }
}
{'fraction_non_alphanumeric': 0.08706451402052422, 'fraction_numerical': 0.002614549970586313, 'mean_word_length': 1.981293842556508, 'pattern_counts': {'":': 2, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1213301', 'n_tokens_mistral': 3773, 'n_tokens_neox': 3568, 'n_words': 1083}