package com.oracle.truffle.js.runtime.builtins;
import static com.oracle.truffle.js.runtime.objects.JSObjectUtil.putConstructorProperty;
import static com.oracle.truffle.js.runtime.objects.JSObjectUtil.putFunctionsFromContainer;
import java.nio.ByteBuffer;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.js.builtins.SharedArrayBufferFunctionBuiltins;
import com.oracle.truffle.js.builtins.SharedArrayBufferPrototypeBuiltins;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.JSAgentWaiterList;
import com.oracle.truffle.js.runtime.JSArguments;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.JSContext.BuiltinFunctionKey;
import com.oracle.truffle.js.runtime.JSRealm;
import com.oracle.truffle.js.runtime.JavaScriptRootNode;
import com.oracle.truffle.js.runtime.objects.JSObjectUtil;
import com.oracle.truffle.js.runtime.objects.Undefined;
import com.oracle.truffle.js.runtime.util.DirectByteBufferHelper;
public final class JSSharedArrayBuffer extends JSAbstractBuffer implements JSConstructorFactory.Default.WithFunctionsAndSpecies, PrototypeSupplier {
public static final String CLASS_NAME = "SharedArrayBuffer";
public static final String PROTOTYPE_NAME = CLASS_NAME + ".prototype";
public static final JSSharedArrayBuffer INSTANCE = new JSSharedArrayBuffer();
private JSSharedArrayBuffer() {
}
public static DynamicObject createSharedArrayBuffer(JSContext context, int length) {
return createSharedArrayBuffer(context, DirectByteBufferHelper.allocateDirect(length));
}
public static DynamicObject createSharedArrayBuffer(JSContext context, ByteBuffer buffer) {
assert buffer != null;
JSRealm realm = context.getRealm();
JSObjectFactory factory = context.getSharedArrayBufferFactory();
DynamicObject obj = JSArrayBufferObject.createSharedArrayBuffer(factory.getShape(realm), buffer, new JSAgentWaiterList());
factory.initProto(obj, realm);
assert isJSSharedArrayBuffer(obj);
return context.trackAllocation(obj);
}
@Override
public DynamicObject createPrototype(JSRealm realm, DynamicObject ctor) {
JSContext context = realm.getContext();
DynamicObject arrayBufferPrototype = JSObjectUtil.createOrdinaryPrototypeObject(realm);
putConstructorProperty(context, arrayBufferPrototype, ctor);
putFunctionsFromContainer(realm, arrayBufferPrototype, SharedArrayBufferPrototypeBuiltins.BUILTINS);
JSFunctionData fd = realm.getContext().getOrCreateBuiltinFunctionData(BuiltinFunctionKey.SharedArrayBufferGetByteLength, (c) -> {
return JSFunctionData.createCallOnly(context, createByteLengthGetterCallTarget(context), 0, "get " + BYTE_LENGTH);
});
DynamicObject byteLengthGetter = JSFunction.create(realm, fd);
JSObjectUtil.putToStringTag(arrayBufferPrototype, CLASS_NAME);
JSObjectUtil.putBuiltinAccessorProperty(arrayBufferPrototype, BYTE_LENGTH, byteLengthGetter, Undefined.instance);
return arrayBufferPrototype;
}
private static CallTarget createByteLengthGetterCallTarget(JSContext context) {
return Truffle.getRuntime().createCallTarget(new JavaScriptRootNode(context.getLanguage(), null, null) {
@Override
public Object execute(VirtualFrame frame) {
Object obj = JSArguments.getThisObject(frame.getArguments());
if (isJSSharedArrayBuffer(obj)) {
return JSArrayBuffer.getDirectByteLength((DynamicObject) obj);
}
throw Errors.createTypeErrorIncompatibleReceiver(obj);
}
});
}
@Override
public Shape makeInitialShape(JSContext context, DynamicObject prototype) {
Shape initialShape = JSObjectUtil.getProtoChildShape(prototype, INSTANCE, context);
return initialShape;
}
public static JSConstructor createConstructor(JSRealm realm) {
return INSTANCE.createConstructorAndPrototype(realm, SharedArrayBufferFunctionBuiltins.BUILTINS);
}
@Override
public String getClassName() {
return CLASS_NAME;
}
@Override
public String getClassName(DynamicObject object) {
return getClassName();
}
public static boolean isJSSharedArrayBuffer(Object obj) {
return obj instanceof JSArrayBufferObject.Shared;
}
public static ByteBuffer getDirectByteBuffer(DynamicObject thisObj) {
assert isJSSharedArrayBuffer(thisObj);
return JSArrayBufferObject.getDirectByteBuffer(thisObj);
}
public static JSAgentWaiterList getWaiterList(DynamicObject thisObj) {
assert isJSSharedArrayBuffer(thisObj);
return JSArrayBufferObject.getWaiterList(thisObj);
}
public static void setWaiterList(DynamicObject thisObj, JSAgentWaiterList wl) {
assert isJSSharedArrayBuffer(thisObj);
JSArrayBufferObject.setWaiterList(thisObj, wl);
}
@Override
public DynamicObject getIntrinsicDefaultProto(JSRealm realm) {
return realm.getSharedArrayBufferPrototype();
}
}