package com.oracle.truffle.js.runtime.builtins;
import com.oracle.truffle.api.TruffleLanguage.LanguageReference;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.CachedLanguage;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.js.lang.JavaScriptLanguage;
import com.oracle.truffle.js.nodes.access.ReadElementNode;
import com.oracle.truffle.js.nodes.access.WriteElementNode;
import com.oracle.truffle.js.nodes.interop.ExportValueNode;
import com.oracle.truffle.js.nodes.interop.ImportValueNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.array.TypedArray;
import com.oracle.truffle.js.runtime.interop.InteropArray;
import com.oracle.truffle.js.runtime.objects.JSObject;
import com.oracle.truffle.js.runtime.objects.Undefined;
@ExportLibrary(InteropLibrary.class)
public final class JSTypedArrayObject extends JSArrayBufferViewBase {
TypedArray arrayType;
protected JSTypedArrayObject(Shape shape, TypedArray arrayType, JSArrayBufferObject arrayBuffer, int length, int offset) {
super(shape, arrayBuffer, length, offset);
this.arrayType = arrayType;
}
@SuppressWarnings("static-method")
public TypedArrayAccess typedArrayAccess() {
return TypedArrayAccess.SINGLETON;
}
public TypedArray getArrayType() {
return arrayType;
}
public static JSTypedArrayObject create(Shape shape, TypedArray arrayType, JSArrayBufferObject arrayBuffer, int length, int offset) {
return new JSTypedArrayObject(shape, arrayType, arrayBuffer, length, offset);
}
@Override
public String getClassName() {
return typedArrayAccess().getTypedArrayName(this);
}
@Override
public String getBuiltinToStringTag() {
return "Object";
}
@ExportMessage
public Object getMembers(@SuppressWarnings("unused") boolean includeInternal) {
assert JSObject.getJSClass(this) == JSArrayBufferView.INSTANCE;
return InteropArray.create(filterEnumerableNames(this, JSNonProxy.ordinaryOwnPropertyKeys(this), JSArrayBufferView.INSTANCE));
}
@SuppressWarnings("static-method")
@ExportMessage
public boolean hasArrayElements() {
return true;
}
@ExportMessage
public long getArraySize() {
return JSArrayBufferView.typedArrayGetLength(this);
}
@ExportMessage
public Object readArrayElement(long index,
@CachedLanguage @SuppressWarnings("unused") LanguageReference<JavaScriptLanguage> languageRef,
@Cached(value = "create(languageRef.get().getJSContext())", uncached = "getUncachedRead()") ReadElementNode readNode,
@Cached ExportValueNode exportNode,
@CachedLibrary("this") InteropLibrary thisLibrary) throws InvalidArrayIndexException, UnsupportedMessageException {
DynamicObject target = this;
if (index < 0 || index >= thisLibrary.getArraySize(this)) {
throw InvalidArrayIndexException.create(index);
}
Object result;
if (readNode == null) {
result = JSObject.getOrDefault(target, index, target, Undefined.instance);
} else {
result = readNode.executeWithTargetAndIndexOrDefault(target, index, Undefined.instance);
}
return exportNode.execute(result);
}
@ExportMessage(name = "isArrayElementReadable")
@ExportMessage(name = "isArrayElementModifiable")
public boolean isArrayElementReadable(long index,
@CachedLibrary("this") InteropLibrary thisLibrary) {
try {
return (index >= 0 && index < thisLibrary.getArraySize(this));
} catch (UnsupportedMessageException e) {
throw Errors.shouldNotReachHere(e);
}
}
@ExportMessage
public void writeArrayElement(long index, Object value,
@Cached ImportValueNode castValueNode,
@CachedLanguage @SuppressWarnings("unused") LanguageReference<JavaScriptLanguage> languageRef,
@Cached(value = "createCachedInterop(languageRef)", uncached = "getUncachedWrite()") WriteElementNode writeNode,
@CachedLibrary("this") InteropLibrary thisLibrary) throws InvalidArrayIndexException, UnsupportedMessageException {
DynamicObject target = this;
if (index < 0 || index >= thisLibrary.getArraySize(this)) {
throw InvalidArrayIndexException.create(index);
}
Object importedValue = castValueNode.executeWithTarget(value);
if (writeNode == null) {
JSObject.set(target, index, importedValue, true, null);
} else {
writeNode.executeWithTargetAndIndexAndValue(target, index, importedValue);
}
}
@SuppressWarnings("static-method")
@ExportMessage
public boolean isArrayElementInsertable(@SuppressWarnings("unused") long index) {
return false;
}
}