text:
package com.github.anba.es6draft.runtime.types.builtins;

import static com.github.anba.es6draft.runtime.AbstractOperations.*;
import static com.github.anba.es6draft.runtime.types.Undefined.UNDEFINED;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.github.anba.es6draft.runtime.ExecutionContext;
import com.github.anba.es6draft.runtime.Realm;
import com.github.anba.es6draft.runtime.internal.IndexedMap;
import com.github.anba.es6draft.runtime.internal.ObjectAllocator;
import com.github.anba.es6draft.runtime.internal.PropertyMap;
import com.github.anba.es6draft.runtime.internal.ScriptException;
import com.github.anba.es6draft.runtime.internal.ScriptIterator;
import com.github.anba.es6draft.runtime.objects.simd.SIMDValue;
import com.github.anba.es6draft.runtime.types.Callable;
import com.github.anba.es6draft.runtime.types.Intrinsics;
import com.github.anba.es6draft.runtime.types.Property;
import com.github.anba.es6draft.runtime.types.PropertyDescriptor;
import com.github.anba.es6draft.runtime.types.ScriptObject;
import com.github.anba.es6draft.runtime.types.Symbol;
import com.github.anba.es6draft.runtime.types.Type;

/**
 *
9 Ordinary and Exotic Objects Behaviours

 *

 *
9.1 Ordinary Object Internal Methods and Internal Slots
 *

 */
public class OrdinaryObject implements ScriptObject {
    private static final int STRING_PROPERTIES_DEFAULT_INITIAL_CAPACITY = 16;
    private static final int SYMBOL_PROPERTIES_DEFAULT_INITIAL_CAPACITY = 4;
    private static final Object[] EMPTY_GETTER_ARGS = new Object[0];

    // Maps for String and Symbol valued property keys
    private final PropertyMap<String, Property> properties;
    private final PropertyMap<Symbol, Property> symbolProperties;
    // Map for indexed properties [0, 2^53 - 1]
    private final IndexedMap<Property> indexedProperties;

    /** [[Realm]] */
    @SuppressWarnings("unused")
    private final Realm realm;

    /** [[Prototype]] */
    private ScriptObject prototype = null;

    /** [[Extensible]] */
    private boolean extensible = true;

    /**
     * Constructs a new Ordinary Object instance.
     *
     * @param realm
     *            the realm object
     */
    public OrdinaryObject(Realm realm) {
        this.realm = realm;
        this.properties = new PropertyMap<>(STRING_PROPERTIES_DEFAULT_INITIAL_CAPACITY);
        this.symbolProperties = new PropertyMap<>(SYMBOL_PROPERTIES_DEFAULT_INITIAL_CAPACITY);
        this.indexedProperties = new IndexedMap<>();
    }

    /**
     * Constructs a new Ordinary Object instance.
     *
     * @param realm
     *            the realm object
     * @param prototype
     *            the prototype object
     */
    private OrdinaryObject(Realm realm, ScriptObject prototype) {
        this(realm);
        this.prototype = prototype;
    }

    @Override
    public String toString() {
        return String.format("%s@%x: indexed=%s, strings=%s, symbols=%s, extensible=%b", getClass().getSimpleName(),
                System.identityHashCode(this), indexedProperties, properties.keySet(), symbolProperties.keySet(),
                extensible);
    }

    /**
     * Returns {@code true} if arguments {@code x} and {@code y} are not the same object reference and:
     *

     *
{@code x} and {@code y} are both NaN values
     *
{@code x} and {@code y} are both equal SIMD values
     *

     *
     * @param x
     *            the first argument
     * @param y
     *            the second argument
     * @return {@code true} if x and y are both NaN values
     */
    private static final boolean SameValueNaNorSIMD(Object x, Object y) {
        if (x == y) {
            return false;
        }
        if (x instanceof Double && y instanceof Double) {
            return Double.isNaN(((Double) x).doubleValue()) && Double.isNaN(((Double) y).doubleValue());
        }
        if (x instanceof SIMDValue && y instanceof SIMDValue) {
            return ((SIMDValue) x).equals(y);
        }
        return false;
    }

    /**
     * Returns the total number of properties.
     *
     * @param withSymbols
     *            {@code true} to include symbol properties
     * @return the number of properties
     */
    final int countProperties(boolean withSymbols) {
        return properties.size() + indexedProperties.size() + (withSymbols ? symbolProperties.size() : 0);
    }

    /**
     * Appends all own string valued properties to the target list.
     *
     * @param list
     *            the target list
     */
    final void appendProperties(List<? super String> list) {
        if (!properties.isEmpty()) {
            list.addAll(properties.keySet());
        }
    }

    /**
     * Appends all own symbol valued properties to the target list.
     *
     * @param list
     *            the target list
     */
    final void appendSymbolProperties(List<? super Symbol> list) {
        if (!symbolProperties.isEmpty()) {
            list.addAll(symbolProperties.keySet());
        }
    }

    /**
     * Appends all own integer indexed properties to the target list.
     *
     * @param list
     *            the target list
     */
    final void appendIndexedProperties(List<? super String> list) {
        if (!indexedProperties.isEmpty()) {
            list.addAll(indexedProperties.keys());
        }
    }

    final void defineOwnPropertyUnchecked(String propertyKey, Property property) {
        // Same as infallibleDefineOwnProperty except extensible check removed.
        assert !IndexedMap.isIndex(IndexedMap.toIndex(propertyKey));
        assert !properties.containsKey(propertyKey) : "illegal property = " + propertyKey;
        properties.put(propertyKey, property);
    }

    public final void infallibleDefineOwnProperty(String propertyKey, Property property) {
        assert extensible : "object not extensible";
        assert !IndexedMap.isIndex(IndexedMap.toIndex(propertyKey));
        assert !properties.containsKey(propertyKey) : "illegal property = " + propertyKey;
        properties.put(propertyKey, property);
    }

    public final void infallibleDefineOwnProperty(Symbol propertyKey, Property property) {
        assert extensible : "object not extensible";
        assert !symbolProperties.containsKey(propertyKey) : "illegal property = " + propertyKey;
        symbolProperties.put(propertyKey, property);
    }

    public final Property lookupOwnProperty(String propertyKey) {
        assert !IndexedMap.isIndex(IndexedMap.toIndex(propertyKey));
        return properties.get(propertyKey);
    }

    public final Property lookupOwnProperty(Symbol propertyKey) {
        return symbolProperties.get(propertyKey);
    }

    public final void infallibleSetPrototype(ScriptObject prototype) {
        this.prototype = prototype;
    }

    /**
     * Returns the indexed properties length.
     *
     * @return the indexed properties length
     */
    long getIndexedLength() {
        return indexedProperties.getLength();
    }

    /**
     * Returns the own property value from the given index.
     *
     * @param propertyKey
     *            the indexed property key
     * @return the property value
     */
    Object getIndexed(long propertyKey) {
        return indexedProperties.get(propertyKey).getValue();
    }

    /**
     * Set the own property value at the given index to the new value.
     *
     * @param propertyKey
     *            the indexed property key
     * @param value
     *            the property value
     */
    final void setIndexed(long propertyKey, Object value) {
        indexedProperties.put(propertyKey, new Property(value, true, true, true));
    }

    /**
     * Deletes all indexed properties within the range {@code [startIndex, endIndex)} in reverse order, i.e. starting
     * from index {@code endIndex - 1}. The range must not be empty.
     *
     * @param startIndex
     *            the start index (inclusive)
     * @param endIndex
     *            the end index (exclusive)
     * @return {@code -1} if all indexed properties over the requested range have been removed successfully; otherwise
     *         the index of the first property which is not deletable.
     */
    final long deleteRange(long startIndex, long endIndex) {
        assert startIndex < endIndex;
        IndexedMap<Property> indexed = indexedProperties;
        if (indexed.isEmpty()) {
            return -1;
        }
        long lastIndex;
        if (indexed.isSparse()) {
            lastIndex = deleteRangeSparse(startIndex, endIndex);
        } else {
            lastIndex = deleteRangeDense(startIndex, endIndex);
        }
        // Need to call updateLength() manually.
        indexed.updateLength();
        return lastIndex;
    }

    private long deleteRangeDense(long startIndex, long endIndex) {
        IndexedMap<Property> indexed = indexedProperties;
        for (long index = endIndex; startIndex < index;) {
            Property prop = indexed.get(--index);
            if (prop != null && !prop.isConfigurable()) {
                return index;
            }
            indexed.removeUnchecked(index);
        }
        return -1;
    }

    private long deleteRangeSparse(long startIndex, long endIndex) {
        Iterator<Map.Entry<Long, Property>> iter = indexedProperties.descendingIterator(startIndex, endIndex);
        while (iter.hasNext()) {
            Map.Entry<Long, Property> entry = iter.next();
            if (!entry.getValue().isConfigurable()) {
                return entry.getKey();
            }
            // Cannot call remove[Unchecked]() directly b/c of ConcurrentModificationException.
            iter.remove();
        }
        return -1;
    }

    /**
     * Returns the list of integer indexed properties.
     *
     * @return the list of integer indexed properties
     */
    public final long[] indices() {
        return indexedProperties.indices();
    }

    /**
     * Returns the list of integer indexed properties.
     *
     * @param from
     *            from index (inclusive)
     * @param to
     *            to index (exclusive)
     * @return the list of integer indexed properties
     */
    public final long[] indices(long from, long to) {
        return indexedProperties.indices(from, to);
    }

    /**
     * Returns {@code true} if this object has indexed properties.
     *
     * @return {@code true} if this object has indexed properties
     */
    public final boolean hasIndexedProperties() {
        return !indexedProperties.isEmpty();
    }

