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 31 import jdk.nashorn.internal.objects.annotations.Attribute; 32 import jdk.nashorn.internal.objects.annotations.Constructor; 33 import jdk.nashorn.internal.objects.annotations.Function; 34 import jdk.nashorn.internal.objects.annotations.ScriptClass; 35 import jdk.nashorn.internal.objects.annotations.Where; 36 import jdk.nashorn.internal.runtime.JSType; 37 import jdk.nashorn.internal.runtime.ScriptFunction; 38 import jdk.nashorn.internal.runtime.ScriptObject; 39 import jdk.nashorn.internal.runtime.ScriptRuntime; 40 import jdk.nashorn.internal.runtime.linker.InvokeByName; 41 42 /** 43 * ECMA 15.2 Object objects 44 * 45 * JavaScript Object constructor/prototype. Note: instances of this class are 46 * never created. This class is not even a subclass of ScriptObject. But, we use 47 * this class to generate prototype and constructor for "Object". 48 * 49 */ 50 @ScriptClass("Object") 51 public final class NativeObject { 52 private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class); 53 54 private NativeObject() { 55 } 56 57 /** 58 * ECMA 15.2.3.2 Object.getPrototypeOf ( O ) 59 * 60 * @param self self reference 61 * @param obj object to get prototype from 62 * @return the prototype of an object 63 */ 64 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 65 public static Object getPrototypeOf(final Object self, final Object obj) { 66 Global.checkObject(obj); 67 68 return ((ScriptObject)obj).getProto(); 69 } 70 71 /** 72 * ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P ) 73 * 74 * @param self self reference 75 * @param obj object from which to get property descriptor for {@code ToString(prop)} 76 * @param prop property descriptor 77 * @return property descriptor 78 */ 79 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 80 public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) { 81 Global.checkObject(obj); 82 83 final String key = JSType.toString(prop); 84 final ScriptObject sobj = (ScriptObject)obj; 85 86 return sobj.getOwnPropertyDescriptor(key); 87 } 88 89 /** 90 * ECMA 15.2.3.4 Object.getOwnPropertyNames ( O ) 91 * 92 * @param self self reference 93 * @param obj object to query for property names 94 * @return array of property names 95 */ 96 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 97 public static Object getOwnPropertyNames(final Object self, final Object obj) { 98 Global.checkObject(obj); 99 100 return new NativeArray(((ScriptObject)obj).getOwnKeys(true)); 101 } 102 103 /** 104 * ECMA 15.2.3.5 Object.create ( O [, Properties] ) 105 * 106 * @param self self reference 107 * @param proto prototype object 108 * @param props properties to define 109 * @return object created 110 */ 111 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 112 public static Object create(final Object self, final Object proto, final Object props) { 113 if (proto != null) { 114 Global.checkObject(proto); 115 } 116 117 // FIXME: should we create a proper object with correct number of 118 // properties? 119 final ScriptObject newObj = Global.newEmptyInstance(); 120 newObj.setProtoCheck(proto); 121 if (props != UNDEFINED) { 122 NativeObject.defineProperties(self, newObj, props); 123 } 124 125 return newObj; 126 } 127 128 /** 129 * ECMA 15.2.3.6 Object.defineProperty ( O, P, Attributes ) 130 * 131 * @param self self reference 132 * @param obj object in which to define a property 133 * @param prop property to define 134 * @param attr attributes for property descriptor 135 * @return object 136 */ 137 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 138 public static Object defineProperty(final Object self, final Object obj, final Object prop, final Object attr) { 139 Global.checkObject(obj); 140 ((ScriptObject)obj).defineOwnProperty(JSType.toString(prop), attr, true); 141 return obj; 142 } 143 144 /** 145 * ECMA 5.2.3.7 Object.defineProperties ( O, Properties ) 146 * 147 * @param self self reference 148 * @param obj object in which to define properties 149 * @param props properties 150 * @return object 151 */ 152 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 153 public static Object defineProperties(final Object self, final Object obj, final Object props) { 154 Global.checkObject(obj); 155 156 final ScriptObject sobj = (ScriptObject)obj; 157 final Object propsObj = Global.toObject(props); 158 159 if (propsObj instanceof ScriptObject) { 160 final Object[] keys = ((ScriptObject)propsObj).getOwnKeys(false); 161 for (final Object key : keys) { 162 final String prop = JSType.toString(key); 163 sobj.defineOwnProperty(prop, ((ScriptObject)propsObj).get(prop), true); 164 } 165 } 166 return sobj; 167 } 168 169 /** 170 * ECMA 15.2.3.8 Object.seal ( O ) 171 * 172 * @param self self reference 173 * @param obj object to seal 174 * @return sealed object 175 */ 176 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 177 public static Object seal(final Object self, final Object obj) { 178 Global.checkObject(obj); 179 return ((ScriptObject)obj).seal(); 180 } 181 182 183 /** 184 * ECMA 15.2.3.9 Object.freeze ( O ) 185 * 186 * @param self self reference 187 * @param obj object to freeze 188 * @return frozen object 189 */ 190 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 191 public static Object freeze(final Object self, final Object obj) { 192 Global.checkObject(obj); 193 return ((ScriptObject)obj).freeze(); 194 } 195 196 /** 197 * ECMA 15.2.3.10 Object.preventExtensions ( O ) 198 * 199 * @param self self reference 200 * @param obj object, for which to set the internal extensible property to false 201 * @return object 202 */ 203 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 204 public static Object preventExtensions(final Object self, final Object obj) { 205 Global.checkObject(obj); 206 return ((ScriptObject)obj).preventExtensions(); 207 } 208 209 /** 210 * ECMA 15.2.3.11 Object.isSealed ( O ) 211 * 212 * @param self self reference 213 * @param obj check whether an object is sealed 214 * @return true if sealed, false otherwise 215 */ 216 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 217 public static Object isSealed(final Object self, final Object obj) { 218 Global.checkObject(obj); 219 return ((ScriptObject)obj).isSealed(); 220 } 221 222 /** 223 * ECMA 15.2.3.12 Object.isFrozen ( O ) 224 * 225 * @param self self reference 226 * @param obj check whether an object 227 * @return true if object is frozen, false otherwise 228 */ 229 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 230 public static Object isFrozen(final Object self, final Object obj) { 231 Global.checkObject(obj); 232 return ((ScriptObject)obj).isFrozen(); 233 } 234 235 /** 236 * ECMA 15.2.3.13 Object.isExtensible ( O ) 237 * 238 * @param self self reference 239 * @param obj check whether an object is extensible 240 * @return true if object is extensible, false otherwise 241 */ 242 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 243 public static Object isExtensible(final Object self, final Object obj) { 244 Global.checkObject(obj); 245 return ((ScriptObject)obj).isExtensible(); 246 } 247 248 /** 249 * ECMA 15.2.3.14 Object.keys ( O ) 250 * 251 * @param self self reference 252 * @param obj object from which to extract keys 253 * @return array of keys in object 254 */ 255 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) 256 public static Object keys(final Object self, final Object obj) { 257 Global.checkObject(obj); 258 final ScriptObject sobj = (ScriptObject)obj; 259 return new NativeArray(sobj.getOwnKeys(false)); 260 } 261 262 /** 263 * ECMA 15.2.2.1 , 15.2.1.1 new Object([value]) and Object([value]) 264 * 265 * Constructor 266 * 267 * @param newObj is the new object instantiated with the new operator 268 * @param self self reference 269 * @param value value of object to be instantiated 270 * @return the new NativeObject 271 */ 272 @Constructor 273 public static Object construct(final boolean newObj, final Object self, final Object value) { 274 final JSType type = JSType.of(value); 275 276 // Object(null), Object(undefined), Object() are same as "new Object()" 277 278 if (newObj || (type == JSType.NULL || type == JSType.UNDEFINED)) { 279 switch (type) { 280 case BOOLEAN: 281 case NUMBER: 282 case STRING: 283 return Global.toObject(value); 284 case OBJECT: 285 case FUNCTION: 286 return value; 287 case NULL: 288 case UNDEFINED: 289 // fall through.. 290 default: 291 break; 292 } 293 294 return Global.newEmptyInstance(); 295 } 296 297 return Global.toObject(value); 298 } 299 300 /** 301 * ECMA 15.2.4.2 Object.prototype.toString ( ) 302 * 303 * @param self self reference 304 * @return ToString of object 305 */ 306 @Function(attributes = Attribute.NOT_ENUMERABLE) 307 public static Object toString(final Object self) { 308 return ScriptRuntime.builtinObjectToString(self); 309 } 310 311 /** 312 * ECMA 15.2.4.3 Object.prototype.toLocaleString ( ) 313 * 314 * @param self self reference 315 * @return localized ToString 316 */ 317 @Function(attributes = Attribute.NOT_ENUMERABLE) 318 public static Object toLocaleString(final Object self) { 319 final Object obj = JSType.toScriptObject(self); 320 if (obj instanceof ScriptObject) { 321 final ScriptObject sobj = (ScriptObject)self; 322 try { 323 final Object toString = TO_STRING.getGetter().invokeExact(sobj); 324 325 if (toString instanceof ScriptFunction) { 326 return TO_STRING.getInvoker().invokeExact(toString, sobj); 327 } 328 } catch (final RuntimeException | Error e) { 329 throw e; 330 } catch (final Throwable t) { 331 throw new RuntimeException(t); 332 } 333 334 throw typeError("not.a.function", "toString"); 335 } 336 337 return ScriptRuntime.builtinObjectToString(self); 338 } 339 340 /** 341 * ECMA 15.2.4.4 Object.prototype.valueOf ( ) 342 * 343 * @param self self reference 344 * @return value of object 345 */ 346 @Function(attributes = Attribute.NOT_ENUMERABLE) 347 public static Object valueOf(final Object self) { 348 return Global.toObject(self); 349 } 350 351 /** 352 * ECMA 15.2.4.5 Object.prototype.hasOwnProperty (V) 353 * 354 * @param self self reference 355 * @param v property to check for 356 * @return true if property exists in object 357 */ 358 @Function(attributes = Attribute.NOT_ENUMERABLE) 359 public static Object hasOwnProperty(final Object self, final Object v) { 360 final String str = JSType.toString(v); 361 final Object obj = Global.toObject(self); 362 363 return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(str); 364 } 365 366 /** 367 * ECMA 15.2.4.6 Object.prototype.isPrototypeOf (V) 368 * 369 * @param self self reference 370 * @param v v prototype object to check against 371 * @return true if object is prototype of v 372 */ 373 @Function(attributes = Attribute.NOT_ENUMERABLE) 374 public static Object isPrototypeOf(final Object self, final Object v) { 375 if (!(v instanceof ScriptObject)) { 376 return false; 377 } 378 379 final Object obj = Global.toObject(self); 380 ScriptObject proto = (ScriptObject)v; 381 382 do { 383 proto = proto.getProto(); 384 if (proto == obj) { 385 return true; 386 } 387 } while (proto != null); 388 389 return false; 390 } 391 392 /** 393 * ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V) 394 * 395 * @param self self reference 396 * @param v property to check if enumerable 397 * @return true if property is enumerable 398 */ 399 @Function(attributes = Attribute.NOT_ENUMERABLE) 400 public static Object propertyIsEnumerable(final Object self, final Object v) { 401 final String str = JSType.toString(v); 402 final Object obj = Global.toObject(self); 403 404 if (obj instanceof ScriptObject) { 405 final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str); 406 return property != null && property.isEnumerable(); 407 } 408 409 return false; 410 } 411 } --- EOF ---