src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java

Print this page




 258 
 259     @Override
 260     public Object getLength() {
 261         final long length = JSType.toUint32(getArray().length());
 262         if (length < Integer.MAX_VALUE) {
 263             return (int)length;
 264         }
 265         return length;
 266     }
 267 
 268     private boolean defineLength(final long oldLen, final PropertyDescriptor oldLenDesc, final PropertyDescriptor desc, final boolean reject) {
 269         // Step 3a
 270         if (!desc.has(VALUE)) {
 271             return super.defineOwnProperty("length", desc, reject);
 272         }
 273 
 274         // Step 3b
 275         final PropertyDescriptor newLenDesc = desc;
 276 
 277         // Step 3c and 3d - get new length and convert to long
 278         final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
 279 
 280         // Step 3e
 281         newLenDesc.setValue(newLen);
 282 
 283         // Step 3f
 284         // increasing array length - just need to set new length value (and attributes if any) and return
 285         if (newLen >= oldLen) {
 286             return super.defineOwnProperty("length", newLenDesc, reject);
 287         }
 288 
 289         // Step 3g
 290         if (!oldLenDesc.isWritable()) {
 291             if (reject) {
 292                 throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
 293             }
 294             return false;
 295         }
 296 
 297         // Step 3h and 3i
 298         final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();


 331             final ScriptObject newDesc = Global.newEmptyInstance();
 332             newDesc.set(WRITABLE, false, 0);
 333             return super.defineOwnProperty("length", newDesc, false);
 334         }
 335 
 336         return true;
 337     }
 338 
 339     /**
 340      * ECMA 15.4.5.1 [[DefineOwnProperty]] ( P, Desc, Throw )
 341      */
 342     @Override
 343     public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) {
 344         final PropertyDescriptor desc = toPropertyDescriptor(Global.instance(), propertyDesc);
 345 
 346         // never be undefined as "length" is always defined and can't be deleted for arrays
 347         // Step 1
 348         final PropertyDescriptor oldLenDesc = (PropertyDescriptor) super.getOwnPropertyDescriptor("length");
 349 
 350         // Step 2
 351         // get old length and convert to long
 352         final long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
 353 
 354         // Step 3
 355         if ("length".equals(key)) {
 356             // check for length being made non-writable
 357             final boolean result = defineLength(oldLen, oldLenDesc, desc, reject);
 358             if (desc.has(WRITABLE) && !desc.isWritable()) {
 359                 setIsLengthNotWritable();
 360             }
 361             return result;
 362         }
 363 
 364         // Step 4a
 365         final int index = ArrayIndex.getArrayIndex(key);
 366         if (ArrayIndex.isValidArrayIndex(index)) {
 367             final long longIndex = ArrayIndex.toLongIndex(index);
 368             // Step 4b
 369             // setting an element beyond current length, but 'length' is not writable
 370             if (longIndex >= oldLen && !oldLenDesc.isWritable()) {
 371                 if (reject) {
 372                     throw typeError("property.not.writable", Long.toString(longIndex), ScriptRuntime.safeToString(this));


 454      * @param self self reference
 455      * @return the length of the object
 456      */
 457     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 458     public static Object length(final Object self) {
 459         if (isArray(self)) {
 460             return JSType.toUint32(((ScriptObject) self).getArray().length());
 461         }
 462 
 463         return 0;
 464     }
 465 
 466     /**
 467      * Length setter
 468      * @param self   self reference
 469      * @param length new length property
 470      */
 471     @Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 472     public static void length(final Object self, final Object length) {
 473         if (isArray(self)) {
 474             ((ScriptObject)self).setLength(validLength(length, true));
 475         }
 476     }
 477 
 478     /**
 479      * Prototype length getter
 480      * @param self self reference
 481      * @return the length of the object
 482      */
 483     @Getter(name = "length", where = Where.PROTOTYPE, attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 484     public static Object getProtoLength(final Object self) {
 485         return length(self);  // Same as instance getter but we can't make nasgen use the same method for prototype
 486     }
 487 
 488     /**
 489      * Prototype length setter
 490      * @param self   self reference
 491      * @param length new length property
 492      */
 493     @Setter(name = "length", where = Where.PROTOTYPE, attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 494     public static void setProtoLength(final Object self, final Object length) {
 495         length(self, length);  // Same as instance setter but we can't make nasgen use the same method for prototype
 496     }
 497 
 498     static long validLength(final Object length, final boolean reject) {

 499         final double doubleLength = JSType.toNumber(length);
 500         if (!Double.isNaN(doubleLength) && JSType.isRepresentableAsLong(doubleLength)) {
 501             final long len = (long) doubleLength;
 502             if (len >= 0 && len <= JSType.MAX_UINT) {
 503                 return len;
 504             }
 505         }
 506         if (reject) {
 507             throw rangeError("inappropriate.array.length", ScriptRuntime.safeToString(length));
 508         }
 509         return -1;
 510     }
 511 
 512     /**
 513      * ECMA 15.4.4.2 Array.prototype.toString ( )
 514      *
 515      * @param self self reference
 516      * @return string representation of array
 517      */
 518     @Function(attributes = Attribute.NOT_ENUMERABLE)
 519     public static Object toString(final Object self) {
 520         final Object obj = Global.toObject(self);
 521         if (obj instanceof ScriptObject) {
 522             final InvokeByName joinInvoker = getJOIN();
 523             final ScriptObject sobj = (ScriptObject)obj;
 524             try {
 525                 final Object join = joinInvoker.getGetter().invokeExact(sobj);
 526                 if (Bootstrap.isCallable(join)) {
 527                     return joinInvoker.getInvoker().invokeExact(join, sobj);
 528                 }
 529             } catch (final RuntimeException | Error e) {




 258 
 259     @Override
 260     public Object getLength() {
 261         final long length = JSType.toUint32(getArray().length());
 262         if (length < Integer.MAX_VALUE) {
 263             return (int)length;
 264         }
 265         return length;
 266     }
 267 
 268     private boolean defineLength(final long oldLen, final PropertyDescriptor oldLenDesc, final PropertyDescriptor desc, final boolean reject) {
 269         // Step 3a
 270         if (!desc.has(VALUE)) {
 271             return super.defineOwnProperty("length", desc, reject);
 272         }
 273 
 274         // Step 3b
 275         final PropertyDescriptor newLenDesc = desc;
 276 
 277         // Step 3c and 3d - get new length and convert to long
 278         final long newLen = NativeArray.validLength(newLenDesc.getValue());
 279 
 280         // Step 3e
 281         newLenDesc.setValue(newLen);
 282 
 283         // Step 3f
 284         // increasing array length - just need to set new length value (and attributes if any) and return
 285         if (newLen >= oldLen) {
 286             return super.defineOwnProperty("length", newLenDesc, reject);
 287         }
 288 
 289         // Step 3g
 290         if (!oldLenDesc.isWritable()) {
 291             if (reject) {
 292                 throw typeError("property.not.writable", "length", ScriptRuntime.safeToString(this));
 293             }
 294             return false;
 295         }
 296 
 297         // Step 3h and 3i
 298         final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();


 331             final ScriptObject newDesc = Global.newEmptyInstance();
 332             newDesc.set(WRITABLE, false, 0);
 333             return super.defineOwnProperty("length", newDesc, false);
 334         }
 335 
 336         return true;
 337     }
 338 
 339     /**
 340      * ECMA 15.4.5.1 [[DefineOwnProperty]] ( P, Desc, Throw )
 341      */
 342     @Override
 343     public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) {
 344         final PropertyDescriptor desc = toPropertyDescriptor(Global.instance(), propertyDesc);
 345 
 346         // never be undefined as "length" is always defined and can't be deleted for arrays
 347         // Step 1
 348         final PropertyDescriptor oldLenDesc = (PropertyDescriptor) super.getOwnPropertyDescriptor("length");
 349 
 350         // Step 2
 351         // get old length and convert to long. Always a Long/Uint32 but we take the safe road.
 352         final long oldLen = JSType.toUint32(oldLenDesc.getValue());
 353 
 354         // Step 3
 355         if ("length".equals(key)) {
 356             // check for length being made non-writable
 357             final boolean result = defineLength(oldLen, oldLenDesc, desc, reject);
 358             if (desc.has(WRITABLE) && !desc.isWritable()) {
 359                 setIsLengthNotWritable();
 360             }
 361             return result;
 362         }
 363 
 364         // Step 4a
 365         final int index = ArrayIndex.getArrayIndex(key);
 366         if (ArrayIndex.isValidArrayIndex(index)) {
 367             final long longIndex = ArrayIndex.toLongIndex(index);
 368             // Step 4b
 369             // setting an element beyond current length, but 'length' is not writable
 370             if (longIndex >= oldLen && !oldLenDesc.isWritable()) {
 371                 if (reject) {
 372                     throw typeError("property.not.writable", Long.toString(longIndex), ScriptRuntime.safeToString(this));


 454      * @param self self reference
 455      * @return the length of the object
 456      */
 457     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 458     public static Object length(final Object self) {
 459         if (isArray(self)) {
 460             return JSType.toUint32(((ScriptObject) self).getArray().length());
 461         }
 462 
 463         return 0;
 464     }
 465 
 466     /**
 467      * Length setter
 468      * @param self   self reference
 469      * @param length new length property
 470      */
 471     @Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 472     public static void length(final Object self, final Object length) {
 473         if (isArray(self)) {
 474             ((ScriptObject)self).setLength(validLength(length));
 475         }
 476     }
 477 
 478     /**
 479      * Prototype length getter
 480      * @param self self reference
 481      * @return the length of the object
 482      */
 483     @Getter(name = "length", where = Where.PROTOTYPE, attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 484     public static Object getProtoLength(final Object self) {
 485         return length(self);  // Same as instance getter but we can't make nasgen use the same method for prototype
 486     }
 487 
 488     /**
 489      * Prototype length setter
 490      * @param self   self reference
 491      * @param length new length property
 492      */
 493     @Setter(name = "length", where = Where.PROTOTYPE, attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
 494     public static void setProtoLength(final Object self, final Object length) {
 495         length(self, length);  // Same as instance setter but we can't make nasgen use the same method for prototype
 496     }
 497 
 498     static long validLength(final Object length) {
 499         // ES5 15.4.5.1, steps 3.c and 3.d require two ToNumber conversions here
 500         final double doubleLength = JSType.toNumber(length);
 501         if (doubleLength != JSType.toUint32(length)) {






 502             throw rangeError("inappropriate.array.length", ScriptRuntime.safeToString(length));
 503         }
 504         return (long) doubleLength;
 505     }
 506 
 507     /**
 508      * ECMA 15.4.4.2 Array.prototype.toString ( )
 509      *
 510      * @param self self reference
 511      * @return string representation of array
 512      */
 513     @Function(attributes = Attribute.NOT_ENUMERABLE)
 514     public static Object toString(final Object self) {
 515         final Object obj = Global.toObject(self);
 516         if (obj instanceof ScriptObject) {
 517             final InvokeByName joinInvoker = getJOIN();
 518             final ScriptObject sobj = (ScriptObject)obj;
 519             try {
 520                 final Object join = joinInvoker.getGetter().invokeExact(sobj);
 521                 if (Bootstrap.isCallable(join)) {
 522                     return joinInvoker.getInvoker().invokeExact(join, sobj);
 523                 }
 524             } catch (final RuntimeException | Error e) {