    /**
     * Returns {@code true} if the object has indexed accessors.
     *
     * @return {@code true} if the object has indexed accessors
     */
    public boolean hasIndexedAccessors() {
        if (indexedProperties.isEmpty()) {
            return false;
        }
        for (Iterator<Property> iter = indexedProperties.valuesIterator(); iter.hasNext();) {
            if (iter.next().isAccessorDescriptor()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns the object's length.
     *
     * @return the length or {@code -1} if not available
     */
    public long getLength() {
        Property length = ordinaryGetOwnProperty("length");
        if (length == null || !length.isDataDescriptor() || !Type.isNumber(length.getValue())) {
            return -1;
        }
        return ToLength(Type.numberValue(length.getValue()));
    }

    /**
     * Returns the number of indexed properties.
     *
     * @return the number of indexed properties
     */
    public int getIndexedSize() {
        return indexedProperties.size();
    }

    /**
     * Returns {@code true} if the array is dense and has no indexed accessors.
     *
     * @return {@code true} if the array is dense
     */
    public final boolean isDenseArray() {
        return isDenseArray(getLength());
    }

    /**
     * Returns {@code true} if the array is dense and has no indexed accessors.
     *
     * @param length
     *            the array length
     * @return {@code true} if the array is dense
     */
    public final boolean isDenseArray(long length) {
        assert !hasSpecialIndexedProperties() : "cannot report dense if special indexed present";
        IndexedMap<Property> ix = indexedProperties;
        return !hasIndexedAccessors() && ix.getLength() == length && !ix.isSparse() && !ix.hasHoles();
    }

    /**
     * Returns {@code true} if this object has "special" indexed properties.
     *
     * @return {@code true} if this object has special indexed properties
     */
    public boolean hasSpecialIndexedProperties() {
        return false;
    }

    /**
     * Returns the array's indexed property values. Only applicable for dense arrays.
     *
     * @return the array's indexed values
     */
    public final Object[] toArray() {
        return toArray(getLength());
    }

    /**
     * Returns the array's indexed property values. Only applicable for dense arrays.
     *
     * @param length
     *            the array length
     * @return the array's indexed values
     */
    public final Object[] toArray(long length) {
        assert isDenseArray(length);
        assert 0 <= length && length <= Integer.MAX_VALUE : "length=" + length;
        int len = (int) length;
        Object[] values = new Object[len];
        for (int i = 0; i < len; ++i) {
            values[i] = getIndexed(i);
        }
        return values;
    }

    /**
     * [[Prototype]]
     *
     * @return the prototype object
     */
    public final ScriptObject getPrototype() {
        return prototype;
    }

    /**
     * [[Prototype]]
     *
     * @param prototype
     *            the new prototype object
     */
    protected final void setPrototype(ScriptObject prototype) {
        this.prototype = prototype;
    }

    /**
     * [[Extensible]]
     *
     * @return {@code true} if this object is extensible
     */
    protected final boolean isExtensible() {
        return extensible;
    }

    /**
     * [[Extensible]]
     *
     * @param extensible
     *            the new extensible mode
     */
    protected final void setExtensible(boolean extensible) {
        assert this.extensible || !extensible;
        this.extensible = extensible;
    }

    /**
     * [[HasOwnProperty]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if an own property was found
     */
    protected boolean hasOwnProperty(ExecutionContext cx, long propertyKey) {
        return ordinaryHasOwnProperty(propertyKey);
    }

    /**
     * [[HasOwnProperty]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if an own property was found
     */
    protected boolean hasOwnProperty(ExecutionContext cx, String propertyKey) {
        return ordinaryHasOwnProperty(propertyKey);
    }

    /**
     * [[HasOwnProperty]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if an own property was found
     */
    protected boolean hasOwnProperty(ExecutionContext cx, Symbol propertyKey) {
        return ordinaryHasOwnProperty(propertyKey);
    }

    /**
     * OrdinaryHasOwnProperty (P) (not in spec)
     *
     * @param propertyKey
     *            the property key
     * @return {@code true} if an own property was found
     */
    protected final boolean ordinaryHasOwnProperty(long propertyKey) {
        // optimized: HasOwnProperty(cx, this, propertyKey)
        return indexedProperties.containsKey(propertyKey);
    }

    /**
     * OrdinaryHasOwnProperty (P) (not in spec)
     *
     * @param propertyKey
     *            the property key
     * @return {@code true} if an own property was found
     */
    protected final boolean ordinaryHasOwnProperty(String propertyKey) {
        // optimized: HasOwnProperty(cx, this, propertyKey)
        return properties.containsKey(propertyKey);
    }

    /**
     * OrdinaryHasOwnProperty (P) (not in spec)
     *
     * @param propertyKey
     *            the property key
     * @return {@code true} if an own property was found
     */
    protected final boolean ordinaryHasOwnProperty(Symbol propertyKey) {
        // optimized: HasOwnProperty(cx, this, propertyKey)
        return symbolProperties.containsKey(propertyKey);
    }

    /** 9.1.1 [[GetPrototypeOf]] ( ) */
    @Override
    public ScriptObject getPrototypeOf(ExecutionContext cx) {
        /* step 1 */
        return prototype;
    }

    /** 9.1.2 [[SetPrototypeOf]] (V) */
    @Override
    public boolean setPrototypeOf(ExecutionContext cx, ScriptObject prototype) {
        /* steps 1-3 */
        boolean extensible = this.extensible;
        ScriptObject current = this.prototype;
        /* step 4 */
        if (prototype == current) { // SameValue(prototype, current)
            return true;
        }
        /* step 5 */
        if (!extensible) {
            return false;
        }
        /* steps 6-8 */
        for (ScriptObject p = prototype; p != null;) {
            if (p == this) { // SameValue(p, O)
                return false;
            }
            if (!(p instanceof OrdinaryObject)) {
                break;
            }
            p = ((OrdinaryObject) p).prototype;
        }
        /* step 9 */
        this.prototype = prototype;
        /* step 10 */
        return true;
    }

    /** 9.1.3 [[IsExtensible]] ( ) */
    @Override
    public boolean isExtensible(ExecutionContext cx) {
        /* step 1 */
        return extensible;
    }

    /** 9.1.4 [[PreventExtensions]] ( ) */
    @Override
    public boolean preventExtensions(ExecutionContext cx) {
        /* step 1 */
        this.extensible = false;
        /* step 2 */
        return true;
    }

    /** 9.1.5 [[GetOwnProperty]] (P) */
    @Override
    public final Property getOwnProperty(ExecutionContext cx, long propertyKey) {
        if (IndexedMap.isIndex(propertyKey)) {
            return getProperty(cx, propertyKey);
        }
        return getProperty(cx, ToString(propertyKey));
    }

    /** 9.1.5 [[GetOwnProperty]] (P) */
    @Override
    public final Property getOwnProperty(ExecutionContext cx, String propertyKey) {
        long index = IndexedMap.toIndex(propertyKey);
        if (IndexedMap.isIndex(index)) {
            return getProperty(cx, index);
        }
        return getProperty(cx, propertyKey);
    }

    /** 9.1.5 [[GetOwnProperty]] (P) */
    @Override
    public final Property getOwnProperty(ExecutionContext cx, Symbol propertyKey) {
        /* step 1 */
        return getProperty(cx, propertyKey);
    }

    /**
     * 9.1.5 [[GetOwnProperty]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return the property or {@code null} if none found
     */
    protected Property getProperty(ExecutionContext cx, long propertyKey) {
        return ordinaryGetOwnProperty(propertyKey);
    }

    /**
     * 9.1.5 [[GetOwnProperty]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return the property or {@code null} if none found
     */
    protected Property getProperty(ExecutionContext cx, String propertyKey) {
        return ordinaryGetOwnProperty(propertyKey);
    }

    /**
     * 9.1.5 [[GetOwnProperty]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return the property or {@code null} if none found
     */
    protected Property getProperty(ExecutionContext cx, Symbol propertyKey) {
        return ordinaryGetOwnProperty(propertyKey);
    }

    /**
     * 9.1.5.1 OrdinaryGetOwnProperty (O, P)
     *
     * @param propertyKey
     *            the property key
     * @return the property record or {@code null} if none found
     */
    protected final Property ordinaryGetOwnProperty(long propertyKey) {
        /* steps 1-9 (altered: returns live view) */
        return indexedProperties.get(propertyKey);
    }

    /**
     * 9.1.5.1 OrdinaryGetOwnProperty (O, P)
     *
     * @param propertyKey
     *            the property key
     * @return the property record or {@code null} if none found
     */
    protected final Property ordinaryGetOwnProperty(String propertyKey) {
        /* steps 1-9 (altered: returns live view) */
        return properties.get(propertyKey);
    }

    /**
     * 9.1.5.1 OrdinaryGetOwnProperty (O, P)
     *
     * @param propertyKey
     *            the property key
     * @return the property record or {@code null} if none found
     */
    protected final Property ordinaryGetOwnProperty(Symbol propertyKey) {
        /* steps 1-9 (altered: returns live view) */
        return symbolProperties.get(propertyKey);
    }

    /** 9.1.6 [[DefineOwnProperty]] (P, Desc) */
    @Override
    public final boolean defineOwnProperty(ExecutionContext cx, long propertyKey, PropertyDescriptor desc) {
        if (IndexedMap.isIndex(propertyKey)) {
            return defineProperty(cx, propertyKey, desc);
        }
        return defineProperty(cx, ToString(propertyKey), desc);
    }

    /** 9.1.6 [[DefineOwnProperty]] (P, Desc) */
    @Override
    public final boolean defineOwnProperty(ExecutionContext cx, String propertyKey, PropertyDescriptor desc) {
        long index = IndexedMap.toIndex(propertyKey);
        if (IndexedMap.isIndex(index)) {
            return defineProperty(cx, index, desc);
        }
        return defineProperty(cx, propertyKey, desc);
    }

    /** 9.1.6 [[DefineOwnProperty]] (P, Desc) */
    @Override
    public final boolean defineOwnProperty(ExecutionContext cx, Symbol propertyKey, PropertyDescriptor desc) {
        return defineProperty(cx, propertyKey, desc);
    }

    /**
     * 9.1.6 [[DefineOwnProperty]] (P, Desc)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param desc
     *            the property descriptor
     * @return {@code true} if the property was successfully defined
     */
    protected boolean defineProperty(ExecutionContext cx, long propertyKey, PropertyDescriptor desc) {
        return ordinaryDefineOwnProperty(cx, propertyKey, desc);
    }

    /**
     * 9.1.6 [[DefineOwnProperty]] (P, Desc)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param desc
     *            the property descriptor
     * @return {@code true} if the property was successfully defined
     */
    protected boolean defineProperty(ExecutionContext cx, String propertyKey, PropertyDescriptor desc) {
        return ordinaryDefineOwnProperty(cx, propertyKey, desc);
    }

    /**
     * 9.1.6 [[DefineOwnProperty]] (P, Desc)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param desc
     *            the property descriptor
     * @return {@code true} if the property was successfully defined
     */
    protected boolean defineProperty(ExecutionContext cx, Symbol propertyKey, PropertyDescriptor desc) {
        return ordinaryDefineOwnProperty(cx, propertyKey, desc);
    }

    /**
     * 9.1.6.1 OrdinaryDefineOwnProperty (O, P, Desc)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param desc
     *            the property descriptor
     * @return {@code true} on success
     */
    protected final boolean ordinaryDefineOwnProperty(ExecutionContext cx, long propertyKey, PropertyDescriptor desc) {
        /* steps 1-2 */
        Property current = getProperty(cx, propertyKey);
        /* step 3 */
        boolean extensible = isExtensible();
        /* step 4 */
        return validateAndApplyPropertyDescriptor(indexedProperties, propertyKey, extensible, desc, current);
    }

    /**
     * 9.1.6.1 OrdinaryDefineOwnProperty (O, P, Desc)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param desc
     *            the property descriptor
     * @return {@code true} on success
     */
    protected final boolean ordinaryDefineOwnProperty(ExecutionContext cx, String propertyKey,
            PropertyDescriptor desc) {
        /* steps 1-2 */
        Property current = getProperty(cx, propertyKey);
        /* step 3 */
        boolean extensible = isExtensible();
        /* step 4 */
        return validateAndApplyPropertyDescriptor(properties, propertyKey, extensible, desc, current);
    }

    /**
     * 9.1.6.1 OrdinaryDefineOwnProperty (O, P, Desc)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param desc
     *            the property descriptor
     * @return {@code true} on success
     */
    protected final boolean ordinaryDefineOwnProperty(ExecutionContext cx, Symbol propertyKey,
            PropertyDescriptor desc) {
        /* steps 1-2 */
        Property current = getProperty(cx, propertyKey);
        /* step 3 */
        boolean extensible = isExtensible();
        /* step 4 */
        return validateAndApplyPropertyDescriptor(symbolProperties, propertyKey, extensible, desc, current);
    }

    /**
     * 9.1.6.2 IsCompatiblePropertyDescriptor (Extensible, Desc, Current)
     *
     * @param extensible
     *            the extensible mode
     * @param desc
     *            the property descriptor
     * @param current
     *            the current property
     * @return {@code true} if <var>desc</var> is compatible
     */
    protected static final boolean IsCompatiblePropertyDescriptor(boolean extensible, PropertyDescriptor desc,
            Property current) {
        /* step 1 */
        return validateAndApplyPropertyDescriptor(null, null, extensible, desc, current);
    }

    /**
     * 9.1.6.3 ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current)
     *
     * @param object
     *            the script object
     * @param propertyKey
     *            the property key
     * @param extensible
     *            the extensible mode
     * @param desc
     *            the property descriptor
     * @param current
     *            the current property
     * @return {@code true} on success
     */
    protected static final boolean ValidateAndApplyPropertyDescriptor(OrdinaryObject object, long propertyKey,
            boolean extensible, PropertyDescriptor desc, Property current) {
        return validateAndApplyPropertyDescriptor(object.indexedProperties, propertyKey, extensible, desc, current);
    }

    /**
     * 9.1.6.3 ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current)
     *
     * @param object
     *            the script object
     * @param propertyKey
     *            the property key
     * @param extensible
     *            the extensible mode
     * @param desc
     *            the property descriptor
     * @param current
     *            the current property
     * @return {@code true} on success
     */
    protected static final boolean ValidateAndApplyPropertyDescriptor(OrdinaryObject object, String propertyKey,
            boolean extensible, PropertyDescriptor desc, Property current) {
        return validateAndApplyPropertyDescriptor(object.properties, propertyKey, extensible, desc, current);
    }

    /**
     * 9.1.6.3 ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current)
     *
     * @param object
     *            the script object
     * @param propertyKey
     *            the property key
     * @param extensible
     *            the extensible mode
     * @param desc
     *            the property descriptor
     * @param current
     *            the current property
     * @return {@code true} on success
     */
    protected static final boolean ValidateAndApplyPropertyDescriptor(OrdinaryObject object, Symbol propertyKey,
            boolean extensible, PropertyDescriptor desc, Property current) {
        return validateAndApplyPropertyDescriptor(object.symbolProperties, propertyKey, extensible, desc, current);
    }

    /**
     * 9.1.6.3 ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current)
     *
     * @param object
     *            the script object
     * @param propertyKey
     *            the property key
     * @param extensible
     *            the extensible mode
     * @param desc
     *            the property descriptor
     * @param current
     *            the current property
     * @return {@code true} on success
     */
    private static final <KEY> boolean validateAndApplyPropertyDescriptor(PropertyMap<KEY, Property> object,
            KEY propertyKey, boolean extensible, PropertyDescriptor desc, Property current) {
        /* step 1 */
        assert (object == null || propertyKey != null);
        /* step 2 */
        if (current == null) {
            if (!extensible) {
                return false;
            }
            if (object != null) {
                object.put(propertyKey, desc.toProperty());
            }
            return true;
        }
        /* step 3 */
        if (desc.isEmpty()) {
            return true;
        }
        /* step 4 */
        if (current.isSubset(desc)) {
            return true;
        }
        /* step 5 */
        if (!current.isConfigurable()) {
            if (desc.isConfigurable()) {
                return false;
            }
            if (desc.hasEnumerable() && desc.isEnumerable() != current.isEnumerable()) {
                return false;
            }
        }
        if (desc.isGenericDescriptor()) {
            /* step 6 */
            // no further validation required, proceed below...
        } else if (desc.isDataDescriptor() != current.isDataDescriptor()) {
            /* step 7 */
            if (!current.isConfigurable()) {
                return false;
            }
            if (current.isDataDescriptor()) {
                if (object != null) {
                    object.get(propertyKey).toAccessorProperty();
                }
            } else {
                if (object != null) {
                    object.get(propertyKey).toDataProperty();
                }
            }
        } else if (desc.isDataDescriptor()) {
            /* step 8 */
            assert current.isDataDescriptor();
            if (!current.isConfigurable() && !current.isWritable()) {
                if (desc.isWritable()) {
                    return false;
                }
                if (desc.hasValue() && !SameValue(desc.getValue(), current.getValue())) {
                    return false;
                }
            }
        } else {
            /* step 9 */
            assert desc.isAccessorDescriptor() && current.isAccessorDescriptor();
            if (!current.isConfigurable()) {
                if (desc.hasSetter() && desc.getSetter() != current.getSetter()) {
                    return false;
                }
                if (desc.hasGetter() && desc.getGetter() != current.getGetter()) {
                    return false;
                }
            }
        }
        /* step 10 */
        if (object != null) {
            object.get(propertyKey).apply(desc);
        }
        /* step 11 */
        return true;
    }

    /**
     * 9.1.6.3 ValidateAndApplyPropertyDescriptor (O, P, extensible, Desc, current)
     *
     * @param object
     *            the script object
     * @param propertyKey
     *            the property key
     * @param extensible
     *            the extensible mode
     * @param desc
     *            the property descriptor
     * @param current
     *            the current property
     * @return {@code true} on success
     */
    private static final boolean validateAndApplyPropertyDescriptor(IndexedMap<Property> object, long propertyKey,
            boolean extensible, PropertyDescriptor desc, Property current) {
        /* step 1 */
        assert (object == null || IndexedMap.isIndex(propertyKey));
        /* step 2 */
        if (current == null) {
            if (!extensible) {
                return false;
            }
            if (object != null) {
                object.put(propertyKey, desc.toProperty());
            }
            return true;
        }
        /* step 3 */
        if (desc.isEmpty()) {
            return true;
        }
        /* step 4 */
        if (current.isSubset(desc)) {
            return true;
        }
        /* step 5 */
        if (!current.isConfigurable()) {
            if (desc.isConfigurable()) {
                return false;
            }
            if (desc.hasEnumerable() && desc.isEnumerable() != current.isEnumerable()) {
                return false;
            }
        }
        if (desc.isGenericDescriptor()) {
            /* step 6 */
            // no further validation required, proceed below...
        } else if (desc.isDataDescriptor() != current.isDataDescriptor()) {
            /* step 7 */
            if (!current.isConfigurable()) {
                return false;
            }
            if (current.isDataDescriptor()) {
                if (object != null) {
                    object.get(propertyKey).toAccessorProperty();
                }
            } else {
                if (object != null) {
                    object.get(propertyKey).toDataProperty();
                }
            }
        } else if (desc.isDataDescriptor()) {
            /* step 8 */
            assert current.isDataDescriptor();
            if (!current.isConfigurable() && !current.isWritable()) {
                if (desc.isWritable()) {
                    return false;
                }
                if (desc.hasValue() && !SameValue(desc.getValue(), current.getValue())) {
                    return false;
                }
            }
        } else {
            /* step 9 */
            assert desc.isAccessorDescriptor() && current.isAccessorDescriptor();
            if (!current.isConfigurable()) {
                if (desc.hasSetter() && desc.getSetter() != current.getSetter()) {
                    return false;
                }
                if (desc.hasGetter() && desc.getGetter() != current.getGetter()) {
                    return false;
                }
            }
        }
        /* step 10 */
        if (object != null) {
            object.get(propertyKey).apply(desc);
        }
        /* step 11 */
        return true;
    }

    /**
     * 9.1.7 [[HasProperty]](P)
     */
    @Override
    public final boolean hasProperty(ExecutionContext cx, long propertyKey) {
        if (IndexedMap.isIndex(propertyKey)) {
            return has(cx, propertyKey);
        }
        return has(cx, ToString(propertyKey));
    }

    /**
     * 9.1.7 [[HasProperty]](P)
     */
    @Override
    public final boolean hasProperty(ExecutionContext cx, String propertyKey) {
        long index = IndexedMap.toIndex(propertyKey);
        if (IndexedMap.isIndex(index)) {
            return has(cx, index);
        }
        return has(cx, propertyKey);
    }

    /**
     * 9.1.7 [[HasProperty]](P)
     */
    @Override
    public final boolean hasProperty(ExecutionContext cx, Symbol propertyKey) {
        return has(cx, propertyKey);
    }

    /**
     * 9.1.7 [[HasProperty]](P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was found
     */
    protected boolean has(ExecutionContext cx, long propertyKey) {
        return ordinaryHasProperty(cx, propertyKey);
    }

    /**
     * 9.1.7 [[HasProperty]](P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was found
     */
    protected boolean has(ExecutionContext cx, String propertyKey) {
        return ordinaryHasProperty(cx, propertyKey);
    }

    /**
     * 9.1.7 [[HasProperty]](P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was found
     */
    protected boolean has(ExecutionContext cx, Symbol propertyKey) {
        return ordinaryHasProperty(cx, propertyKey);
    }

    /**
     * 9.1.7.1 OrdinaryHasProperty (O, P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was found
     */
    protected final boolean ordinaryHasProperty(ExecutionContext cx, long propertyKey) {
        /* step 1 (implicit) */
        /* step 2 */
        boolean hasOwn = ordinaryHasOwnProperty(propertyKey);
        /* step 3 */
        if (hasOwn) {
            return true;
        }
        /* steps 4-5 */
        ScriptObject parent = getPrototypeOf(cx);
        /* step 6 */
        if (parent != null) {
            return parent.hasProperty(cx, propertyKey);
        }
        /* step 7 */
        return false;
    }

    /**
     * 9.1.7.1 OrdinaryHasProperty (O, P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was found
     */
    protected final boolean ordinaryHasProperty(ExecutionContext cx, String propertyKey) {
        /* step 1 (implicit) */
        /* step 2 */
        boolean hasOwn = ordinaryHasOwnProperty(propertyKey);
        /* step 3 */
        if (hasOwn) {
            return true;
        }
        /* steps 4-5 */
        ScriptObject parent = getPrototypeOf(cx);
        /* step 6 */
        if (parent != null) {
            return parent.hasProperty(cx, propertyKey);
        }
        /* step 7 */
        return false;
    }

    /**
     * 9.1.7.1 OrdinaryHasProperty (O, P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was found
     */
    protected final boolean ordinaryHasProperty(ExecutionContext cx, Symbol propertyKey) {
        /* step 1 (implicit) */
        /* step 2 */
        boolean hasOwn = ordinaryHasOwnProperty(propertyKey);
        /* step 3 */
        if (hasOwn) {
            return true;
        }
        /* steps 4-5 */
        ScriptObject parent = getPrototypeOf(cx);
        /* step 6 */
        if (parent != null) {
            return parent.hasProperty(cx, propertyKey);
        }
        /* step 7 */
        return false;
    }

    /** 9.1.8 [[Get]] (P, Receiver) */
    @Override
    public final Object get(ExecutionContext cx, long propertyKey, Object receiver) {
        if (IndexedMap.isIndex(propertyKey)) {
            return getValue(cx, propertyKey, receiver);
        }
        return getValue(cx, ToString(propertyKey), receiver);
    }

    /** 9.1.8 [[Get]] (P, Receiver) */
    @Override
    public final Object get(ExecutionContext cx, String propertyKey, Object receiver) {
        long index = IndexedMap.toIndex(propertyKey);
        if (IndexedMap.isIndex(index)) {
            return getValue(cx, index, receiver);
        }
        return getValue(cx, propertyKey, receiver);
    }

    /** 9.1.8 [[Get]] (P, Receiver) */
    @Override
    public final Object get(ExecutionContext cx, Symbol propertyKey, Object receiver) {
        return getValue(cx, propertyKey, receiver);
    }

    /**
     * 9.1.8 [[Get]] (P, Receiver)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param receiver
     *            the receiver object
     * @return the property value
     */
    protected Object getValue(ExecutionContext cx, long propertyKey, Object receiver) {
        /* step 1 (implicit) */
        /* steps 2-3 */
        Property desc = getProperty(cx, propertyKey);
        /* step 4 */
        if (desc == null) {
            ScriptObject parent = getPrototypeOf(cx);
            if (parent == null) {
                return UNDEFINED;
            }
            return parent.get(cx, propertyKey, receiver);
        }
        /* step 5 */
        if (desc.isDataDescriptor()) {
            return desc.getValue();
        }
        assert desc.isAccessorDescriptor();
        /* step 6 */
        Callable getter = desc.getGetter();
        /* step 7 */
        if (getter == null) {
            return UNDEFINED;
        }
        /* step 8 */
        return getter.call(cx, receiver, EMPTY_GETTER_ARGS);
    }

    /**
     * 9.1.8 [[Get]] (P, Receiver)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param receiver
     *            the receiver object
     * @return the property value
     */
    protected Object getValue(ExecutionContext cx, String propertyKey, Object receiver) {
        /* step 1 (implicit) */
        /* steps 2-3 */
        Property desc = getProperty(cx, propertyKey);
        /* step 4 */
        if (desc == null) {
            ScriptObject parent = getPrototypeOf(cx);
            if (parent == null) {
                return UNDEFINED;
            }
            return parent.get(cx, propertyKey, receiver);
        }
        /* step 5 */
        if (desc.isDataDescriptor()) {
            return desc.getValue();
        }
        assert desc.isAccessorDescriptor();
        /* step 6 */
        Callable getter = desc.getGetter();
        /* step 7 */
        if (getter == null) {
            return UNDEFINED;
        }
        /* step 8 */
        return getter.call(cx, receiver, EMPTY_GETTER_ARGS);
    }

    /**
     * 9.1.8 [[Get]] (P, Receiver)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param receiver
     *            the receiver object
     * @return the property value
     */
    protected Object getValue(ExecutionContext cx, Symbol propertyKey, Object receiver) {
        /* step 1 (implicit) */
        /* steps 2-3 */
        Property desc = getProperty(cx, propertyKey);
        /* step 4 */
        if (desc == null) {
            ScriptObject parent = getPrototypeOf(cx);
            if (parent == null) {
                return UNDEFINED;
            }
            return parent.get(cx, propertyKey, receiver);
        }
        /* step 5 */
        if (desc.isDataDescriptor()) {
            return desc.getValue();
        }
        assert desc.isAccessorDescriptor();
        /* step 6 */
        Callable getter = desc.getGetter();
        /* step 7 */
        if (getter == null) {
            return UNDEFINED;
        }
        /* step 8 */
        return getter.call(cx, receiver, EMPTY_GETTER_ARGS);
    }

    /** 9.1.9 [[Set] (P, V, Receiver) */
    @Override
    public final boolean set(ExecutionContext cx, long propertyKey, Object value, Object receiver) {
        if (IndexedMap.isIndex(propertyKey)) {
            return setValue(cx, propertyKey, value, receiver);
        }
        return setValue(cx, ToString(propertyKey), value, receiver);
    }

    /** 9.1.9 [[Set] (P, V, Receiver) */
    @Override
    public final boolean set(ExecutionContext cx, String propertyKey, Object value, Object receiver) {
        long index = IndexedMap.toIndex(propertyKey);
        if (IndexedMap.isIndex(index)) {
            return setValue(cx, index, value, receiver);
        }
        return setValue(cx, propertyKey, value, receiver);
    }

    /** 9.1.9 [[Set] (P, V, Receiver) */
    @Override
    public final boolean set(ExecutionContext cx, Symbol propertyKey, Object value, Object receiver) {
        return setValue(cx, propertyKey, value, receiver);
    }

    /**
     * 9.1.9 [[Set] (P, V, Receiver)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param value
     *            the new property value
     * @param receiver
     *            the receiver object
     * @return {@code true} on success
     */
    protected boolean setValue(ExecutionContext cx, long propertyKey, Object value, Object receiver) {
        /* step 1 (implicit) */
        /* steps 2-3 */
        Property ownDesc = getProperty(cx, propertyKey);
        /* step 4 */
        if (ownDesc == null) {
            ScriptObject parent = getPrototypeOf(cx);
            if (parent != null) {
                return parent.set(cx, propertyKey, value, receiver);
            } else {
                ownDesc = new Property(UNDEFINED, true, true, true);
            }
        } else if (receiver == this && ownDesc.isWritable()) {
            // Optimize the common case for own, writable properties
            return setPropertyValue(cx, propertyKey, value, ownDesc);
        }
        /* step 5 */
        if (ownDesc.isDataDescriptor()) {
            if (!ownDesc.isWritable()) {
                return false;
            }
            if (!Type.isObject(receiver)) {
                return false;
            }
            ScriptObject _receiver = Type.objectValue(receiver);
            Property existingDescriptor = _receiver.getOwnProperty(cx, propertyKey);
            if (existingDescriptor != null) {
                if (existingDescriptor.isAccessorDescriptor() || !existingDescriptor.isWritable()) {
                    return false;
                }
                PropertyDescriptor valueDesc = new PropertyDescriptor(value);
                return _receiver.defineOwnProperty(cx, propertyKey, valueDesc);
            } else {
                return CreateDataProperty(cx, _receiver, propertyKey, value);
            }
        }
        /* step 6 */
        assert ownDesc.isAccessorDescriptor();
        Callable setter = ownDesc.getSetter();
        if (setter == null) {
            return false;
        }
        setter.call(cx, receiver, value);
        return true;
    }

    protected boolean setPropertyValue(ExecutionContext cx, long propertyKey, Object value, Property current) {
        assert current.isDataDescriptor() && current.isWritable();
        if (!SameValueNaNorSIMD(current.getValue(), value)) {
            current.setValue(value);
        }
        return true;
    }

    /**
     * 9.1.9 [[Set] (P, V, Receiver)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param value
     *            the new property value
     * @param receiver
     *            the receiver object
     * @return {@code true} on success
     */
    protected boolean setValue(ExecutionContext cx, String propertyKey, Object value, Object receiver) {
        /* step 1 (implicit) */
        /* steps 2-3 */
        Property ownDesc = getProperty(cx, propertyKey);
        /* step 4 */
        if (ownDesc == null) {
            ScriptObject parent = getPrototypeOf(cx);
            if (parent != null) {
                return parent.set(cx, propertyKey, value, receiver);
            } else {
                ownDesc = new Property(UNDEFINED, true, true, true);
            }
        } else if (receiver == this && ownDesc.isWritable()) {
            // Optimize the common case for own, writable properties
            return setPropertyValue(cx, propertyKey, value, ownDesc);
        }
        /* step 5 */
        if (ownDesc.isDataDescriptor()) {
            if (!ownDesc.isWritable()) {
                return false;
            }
            if (!Type.isObject(receiver)) {
                return false;
            }
            ScriptObject _receiver = Type.objectValue(receiver);
            Property existingDescriptor = _receiver.getOwnProperty(cx, propertyKey);
            if (existingDescriptor != null) {
                if (existingDescriptor.isAccessorDescriptor() || !existingDescriptor.isWritable()) {
                    return false;
                }
                PropertyDescriptor valueDesc = new PropertyDescriptor(value);
                return _receiver.defineOwnProperty(cx, propertyKey, valueDesc);
            } else {
                return CreateDataProperty(cx, _receiver, propertyKey, value);
            }
        }
        /* step 6 */
        assert ownDesc.isAccessorDescriptor();
        Callable setter = ownDesc.getSetter();
        if (setter == null) {
            return false;
        }
        setter.call(cx, receiver, value);
        return true;
    }

    protected boolean setPropertyValue(ExecutionContext cx, String propertyKey, Object value, Property current) {
        assert current.isDataDescriptor() && current.isWritable();
        if (!SameValueNaNorSIMD(current.getValue(), value)) {
            current.setValue(value);
        }
        return true;
    }

    /**
     * 9.1.9 [[Set] (P, V, Receiver)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @param value
     *            the new property value
     * @param receiver
     *            the receiver object
     * @return {@code true} on success
     */
    protected boolean setValue(ExecutionContext cx, Symbol propertyKey, Object value, Object receiver) {
        /* step 1 (implicit) */
        /* steps 2-3 */
        Property ownDesc = getProperty(cx, propertyKey);
        /* step 4 */
        if (ownDesc == null) {
            ScriptObject parent = getPrototypeOf(cx);
            if (parent != null) {
                return parent.set(cx, propertyKey, value, receiver);
            } else {
                ownDesc = new Property(UNDEFINED, true, true, true);
            }
        } else if (receiver == this && ownDesc.isWritable()) {
            // Optimize the common case for own, writable properties
            return setPropertyValue(cx, propertyKey, value, ownDesc);
        }
        /* step 5 */
        if (ownDesc.isDataDescriptor()) {
            if (!ownDesc.isWritable()) {
                return false;
            }
            if (!Type.isObject(receiver)) {
                return false;
            }
            ScriptObject _receiver = Type.objectValue(receiver);
            Property existingDescriptor = _receiver.getOwnProperty(cx, propertyKey);
            if (existingDescriptor != null) {
                if (existingDescriptor.isAccessorDescriptor() || !existingDescriptor.isWritable()) {
                    return false;
                }
                PropertyDescriptor valueDesc = new PropertyDescriptor(value);
                return _receiver.defineOwnProperty(cx, propertyKey, valueDesc);
            } else {
                return CreateDataProperty(cx, _receiver, propertyKey, value);
            }
        }
        /* step 6 */
        assert ownDesc.isAccessorDescriptor();
        Callable setter = ownDesc.getSetter();
        if (setter == null) {
            return false;
        }
        setter.call(cx, receiver, value);
        return true;
    }

    protected boolean setPropertyValue(ExecutionContext cx, Symbol propertyKey, Object value, Property current) {
        assert current.isDataDescriptor() && current.isWritable();
        if (!SameValueNaNorSIMD(current.getValue(), value)) {
            current.setValue(value);
        }
        return true;
    }

    /** 9.1.10 [[Delete]] (P) */
    @Override
    public final boolean delete(ExecutionContext cx, long propertyKey) {
        if (IndexedMap.isIndex(propertyKey)) {
            return deleteProperty(cx, propertyKey);
        }
        return deleteProperty(cx, ToString(propertyKey));
    }

    /** 9.1.10 [[Delete]] (P) */
    @Override
    public final boolean delete(ExecutionContext cx, String propertyKey) {
        long index = IndexedMap.toIndex(propertyKey);
        if (IndexedMap.isIndex(index)) {
            return deleteProperty(cx, index);
        }
        return deleteProperty(cx, propertyKey);
    }

    /** 9.1.10 [[Delete]] (P) */
    @Override
    public final boolean delete(ExecutionContext cx, Symbol propertyKey) {
        return deleteProperty(cx, propertyKey);
    }

    /**
     * 9.1.10 [[Delete]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was successfully deleted
     */
    protected boolean deleteProperty(ExecutionContext cx, long propertyKey) {
        /* step 1 (not applicable) */
        /* steps 2-3 */
        Property desc = getProperty(cx, propertyKey);
        /* step 4 */
        if (desc == null) {
            return true;
        }
        /* step 5 */
        if (desc.isConfigurable()) {
            indexedProperties.remove(propertyKey);
            return true;
        }
        /* step 6 */
        return false;
    }

    /**
     * 9.1.10 [[Delete]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was successfully deleted
     */
    protected boolean deleteProperty(ExecutionContext cx, String propertyKey) {
        /* step 1 (not applicable) */
        /* steps 2-3 */
        Property desc = getProperty(cx, propertyKey);
        /* step 4 */
        if (desc == null) {
            return true;
        }
        /* step 5 */
        if (desc.isConfigurable()) {
            properties.remove(propertyKey);
            return true;
        }
        /* step 6 */
        return false;
    }

    /**
     * 9.1.10 [[Delete]] (P)
     *
     * @param cx
     *            the execution context
     * @param propertyKey
     *            the property key
     * @return {@code true} if the property was successfully deleted
     */
    protected boolean deleteProperty(ExecutionContext cx, Symbol propertyKey) {
        /* step 1 (not applicable) */
        /* steps 2-3 */
        Property desc = getProperty(cx, propertyKey);
        /* step 4 */
        if (desc == null) {
            return true;
        }
        /* step 5 */
        if (desc.isConfigurable()) {
            symbolProperties.remove(propertyKey);
            return true;
        }
        /* step 6 */
        return false;
    }

    /** 9.1.11 [[Enumerate]] () */
    @Override
    public final ScriptObject enumerate(ExecutionContext cx) {
        return CreateListIterator(cx, new EnumKeysIterator(cx, this));
    }

    /** 9.1.11 [[Enumerate]] () */
    @Override
    public final ScriptIterator<?> enumerateKeys(ExecutionContext cx) {
        return new EnumKeysIterator(cx, this);
    }

    /**
     * 9.1.11 [[Enumerate]] ()
     *
     * @param cx
     *            the execution context
     * @return the list of enumerable string valued property keys
     */
    protected List<String> getEnumerableKeys(ExecutionContext cx) {
        int totalSize = countProperties(false);
        if (totalSize == 0) {
            return Collections.emptyList();
        }
        ArrayList<String> keys = new ArrayList<>(totalSize);
        appendIndexedProperties(keys);
        appendProperties(keys);
        return keys;
    }

    /**
     * Subclasses need to override this method if they have virtual, configurable properties.
     *
     * @param propertyKey
     *            the property key
     * @return the property enumerable status
     */
    protected Enumerability isEnumerableOwnProperty(String propertyKey) {
        Property prop;
        long index = IndexedMap.toIndex(propertyKey);
        if (IndexedMap.isIndex(index)) {
            prop = ordinaryGetOwnProperty(index);
        } else {
            prop = ordinaryGetOwnProperty(propertyKey);
        }
        if (prop == null) {
            return Enumerability.Deleted;
        }
        return Enumerability.isEnumerable(prop.isEnumerable());
    }

    private static final class EnumKeysIterator extends com.github.anba.es6draft.runtime.internal.SimpleIterator<Object>
            implements com.github.anba.es6draft.runtime.internal.ScriptIterator<Object> {
        private final HashSet<Object> visitedKeys = new HashSet<>();
        private final ExecutionContext cx;
        private OrdinaryObject obj;
        private Iterator<String> keys;
        private ScriptIterator<?> protoKeys;
        private ScriptObject scriptIter;

        EnumKeysIterator(ExecutionContext cx, OrdinaryObject obj) {
            this.cx = cx;
            this.obj = obj;
            this.keys = obj.getEnumerableKeys(cx).iterator();
        }

        @Override
        protected Object findNext() {
            HashSet<Object> visitedKeys = this.visitedKeys;
            for (Iterator<String> keys; (keys = this.keys) != null;) {
                assert protoKeys == null;
                OrdinaryObject obj = this.obj;
                while (keys.hasNext()) {
                    String key = keys.next();
                    Enumerability e = obj.isEnumerableOwnProperty(key);
                    if (e != Enumerability.Deleted) {
                        if (visitedKeys.add(key) && e == Enumerability.Enumerable) {
                            return key;
                        }
                    }
                }
                nextObject();
            }
            if (this.protoKeys != null) {
                return findNextFromProtoKeys();
            }
            return null;
        }

        private Object findNextFromProtoKeys() {
            HashSet<Object> visitedKeys = this.visitedKeys;
            ScriptIterator<?> protoKeys = this.protoKeys;
            try {
                while (protoKeys.hasNext()) {
                    Object key = protoKeys.next();
                    if (visitedKeys.add(key)) {
                        return key;
                    }
                }
                // visited all inherited keys
                this.protoKeys = null;
                return null;
            } catch (ScriptException e) {
                this.protoKeys = null;
                throw e;
            }
        }

        private void nextObject() {
            // switch to prototype enumerate
            try {
                ScriptObject proto = obj.getPrototypeOf(cx);
                if (proto != null) {
                    if (proto instanceof OrdinaryObject) {
                        this.obj = (OrdinaryObject) proto;
                        this.keys = ((OrdinaryObject) proto).getEnumerableKeys(cx).iterator();
                    } else {
                        ScriptIterator<?> protoKeys = proto.enumerateKeys(cx);
                        if (protoKeys instanceof EnumKeysIterator) {
                            EnumKeysIterator keysIterator = (EnumKeysIterator) protoKeys;
                            assert keysIterator.visitedKeys.isEmpty();
                            assert keysIterator.keys != null && keysIterator.protoKeys == null;
                            this.obj = keysIterator.obj;
                            this.keys = keysIterator.keys;
                        } else {
                            this.obj = null;
                            this.keys = null;
                            this.protoKeys = protoKeys;
                        }
                    }
                } else {
                    this.obj = null;
                    this.keys = null;
                    this.protoKeys = null;
                }
            } catch (ScriptException e) {
                this.obj = null;
                this.keys = null;
                this.protoKeys = null;
                throw e;
            }
        }

        @Override
        public void close() throws ScriptException {
            if (!isDone() && hasReturn()) {
                IteratorClose(cx, getScriptObject());
            }
        }

        @Override
        public void close(Throwable cause) throws ScriptException {
            if (!isDone() && hasReturn()) {
                IteratorClose(cx, getScriptObject(), cause);
            }
        }

        private ScriptObject getScriptObject() {
            if (scriptIter == null) {
                scriptIter = CreateListIterator(cx, this);
            }
            return scriptIter;
        }

        private boolean isDone() {
            return obj == null && keys == null && protoKeys == null;
        }

        private boolean hasReturn() {
            if (scriptIter != null) {
                return true;
            }
            OrdinaryObject iterProto = cx.getIntrinsic(Intrinsics.IteratorPrototype);
            for (;;) {
                if (iterProto.ordinaryHasOwnProperty("return")) {
                    return true;
                }
                ScriptObject proto = iterProto.getPrototype();
                if (proto == null) {
                    return false;
                }
                if (!(proto instanceof OrdinaryObject)) {
                    return true;
                }
                iterProto = (OrdinaryObject) proto;
            }
        }
    }

    @Override
    public final Iterator<String> ownEnumerablePropertyKeys(ExecutionContext cx) {
        return getEnumerableKeys(cx).iterator();
    }

    @Override
    public final Enumerability isEnumerableOwnProperty(ExecutionContext cx, String propertyKey) {
        return isEnumerableOwnProperty(propertyKey);
    }

    /** 9.1.12 [[OwnPropertyKeys]] ( ) */
    @Override
    public final List<?> ownPropertyKeys(ExecutionContext cx) {
        return getOwnPropertyKeys(cx);
    }

    /** 9.1.12 [[OwnPropertyKeys]] ( ) */
    @Override
    public final Iterator<?> ownKeys(ExecutionContext cx) {
        return getOwnPropertyKeys(cx).iterator();
    }

    /**
     * 9.1.12 [[OwnPropertyKeys]] ( )
     *
     * @param cx
     *            the execution context
     * @return the list of own property keys
     */
    protected List<Object> getOwnPropertyKeys(ExecutionContext cx) {
        int totalSize = countProperties(true);
        if (totalSize == 0) {
            return Collections.emptyList();
        }
        /* step 1 */
        ArrayList<Object> ownKeys = new ArrayList<>(totalSize);
        /* step 2 */
        appendIndexedProperties(ownKeys);
        /* step 3 */
        appendProperties(ownKeys);
        /* step 4 */
        appendSymbolProperties(ownKeys);
        /* step 5 */
        return ownKeys;
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param cx
     *            the execution context
     * @param proto
     *            the prototype object
     * @return the new object
     */
    public static final OrdinaryObject ObjectCreate(ExecutionContext cx, ScriptObject proto) {
        return new OrdinaryObject(cx.getRealm(), proto);
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param cx
     *            the execution context
     * @param proto
     *            the prototype object
     * @return the new object
     */
    public static final OrdinaryObject ObjectCreate(ExecutionContext cx, Intrinsics proto) {
        return new OrdinaryObject(cx.getRealm(), cx.getIntrinsic(proto));
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param <OBJECT>
     *            the object type
     * @param cx
     *            the execution context
     * @param proto
     *            the prototype object
     * @param allocator
     *            the object allocator
     * @return the new object
     */
    public static final <OBJECT extends OrdinaryObject> OBJECT ObjectCreate(ExecutionContext cx, ScriptObject proto,
            ObjectAllocator<OBJECT> allocator) {
        OBJECT obj = allocator.newInstance(cx.getRealm());
        obj.setPrototype(proto);
        return obj;
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param <OBJECT>
     *            the object type
     * @param cx
     *            the execution context
     * @param proto
     *            the prototype object
     * @param allocator
     *            the object allocator
     * @return the new object
     */
    public static final <OBJECT extends OrdinaryObject> OBJECT ObjectCreate(ExecutionContext cx, Intrinsics proto,
            ObjectAllocator<OBJECT> allocator) {
        OBJECT obj = allocator.newInstance(cx.getRealm());
        obj.setPrototype(cx.getIntrinsic(proto));
        return obj;
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param realm
     *            the realm instance
     * @param proto
     *            the prototype object
     * @return the new object
     */
    public static final OrdinaryObject ObjectCreate(Realm realm, ScriptObject proto) {
        return new OrdinaryObject(realm, proto);
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param realm
     *            the realm instance
     * @param proto
     *            the prototype object
     * @return the new object
     */
    public static final OrdinaryObject ObjectCreate(Realm realm, Intrinsics proto) {
        return new OrdinaryObject(realm, realm.getIntrinsic(proto));
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param <OBJECT>
     *            the object type
     * @param realm
     *            the realm instance
     * @param proto
     *            the prototype object
     * @param allocator
     *            the object allocator
     * @return the new object
     */
    public static final <OBJECT extends OrdinaryObject> OBJECT ObjectCreate(Realm realm, ScriptObject proto,
            ObjectAllocator<OBJECT> allocator) {
        OBJECT obj = allocator.newInstance(realm);
        obj.setPrototype(proto);
        return obj;
    }

    /**
     * 9.1.13 ObjectCreate(proto, internalSlotsList)
     *
     * @param <OBJECT>
     *            the object type
     * @param realm
     *            the realm instance
     * @param proto
     *            the prototype object
     * @param allocator
     *            the object allocator
     * @return the new object
     */
    public static final <OBJECT extends OrdinaryObject> OBJECT ObjectCreate(Realm realm, Intrinsics proto,
            ObjectAllocator<OBJECT> allocator) {
        OBJECT obj = allocator.newInstance(realm);
        obj.setPrototype(realm.getIntrinsic(proto));
        return obj;
    }

    /**
     * 9.1.14 OrdinaryCreateFromConstructor (constructor, intrinsicDefaultProto, internalSlotsList)
     *
     * @param cx
     *            the execution context
     * @param constructor
     *            the constructor function
     * @param intrinsicDefaultProto
     *            the default prototype
     * @return the new object
     */
    public static final OrdinaryObject OrdinaryCreateFromConstructor(ExecutionContext cx, Callable constructor,
            Intrinsics intrinsicDefaultProto) {
        /* step 1 (not applicable) */
        /* steps 2-3 */
        ScriptObject proto = GetPrototypeFromConstructor(cx, constructor, intrinsicDefaultProto);
        /* step 4 */
        return ObjectCreate(cx, proto);
    }

    /**
     * 9.1.14 OrdinaryCreateFromConstructor (constructor, intrinsicDefaultProto, internalSlotsList)
     *
     * @param <OBJECT>
     *            the object type
     * @param cx
     *            the execution context
     * @param constructor
     *            the constructor function
     * @param intrinsicDefaultProto
     *            the default prototype
     * @param allocator
     *            the object allocator
     * @return the new object
     */
    public static final <OBJECT extends OrdinaryObject> OBJECT OrdinaryCreateFromConstructor(ExecutionContext cx,
            Callable constructor, Intrinsics intrinsicDefaultProto, ObjectAllocator<OBJECT> allocator) {
        /* step 1 (not applicable) */
        /* steps 2-3 */
        ScriptObject proto = GetPrototypeFromConstructor(cx, constructor, intrinsicDefaultProto);
        /* step 4 */
        return ObjectCreate(cx, proto, allocator);
    }

    /**
     * 9.1.15 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )
     *
     * @param cx
     *            the execution context
     * @param constructor
     *            the constructor object
     * @param intrinsicDefaultProto
     *            the default prototype
     * @return the prototype object
     */
    public static final ScriptObject GetPrototypeFromConstructor(ExecutionContext cx, Callable constructor,
            Intrinsics intrinsicDefaultProto) {
        /* steps 1-2 (not applicable) */
        /* steps 3-4 */
        Object proto = Get(cx, constructor, "prototype");
        /* step 5 */
        if (!Type.isObject(proto)) {
            /* steps 5.a-b */
            Realm realm = GetFunctionRealm(cx, constructor);
            /* step 5.c */
            proto = realm.getIntrinsic(intrinsicDefaultProto);
        }
        /* step 6 */
        return Type.objectValue(proto);
    }
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>Uses of Package com.badlogic.gdx.assets (libgdx API)</title>
<meta name="date" content="2016-02-02">
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

				libgdx API

Prev

Next

Frames

No Frames

All Classes

Uses of Package
com.badlogic.gdx.assets

Packages that use com.badlogic.gdx.assets

Package
Description

com.badlogic.gdx.assets

com.badlogic.gdx.assets.loaders

com.badlogic.gdx.graphics

com.badlogic.gdx.graphics.g2d

com.badlogic.gdx.graphics.g3d.loader

com.badlogic.gdx.graphics.g3d.particles

com.badlogic.gdx.graphics.g3d.particles.batches

com.badlogic.gdx.graphics.g3d.particles.influencers

com.badlogic.gdx.graphics.g3d.particles.values

com.badlogic.gdx.graphics.g3d.utils

com.badlogic.gdx.maps

com.badlogic.gdx.maps.tiled

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.assets

Class and Description

AssetDescriptor

Describes an asset to be loaded by it's filename, type and AssetLoaderParameters.

AssetErrorListener

AssetLoaderParameters

AssetLoaderParameters.LoadedCallback

Callback interface that will be invoked when the AssetManager loaded an asset.

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.assets.loaders

Class and Description

AssetDescriptor

Describes an asset to be loaded by it's filename, type and AssetLoaderParameters.

AssetLoaderParameters

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics

Class and Description

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics.g2d

Class and Description

AssetDescriptor

Describes an asset to be loaded by it's filename, type and AssetLoaderParameters.

AssetLoaderParameters

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics.g3d.loader

Class and Description

AssetLoaderParameters

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics.g3d.particles

Class and Description

AssetDescriptor

Describes an asset to be loaded by it's filename, type and AssetLoaderParameters.

AssetLoaderParameters

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics.g3d.particles.batches

Class and Description

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics.g3d.particles.influencers

Class and Description

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics.g3d.particles.values

Class and Description

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.graphics.g3d.utils

Class and Description

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.maps

Class and Description

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Classes in com.badlogic.gdx.assets used by com.badlogic.gdx.maps.tiled

Class and Description

AssetDescriptor

Describes an asset to be loaded by it's filename, type and AssetLoaderParameters.

AssetLoaderParameters

AssetManager

Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

libgdx API

Prev

Next

Frames

No Frames

All Classes

				Copyright © 2010-2013 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)

redpajama_set_name: RedPajamaGithub


text:
import React, { useState } from 'react';

import { Box, Calendar } from 'grommet';

export const Multiple = () => {
  const [dates, setDates] = useState([]);

  return (
    // Uncomment <Grommet> lines when using outside of storybook
    // <Grommet theme={...}>
    <Box align="center" pad="large">
      <Calendar
        dates={dates}
        onSelect={(date) => {
          const nextDates = [...dates];
          const index = nextDates.indexOf(date);
          if (index === -1) {
            nextDates.push(date);
          } else {
            nextDates.splice(index, 1);
          }
          setDates(nextDates);
          console.log('Select iso date:', date, nextDates);
          console.log('Select utc date:', new Date(date));
        }}
        bounds={['2020-09-08', '2025-12-13']}
      />
    </Box>
    // </Grommet>
  );
};

export default {
  title: 'Visualizations/Calendar/Multiple',
};


text:
> Gulp plugin to transform json files into dot notation json files

## Installation

Install package with NPM and add it to your development dependencies:

`npm install --save-dev gulp-dotify-json`

## Usage

```javascript
var dotify = require('gulp-dotify-json');

gulp.task('dotify-locales', function() {
  return gulp.src('./app/locales/*.json')
    .pipe(dotify())
    .pipe(gulp.dest('./dist/locales'));
});
```

## Options

Coming soon!


text:
require File.expand_path('../../helper', __FILE__)
require File.join(Zen::FIXTURES, 'validation')
require 'fileutils'

describe 'Zen::Validation' do

  it 'Validate the presence of an attribute' do
    object = ValidationObject.new

    should.raise?(Zen::ValidationError) { object.presence }

    # Now validate it with a value
    object.name = 'yorick'

    should.not.raise?(Zen::ValidationError) { object.presence }
  end

  it 'Validate the length of an attribute' do
    object = ValidationObject.new

    should.raise?(Zen::ValidationError) { object.length }

    # Too short
    object.name = 'ab'

    should.raise?(Zen::ValidationError) { object.length }

    # Too long
    object.name = 'abcdef'

    should.raise?(Zen::ValidationError) { object.length }

    # Perfect
    object.name = 'ab3'

    should.not.raise?(Zen::ValidationError) { object.length }
  end

  it 'Validate the format of an attribute' do
    object      = ValidationObject.new
    object.name = 10

    should.raise?(Zen::ValidationError) { object.format }

    object.name = 'hello'

    should.not.raise?(Zen::ValidationError) { object.format }
  end

  it 'Validate a file' do
    object      = ValidationObject.new
    object.file = '/tmp/zen_validation'

    should.raise?(Zen::ValidationError) { object.exists }

    FileUtils.touch('/tmp/zen_validation')

    should.not.raise?(Zen::ValidationError) { object.exists }

    File.unlink('/tmp/zen_validation')
  end
end


text:
using Microsoft.Office.Interop.Outlook;
using VSTOContrib.Core;
using VSTOContrib.Core.RibbonFactory.Interfaces;

namespace VSTOContrib.Outlook.RibbonFactory
{
    public class OutlookViewContextProvider : IViewContextProvider
    {
        /// <summary>
        /// Gets the context for view.
        /// </summary>
        /// <param name="view">The view.</param>
        /// <returns></returns>
        public object GetContextForView(object view)
        {
            var inspector = view as Inspector;
            if (inspector != null)
                return inspector.CurrentItem;

            var explorer = view as Explorer;
            if (explorer != null)
                return explorer;

            var selection = view as Selection;
            if (selection != null)
                return GetContextForView(selection.Parent);

            return null;
        }

        /// <summary>
        /// Gets the ribbon type for view.
        /// </summary>
        /// <param name="view">The view.</param>
        /// <returns></returns>
        public string GetRibbonTypeForView(object view)
        {
            if (view is Explorer)
                return OutlookRibbonType.OutlookExplorer.GetEnumDescription();

            var selection = view as Selection;
            if (selection != null)
                return GetRibbonTypeForView(selection.Parent);

            return InspectorToRibbonTypeConverter.Convert((Inspector) view).GetEnumDescription();
        }
    }
}


text:
package audit.query.search.api;

import java.util.Objects;

import static java.util.Objects.*;

public abstract class Matcher<T> {
    private final Object searchedText;

    public Matcher(Object searchedText) {
        this.searchedText = requireNonNull(searchedText);
    }

    public abstract String getFieldName();
    public abstract Class<T> getEntityType();

    public Object getSearchedText() {
        return searchedText;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Matcher<?> matcher = (Matcher<?>) o;
        return Objects.equals(getFieldName(), matcher.getFieldName())
                && Objects.equals(getEntityType(), matcher.getEntityType());
    }

    @Override
    public int hashCode() {
        return hash(getFieldName(), getEntityType());
    }

    public static <T> Matcher<T> field(Object searchedText, String fieldName, Class<T> entityType) {
        return new StringFieldMatcher<>(searchedText, fieldName, entityType);
    }
}


text:
package org.baswell.routes;

import static org.baswell.routes.RoutesMethods.*;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.baswell.routes.CriterionForParameter.RequestParameterType;
import org.baswell.routes.CriterionForPathSegment.RequestPathSegmentCrierionType;

class CriteriaBuilder
{
  Criteria buildCriteria(Method method, ParsedRouteTree routeTree, RouteConfiguration routeConfiguration, RoutesConfiguration routesConfiguration) throws RoutesException
  {
    List<CriterionForPathSegment> pathCriteria = new ArrayList<CriterionForPathSegment>();
    int urlParameterIndex = 0;
    for (int i = 0; i < routeTree.pathTerminals.size(); i++)
    {
      ParsedPathTerminal pathTerminal = routeTree.pathTerminals.get(i);
      if (pathTerminal instanceof ParsedExactPathTerminal)
      {
        ParsedExactPathTerminal exactTerminal = (ParsedExactPathTerminal)pathTerminal;
        pathCriteria.add(new CriterionForPathSegment(i, exactTerminal.segment, RequestPathSegmentCrierionType.FIXED, null));
      }
      else if (pathTerminal instanceof ParsedPatternPathTerminal)
      {
        ParsedPatternPathTerminal patternTerminal = (ParsedPatternPathTerminal)pathTerminal;
        CriterionForPathSegment patternCriteria = new CriterionForPathSegment(i, patternTerminal.pattern, RequestPathSegmentCrierionType.PATTERN, compile(patternTerminal.pattern, method));
        urlParameterIndex += Math.min(1, patternCriteria.numberPatternGroups);
        pathCriteria.add(patternCriteria);
      }
      else if (pathTerminal instanceof ParsedWildcardPathTerminal)
      {
        ++urlParameterIndex;
        pathCriteria.add(new CriterionForPathSegment(i, "*", RequestPathSegmentCrierionType.PATTERN, compile(WILDCARD_PATTERN, method)));
      }
      else if (pathTerminal instanceof ParsedDoubleWildcardPathTerminal)
      {
        ++urlParameterIndex;
        pathCriteria.add(new CriterionForPathSegment(i, "**", RequestPathSegmentCrierionType.MULTI, null));
      }
      else if (pathTerminal instanceof ParsedMethodParameterPathTerminal)
      {
        RoutesPair<Type, Integer> parameterIndex = findDynamicParameterAndIndex(method, urlParameterIndex++);
        if (parameterIndex == null)
        {
          throw new RoutesException("Route path pattern {} at index: " + (urlParameterIndex - 1) + " has no matching method parameter for method: " + method);
        }
        else
        {
          Type parameter = parameterIndex.x;
          if (typesToPatterns.containsKey(parameter))
          {
            String pattern = typesToPatterns.get(parameter);
            pathCriteria.add(new CriterionForPathSegment(i, pattern, RequestPathSegmentCrierionType.PATTERN, compile(pattern, method), 0));
          }
          else
          {
            throw new RoutesException("Invalid route parameter: " + parameter + " for method: " + method);
          }
        }
      }
      else if (pathTerminal instanceof ParsedSymbolPathTerminal)
      {
        ParsedSymbolPathTerminal symbolTerminal = (ParsedSymbolPathTerminal)pathTerminal;
        if (routesConfiguration.symbolsToPatterns.containsKey(symbolTerminal.symbol))
        {
          CriterionForPathSegment patternCriteria = new CriterionForPathSegment(i, symbolTerminal.symbol, RequestPathSegmentCrierionType.PATTERN, routesConfiguration.symbolsToPatterns.get(symbolTerminal.symbol));
          urlParameterIndex += Math.min(1, patternCriteria.numberPatternGroups);
          pathCriteria.add(patternCriteria);
        }
        else
        {
          throw new RoutesException("Invalid symbol: " + symbolTerminal.symbol + " in method: " + method);
        }
      }
      else
      {
        throw new RoutesException("Unsupported PathTerminal class: " + pathTerminal.getClass());
      }
    }

    List<CriterionForParameter> parameterCriteria = new ArrayList<CriterionForParameter>();
    if (routeTree.parameterTerminals != null)
    {
      for (int i = 0; i < routeTree.parameterTerminals.size(); i++)
      {
        ParsedParameterTerminal parameterTerminal = routeTree.parameterTerminals.get(i);

        if (parameterTerminal instanceof ParsedExactParameterTerminal)
        {
          ParsedExactParameterTerminal exactTerminal = (ParsedExactParameterTerminal)parameterTerminal;
          parameterCriteria.add(new CriterionForParameter(exactTerminal.name, exactTerminal.value, RequestParameterType.FIXED, !parameterTerminal.optional, null));
        }
        else if (parameterTerminal instanceof ParsedPatternParameterTerminal)
        {
          ParsedPatternParameterTerminal patternParameter = (ParsedPatternParameterTerminal)parameterTerminal;
          CriterionForParameter parameterCriterion = new CriterionForParameter(patternParameter.name, patternParameter.pattern, RequestParameterType.PATTERN, !parameterTerminal.optional, compile(patternParameter.pattern, method));
          urlParameterIndex += Math.min(1, parameterCriterion.numberPatternGroups);
          parameterCriteria.add(parameterCriterion);
        }
        else if (parameterTerminal instanceof ParsedWildcardParameterTerminal)
        {
          ++urlParameterIndex;
          parameterCriteria.add(new CriterionForParameter(parameterTerminal.name, "*", RequestParameterType.PATTERN, !parameterTerminal.optional, compile(WILDCARD_PATTERN, method)));
        }
        else if (parameterTerminal instanceof ParsedMethodParameterParameterTerminal)
        {
          RoutesPair<Type, Integer> parameterIndex = findDynamicParameterAndIndex(method, urlParameterIndex++);
          if (parameterIndex == null)
          {
            throw new RoutesException("Route parameter pattern {} at index: " + (urlParameterIndex - 1) + " has no matching method parameter for method: " + method);
          }
          else
          {
            Type parameter = parameterIndex.x;
            Class parameterClass = typeToClass(parameter);
            if (parameterClass == List.class)
            {
              parameterClass = getListSingleParameterType(parameter);
            }

            if ((parameterClass != null) && typesToPatterns.containsKey(parameterClass))
            {
              String pattern = typesToPatterns.get(parameterClass);
              parameterCriteria.add(new CriterionForParameter(parameterTerminal.name, pattern, RequestParameterType.PATTERN, !parameterTerminal.optional, compile(pattern, method), 0));
            }
            else
            {
              throw new RoutesException("Invalid route parameter: " + parameter + " for method: " + method);
            }
          }
        }
        else if (parameterTerminal instanceof ParsedSymbolParameterTerminal)
        {
          ParsedSymbolParameterTerminal symbolTerminal = (ParsedSymbolParameterTerminal)parameterTerminal;
          if (routesConfiguration.symbolsToPatterns.containsKey(symbolTerminal.symbol))
          {
            CriterionForParameter parameterCriterion = new CriterionForParameter(parameterTerminal.name, "", RequestParameterType.PATTERN, !parameterTerminal.optional, routesConfiguration.symbolsToPatterns.get(symbolTerminal.symbol));
            urlParameterIndex += Math.min(1, parameterCriterion.numberPatternGroups);
            parameterCriteria.add(parameterCriterion);
          }
          else
          {
            throw new RoutesException("Invalid parameter symbol: " + symbolTerminal.symbol + " in method: " + method);
          }
        }
        else
        {
          throw new RoutesException("Unsupported ParameterTerminal class: " + parameterTerminal.getClass());
        }
      }
    }

    return new Criteria(pathCriteria, parameterCriteria, routeConfiguration, routesConfiguration);
  }

  static Pattern compile(String pattern, Method method)
  {
    try
    {
      return Pattern.compile(pattern, Pattern.DOTALL); // Support multi-lines for parameters
    }
    catch (PatternSyntaxException e)
    {
      throw new RoutesException("Invalid pattern: " + pattern + " for method: " + method);
    }
  }

  static RoutesPair<Type, Integer> findDynamicParameterAndIndex(Method method, int dynamicIndex)
  {
    Type[] parameters = method.getGenericParameterTypes();
    int dynamicParameterCounter = 0;
    for (int i = 0; i < parameters.length; i++)
    {
      Type parameter = parameters[i];
      if (!methodRouteParameterTypes.contains(parameter))
      {
        if (dynamicParameterCounter++ == dynamicIndex)
        {
          return RoutesPair.pair(parameter, i);
        }
      }
    }
    return null;
  }
}


text:
package com.planet_ink.coffee_mud.Abilities.Druid;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.util.*;

@SuppressWarnings("unchecked")
public class Chant_SnatchLight extends Chant
{
	public String ID() { return "Chant_SnatchLight"; }
	public String name(){return "Snatch Light";}
	public String displayText(){return "(Snatch Light)";}
    public int classificationCode(){return Ability.ACODE_CHANT|Ability.DOMAIN_DEEPMAGIC;}
	public int abstractQuality(){ return Ability.QUALITY_OK_SELF;}
	protected int canAffectCode(){return CAN_MOBS;}

	public Room snatchLocation()
	{
		if((invoker!=null)
		&&CMLib.flags().isInTheGame(invoker,false)
		&&(invoker.fetchEffect(ID())!=null))
		   return invoker.location();
		return null;
	}

	public void affectEnvStats(Environmental affected, EnvStats affectableStats)
	{
		super.affectEnvStats(affected,affectableStats);
		if(CMLib.map().roomLocation(affected)==snatchLocation())
		{
			affectableStats.setDisposition(affectableStats.disposition() |  EnvStats.IS_DARK);
			if(CMath.bset(affectableStats.disposition(),EnvStats.IS_LIGHTSOURCE))
				affectableStats.setDisposition(CMath.unsetb(affectableStats.disposition(),EnvStats.IS_LIGHTSOURCE));
			if(CMath.bset(affectableStats.disposition(),EnvStats.IS_GLOWING))
				affectableStats.setDisposition(CMath.unsetb(affectableStats.disposition(),EnvStats.IS_GLOWING));
		}
		else
			unInvoke();
	}

	public boolean tick(Tickable ticking, int tickID)
	{
		if(!super.tick(ticking,tickID))
			return false;
		if((affected==invoker)&&(invoker!=null))
		{
			MOB mob=invoker;
			Room R=mob.location();
			if(R==null) return true;
			if(R.fetchEffect(ID())==null)
			{
				Ability A=(Ability)copyOf();
				A.setSavable(false);
				R.addEffect(A);
			}
			for(int m=0;m<R.numInhabitants();m++)
			{
				MOB M=R.fetchInhabitant(m);
				if((M!=null)&&(CMLib.flags().isGlowing(M)||CMLib.flags().isLightSource(M))&&(M.fetchEffect(ID())==null))
				{
					Ability A=(Ability)copyOf();
					A.setSavable(false);
					M.addEffect(A);
				}
				if(M!=null)
				for(int i=0;i<M.inventorySize();i++)
				{
					Item I=M.fetchInventory(i);
					if((I!=null)&&(I.container()==null)&&(CMLib.flags().isGlowing(I)||CMLib.flags().isLightSource(I))&&(I.fetchEffect(ID())==null))
					{
						Ability A=(Ability)copyOf();
						A.setSavable(false);
						I.addEffect(A);
					}
				}
			}
			for(int i=0;i<R.numItems();i++)
			{
				Item I=R.fetchItem(i);
				if((I!=null)&&(CMLib.flags().isGlowing(I)||CMLib.flags().isLightSource(I))&&(I.fetchEffect(ID())==null))
				{
					Ability A=(Ability)copyOf();
					A.setSavable(false);
					I.addEffect(A);
				}
			}
			R.recoverRoomStats();
			R.recoverRoomStats();
		}
		else
		if(affected!=null)
		{
			Room R=CMLib.map().roomLocation(affected);
			if((invoker==null)||(R!=invoker.location()))
			{
				unInvoke();
				return false;
			}
		}
		return true;
	}

	public void unInvoke()
	{
		// undo the affects of this spell
		if((affected==null)||(invoker==null)||(affected!=invoker))
		{
			Environmental E=affected;
			MOB oldI=invoker;
			super.unInvoke();
			if(E!=null)
			{
				if(E instanceof MOB)
				{
					MOB M=(MOB)E;
					for(int i=0;i<M.inventorySize();i++)
					{
						Item I=M.fetchInventory(i);
						if(I!=null)
						{
							Ability A=I.fetchEffect(ID());
							if((A!=null)&&(A.invoker()==oldI))
								A.unInvoke();
						}
					}
				}
				Room R=CMLib.map().roomLocation(E);
				if(R!=null) R.recoverRoomStats();
			}
			return;
		}
		MOB mob=invoker;
		super.unInvoke();

		if((canBeUninvoked())&&(mob!=null))
		{
			mob.tell("Your ability to snatch light dissipates.");
			if(mob.location()!=null)
			{
				mob.location().recoverRoomStats();
				mob.location().recoverRoomStats();
			}
		}
	}

	public boolean invoke(MOB mob, Vector commands, Environmental givenTarget, boolean auto, int asLevel)
	{
		MOB target=mob;
		if((auto)&&(givenTarget!=null)&&(givenTarget instanceof MOB))
			target=(MOB)givenTarget;

		if(target.fetchEffect(ID())!=null)
		{
			mob.tell(target,null,null,"<S-NAME> <S-IS-ARE> already snatching light.");
			return false;
		}

		// the invoke method for spells receives as
		// parameters the invoker, and the REMAINING
		// command line parameters, divided into words,
		// and added as String objects to a vector.
		if(!super.invoke(mob,commands,givenTarget,auto,asLevel))
			return false;

		boolean success=proficiencyCheck(mob,0,auto);

		if(success)
		{
			// it worked, so build a copy of this ability,
			// and add it to the affects list of the
			// affected MOB.  Then tell everyone else
			// what happened.
			invoker=mob;
			CMMsg msg=CMClass.getMsg(mob,target,this,verbalCastCode(mob,target,auto),auto?"<S-NAME> gain(s) an aura of light snatching!":"^S<S-NAME> chant(s), feeling <S-HIS-HER> body become a light snatcher!^?");
			if(mob.location().okMessage(mob,msg))
			{
				mob.location().send(mob,msg);
				beneficialAffect(mob,target,asLevel,0);
			}
		}
		else
			return beneficialWordsFizzle(mob,target,"<S-NAME> chant(s), but nothing more happens.");

		// return whether it worked
		return success;
	}
}


text:
<?php
namespace SHH\TokenParser;

/**
 * Escape TokenParser
 */
class Escape extends \SHH\TokenParser
{
	const TYPE = ESCAPE_TYPE;

	/**
	 * Parse token.
	 *
	 * @param 	Parser 	$parser 	a Parser instance
	 */
	public function parse(\SHH\Parser &$parser){}
}