1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.objects; 27 28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; 29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; 30 import static jdk.nashorn.internal.runtime.ScriptRuntime.sameValue; 31 32 import java.util.Objects; 33 import jdk.nashorn.internal.objects.annotations.Property; 34 import jdk.nashorn.internal.objects.annotations.ScriptClass; 35 import jdk.nashorn.internal.runtime.JSType; 36 import jdk.nashorn.internal.runtime.PropertyDescriptor; 37 import jdk.nashorn.internal.runtime.PropertyMap; 38 import jdk.nashorn.internal.runtime.ScriptFunction; 39 import jdk.nashorn.internal.runtime.ScriptObject; 40 import jdk.nashorn.internal.runtime.ScriptRuntime; 41 42 /** 43 * Accessor Property descriptor is used to represent attributes an object property 44 * that either has a getter or a setter. 45 * 46 * See ECMA 8.10 The Property Descriptor and Property Identifier Specification Types 47 * 48 */ 49 @ScriptClass("AccessorPropertyDescriptor") 50 public final class AccessorPropertyDescriptor extends ScriptObject implements PropertyDescriptor { 51 /** is this property configurable? */ 52 @Property 53 public Object configurable; 54 55 /** is this property enumerable? */ 56 @Property 57 public Object enumerable; 58 59 /** getter for property */ 60 @Property 61 public Object get; 62 63 /** setter for property */ 64 @Property 65 public Object set; 66 67 // initialized by nasgen 68 private static PropertyMap $nasgenmap$; 69 70 static PropertyMap getInitialMap() { 71 return $nasgenmap$; 72 } 73 74 AccessorPropertyDescriptor(final boolean configurable, final boolean enumerable, final Object get, final Object set, final Global global) { 75 super(global.getObjectPrototype(), getInitialMap()); 76 this.configurable = configurable; 77 this.enumerable = enumerable; 78 this.get = get; 79 this.set = set; 80 } 81 82 @Override 83 public boolean isConfigurable() { 84 return JSType.toBoolean(configurable); 85 } 86 87 @Override 88 public boolean isEnumerable() { 89 return JSType.toBoolean(enumerable); 90 } 91 92 @Override 93 public boolean isWritable() { 94 // Not applicable for this. But simplifies flag calculations. 95 return true; 96 } 97 98 @Override 99 public Object getValue() { 100 throw new UnsupportedOperationException("value"); 101 } 102 103 @Override 104 public ScriptFunction getGetter() { 105 return (get instanceof ScriptFunction) ? (ScriptFunction)get : null; 106 } 107 108 @Override 109 public ScriptFunction getSetter() { 110 return (set instanceof ScriptFunction) ? (ScriptFunction)set : null; 111 } 112 113 @Override 114 public void setConfigurable(final boolean flag) { 115 this.configurable = flag; 116 } 117 118 @Override 119 public void setEnumerable(final boolean flag) { 120 this.enumerable = flag; 121 } 122 123 @Override 124 public void setWritable(final boolean flag) { 125 throw new UnsupportedOperationException("set writable"); 126 } 127 128 @Override 129 public void setValue(final Object value) { 130 throw new UnsupportedOperationException("set value"); 131 } 132 133 @Override 134 public void setGetter(final Object getter) { 135 this.get = getter; 136 } 137 138 @Override 139 public void setSetter(final Object setter) { 140 this.set = setter; 141 } 142 143 @Override 144 public PropertyDescriptor fillFrom(final ScriptObject sobj) { 145 if (sobj.has(CONFIGURABLE)) { 146 this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE)); 147 } else { 148 delete(CONFIGURABLE, false); 149 } 150 151 if (sobj.has(ENUMERABLE)) { 152 this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE)); 153 } else { 154 delete(ENUMERABLE, false); 155 } 156 157 if (sobj.has(GET)) { 158 final Object getter = sobj.get(GET); 159 if (getter == UNDEFINED || getter instanceof ScriptFunction) { 160 this.get = getter; 161 } else { 162 throw typeError("not.a.function", ScriptRuntime.safeToString(getter)); 163 } 164 } else { 165 delete(GET, false); 166 } 167 168 if (sobj.has(SET)) { 169 final Object setter = sobj.get(SET); 170 if (setter == UNDEFINED || setter instanceof ScriptFunction) { 171 this.set = setter; 172 } else { 173 throw typeError("not.a.function", ScriptRuntime.safeToString(setter)); 174 } 175 } else { 176 delete(SET, false); 177 } 178 179 return this; 180 } 181 182 @Override 183 public int type() { 184 return ACCESSOR; 185 } 186 187 @Override 188 public boolean hasAndEquals(final PropertyDescriptor otherDesc) { 189 if (! (otherDesc instanceof AccessorPropertyDescriptor)) { 190 return false; 191 } 192 final AccessorPropertyDescriptor other = (AccessorPropertyDescriptor)otherDesc; 193 return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) && 194 (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) && 195 (!has(GET) || sameValue(get, other.get)) && 196 (!has(SET) || sameValue(set, other.set)); 197 } 198 199 @Override 200 public boolean equals(final Object obj) { 201 if (this == obj) { 202 return true; 203 } 204 if (! (obj instanceof AccessorPropertyDescriptor)) { 205 return false; 206 } 207 208 final AccessorPropertyDescriptor other = (AccessorPropertyDescriptor)obj; 209 return sameValue(configurable, other.configurable) && 210 sameValue(enumerable, other.enumerable) && 211 sameValue(get, other.get) && 212 sameValue(set, other.set); 213 } 214 215 @Override 216 public int hashCode() { 217 int hash = 7; 218 hash = 41 * hash + Objects.hashCode(this.configurable); 219 hash = 41 * hash + Objects.hashCode(this.enumerable); 220 hash = 41 * hash + Objects.hashCode(this.get); 221 hash = 41 * hash + Objects.hashCode(this.set); 222 return hash; 223 } 224 }