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 AccessorPropertyDescriptor(final boolean configurable, final boolean enumerable, final Object get, final Object set, final Global global) { 71 super(global.getObjectPrototype(), $nasgenmap$); 72 this.configurable = configurable; 73 this.enumerable = enumerable; 74 this.get = get; 75 this.set = set; 76 } 77 78 @Override 79 public boolean isConfigurable() { 80 return JSType.toBoolean(configurable); 81 } 82 83 @Override 84 public boolean isEnumerable() { 85 return JSType.toBoolean(enumerable); 86 } 87 88 @Override 89 public boolean isWritable() { 90 // Not applicable for this. But simplifies flag calculations. 91 return true; 92 } 93 94 @Override 95 public Object getValue() { 96 throw new UnsupportedOperationException("value"); 97 } 98 99 @Override 100 public ScriptFunction getGetter() { 101 return (get instanceof ScriptFunction) ? (ScriptFunction)get : null; 102 } 103 104 @Override 105 public ScriptFunction getSetter() { 106 return (set instanceof ScriptFunction) ? (ScriptFunction)set : null; 107 } 108 109 @Override 110 public void setConfigurable(final boolean flag) { 111 this.configurable = flag; 112 } 113 114 @Override 115 public void setEnumerable(final boolean flag) { 116 this.enumerable = flag; 117 } 118 119 @Override 120 public void setWritable(final boolean flag) { 121 throw new UnsupportedOperationException("set writable"); 122 } 123 124 @Override 125 public void setValue(final Object value) { 126 throw new UnsupportedOperationException("set value"); 127 } 128 129 @Override 130 public void setGetter(final Object getter) { 131 this.get = getter; 132 } 133 134 @Override 135 public void setSetter(final Object setter) { 136 this.set = setter; 137 } 138 139 @Override 140 public PropertyDescriptor fillFrom(final ScriptObject sobj) { 141 if (sobj.has(CONFIGURABLE)) { 142 this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE)); 143 } else { 144 delete(CONFIGURABLE, false); 145 } 146 147 if (sobj.has(ENUMERABLE)) { 148 this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE)); 149 } else { 150 delete(ENUMERABLE, false); 151 } 152 153 if (sobj.has(GET)) { 154 final Object getter = sobj.get(GET); 155 if (getter == UNDEFINED || getter instanceof ScriptFunction) { 156 this.get = getter; 157 } else { 158 throw typeError("not.a.function", ScriptRuntime.safeToString(getter)); 159 } 160 } else { 161 delete(GET, false); 162 } 163 164 if (sobj.has(SET)) { 165 final Object setter = sobj.get(SET); 166 if (setter == UNDEFINED || setter instanceof ScriptFunction) { 167 this.set = setter; 168 } else { 169 throw typeError("not.a.function", ScriptRuntime.safeToString(setter)); 170 } 171 } else { 172 delete(SET, false); 173 } 174 175 return this; 176 } 177 178 @Override 179 public int type() { 180 return ACCESSOR; 181 } 182 183 @Override 184 public boolean hasAndEquals(final PropertyDescriptor otherDesc) { 185 if (! (otherDesc instanceof AccessorPropertyDescriptor)) { 186 return false; 187 } 188 final AccessorPropertyDescriptor other = (AccessorPropertyDescriptor)otherDesc; 189 return (!has(CONFIGURABLE) || sameValue(configurable, other.configurable)) && 190 (!has(ENUMERABLE) || sameValue(enumerable, other.enumerable)) && 191 (!has(GET) || sameValue(get, other.get)) && 192 (!has(SET) || sameValue(set, other.set)); 193 } 194 195 @Override 196 public boolean equals(final Object obj) { 197 if (this == obj) { 198 return true; 199 } 200 if (! (obj instanceof AccessorPropertyDescriptor)) { 201 return false; 202 } 203 204 final AccessorPropertyDescriptor other = (AccessorPropertyDescriptor)obj; 205 return sameValue(configurable, other.configurable) && 206 sameValue(enumerable, other.enumerable) && 207 sameValue(get, other.get) && 208 sameValue(set, other.set); 209 } 210 211 @Override 212 public int hashCode() { 213 int hash = 7; 214 hash = 41 * hash + Objects.hashCode(this.configurable); 215 hash = 41 * hash + Objects.hashCode(this.enumerable); 216 hash = 41 * hash + Objects.hashCode(this.get); 217 hash = 41 * hash + Objects.hashCode(this.set); 218 return hash; 219 } 220 }