private static Object evalImpl(final Context.MultiGlobalCompiledScript mgcs,final ScriptContext ctxt,final Global ctxtGlobal) throws ScriptException {
final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != ctxtGlobal);
try {
if (globalChanged) {
Context.setGlobal(ctxtGlobal);
}
final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
ctxtGlobal.setScriptContext(ctxt);
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script,ctxtGlobal),ctxtGlobal));
} catch (final Exception e) {
throwAsScriptException(e,ctxtGlobal);
throw new AssertionError("should not reach here");
} finally {
if (globalChanged) {
Context.setGlobal(oldGlobal);
}
}
}
private static Object evalImpl(final ScriptFunction script,final Global ctxtGlobal) throws ScriptException {
if (script == null) {
return null;
}
final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != ctxtGlobal);
try {
if (globalChanged) {
Context.setGlobal(ctxtGlobal);
}
ctxtGlobal.setScriptContext(ctxt);
return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script,ctxtGlobal);
throw new AssertionError("should not reach here");
} finally {
if (globalChanged) {
Context.setGlobal(oldGlobal);
}
}
}
/**
* ECMA 15.5.4.20 String.prototype.trim ( )
* @param self self reference
* @return string trimmed from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static String trim(final Object self) {
final String str = checkObjectToString(self);
int start = 0;
int end = str.length() - 1;
while (start <= end && ScriptRuntime.isJSWhitespace(str.charat(start))) {
start++;
}
while (end > start && ScriptRuntime.isJSWhitespace(str.charat(end))) {
end--;
}
return str.substring(start,end + 1);
}
项目:openjdk-jdk10
文件:NativeSet.java
/**
* ECMA6 23.2.3.6 Set.prototype.forEach ( callbackfn [,thisArg ] )
*
* @param self the self reference
* @param callbackFn the callback function
* @param thisArg optional this object
*/
@Function(attributes = Attribute.NOT_ENUMERABLE,arity = 1)
public static void forEach(final Object self,final Object callbackFn,final Object thisArg) {
final NativeSet set = getNativeSet(self);
if (!Bootstrap.isCallable(callbackFn)) {
throw typeError("not.a.function",ScriptRuntime.safetoString(callbackFn));
}
final MethodHandle invoker = Global.instance().getDynamicInvoker(FOREACH_INVOKER_KEY,() -> Bootstrap.createDynamicCallInvoker(Object.class,Object.class,Object.class));
final LinkedMap.LinkedMapIterator iterator = set.getJavaMap().getIterator();
for (;;) {
final LinkedMap.Node node = iterator.next();
if (node == null) {
break;
}
try {
final Object result = invoker.invokeExact(callbackFn,thisArg,node.getKey(),self);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
throw new RuntimeException(t);
}
}
}
项目:openjdk-jdk10
文件:NativeFunction.java
/**
* ECMA 15.3.4.4 Function.prototype.call (thisArg [,arg1 [,arg2,... ] ] )
*
* @param self self reference
* @param args arguments for call
* @return result of call
*/
@Function(attributes = Attribute.NOT_ENUMERABLE,arity = 1)
public static Object call(final Object self,final Object... args) {
checkCallable(self);
final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
Object[] arguments;
if (args.length > 1) {
arguments = new Object[args.length - 1];
System.arraycopy(args,1,arguments,arguments.length);
} else {
arguments = ScriptRuntime.EMPTY_ARRAY;
}
if (self instanceof ScriptFunction) {
return ScriptRuntime.apply((ScriptFunction)self,thiz,arguments);
} else if (self instanceof JSObject) {
return ((JSObject)self).call(thiz,arguments);
}
throw new AssertionError("should not reach here");
}
NativeArray(final Object[] array) {
this(ArrayData.allocate(array.length));
ArrayData arrayData = this.getArray();
if (array.length > 0) {
arrayData.ensure(array.length - 1);
}
for (int index = 0; index < array.length; index++) {
final Object value = array[index];
if (value == ScriptRuntime.EMPTY) {
arrayData = arrayData.delete(index);
} else {
arrayData = arrayData.set(index,value,false);
}
}
this.setArray(arrayData);
}
项目:openjdk-jdk10
文件:NativeArray.java
/**
* ECMA 15.4.4.2 Array.prototype.toString ( )
*
* @param self self reference
* @return string representation of array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object toString(final Object self) {
final Object obj = Global.toObject(self);
if (obj instanceof ScriptObject) {
final InvokeByName joinInvoker = getJOIN();
final ScriptObject sobj = (ScriptObject)obj;
try {
final Object join = joinInvoker.getGetter().invokeExact(sobj);
if (Bootstrap.isCallable(join)) {
return joinInvoker.getInvoker().invokeExact(join,sobj);
}
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
throw new RuntimeException(t);
}
}
// FIXME: should lookup Object.prototype.toString and call that?
return ScriptRuntime.builtinObjectToString(self);
}
/**
* ECMA 15.4.4.5 Array.prototype.join (separator)
*
* @param self self reference
* @param separator element separator
* @return string representation after join
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static String join(final Object self,final Object separator) {
final StringBuilder sb = new StringBuilder();
final Iterator<Object> iter = arrayLikeIterator(self,true);
final String sep = separator == ScriptRuntime.UNDEFINED ? "," : JSType.toString(separator);
while (iter.hasNext()) {
final Object obj = iter.next();
if (obj != null && obj != ScriptRuntime.UNDEFINED) {
sb.append(JSType.toString(obj));
}
if (iter.hasNext()) {
sb.append(sep);
}
}
return sb.toString();
}
/**
* ECMA 15.4.4.7 Array.prototype.push (args...)
*
* @param self self reference
* @param args arguments to push
* @return array length after pushes
*/
@Function(attributes = Attribute.NOT_ENUMERABLE,arity = 1)
public static Object push(final Object self,final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)self;
if (bulkable(sobj) && sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
final ArrayData newData = sobj.getArray().push(true,args);
sobj.setArray(newData);
return newData.length();
}
long len = JSType.toUint32(sobj.getLength());
for (final Object element : args) {
sobj.set(len++,element,CALLSITE_STRICT);
}
sobj.set("length",len,CALLSITE_STRICT);
return len;
} catch (final ClassCastException | NullPointerException e) {
throw typeError(Context.getGlobal(),e,"not.an.object",ScriptRuntime.safetoString(self));
}
}
项目:openjdk-jdk10
文件:JSTypeTest.java
/**
* Test of toString method,of class Runtime.
*/
@Test
public void testToString_Object() {
assertEquals(JSType.toString(ScriptRuntime.UNDEFINED),"undefined");
assertEquals(JSType.toString(null),"null");
assertEquals(JSType.toString(Boolean.TRUE),"true");
assertEquals(JSType.toString(Boolean.FALSE),"false");
assertEquals(JSType.toString(""),"");
assertEquals(JSType.toString("nashorn"),"nashorn");
assertEquals(JSType.toString(Double.NaN),"NaN");
assertEquals(JSType.toString(Double.POSITIVE_INFINITY),"Infinity");
assertEquals(JSType.toString(Double.NEGATIVE_INFINITY),"-Infinity");
assertEquals(JSType.toString(0.0),"0");
// FIXME: add more number-to-string test cases
// FIXME: add case for Object type (JSObject with getDefaultValue)
}
项目:openjdk-jdk10
文件:SparseArrayData.java
@Override
public Object[] asObjectArray() {
final int len = (int)Math.min(length(),Integer.MAX_VALUE);
final int underlyingLength = (int)Math.min(len,underlying.length());
final Object[] objArray = new Object[len];
for (int i = 0; i < underlyingLength; i++) {
objArray[i] = underlying.getobject(i);
}
Arrays.fill(objArray,underlyingLength,ScriptRuntime.UNDEFINED);
for (final Map.Entry<Long,Object> entry : sparseMap.entrySet()) {
final long key = entry.getKey();
if (key < Integer.MAX_VALUE) {
objArray[(int)key] = entry.getValue();
} else {
break; // ascending key order
}
}
return objArray;
}
项目:openjdk-jdk10
文件:SparseArrayData.java
@Override
public Object pop() {
final long len = length();
final long underlyingLen = underlying.length();
if (len == 0) {
return ScriptRuntime.UNDEFINED;
}
if (len == underlyingLen) {
final Object result = underlying.pop();
setLength(underlying.length());
return result;
}
setLength(len - 1);
final Long key = len - 1;
return sparseMap.containsKey(key) ? sparseMap.remove(key) : ScriptRuntime.UNDEFINED;
}
private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception {
final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
final Object self = linkRequest.getReceiver();
switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
case NEW:
if(BeansLinker.isDynamicConstructor(self)) {
throw typeError("no.constructor.matches.args",ScriptRuntime.safetoString(self));
}
if(BeansLinker.isDynamicmethod(self)) {
throw typeError("method.not.constructor",ScriptRuntime.safetoString(self));
}
throw typeError("not.a.function",NashornCallSiteDescriptor.getFunctionErrorMessage(desc,self));
case CALL:
if(BeansLinker.isDynamicConstructor(self)) {
throw typeError("constructor.requires.new",ScriptRuntime.safetoString(self));
}
if(BeansLinker.isDynamicmethod(self)) {
throw typeError("no.method.matches.args",self));
default:
// Everything else is supposed to have been already handled by Bootstrap.beansLinker
// delegating to linkNoSuchBeanMember
throw new AssertionError("unkNown call type " + desc);
}
}
项目:openjdk-jdk10
文件:NativeJSAdapter.java
@Override
public Iterator<String> propertyIterator() {
// Try __getIds__ first,if not found then try __getKeys__
// In jdk6,we had added "__getIds__" so this is just for compatibility.
Object func = adaptee.get(__getIds__);
if (!(func instanceof ScriptFunction)) {
func = adaptee.get(__getKeys__);
}
Object obj;
if (func instanceof ScriptFunction) {
obj = ScriptRuntime.apply((ScriptFunction)func,this);
} else {
obj = new NativeArray(0);
}
final List<String> array = new ArrayList<>();
for (final Iterator<Object> iter = ArrayLikeIterator.arrayLikeIterator(obj); iter.hasNext(); ) {
array.add((String)iter.next());
}
return array.iterator();
}
@Override
public Object[] asObjectArray() {
final int len = (int)Math.min(length(),Object> entry : sparseMap.entrySet()) {
final long key = entry.getKey();
if (key < Integer.MAX_VALUE) {
objArray[(int)key] = entry.getValue();
} else {
break; // ascending key order
}
}
return objArray;
}
项目:openjdk-jdk10
文件:NativeArray.java
NativeArray(final Object[] array) {
this(ArrayData.allocate(array.length));
ArrayData arrayData = this.getArray();
for (int index = 0; index < array.length; index++) {
final Object value = array[index];
if (value == ScriptRuntime.EMPTY) {
arrayData = arrayData.delete(index);
} else {
arrayData = arrayData.set(index,false);
}
}
this.setArray(arrayData);
}
@Override
public String toString() {
return inGlobal(new Callable<String>() {
@Override
public String call() {
return ScriptRuntime.safetoString(sobj);
}
});
}
项目:openjdk-jdk10
文件:Shell.java
/**
* Converts {@code result} to a printable string. The reason we don't use {@link JSType#toString(Object)}
* or {@link ScriptRuntime#safetoString(Object)} is that we want to be able to render Symbol values
* even if they occur within an Array,and therefore have to implement our own Array to String
* conversion.
*
* @param result the result
* @param global the global object
* @return the string representation
*/
protected static String toString(final Object result,final Global global) {
if (result instanceof Symbol) {
// normal implicit conversion of symbol to string would throw TypeError
return result.toString();
}
if (result instanceof NativeSymbol) {
return JSType.toPrimitive(result).toString();
}
if (isArrayWithDefaultToString(result,global)) {
// This should yield the same string as Array.prototype.toString but
// will not throw if the array contents include symbols.
final StringBuilder sb = new StringBuilder();
final Iterator<Object> iter = ArrayLikeIterator.arrayLikeIterator(result,true);
while (iter.hasNext()) {
final Object obj = iter.next();
if (obj != null && obj != ScriptRuntime.UNDEFINED) {
sb.append(toString(obj,global));
}
if (iter.hasNext()) {
sb.append(',');
}
}
return sb.toString();
}
return JSType.toString(result);
}
项目:openjdk-jdk10
文件:ScriptObjectMirror.java
/**
* Call member function
* @param functionName function name
* @param args arguments
* @return return value of function
*/
public Object callMember(final String functionName,final Object... args) {
Objects.requireNonNull(functionName);
final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {
if (globalChanged) {
Context.setGlobal(global);
}
final Object val = sobj.get(functionName);
if (val instanceof ScriptFunction) {
final Object[] modArgs = globalChanged? wrapArrayLikeMe(args,oldGlobal) : args;
return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)val,sobj,unwrapArray(modArgs,global)));
} else if (val instanceof JSObject && ((JSObject)val).isFunction()) {
return ((JSObject)val).call(sobj,args);
}
throw new NoSuchMethodException("No such function " + functionName);
} catch (final NashornException ne) {
throw ne.initEcmaError(global);
} catch (final RuntimeException | Error e) {
throw e;
} catch (final Throwable t) {
throw new RuntimeException(t);
} finally {
if (globalChanged) {
Context.setGlobal(oldGlobal);
}
}
}
private boolean checkDeleteIndex(final int index,final boolean strict) {
if (isValidStringIndex(index)) {
if (strict) {
throw typeError("cant.delete.property",Integer.toString(index),ScriptRuntime.safetoString(this));
}
return true;
}
return false;
}
/**
* Nashorn extension: String.prototype.trimRight ( )
* @param self self reference
* @return string trimmed right from whitespace
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static String trimRight(final Object self) {
final String str = checkObjectToString(self);
final int start = 0;
int end = str.length() - 1;
while (end >= start && ScriptRuntime.isJSWhitespace(str.charat(end))) {
end--;
}
return str.substring(start,end + 1);
}
项目:openjdk-jdk10
文件:NativeJSAdapter.java
private Object callAdaptee(final Object retValue,final String name,final Object... args) {
final Object func = adaptee.get(name);
if (func instanceof ScriptFunction) {
return ScriptRuntime.apply((ScriptFunction)func,this,args);
}
return retValue;
}
项目:openjdk-jdk10
文件:JSTypeTest.java
/**
* Test of toNumber method,of class Runtime.
*/
@Test
public void testToNumber_Object() {
assertTrue(Double.isNaN(JSType.toNumber(ScriptRuntime.UNDEFINED)));
assertEquals(JSType.toNumber((Object)null),0.0,0.0);
assertEquals(JSType.toNumber(Boolean.TRUE),1.0,0.0);
assertEquals(JSType.toNumber(Boolean.FALSE),0.0);
assertEquals(JSType.toNumber(3.14),3.14,0.0);
// FIXME: add more assertions for specific String to number cases
// FIXME: add case for Object type (JSObject with getDefaultValue)
}
项目:openjdk-jdk10
文件:NativeArray.java
/**
* ECMA 15.4.4.11 Array.prototype.sort ( comparefn )
*
* @param self self reference
* @param comparefn element comparison function
* @return sorted array
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static ScriptObject sort(final Object self,final Object comparefn) {
try {
final ScriptObject sobj = (ScriptObject) self;
final long len = JSType.toUint32(sobj.getLength());
ArrayData array = sobj.getArray();
if (len > 1) {
// Get only non-missing elements. Missing elements go at the end
// of the sorted array. So,just don't copy these to sort input.
final ArrayList<Object> src = new ArrayList<>();
for (final Iterator<Long> iter = array.indexIterator(); iter.hasNext(); ) {
final long index = iter.next();
if (index >= len) {
break;
}
src.add(array.getobject((int)index));
}
final Object[] sorted = sort(src.toArray(),comparefn);
for (int i = 0; i < sorted.length; i++) {
array = array.set(i,sorted[i],true);
}
// delete missing elements - which are at the end of sorted array
if (sorted.length != len) {
array = array.delete(sorted.length,len - 1);
}
sobj.setArray(array);
}
return sobj;
} catch (final ClassCastException | NullPointerException e) {
throw typeError("not.an.object",ScriptRuntime.safetoString(self));
}
}
项目:openjdk-jdk10
文件:NativeWeakMap.java
private static NativeWeakMap getMap(final Object self) {
if (self instanceof NativeWeakMap) {
return (NativeWeakMap)self;
} else {
throw typeError("not.a.weak.map",ScriptRuntime.safetoString(self));
}
}
/**
* ECMA 15.3.4.3 Function.prototype.apply (thisArg,argArray)
*
* @param self self reference
* @param thiz {@code this} arg for apply
* @param array array of argument for apply
* @return result of apply
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object apply(final Object self,final Object thiz,final Object array) {
checkCallable(self);
final Object[] args = toApplyArgs(array);
if (self instanceof ScriptFunction) {
return ScriptRuntime.apply((ScriptFunction)self,args);
} else if (self instanceof JSObject) {
return ((JSObject)self).call(thiz,args);
}
throw new AssertionError("Should not reach here");
}
/**
* Nashorn extension: Function.prototype.toSource
*
* @param self self reference
* @return source for function
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static String toSource(final Object self) {
if (!(self instanceof ScriptFunction)) {
throw typeError("not.a.function",ScriptRuntime.safetoString(self));
}
return ((ScriptFunction)self).toSource();
}
项目:openjdk-jdk10
文件:NativeArguments.java
/**
* ECMA 15.4.5.1 [[DefineOwnProperty]] ( P,Desc,Throw ) as specialized in
* ECMA 10.6 for Arguments object.
*/
@Override
public boolean defineOwnProperty(final Object key,final Object propertyDesc,final boolean reject) {
final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0) {
final boolean isMapped = isMapped(index);
final Object oldValue = isMapped ? getArray().getobject(index) : null;
if (!super.defineOwnProperty(key,propertyDesc,false)) {
if (reject) {
throw typeError("cant.redefine.property",key.toString(),ScriptRuntime.safetoString(this));
}
return false;
}
if (isMapped) {
// When mapped argument is redefined,if new descriptor is accessor property
// or data-non-writable property,we have to "unmap" (unlink).
final PropertyDescriptor desc = toPropertyDescriptor(Global.instance(),propertyDesc);
if (desc.type() == PropertyDescriptor.ACCESSOR) {
setDeleted(index,oldValue);
} else if (desc.has(PropertyDescriptor.WRITABLE) && !desc.isWritable()) {
// delete and set value from new descriptor if it has one,otherwise use old value
setDeleted(index,desc.has(PropertyDescriptor.VALUE) ? desc.getValue() : oldValue);
} else if (desc.has(PropertyDescriptor.VALUE)) {
setArray(getArray().set(index,desc.getValue(),false));
}
}
return true;
}
return super.defineOwnProperty(key,reject);
}
/**
* ECMA 15.4.5.1 [[DefineOwnProperty]] ( P,Throw ) as specialized in
* ECMA 10.6 for Arguments object.
*/
@Override
public boolean defineOwnProperty(final String key,key,reject);
}
/**
* ECMA 9.9 ToObject implementation
*
* @param obj an item for which to run ToObject
* @return ToObject version of given item
*/
public static Object toObject(final Object obj) {
if (obj == null || obj == UNDEFINED) {
throw typeError("not.an.object",ScriptRuntime.safetoString(obj));
}
if (obj instanceof ScriptObject) {
return obj;
}
return instance().wrapAsObject(obj);
}
项目:openjdk-jdk10
文件:NativeArray.java
static long validLength(final Object length) {
// ES5 15.4.5.1,steps 3.c and 3.d require two ToNumber conversions here
final double doubleLength = JSType.toNumber(length);
if (doubleLength != JSType.toUint32(length)) {
throw rangeError("inappropriate.array.length",ScriptRuntime.safetoString(length));
}
return (long) doubleLength;
}
private static double getNumberValue(final Object self) {
if (self instanceof Number) {
return ((Number)self).doubleValue();
} else if (self instanceof NativeNumber) {
return ((NativeNumber)self).getValue();
} else if (self != null && self == Global.instance().getNumberPrototype()) {
return 0.0;
} else {
throw typeError("not.a.number",ScriptRuntime.safetoString(self));
}
}
private static Type getPropertyType(final ScriptObject sobj,final String name) {
final FindProperty find = sobj.findProperty(name,true);
if (find == null) {
return null;
}
final Property property = find.getproperty();
final Class<?> propertyClass = property.getType();
if (propertyClass == null) {
// propertyClass == null means its value is Undefined. It is probably not initialized yet,so we won't make
// a type assumption yet.
return null;
} else if (propertyClass.isPrimitive()) {
return Type.typeFor(propertyClass);
}
final ScriptObject owner = find.getowner();
if (property.hasGetterFunction(owner)) {
// Can have side effects,so we can't safely evaluate it; since !propertyClass.isPrimitive(),it's Object.
return Type.OBJECT;
}
// Safely evaluate the property,and return the narrowest type for the actual value (e.g. Type.INT for a Boxed
// integer).
final Object value = property.needsDeclaration() ? ScriptRuntime.UNDEFINED : property.getobjectValue(owner,owner);
if (value == ScriptRuntime.UNDEFINED) {
return null;
}
return Type.typeFor(JSType.unBoxedFieldType(value));
}
/**
* Slice function
* @param self native array buffer
* @param begin0 start byte index
* @param end0 end byte index
* @return new array buffer,sliced
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static NativeArrayBuffer slice(final Object self,final Object begin0,final Object end0) {
final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
final int byteLength = arrayBuffer.getByteLength();
final int begin = adjustIndex(JSType.toInt32(begin0),byteLength);
final int end = adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : byteLength,byteLength);
return new NativeArrayBuffer(arrayBuffer,begin,Math.max(end,begin));
}
private static Boolean getBoolean(final Object self) {
if (self instanceof Boolean) {
return ((Boolean)self);
} else if (self instanceof NativeBoolean) {
return ((NativeBoolean)self).getValue();
} else if (self != null && self == Global.instance().getBooleanPrototype()) {
return false;
} else {
throw typeError("not.a.boolean",ScriptRuntime.safetoString(self));
}
}
static long validLength(final Object length,final boolean reject) {
final double doubleLength = JSType.toNumber(length);
if (!Double.isNaN(doubleLength) && JSType.isRepresentableAsLong(doubleLength)) {
final long len = (long) doubleLength;
if (len >= 0 && len <= JSType.MAX_UINT) {
return len;
}
}
if (reject) {
throw rangeError("inappropriate.array.length",ScriptRuntime.safetoString(length));
}
return -1;
}
/**
* Assert that an array is numeric,if not throw type error
* @param self self array to check
* @return true if numeric
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object assertNumeric(final Object self) {
if(!(self instanceof NativeArray && ((NativeArray)self).getArray().getoptimisticType().isNumeric())) {
throw typeError("not.a.numeric.array",ScriptRuntime.safetoString(self));
}
return Boolean.TRUE;
}
项目:openjdk-jdk10
文件:NativeArray.java
/**
* Assert that an array is numeric,ScriptRuntime.safetoString(self));
}
return Boolean.TRUE;
}
/**
* ECMA 15.4.4.6 Array.prototype.pop ()
*
* @param self self reference
* @return array after pop
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object pop(final Object self) {
try {
final ScriptObject sobj = (ScriptObject)self;
if (bulkable(sobj)) {
return sobj.getArray().pop();
}
final long len = JSType.toUint32(sobj.getLength());
if (len == 0) {
sobj.set("length",CALLSITE_STRICT);
return ScriptRuntime.UNDEFINED;
}
final long index = len - 1;
final Object element = sobj.get(index);
sobj.delete(index,true);
sobj.set("length",index,CALLSITE_STRICT);
return element;
} catch (final ClassCastException | NullPointerException e) {
throw typeError("not.an.object",ScriptRuntime.safetoString(self));
}
}