package com.oracle.truffle.js.nodes.cast;
import java.util.Set;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.js.nodes.JavaScriptNode;
import com.oracle.truffle.js.nodes.access.GlobalObjectNode;
import com.oracle.truffle.js.nodes.unary.JSUnaryNode;
import com.oracle.truffle.js.runtime.BigInt;
import com.oracle.truffle.js.runtime.JSConfig;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.Symbol;
import com.oracle.truffle.js.runtime.builtins.JSBigInt;
import com.oracle.truffle.js.runtime.builtins.JSBoolean;
import com.oracle.truffle.js.runtime.builtins.JSNumber;
import com.oracle.truffle.js.runtime.builtins.JSString;
import com.oracle.truffle.js.runtime.builtins.JSSymbol;
import com.oracle.truffle.js.runtime.objects.JSLazyString;
@ImportStatic({JSConfig.class})
public abstract class JSPrepareThisNode extends JSUnaryNode {
final JSContext context;
protected JSPrepareThisNode(JSContext context, JavaScriptNode child) {
super(child);
this.context = context;
}
public static JSPrepareThisNode createPrepareThisBinding(JSContext context, JavaScriptNode child) {
return JSPrepareThisNodeGen.create(context, child);
}
@Specialization(guards = "isNullOrUndefined(object)")
protected DynamicObject doJSObject(@SuppressWarnings("unused") Object object) {
return GlobalObjectNode.getGlobalObject(context);
}
@SuppressWarnings("unused")
@Specialization(guards = {"cachedClass != null", "cachedClass.isInstance(object)"}, limit = "1")
protected Object doJSObjectCached(Object object,
@Cached("getClassIfJSObject(object)") Class<?> cachedClass) {
return object;
}
@Specialization(guards = "isJSObject(object)", replaces = "doJSObjectCached")
protected DynamicObject doJSObject(DynamicObject object) {
return object;
}
@Specialization
protected DynamicObject doBoolean(boolean value) {
return JSBoolean.create(context, value);
}
@Specialization
protected DynamicObject doJSLazyString(JSLazyString value) {
return JSString.create(context, value);
}
@Specialization
protected DynamicObject doString(String value) {
return JSString.create(context, value);
}
@Specialization
protected DynamicObject doInt(int value) {
return JSNumber.create(context, value);
}
@Specialization
protected DynamicObject doDouble(double value) {
return JSNumber.create(context, value);
}
@Specialization
protected DynamicObject doBigInt(BigInt value) {
return JSBigInt.create(context, value);
}
@Specialization(guards = "isJavaNumber(value)")
protected DynamicObject doNumber(Object value) {
return JSNumber.create(context, (Number) value);
}
@Specialization
protected DynamicObject doSymbol(Symbol value) {
return JSSymbol.create(context, value);
}
@Specialization(guards = "isForeignObject(object)", limit = "InteropLibraryLimit")
protected Object doForeignObject(Object object,
@CachedLibrary("object") InteropLibrary interop) {
if (interop.isNull(object)) {
return GlobalObjectNode.getGlobalObject(context);
}
return object;
}
@Override
protected JavaScriptNode copyUninitialized(Set<Class<? extends Tag>> materializedTags) {
return JSPrepareThisNodeGen.create(context, cloneUninitialized(getOperand(), materializedTags));
}
}