Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright 2013 Douglas Campos, and individual contributors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
 
 package org.dynjs.runtime;
 
 import java.util.Map;
 import java.util.Set;
 
 
 public class DynObject implements JSObjectMap<StringObject> {
 
     private String className;
     private JSObject prototype = null;
 
     private final Map<StringPropertyDescriptorproperties = new LinkedHashMap<>();
     private boolean extensible = true;
 
     // Support for an array-backed set of indexed properties.
     protected Object[] buffer = null;
 
     public DynObject(GlobalObject globalObject) {
         setClassName("Object");
         setExtensible(true);
         if (globalObject != null) {
             setPrototype(globalObject.getPrototypeFor("Object"));
         }
     }
 
     // ------------------------------------------------------------------------
     // JSObject
     // ------------------------------------------------------------------------
 
     @Override
     public JSObject getPrototype() {
         return this.;
     }
 
     public void setPrototype(final JSObject prototype) {
         this. = prototype;
     }
 
     @Override
     public String getClassName() {
         return this.;
     }
 
     public void setClassName(String className) {
         this. = className;
     }
 
     @Override
     public boolean isExtensible() {
         return ;
     }
 
     public void setExtensible(boolean extensible) {
         this. = extensible;
     }
 
     @Override
     public Object get(ExecutionContext contextString name) {
         // 8.12.3
         Object d = getProperty(contextname);
         if (d == .) {
             return .;
         }
 
         PropertyDescriptor desc = (PropertyDescriptord;
         if (desc.isDataDescriptor()) {
             Object value = desc.getValue();
             if (value == null) {
                 value = .;
             }
             return value;
         }
 
         Object g = desc.getGetter();
         if (g == null || g == .) {
             return .;
         }
        JSFunction getter = (JSFunctiong;
        return context.call(getterthis);
    }
    @Override
    public Object getOwnProperty(ExecutionContext contextString name) {
        // Supports index-based property access that is backed
        // by a byte array. TODO: Should this be an object array?
        if (this. != null && Types.toUint32(contextname).toString().equals(name)) {
            return getOwnIndexedProperty(contextname);
        }
        // 8.12.1
        // Returns PropertyDescriptor or UNDEFINED
        PropertyDescriptor x = this..get(name);
        // System.err.println("x1: " + name + " > " + x);
        if (x == null) {
            return .;
        }
        PropertyDescriptor dup = null;
        if (x.isDataDescriptor()) {
            // System.err.println("isData");
            dup = x.duplicate("Value""Writable""Enumerable""Configurable");
        } else {
            // System.err.println("isAccesor");
            dup = x.duplicate("Get""Set""Enumerable""Configurable");
        }
        // System.err.println("return: " + name + " > " + dup);
        return dup;
    }
    @Override
    public Object getProperty(ExecutionContext contextString name) {
        // 8.12.2
        // Returns PropertyDescriptor or UNDEFINED
        Object d = getOwnProperty(contextname);
        if (d != .) {
            return d;
        }
        if (this. == null) {
            return .;
        }
        return this..getProperty(contextname);
    }
    @Override
    public boolean hasProperty(ExecutionContext contextString name) {
        // 8.12.6
        return (getProperty(contextname) != .);
    }
    @Override
    public void put(ExecutionContext contextfinal String namefinal Object valuefinal boolean shouldThrow) {
        // Support for byte[] storage as indexed property names
        if (this. != null && Types.toUint32(contextname).toString().equals(name)) {
            putIndexedValue(contextnamevalue);
            return;
        }
        // 8.12.5
        // System.err.println("PUT " + name + " > " + value);
        if (!canPut(contextname)) {
            // System.err.println("CANNOT PUT");
            if (shouldThrow) {
                throw new ThrowException(contextcontext.createTypeError("cannot put property '" + name + "'"));
            }
            return;
        }
        Object ownDesc = getOwnProperty(contextname);
        if ((ownDesc != .) && ((PropertyDescriptorownDesc).isDataDescriptor()) {
            // System.err.println("setting value on non-UNDEF");
            PropertyDescriptor newDesc = new PropertyDescriptor() {
                {
                    set("Value"value);
                }
            };
            defineOwnProperty(contextnamenewDescshouldThrow);
            return;
        }
        Object desc = getProperty(contextname);
        if ((desc != .) && ((PropertyDescriptordesc).isAccessorDescriptor()) {
            JSFunction setter = (JSFunction) ((PropertyDescriptordesc).get("Set");
            context.call(setterthisvalue);
        } else {
            PropertyDescriptor newDesc = new PropertyDescriptor() {
                {
                    set("Value"value);
                    set("Writable"true);
                    set("Enumerable"true);
                    set("Configurable"true);
                }
            };
            defineOwnProperty(contextnamenewDescshouldThrow);
        }
    }
    @Override
    public boolean canPut(ExecutionContext contextString name) {
        // 8.12.4
        Object d = getOwnProperty(contextname);
        // Find the property on ourself, or our prototype
        if (d == .) {
            if (this. != null) {
                d = this..getProperty(contextname);
            }
        }
        // System.err.println("canPut?: " + name + " > " + d);
        // If either has it, deal with descriptor appropriately
        if (d != .) {
            PropertyDescriptor desc = (PropertyDescriptord;
            if (desc.isAccessorDescriptor()) {
                if (desc.get("Set") == .) {
                    // System.err.println("NO SET");
                    return false;
                }
                return true;
            } else {
                Object writable = desc.get("Writable");
                // System.err.println("writable? " + writable);
                if (writable == .) {
                    return true;
                }
                return (Booleanwritable;
            }
        }
        // Else, just determine if we are extensible directly
        return isExtensible();
    }
    @Override
    public boolean delete(ExecutionContext contextString nameboolean shouldThrow) {
        // 8.12.7
        if (!this..containsKey(name)) {
            return true;
        }
        Object d = getOwnProperty(contextname);
        if (d == .) {
            return true;
        }
        PropertyDescriptor desc = (PropertyDescriptord;
        if (desc.get("Configurable") == .) {
            this..remove(name);
            return true;
        }
        if (shouldThrow) {
            throw new ThrowException(contextcontext.createTypeError("cannot delete unconfigurable property '" + name + "'"));
        }
        return false;
    }
    @Override
    public Object defaultValue(ExecutionContext contextString hint) {
        // 8.12.8
        if (hint == null) {
            hint = "Number";
        }
        if (hint.equals("String")) {
            Object toString = get(context"toString");
            if (toString instanceof JSFunction) {
                Object result = context.call((JSFunctiontoStringthis);
                if (result instanceof String || result instanceof Number || result instanceof Boolean || result == . || result == .) {
                    return result;
                }
            }
            Object valueOf = get(context"valueOf");
            if (valueOf instanceof JSFunction) {
                Object result = context.call((JSFunctionvalueOfthis);
                if (result instanceof String || result instanceof Number || result instanceof Boolean || result == . || result == .) {
                    return result;
                }
            }
            throw new ThrowException(contextcontext.createTypeError("String coercion must return a primitive value"));
        } else if (hint.equals("Number")) {
            Object valueOf = get(context"valueOf");
            if (valueOf instanceof JSFunction) {
                Object result = context.call((JSFunctionvalueOfthis);
                if (result instanceof String || result instanceof Number || result instanceof Boolean || result == . || result == .) {
                    return result;
                }
            }
            Object toString = get(context"toString");
            if (toString instanceof JSFunction) {
                Object result = context.call((JSFunctiontoStringthis);
                if (result instanceof String || result instanceof Number || result instanceof Boolean || result == . || result == .) {
                    return result;
                }
            }
            throw new ThrowException(contextcontext.createTypeError("String coercion must return a primitive value"));
        }
        return null;
    }
    @Override
    public boolean defineOwnProperty(ExecutionContext contextString namePropertyDescriptor descboolean shouldThrow) {
        // 8.12.9
        Object c = getOwnProperty(contextname);
        if (c == .) {
            if (!isExtensible()) {
                return reject(contextshouldThrow);
            } else {
                PropertyDescriptor newDesc = null;
                if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
                    newDesc = desc.duplicateWithDefaults("Value""Writable""Enumerable""Configurable");
                } else {
                    newDesc = desc.duplicateWithDefaults("Get""Set""Enumerable""Configurable");
                }
                // System.err.println("DEF.initial: " + name + " > " + newDesc);
                this..put(namenewDesc);
                return true;
            }
        }
        if (desc.isEmpty()) {
            return true;
        }
        PropertyDescriptor current = (PropertyDescriptorc;
        if (current.hasConfigurable() && !current.isConfigurable()) {
            if (desc.hasConfigurable() && desc.isConfigurable()) {
                return reject(contextshouldThrow);
            }
            Object currentEnumerable = current.get("Enumerable");
            Object descEnumerable = desc.get("Enumerable");
            if ((currentEnumerable != . && descEnumerable != .) && (currentEnumerable != descEnumerable)) {
                return reject(contextshouldThrow);
            }
        }
        PropertyDescriptor newDesc = null;
        if (desc.isGenericDescriptor()) {
            newDesc = new PropertyDescriptor();
            newDesc.copyAll(current);
            // System.err.println("DEF.generic: " + name + " > " + newDesc);
        } else if (current.isDataDescriptor() != desc.isDataDescriptor()) {
            if (!current.isConfigurable()) {
                return reject(contextshouldThrow);
            }
            if (current.isDataDescriptor()) {
                // System.err.println("accessor");
                newDesc = PropertyDescriptor.newAccessorPropertyDescriptor(true);
            } else {
                // System.err.println("data");
                newDesc = PropertyDescriptor.newDataPropertyDescriptor(true);
            }
            // System.err.println("DEF.mismatch: " + name + " > " + newDesc);
        } else if (current.isDataDescriptor() && desc.isDataDescriptor()) {
            if (!current.isConfigurable()) {
                Object currentWritable = current.get("Writable");
                if ((currentWritable != .) && !current.isWritable()) {
                    if (desc.isWritable()) {
                        return reject(contextshouldThrow);
                    }
                    Object newValue = desc.getValue();
                    if (newValue != null && !Types.sameValue(current.getValue(), newValue)) {
                        return reject(contextshouldThrow);
                    }
                }
            }
            newDesc = PropertyDescriptor.newDataPropertyDescriptor(true);
            if (current.hasValue()) {
                newDesc.set("Value"current.get("Value"));
            }
            if (current.hasWritable()) {
                newDesc.set("Writable"current.get("Writable"));
            }
            // System.err.println("DEF.data: " + name + " > " + newDesc);
        } else if (current.isAccessorDescriptor() && desc.isAccessorDescriptor()) {
            if (!current.isConfigurable()) {
                Object newSetter = desc.getSetter();
                if (newSetter != null && !Types.sameValue(current.getSetter(), newSetter)) {
                    return reject(contextshouldThrow);
                }
                Object newGetter = desc.getGetter();
                if (newGetter != null && !Types.sameValue(current.getGetter(), newGetter)) {
                    return reject(contextshouldThrow);
                }
            }
            newDesc = PropertyDescriptor.newAccessorPropertyDescriptor(true);
            if (current.hasSet()) {
                newDesc.set("Set"current.get("Set"));
            }
            if (current.hasGet()) {
                newDesc.set("Get"current.get("Get"));
            }
            // System.err.println("DEF.accessor: " + name + " > " + newDesc);
        }
        if (current.hasConfigurable()) {
            newDesc.set("Configurable"current.get("Configurable"));
        }
        if (current.hasEnumerable()) {
            newDesc.set("Enumerable"current.get("Enumerable"));
        }
        newDesc.copyAll(desc);
        this..put(namenewDesc);
        return true;
        /*
         * if (current.hasConfigurable()) {
         * newDesc.set("Configurable", current.get("Configurable"));
         * }
         * if (current.hasEnumerable()) {
         * newDesc.set("Enumerable", current.get("Enumerable"));
         * }
         * 
         * if (current.hasWritable()) {
         * newDesc.set("Writable", current.get("Writable"));
         * }
         * 
         * newDesc.copyAll(current);
         * newDesc.copyAll(desc);
         * System.err.println( this + " def: " + name + " > " + newDesc );
         * this.properties.put(name, newDesc);
         * return true;
         * }
         */
    }
    protected boolean reject(ExecutionContext contextboolean shouldThrow) {
        if (shouldThrow) {
            throw new ThrowException(contextcontext.createTypeError("unable to perform operation"));
        }
        return false;
    }
    @Override
        ArrayList<Stringnames = new ArrayList<String>();
        for (String name : this..keySet()) {
            names.add(name);
        }
        return new NameEnumerator(names);
    }
    @Override
        ArrayList<Stringnames = new ArrayList<String>();
        for (String name : this..keySet()) {
            PropertyDescriptor desc = this..get(name);
            if (desc.isEnumerable()) {
                names.add(name);
            }
        }
        return new NameEnumerator(names);
    }
    @Override
        ArrayList<Stringnames = new ArrayList<String>();
        if (this. != null) {
            names.addAll(this..getAllEnumerablePropertyNames().toList());
        }
        for (String name : this..keySet()) {
            PropertyDescriptor desc = this..get(name);
            if (desc.isEnumerable()) {
                names.add(name);
            } else {
                names.remove(name);
            }
        }
        return new NameEnumerator(names);
    }
    @Override
    public void defineNonEnumerableProperty(final GlobalObject globalObjectString namefinal Object value) {
        this.defineOwnProperty(nullnamenew PropertyDescriptor() {
            {
                set("Value"value);
                set("Writable"true);
                set("Enumerable"false);
                set("Configurable"true);
            }
        }, false);
    }
    @Override
    public void defineReadOnlyProperty(final GlobalObject globalObjectString namefinal Object value) {
        this.defineOwnProperty(nullnamenew PropertyDescriptor() {
            {
                set("Value"value);
                set("Writable"false);
                set("Enumerable"false);
                set("Configurable"false);
            }
        }, false);
    }
    protected Object getOwnIndexedProperty(ExecutionContext contextString name) {
        Long number = Types.toUint32(contextname);
        final int index = number.intValue();
        if (index < 0 || index >= .) {
            return .;
        } else {
            synchronized (this) {
                if (!this..containsKey(number)) {
                    this..put(numbernew PropertyDescriptor() {
                        {
                            set("Value"[index]);
                            set("Writable"true);
                            set("Enumerable"false);
                            set("Configurable"false);
                        }
                    });
                }
            }
            return this..get(number);
        }
    }
    protected void putIndexedValue(ExecutionContext contextString nameObject value) {
        Long possibleIndex = Types.toUint32(contextname);
        final int index = possibleIndex.intValue();
        if (index < 0 || index >= .) {
            this.put(contextnamevaluefalse);
        } else {
            synchronized (this) {
                putValueAtIndex(contextvalueindex);
                if (!this..containsKey(possibleIndex)) {
                    this..put(possibleIndexnew PropertyDescriptor() {
                        {
                            set("Value"[index]);
                            set("Writable"true);
                            set("Enumerable"false);
                            set("Configurable"false);
                        }
                    });
                }
            }
        }
    }
    protected void putValueAtIndex(ExecutionContext contextObject valueint index) {
        // buffer[index] = value;
        Long numberValue = Types.toUint32(contextvalue);
        this.getBackingArray()[index] = numberValue.byteValue() & 0xff;
    }
    // May return null
    public Object[] getBackingArray() {
        return ;
    }
    public void setBackingArray(Object[] buffer) {
        this. = buffer;
    }
    // java.util.Map
    @Override
    public int size() {
        return getAllEnumerablePropertyNames().size();
    }
    @Override
    public boolean isEmpty() {
        return getAllEnumerablePropertyNames().isEmpty();
    }
    @Override
    public boolean containsKey(Object key) {
        Object desc = getProperty(nullkey.toString());
        return (desc != .);
    }
    @Override
    public boolean containsValue(Object value) {
        // TODO Auto-generated method stub
        return false;
    }
    @Override
    public Object get(Object key) {
        Object result = get(nullkey.toString());
        if ( result == . ) {
            return null;
        }
        
        return result;
    }
    @Override
    public Object put(String keyObject value) {
        Object oldValue = get(nullkey.toString());
        put(nullkeyvaluefalse);
        return oldValue;
    }
    @Override
    public Object remove(Object key) {
        Object oldValue = get(nullkey.toString());
        delete(nullkey.toString(), false);
        return oldValue;
    }
    @Override
    public void putAll(Map<? extends String, ? extends Objectm) {
        // TODO Auto-generated method stub
    }
    @Override
    public void clear() {
        // TODO Auto-generated method stub
    }
    @Override
    public Set<StringkeySet() {
        return new KeySet();
    }
    @Override
    public Collection<Objectvalues() {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public Set<java.util.Map.Entry<StringObject>> entrySet() {
        // TODO Auto-generated method stub
        return null;
    }
    protected class KeySet implements Set<String> {
        @Override
        public int size() {
            return getAllEnumerablePropertyNames().size();
        }
        @Override
        public boolean isEmpty() {
            return getAllEnumerablePropertyNames().isEmpty();
        }
        @Override
        public boolean contains(Object o) {
            return hasProperty(nullo.toString());
        }
        @Override
        public Iterator<Stringiterator() {
            return getAllEnumerablePropertyNames().toList().iterator();
        }
        @Override
        public Object[] toArray() {
            return getAllEnumerablePropertyNames().toList().toArray();
        }
        @Override
        public <T> T[] toArray(T[] a) {
            return getAllEnumerablePropertyNames().toList().toArray(a);
        }
        @Override
        public boolean add(String e) {
            if (! hasProperty(nulle)) {
                put(e.);
                return true;
            }
            return false;
        }
        @Override
        public boolean remove(Object o) {
            if ( hasProperty(nullo.toString())) {
                deletenullo.toString(), false );
                return true;
            }
            return false;
        }
        @Override
        public boolean containsAll(Collection<?> c) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean addAll(Collection<? extends Stringc) {
            return false;
        }
        @Override
        public boolean retainAll(Collection<?> c) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public boolean removeAll(Collection<?> c) {
            // TODO Auto-generated method stub
            return false;
        }
        @Override
        public void clear() {
            // TODO Auto-generated method stub
        }
        
        public String toString() {
            return getAllEnumerablePropertyNames().toList().toString();
        }
    }
New to GrepCode? Check out our FAQ X