131 @SuppressWarnings("unused")
132 private static PropertyMap $nasgenmap$;
133
134 private NativeObject() {
135 // don't create me!
136 throw new UnsupportedOperationException();
137 }
138
139 private static ECMAException notAnObject(final Object obj) {
140 return typeError("not.an.object", ScriptRuntime.safeToString(obj));
141 }
142
143 /**
144 * Nashorn extension: setIndexedPropertiesToExternalArrayData
145 *
146 * @param self self reference
147 * @param obj object whose index properties are backed by buffer
148 * @param buf external buffer - should be a nio ByteBuffer
149 * @return the 'obj' object
150 */
151 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
152 public static ScriptObject setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) {
153 Global.checkObject(obj);
154 final ScriptObject sobj = (ScriptObject)obj;
155 if (buf instanceof ByteBuffer) {
156 sobj.setArray(ArrayData.allocate((ByteBuffer)buf));
157 } else {
158 throw typeError("not.a.bytebuffer", "setIndexedPropertiesToExternalArrayData's buf argument");
159 }
160 return sobj;
161 }
162
163
164 /**
165 * ECMA 15.2.3.2 Object.getPrototypeOf ( O )
166 *
167 * @param self self reference
168 * @param obj object to get prototype from
169 * @return the prototype of an object
170 */
171 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
172 public static Object getPrototypeOf(final Object self, final Object obj) {
173 if (obj instanceof ScriptObject) {
174 return ((ScriptObject)obj).getProto();
175 } else if (obj instanceof ScriptObjectMirror) {
176 return ((ScriptObjectMirror)obj).getProto();
177 } else {
178 final JSType type = JSType.of(obj);
179 if (type == JSType.OBJECT) {
180 // host (Java) objects have null __proto__
181 return null;
182 }
183
184 // must be some JS primitive
185 throw notAnObject(obj);
186 }
187 }
188
189 /**
190 * Nashorn extension: Object.setPrototypeOf ( O, proto )
191 * Also found in ES6 draft specification.
192 *
193 * @param self self reference
194 * @param obj object to set prototype for
195 * @param proto prototype object to be used
196 * @return object whose prototype is set
197 */
198 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
199 public static Object setPrototypeOf(final Object self, final Object obj, final Object proto) {
200 if (obj instanceof ScriptObject) {
201 ((ScriptObject)obj).setPrototypeOf(proto);
202 return obj;
203 } else if (obj instanceof ScriptObjectMirror) {
204 ((ScriptObjectMirror)obj).setProto(proto);
205 return obj;
206 }
207
208 throw notAnObject(obj);
209 }
210
211 /**
212 * ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P )
213 *
214 * @param self self reference
215 * @param obj object from which to get property descriptor for {@code ToString(prop)}
216 * @param prop property descriptor
217 * @return property descriptor
218 */
219 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
220 public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) {
221 if (obj instanceof ScriptObject) {
222 final String key = JSType.toString(prop);
223 final ScriptObject sobj = (ScriptObject)obj;
224
225 return sobj.getOwnPropertyDescriptor(key);
226 } else if (obj instanceof ScriptObjectMirror) {
227 final String key = JSType.toString(prop);
228 final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
229
230 return sobjMirror.getOwnPropertyDescriptor(key);
231 } else {
232 throw notAnObject(obj);
233 }
234 }
235
236 /**
237 * ECMA 15.2.3.4 Object.getOwnPropertyNames ( O )
238 *
239 * @param self self reference
240 * @param obj object to query for property names
241 * @return array of property names
242 */
243 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
244 public static ScriptObject getOwnPropertyNames(final Object self, final Object obj) {
245 if (obj instanceof ScriptObject) {
246 return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
247 } else if (obj instanceof ScriptObjectMirror) {
248 return new NativeArray(((ScriptObjectMirror)obj).getOwnKeys(true));
249 } else {
250 throw notAnObject(obj);
251 }
252 }
253
254 /**
255 * ECMA 2 19.1.2.8 Object.getOwnPropertySymbols ( O )
256 *
257 * @param self self reference
258 * @param obj object to query for property names
259 * @return array of property names
260 */
261 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
262 public static ScriptObject getOwnPropertySymbols(final Object self, final Object obj) {
263 if (obj instanceof ScriptObject) {
264 return new NativeArray(((ScriptObject)obj).getOwnSymbols(true));
265 } else {
266 // TODO: we don't support this on ScriptObjectMirror objects yet
267 throw notAnObject(obj);
268 }
269 }
270
271 /**
272 * ECMA 15.2.3.5 Object.create ( O [, Properties] )
273 *
274 * @param self self reference
275 * @param proto prototype object
276 * @param props properties to define
277 * @return object created
278 */
279 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
280 public static ScriptObject create(final Object self, final Object proto, final Object props) {
281 if (proto != null) {
282 Global.checkObject(proto);
283 }
284
285 // FIXME: should we create a proper object with correct number of
286 // properties?
287 final ScriptObject newObj = Global.newEmptyInstance();
288 newObj.setProto((ScriptObject)proto);
289 if (props != UNDEFINED) {
290 NativeObject.defineProperties(self, newObj, props);
291 }
292
293 return newObj;
294 }
295
296 /**
297 * ECMA 15.2.3.6 Object.defineProperty ( O, P, Attributes )
298 *
299 * @param self self reference
300 * @param obj object in which to define a property
301 * @param prop property to define
302 * @param attr attributes for property descriptor
303 * @return object
304 */
305 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
306 public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
307 final ScriptObject sobj = Global.checkObject(obj);
308 sobj.defineOwnProperty(JSType.toPropertyKey(prop), attr, true);
309 return sobj;
310 }
311
312 /**
313 * ECMA 5.2.3.7 Object.defineProperties ( O, Properties )
314 *
315 * @param self self reference
316 * @param obj object in which to define properties
317 * @param props properties
318 * @return object
319 */
320 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
321 public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
322 final ScriptObject sobj = Global.checkObject(obj);
323 final Object propsObj = Global.toObject(props);
324
325 if (propsObj instanceof ScriptObject) {
326 final Object[] keys = ((ScriptObject)propsObj).getOwnKeys(false);
327 for (final Object key : keys) {
328 final String prop = JSType.toString(key);
329 sobj.defineOwnProperty(prop, ((ScriptObject)propsObj).get(prop), true);
330 }
331 }
332 return sobj;
333 }
334
335 /**
336 * ECMA 15.2.3.8 Object.seal ( O )
337 *
338 * @param self self reference
339 * @param obj object to seal
340 * @return sealed object
341 */
342 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
343 public static Object seal(final Object self, final Object obj) {
344 if (obj instanceof ScriptObject) {
345 return ((ScriptObject)obj).seal();
346 } else if (obj instanceof ScriptObjectMirror) {
347 return ((ScriptObjectMirror)obj).seal();
348 } else {
349 throw notAnObject(obj);
350 }
351 }
352
353
354 /**
355 * ECMA 15.2.3.9 Object.freeze ( O )
356 *
357 * @param self self reference
358 * @param obj object to freeze
359 * @return frozen object
360 */
361 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
362 public static Object freeze(final Object self, final Object obj) {
363 if (obj instanceof ScriptObject) {
364 return ((ScriptObject)obj).freeze();
365 } else if (obj instanceof ScriptObjectMirror) {
366 return ((ScriptObjectMirror)obj).freeze();
367 } else {
368 throw notAnObject(obj);
369 }
370 }
371
372 /**
373 * ECMA 15.2.3.10 Object.preventExtensions ( O )
374 *
375 * @param self self reference
376 * @param obj object, for which to set the internal extensible property to false
377 * @return object
378 */
379 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
380 public static Object preventExtensions(final Object self, final Object obj) {
381 if (obj instanceof ScriptObject) {
382 return ((ScriptObject)obj).preventExtensions();
383 } else if (obj instanceof ScriptObjectMirror) {
384 return ((ScriptObjectMirror)obj).preventExtensions();
385 } else {
386 throw notAnObject(obj);
387 }
388 }
389
390 /**
391 * ECMA 15.2.3.11 Object.isSealed ( O )
392 *
393 * @param self self reference
394 * @param obj check whether an object is sealed
395 * @return true if sealed, false otherwise
396 */
397 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
398 public static boolean isSealed(final Object self, final Object obj) {
399 if (obj instanceof ScriptObject) {
400 return ((ScriptObject)obj).isSealed();
401 } else if (obj instanceof ScriptObjectMirror) {
402 return ((ScriptObjectMirror)obj).isSealed();
403 } else {
404 throw notAnObject(obj);
405 }
406 }
407
408 /**
409 * ECMA 15.2.3.12 Object.isFrozen ( O )
410 *
411 * @param self self reference
412 * @param obj check whether an object
413 * @return true if object is frozen, false otherwise
414 */
415 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
416 public static boolean isFrozen(final Object self, final Object obj) {
417 if (obj instanceof ScriptObject) {
418 return ((ScriptObject)obj).isFrozen();
419 } else if (obj instanceof ScriptObjectMirror) {
420 return ((ScriptObjectMirror)obj).isFrozen();
421 } else {
422 throw notAnObject(obj);
423 }
424 }
425
426 /**
427 * ECMA 15.2.3.13 Object.isExtensible ( O )
428 *
429 * @param self self reference
430 * @param obj check whether an object is extensible
431 * @return true if object is extensible, false otherwise
432 */
433 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
434 public static boolean isExtensible(final Object self, final Object obj) {
435 if (obj instanceof ScriptObject) {
436 return ((ScriptObject)obj).isExtensible();
437 } else if (obj instanceof ScriptObjectMirror) {
438 return ((ScriptObjectMirror)obj).isExtensible();
439 } else {
440 throw notAnObject(obj);
441 }
442 }
443
444 /**
445 * ECMA 15.2.3.14 Object.keys ( O )
446 *
447 * @param self self reference
448 * @param obj object from which to extract keys
449 * @return array of keys in object
450 */
451 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
452 public static ScriptObject keys(final Object self, final Object obj) {
453 if (obj instanceof ScriptObject) {
454 final ScriptObject sobj = (ScriptObject)obj;
455 return new NativeArray(sobj.getOwnKeys(false));
456 } else if (obj instanceof ScriptObjectMirror) {
457 final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
458 return new NativeArray(sobjMirror.getOwnKeys(false));
459 } else {
460 throw notAnObject(obj);
461 }
462 }
463
464 /**
465 * ECMA 15.2.2.1 , 15.2.1.1 new Object([value]) and Object([value])
466 *
467 * Constructor
468 *
469 * @param newObj is the new object instantiated with the new operator
470 * @param self self reference
471 * @param value value of object to be instantiated
472 * @return the new NativeObject
473 */
474 @Constructor
475 public static Object construct(final boolean newObj, final Object self, final Object value) {
476 final JSType type = JSType.ofNoFunction(value);
477
478 // Object(null), Object(undefined), Object() are same as "new Object()"
479
480 if (newObj || type == JSType.NULL || type == JSType.UNDEFINED) {
481 switch (type) {
482 case BOOLEAN:
483 case NUMBER:
484 case STRING:
485 case SYMBOL:
486 return Global.toObject(value);
487 case OBJECT:
488 return value;
489 case NULL:
490 case UNDEFINED:
491 // fall through..
492 default:
493 break;
494 }
495
496 return Global.newEmptyInstance();
497 }
498
499 return Global.toObject(value);
500 }
501
502 /**
503 * ECMA 15.2.4.2 Object.prototype.toString ( )
504 *
505 * @param self self reference
506 * @return ToString of object
507 */
508 @Function(attributes = Attribute.NOT_ENUMERABLE)
509 public static String toString(final Object self) {
510 return ScriptRuntime.builtinObjectToString(self);
511 }
512
513 /**
514 * ECMA 15.2.4.3 Object.prototype.toLocaleString ( )
515 *
516 * @param self self reference
517 * @return localized ToString
518 */
519 @Function(attributes = Attribute.NOT_ENUMERABLE)
520 public static Object toLocaleString(final Object self) {
521 final Object obj = JSType.toScriptObject(self);
522 if (obj instanceof ScriptObject) {
523 final InvokeByName toStringInvoker = getTO_STRING();
524 final ScriptObject sobj = (ScriptObject)obj;
525 try {
526 final Object toString = toStringInvoker.getGetter().invokeExact(sobj);
527
528 if (Bootstrap.isCallable(toString)) {
541 }
542
543 /**
544 * ECMA 15.2.4.4 Object.prototype.valueOf ( )
545 *
546 * @param self self reference
547 * @return value of object
548 */
549 @Function(attributes = Attribute.NOT_ENUMERABLE)
550 public static Object valueOf(final Object self) {
551 return Global.toObject(self);
552 }
553
554 /**
555 * ECMA 15.2.4.5 Object.prototype.hasOwnProperty (V)
556 *
557 * @param self self reference
558 * @param v property to check for
559 * @return true if property exists in object
560 */
561 @Function(attributes = Attribute.NOT_ENUMERABLE)
562 public static boolean hasOwnProperty(final Object self, final Object v) {
563 // Convert ScriptObjects to primitive with String.class hint
564 // but no need to convert other primitives to string.
565 final Object key = JSType.toPrimitive(v, String.class);
566 final Object obj = Global.toObject(self);
567
568 return obj instanceof ScriptObject && ((ScriptObject)obj).hasOwnProperty(key);
569 }
570
571 /**
572 * ECMA 15.2.4.6 Object.prototype.isPrototypeOf (V)
573 *
574 * @param self self reference
575 * @param v v prototype object to check against
576 * @return true if object is prototype of v
577 */
578 @Function(attributes = Attribute.NOT_ENUMERABLE)
579 public static boolean isPrototypeOf(final Object self, final Object v) {
580 if (!(v instanceof ScriptObject)) {
581 return false;
582 }
583
584 final Object obj = Global.toObject(self);
585 ScriptObject proto = (ScriptObject)v;
586
587 do {
588 proto = proto.getProto();
589 if (proto == obj) {
590 return true;
591 }
592 } while (proto != null);
593
594 return false;
595 }
596
597 /**
598 * ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V)
599 *
600 * @param self self reference
601 * @param v property to check if enumerable
602 * @return true if property is enumerable
603 */
604 @Function(attributes = Attribute.NOT_ENUMERABLE)
605 public static boolean propertyIsEnumerable(final Object self, final Object v) {
606 final String str = JSType.toString(v);
607 final Object obj = Global.toObject(self);
608
609 if (obj instanceof ScriptObject) {
610 final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str);
611 return property != null && property.isEnumerable();
612 }
613
614 return false;
615 }
616
617 /**
618 * Nashorn extension: Object.bindProperties
619 *
620 * Binds the source object's properties to the target object. Binding
621 * properties allows two-way read/write for the properties of the source object.
622 *
623 * Example:
624 * <pre>
659 *
660 * Limitations of property binding:
661 * <ul>
662 * <li> Only enumerable, immediate (not proto inherited) properties of the source object are bound.
663 * <li> If the target object already contains a property called "foo", the source's "foo" is skipped (not bound).
664 * <li> Properties added to the source object after binding to the target are not bound.
665 * <li> Property configuration changes on the source object (or on the target) is not propagated.
666 * <li> Delete of property on the target (or the source) is not propagated -
667 * only the property value is set to 'undefined' if the property happens to be a data property.
668 * </ul>
669 * <p>
670 * It is recommended that the bound properties be treated as non-configurable
671 * properties to avoid surprises.
672 * </p>
673 *
674 * @param self self reference
675 * @param target the target object to which the source object's properties are bound
676 * @param source the source object whose properties are bound to the target
677 * @return the target object after property binding
678 */
679 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
680 public static Object bindProperties(final Object self, final Object target, final Object source) {
681 // target object has to be a ScriptObject
682 final ScriptObject targetObj = Global.checkObject(target);
683 // check null or undefined source object
684 Global.checkObjectCoercible(source);
685
686 if (source instanceof ScriptObject) {
687 final ScriptObject sourceObj = (ScriptObject)source;
688
689 final PropertyMap sourceMap = sourceObj.getMap();
690 final Property[] properties = sourceMap.getProperties();
691 //replace the map and blow up everything to objects to work with dual fields :-(
692
693 // filter non-enumerable properties
694 final ArrayList<Property> propList = new ArrayList<>();
695 for (final Property prop : properties) {
696 if (prop.isEnumerable()) {
697 final Object value = sourceObj.get(prop.getKey());
698 prop.setType(Object.class);
699 prop.setValue(sourceObj, sourceObj, value, false);
|
131 @SuppressWarnings("unused")
132 private static PropertyMap $nasgenmap$;
133
134 private NativeObject() {
135 // don't create me!
136 throw new UnsupportedOperationException();
137 }
138
139 private static ECMAException notAnObject(final Object obj) {
140 return typeError("not.an.object", ScriptRuntime.safeToString(obj));
141 }
142
143 /**
144 * Nashorn extension: setIndexedPropertiesToExternalArrayData
145 *
146 * @param self self reference
147 * @param obj object whose index properties are backed by buffer
148 * @param buf external buffer - should be a nio ByteBuffer
149 * @return the 'obj' object
150 */
151 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
152 documentation = "set ByteBuffer to hold indexed data (nashorn extension)")
153 public static ScriptObject setIndexedPropertiesToExternalArrayData(final Object self, final Object obj, final Object buf) {
154 Global.checkObject(obj);
155 final ScriptObject sobj = (ScriptObject)obj;
156 if (buf instanceof ByteBuffer) {
157 sobj.setArray(ArrayData.allocate((ByteBuffer)buf));
158 } else {
159 throw typeError("not.a.bytebuffer", "setIndexedPropertiesToExternalArrayData's buf argument");
160 }
161 return sobj;
162 }
163
164
165 /**
166 * ECMA 15.2.3.2 Object.getPrototypeOf ( O )
167 *
168 * @param self self reference
169 * @param obj object to get prototype from
170 * @return the prototype of an object
171 */
172 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
173 documentation = "returns the prototype of the specified object")
174 public static Object getPrototypeOf(final Object self, final Object obj) {
175 if (obj instanceof ScriptObject) {
176 return ((ScriptObject)obj).getProto();
177 } else if (obj instanceof ScriptObjectMirror) {
178 return ((ScriptObjectMirror)obj).getProto();
179 } else {
180 final JSType type = JSType.of(obj);
181 if (type == JSType.OBJECT) {
182 // host (Java) objects have null __proto__
183 return null;
184 }
185
186 // must be some JS primitive
187 throw notAnObject(obj);
188 }
189 }
190
191 /**
192 * Nashorn extension: Object.setPrototypeOf ( O, proto )
193 * Also found in ES6 draft specification.
194 *
195 * @param self self reference
196 * @param obj object to set prototype for
197 * @param proto prototype object to be used
198 * @return object whose prototype is set
199 */
200 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
201 documentation = "sets the prototype of the given object (ES6)")
202 public static Object setPrototypeOf(final Object self, final Object obj, final Object proto) {
203 if (obj instanceof ScriptObject) {
204 ((ScriptObject)obj).setPrototypeOf(proto);
205 return obj;
206 } else if (obj instanceof ScriptObjectMirror) {
207 ((ScriptObjectMirror)obj).setProto(proto);
208 return obj;
209 }
210
211 throw notAnObject(obj);
212 }
213
214 /**
215 * ECMA 15.2.3.3 Object.getOwnPropertyDescriptor ( O, P )
216 *
217 * @param self self reference
218 * @param obj object from which to get property descriptor for {@code ToString(prop)}
219 * @param prop property descriptor
220 * @return property descriptor
221 */
222 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
223 documentation = "returns a property descriptor for an own property (not inherited property)")
224 public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) {
225 if (obj instanceof ScriptObject) {
226 final String key = JSType.toString(prop);
227 final ScriptObject sobj = (ScriptObject)obj;
228
229 return sobj.getOwnPropertyDescriptor(key);
230 } else if (obj instanceof ScriptObjectMirror) {
231 final String key = JSType.toString(prop);
232 final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
233
234 return sobjMirror.getOwnPropertyDescriptor(key);
235 } else {
236 throw notAnObject(obj);
237 }
238 }
239
240 /**
241 * ECMA 15.2.3.4 Object.getOwnPropertyNames ( O )
242 *
243 * @param self self reference
244 * @param obj object to query for property names
245 * @return array of property names
246 */
247 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
248 documentation = "returns an array of all properties (enumerable or not) found directly on the given object")
249 public static ScriptObject getOwnPropertyNames(final Object self, final Object obj) {
250 if (obj instanceof ScriptObject) {
251 return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
252 } else if (obj instanceof ScriptObjectMirror) {
253 return new NativeArray(((ScriptObjectMirror)obj).getOwnKeys(true));
254 } else {
255 throw notAnObject(obj);
256 }
257 }
258
259 /**
260 * ECMA 2 19.1.2.8 Object.getOwnPropertySymbols ( O )
261 *
262 * @param self self reference
263 * @param obj object to query for property names
264 * @return array of property names
265 */
266 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
267 documentation = "returns an array of all symbol properties found directly on the given object (ES6)")
268 public static ScriptObject getOwnPropertySymbols(final Object self, final Object obj) {
269 if (obj instanceof ScriptObject) {
270 return new NativeArray(((ScriptObject)obj).getOwnSymbols(true));
271 } else {
272 // TODO: we don't support this on ScriptObjectMirror objects yet
273 throw notAnObject(obj);
274 }
275 }
276
277 /**
278 * ECMA 15.2.3.5 Object.create ( O [, Properties] )
279 *
280 * @param self self reference
281 * @param proto prototype object
282 * @param props properties to define
283 * @return object created
284 */
285 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
286 documentation = "creates a new object with the specified prototype object and properties")
287 public static ScriptObject create(final Object self, final Object proto, final Object props) {
288 if (proto != null) {
289 Global.checkObject(proto);
290 }
291
292 // FIXME: should we create a proper object with correct number of
293 // properties?
294 final ScriptObject newObj = Global.newEmptyInstance();
295 newObj.setProto((ScriptObject)proto);
296 if (props != UNDEFINED) {
297 NativeObject.defineProperties(self, newObj, props);
298 }
299
300 return newObj;
301 }
302
303 /**
304 * ECMA 15.2.3.6 Object.defineProperty ( O, P, Attributes )
305 *
306 * @param self self reference
307 * @param obj object in which to define a property
308 * @param prop property to define
309 * @param attr attributes for property descriptor
310 * @return object
311 */
312 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
313 documentation = "adds an own property and/or update the attributes of an existing own property of an object")
314 public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
315 final ScriptObject sobj = Global.checkObject(obj);
316 sobj.defineOwnProperty(JSType.toPropertyKey(prop), attr, true);
317 return sobj;
318 }
319
320 /**
321 * ECMA 5.2.3.7 Object.defineProperties ( O, Properties )
322 *
323 * @param self self reference
324 * @param obj object in which to define properties
325 * @param props properties
326 * @return object
327 */
328 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
329 documentation = "defines new or modifies existing properties directly on the given object")
330 public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
331 final ScriptObject sobj = Global.checkObject(obj);
332 final Object propsObj = Global.toObject(props);
333
334 if (propsObj instanceof ScriptObject) {
335 final Object[] keys = ((ScriptObject)propsObj).getOwnKeys(false);
336 for (final Object key : keys) {
337 final String prop = JSType.toString(key);
338 sobj.defineOwnProperty(prop, ((ScriptObject)propsObj).get(prop), true);
339 }
340 }
341 return sobj;
342 }
343
344 /**
345 * ECMA 15.2.3.8 Object.seal ( O )
346 *
347 * @param self self reference
348 * @param obj object to seal
349 * @return sealed object
350 */
351 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
352 documentation = "prevents new properties from being added to the given object and marks existing properties as non-configurable")
353 public static Object seal(final Object self, final Object obj) {
354 if (obj instanceof ScriptObject) {
355 return ((ScriptObject)obj).seal();
356 } else if (obj instanceof ScriptObjectMirror) {
357 return ((ScriptObjectMirror)obj).seal();
358 } else {
359 throw notAnObject(obj);
360 }
361 }
362
363
364 /**
365 * ECMA 15.2.3.9 Object.freeze ( O )
366 *
367 * @param self self reference
368 * @param obj object to freeze
369 * @return frozen object
370 */
371 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
372 documentation = "prevents new properties from being added to the given object and prevents existing properties from being removed or re-configured")
373 public static Object freeze(final Object self, final Object obj) {
374 if (obj instanceof ScriptObject) {
375 return ((ScriptObject)obj).freeze();
376 } else if (obj instanceof ScriptObjectMirror) {
377 return ((ScriptObjectMirror)obj).freeze();
378 } else {
379 throw notAnObject(obj);
380 }
381 }
382
383 /**
384 * ECMA 15.2.3.10 Object.preventExtensions ( O )
385 *
386 * @param self self reference
387 * @param obj object, for which to set the internal extensible property to false
388 * @return object
389 */
390 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
391 documentation = "prevents new properties from ever being added to the given object")
392 public static Object preventExtensions(final Object self, final Object obj) {
393 if (obj instanceof ScriptObject) {
394 return ((ScriptObject)obj).preventExtensions();
395 } else if (obj instanceof ScriptObjectMirror) {
396 return ((ScriptObjectMirror)obj).preventExtensions();
397 } else {
398 throw notAnObject(obj);
399 }
400 }
401
402 /**
403 * ECMA 15.2.3.11 Object.isSealed ( O )
404 *
405 * @param self self reference
406 * @param obj check whether an object is sealed
407 * @return true if sealed, false otherwise
408 */
409 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
410 documentation = "tells if an object is sealed or not")
411 public static boolean isSealed(final Object self, final Object obj) {
412 if (obj instanceof ScriptObject) {
413 return ((ScriptObject)obj).isSealed();
414 } else if (obj instanceof ScriptObjectMirror) {
415 return ((ScriptObjectMirror)obj).isSealed();
416 } else {
417 throw notAnObject(obj);
418 }
419 }
420
421 /**
422 * ECMA 15.2.3.12 Object.isFrozen ( O )
423 *
424 * @param self self reference
425 * @param obj check whether an object
426 * @return true if object is frozen, false otherwise
427 */
428 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
429 documentation = "tells if an object is fronzen or not")
430 public static boolean isFrozen(final Object self, final Object obj) {
431 if (obj instanceof ScriptObject) {
432 return ((ScriptObject)obj).isFrozen();
433 } else if (obj instanceof ScriptObjectMirror) {
434 return ((ScriptObjectMirror)obj).isFrozen();
435 } else {
436 throw notAnObject(obj);
437 }
438 }
439
440 /**
441 * ECMA 15.2.3.13 Object.isExtensible ( O )
442 *
443 * @param self self reference
444 * @param obj check whether an object is extensible
445 * @return true if object is extensible, false otherwise
446 */
447 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
448 documentation = "tells if an object is extensible or not")
449 public static boolean isExtensible(final Object self, final Object obj) {
450 if (obj instanceof ScriptObject) {
451 return ((ScriptObject)obj).isExtensible();
452 } else if (obj instanceof ScriptObjectMirror) {
453 return ((ScriptObjectMirror)obj).isExtensible();
454 } else {
455 throw notAnObject(obj);
456 }
457 }
458
459 /**
460 * ECMA 15.2.3.14 Object.keys ( O )
461 *
462 * @param self self reference
463 * @param obj object from which to extract keys
464 * @return array of keys in object
465 */
466 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
467 documentation = "returns an array of the given object's own enumerable properties")
468 public static ScriptObject keys(final Object self, final Object obj) {
469 if (obj instanceof ScriptObject) {
470 final ScriptObject sobj = (ScriptObject)obj;
471 return new NativeArray(sobj.getOwnKeys(false));
472 } else if (obj instanceof ScriptObjectMirror) {
473 final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
474 return new NativeArray(sobjMirror.getOwnKeys(false));
475 } else {
476 throw notAnObject(obj);
477 }
478 }
479
480 /**
481 * ECMA 15.2.2.1 , 15.2.1.1 new Object([value]) and Object([value])
482 *
483 * Constructor
484 *
485 * @param newObj is the new object instantiated with the new operator
486 * @param self self reference
487 * @param value value of object to be instantiated
488 * @return the new NativeObject
489 */
490 @Constructor(documentation = "creates a new script object or converts given value as a script object")
491 public static Object construct(final boolean newObj, final Object self, final Object value) {
492 final JSType type = JSType.ofNoFunction(value);
493
494 // Object(null), Object(undefined), Object() are same as "new Object()"
495
496 if (newObj || type == JSType.NULL || type == JSType.UNDEFINED) {
497 switch (type) {
498 case BOOLEAN:
499 case NUMBER:
500 case STRING:
501 case SYMBOL:
502 return Global.toObject(value);
503 case OBJECT:
504 return value;
505 case NULL:
506 case UNDEFINED:
507 // fall through..
508 default:
509 break;
510 }
511
512 return Global.newEmptyInstance();
513 }
514
515 return Global.toObject(value);
516 }
517
518 /**
519 * ECMA 15.2.4.2 Object.prototype.toString ( )
520 *
521 * @param self self reference
522 * @return ToString of object
523 */
524 @Function(attributes = Attribute.NOT_ENUMERABLE,
525 documentation = "returns a string representing of this object")
526 public static String toString(final Object self) {
527 return ScriptRuntime.builtinObjectToString(self);
528 }
529
530 /**
531 * ECMA 15.2.4.3 Object.prototype.toLocaleString ( )
532 *
533 * @param self self reference
534 * @return localized ToString
535 */
536 @Function(attributes = Attribute.NOT_ENUMERABLE)
537 public static Object toLocaleString(final Object self) {
538 final Object obj = JSType.toScriptObject(self);
539 if (obj instanceof ScriptObject) {
540 final InvokeByName toStringInvoker = getTO_STRING();
541 final ScriptObject sobj = (ScriptObject)obj;
542 try {
543 final Object toString = toStringInvoker.getGetter().invokeExact(sobj);
544
545 if (Bootstrap.isCallable(toString)) {
558 }
559
560 /**
561 * ECMA 15.2.4.4 Object.prototype.valueOf ( )
562 *
563 * @param self self reference
564 * @return value of object
565 */
566 @Function(attributes = Attribute.NOT_ENUMERABLE)
567 public static Object valueOf(final Object self) {
568 return Global.toObject(self);
569 }
570
571 /**
572 * ECMA 15.2.4.5 Object.prototype.hasOwnProperty (V)
573 *
574 * @param self self reference
575 * @param v property to check for
576 * @return true if property exists in object
577 */
578 @Function(attributes = Attribute.NOT_ENUMERABLE,
579 documentation = "tells whether this object has the specified property or not")
580 public static boolean hasOwnProperty(final Object self, final Object v) {
581 // Convert ScriptObjects to primitive with String.class hint
582 // but no need to convert other primitives to string.
583 final Object key = JSType.toPrimitive(v, String.class);
584 final Object obj = Global.toObject(self);
585
586 return obj instanceof ScriptObject && ((ScriptObject)obj).hasOwnProperty(key);
587 }
588
589 /**
590 * ECMA 15.2.4.6 Object.prototype.isPrototypeOf (V)
591 *
592 * @param self self reference
593 * @param v v prototype object to check against
594 * @return true if object is prototype of v
595 */
596 @Function(attributes = Attribute.NOT_ENUMERABLE,
597 documentation = "tests for this object in another object's prototype chain")
598 public static boolean isPrototypeOf(final Object self, final Object v) {
599 if (!(v instanceof ScriptObject)) {
600 return false;
601 }
602
603 final Object obj = Global.toObject(self);
604 ScriptObject proto = (ScriptObject)v;
605
606 do {
607 proto = proto.getProto();
608 if (proto == obj) {
609 return true;
610 }
611 } while (proto != null);
612
613 return false;
614 }
615
616 /**
617 * ECMA 15.2.4.7 Object.prototype.propertyIsEnumerable (V)
618 *
619 * @param self self reference
620 * @param v property to check if enumerable
621 * @return true if property is enumerable
622 */
623 @Function(attributes = Attribute.NOT_ENUMERABLE,
624 documentation = "tells whether the given property is enumerable or not")
625 public static boolean propertyIsEnumerable(final Object self, final Object v) {
626 final String str = JSType.toString(v);
627 final Object obj = Global.toObject(self);
628
629 if (obj instanceof ScriptObject) {
630 final jdk.nashorn.internal.runtime.Property property = ((ScriptObject)obj).getMap().findProperty(str);
631 return property != null && property.isEnumerable();
632 }
633
634 return false;
635 }
636
637 /**
638 * Nashorn extension: Object.bindProperties
639 *
640 * Binds the source object's properties to the target object. Binding
641 * properties allows two-way read/write for the properties of the source object.
642 *
643 * Example:
644 * <pre>
679 *
680 * Limitations of property binding:
681 * <ul>
682 * <li> Only enumerable, immediate (not proto inherited) properties of the source object are bound.
683 * <li> If the target object already contains a property called "foo", the source's "foo" is skipped (not bound).
684 * <li> Properties added to the source object after binding to the target are not bound.
685 * <li> Property configuration changes on the source object (or on the target) is not propagated.
686 * <li> Delete of property on the target (or the source) is not propagated -
687 * only the property value is set to 'undefined' if the property happens to be a data property.
688 * </ul>
689 * <p>
690 * It is recommended that the bound properties be treated as non-configurable
691 * properties to avoid surprises.
692 * </p>
693 *
694 * @param self self reference
695 * @param target the target object to which the source object's properties are bound
696 * @param source the source object whose properties are bound to the target
697 * @return the target object after property binding
698 */
699 @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR,
700 documentation = "binds the source object's properties to the target object (nashorn extension)")
701 public static Object bindProperties(final Object self, final Object target, final Object source) {
702 // target object has to be a ScriptObject
703 final ScriptObject targetObj = Global.checkObject(target);
704 // check null or undefined source object
705 Global.checkObjectCoercible(source);
706
707 if (source instanceof ScriptObject) {
708 final ScriptObject sourceObj = (ScriptObject)source;
709
710 final PropertyMap sourceMap = sourceObj.getMap();
711 final Property[] properties = sourceMap.getProperties();
712 //replace the map and blow up everything to objects to work with dual fields :-(
713
714 // filter non-enumerable properties
715 final ArrayList<Property> propList = new ArrayList<>();
716 for (final Property prop : properties) {
717 if (prop.isEnumerable()) {
718 final Object value = sourceObj.get(prop.getKey());
719 prop.setType(Object.class);
720 prop.setValue(sourceObj, sourceObj, value, false);
|