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