Tue, 22 Jan 2013 22:07:12 +0530
8006678: Avoid too many Context.getGlobal() calls
Reviewed-by: lagergren, jlaskey
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 */
26 package jdk.nashorn.internal.objects;
28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
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;
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);
54 private NativeObject() {
55 }
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);
68 return ((ScriptObject)obj).getProto();
69 }
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);
83 final String key = JSType.toString(prop);
84 final ScriptObject sobj = (ScriptObject)obj;
86 return sobj.getOwnPropertyDescriptor(key);
87 }
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);
100 return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
101 }
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 }
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 }
125 return newObj;
126 }
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 }
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);
156 final ScriptObject sobj = (ScriptObject)obj;
157 final Object propsObj = Global.toObject(props);
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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);
276 // Object(null), Object(undefined), Object() are same as "new Object()"
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 }
294 return Global.newEmptyInstance();
295 }
297 return Global.toObject(value);
298 }
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 }
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);
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 }
334 typeError("not.a.function", "toString");
335 throw new AssertionError(); // never reached
336 }
338 return ScriptRuntime.builtinObjectToString(self);
339 }
341 /**
342 * ECMA 15.2.4.4 Object.prototype.valueOf ( )
343 *
344 * @param self self reference
345 * @return value of object
346 */
347 @Function(attributes = Attribute.NOT_ENUMERABLE)
348 public static Object valueOf(final Object self) {
349 return Global.toObject(self);
350 }
352 /**
353 * ECMA 15.2.4.5 Object.prototype.hasOwnProperty (V)
354 *
355 * @param self self reference
356 * @param v property to check for
357 * @return true if property exists in object
358 */
359 @Function(attributes = Attribute.NOT_ENUMERABLE)
360 public static Object hasOwnProperty(final Object self, final Object v) {
361 final String str = JSType.toString(v);
362 final Object obj = Global.toObject(self);
364 return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(str);
365 }
367 /**
368 * ECMA 15.2.4.6 Object.prototype.isPrototypeOf (V)
369 *
370 * @param self self reference
371 * @param v v prototype object to check against
372 * @return true if object is prototype of v
373 */
374 @Function(attributes = Attribute.NOT_ENUMERABLE)
375 public static Object isPrototypeOf(final Object self, final Object v) {
376 if (!(v instanceof ScriptObject)) {
377 return false;
378 }
380 final Object obj = Global.toObject(self);
381 ScriptObject proto = (ScriptObject)v;
383 do {
384 proto = proto.getProto();
385 if (proto == obj) {
386 return true;
387 }
388 } while (proto != null);
390 return false;
391 }
393 /**
394 * ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V)
395 *
396 * @param self self reference
397 * @param v property to check if enumerable
398 * @return true if property is enumerable
399 */
400 @Function(attributes = Attribute.NOT_ENUMERABLE)
401 public static Object propertyIsEnumerable(final Object self, final Object v) {
402 final String str = JSType.toString(v);
403 final Object obj = Global.toObject(self);
405 if (obj instanceof ScriptObject) {
406 final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str);
407 return property != null && property.isEnumerable();
408 }
410 return false;
411 }
412 }