package com.oracle.truffle.js.builtins;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugTypedArrayDetachBufferNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262AgentBroadcastNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262AgentGetReportNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262AgentLeavingNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262AgentReceiveBroadcastNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262AgentReportNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262AgentSleepNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262AgentStartNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262CreateRealmNodeGen;
import com.oracle.truffle.js.builtins.Test262BuiltinsFactory.Test262EvalScriptNodeGen;
import com.oracle.truffle.js.builtins.helper.GCNodeGen;
import com.oracle.truffle.js.lang.JavaScriptLanguage;
import com.oracle.truffle.js.nodes.cast.JSToStringNode;
import com.oracle.truffle.js.nodes.function.JSBuiltin;
import com.oracle.truffle.js.nodes.function.JSBuiltinNode;
import com.oracle.truffle.js.nodes.function.JSLoadNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.Evaluator;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.JSRealm;
import com.oracle.truffle.js.runtime.JSRuntime;
import com.oracle.truffle.js.runtime.builtins.BuiltinEnum;
import com.oracle.truffle.js.runtime.builtins.JSTest262;
import com.oracle.truffle.js.runtime.objects.JSObject;
import com.oracle.truffle.js.runtime.objects.Undefined;
import com.oracle.truffle.js.runtime.util.DebugJSAgent;
public final class Test262Builtins extends JSBuiltinsContainer.SwitchEnum<Test262Builtins.Test262> {
public static final JSBuiltinsContainer BUILTINS = new Test262Builtins();
protected Test262Builtins() {
super(JSTest262.CLASS_NAME, Test262.class);
}
public enum Test262 implements BuiltinEnum<Test262> {
createRealm(0),
evalScript(1),
detachArrayBuffer(1),
gc(0),
agentStart(1),
agentBroadcast(1),
agentGetReport(0),
agentSleep(1),
agentReceiveBroadcast(1),
agentReport(1),
agentLeaving(0);
private final int length;
Test262(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
}
@Override
protected Object createNode(JSContext context, JSBuiltin builtin, boolean construct, boolean newTarget, Test262 builtinEnum) {
switch (builtinEnum) {
case detachArrayBuffer:
return DebugTypedArrayDetachBufferNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case createRealm:
return Test262CreateRealmNodeGen.create(context, builtin, args().createArgumentNodes(context));
case evalScript:
return Test262EvalScriptNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case gc:
return GCNodeGen.create(context, builtin, args().createArgumentNodes(context));
default:
switch (builtinEnum) {
case agentStart:
return Test262AgentStartNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case agentBroadcast:
return Test262AgentBroadcastNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case agentGetReport:
return Test262AgentGetReportNodeGen.create(context, builtin, args().fixedArgs(0).createArgumentNodes(context));
case agentSleep:
return Test262AgentSleepNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case agentReceiveBroadcast:
return Test262AgentReceiveBroadcastNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case agentReport:
return Test262AgentReportNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case agentLeaving:
return Test262AgentLeavingNodeGen.create(context, builtin, args().fixedArgs(0).createArgumentNodes(context));
}
}
return null;
}
public abstract static class Test262EvalScriptNode extends JSBuiltinNode {
public Test262EvalScriptNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object evalScript(Object obj,
@Cached("create(getContext())") JSLoadNode loadNode) {
String sourceText = JSRuntime.toString(obj);
getContext().checkEvalAllowed();
Source source = createSource(sourceText);
JSRealm realm = getContext().getRealm();
return loadNode.executeLoad(source, realm);
}
@TruffleBoundary
private static Source createSource(String sourceText) {
return Source.newBuilder(JavaScriptLanguage.ID, sourceText, Evaluator.EVAL_SOURCE_NAME).cached(false).build();
}
}
public abstract static class Test262CreateRealmNode extends JSBuiltinNode {
public Test262CreateRealmNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object createRealm() {
DynamicObject newGlobalObj = createChildRealm().getGlobalObject();
return JSObject.get(newGlobalObj, JSTest262.GLOBAL_PROPERTY_NAME);
}
@TruffleBoundary
private JSRealm createChildRealm() {
return getContext().getRealm().createChildRealm();
}
}
public abstract static class Test262AgentStart extends JSBuiltinNode {
public Test262AgentStart(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object start(Object obj) {
String sourceText = JSRuntime.toString(obj);
return ((DebugJSAgent) getContext().getJSAgent()).startNewAgent(sourceText);
}
}
public abstract static class Test262AgentBroadcast extends JSBuiltinNode {
public Test262AgentBroadcast(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object broadcast(Object sab) {
((DebugJSAgent) getContext().getJSAgent()).broadcast(sab);
return Undefined.instance;
}
}
public abstract static class Test262AgentGetReport extends JSBuiltinNode {
public Test262AgentGetReport(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object getReport() {
return ((DebugJSAgent) getContext().getJSAgent()).getReport();
}
}
public abstract static class Test262AgentSleep extends JSBuiltinNode {
public Test262AgentSleep(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object doSleep(int time) {
((DebugJSAgent) getContext().getJSAgent()).sleep(time);
return Undefined.instance;
}
@Fallback
protected Object doSleep(@SuppressWarnings("unused") Object time) {
throw Errors.createTypeError("Integer expected");
}
}
public abstract static class Test262AgentReceiveBroadcast extends JSBuiltinNode {
public Test262AgentReceiveBroadcast(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object receiveBroadcast(Object lambda) {
((DebugJSAgent) getContext().getJSAgent()).setDebugReceiveBroadcast(lambda);
return Undefined.instance;
}
}
public abstract static class Test262AgentReport extends JSBuiltinNode {
@Child private JSToStringNode toStringNode = JSToStringNode.create();
public Test262AgentReport(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object report(Object value) {
String message = toStringNode.executeString(value);
((DebugJSAgent) getContext().getJSAgent()).report(message);
return Undefined.instance;
}
}
public abstract static class Test262AgentLeaving extends JSBuiltinNode {
public Test262AgentLeaving(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object leaving() {
((DebugJSAgent) getContext().getJSAgent()).leaving();
return Undefined.instance;
}
}
}