package com.oracle.truffle.js.nodes.access;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Executed;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.js.nodes.JavaScriptNode;
import com.oracle.truffle.js.nodes.cast.JSToObjectArrayNode;
import com.oracle.truffle.js.nodes.cast.JSToObjectNode;
import com.oracle.truffle.js.runtime.JSContext;
import java.util.Set;
public abstract class RestObjectNode extends JavaScriptNode {
@Child @Executed protected JavaScriptNode targetNode;
@Child @Executed protected JavaScriptNode sourceNode;
@Child private CopyDataPropertiesNode copyDataPropertiesNode;
protected final JSContext context;
protected RestObjectNode(JSContext context, JavaScriptNode targetNode, JavaScriptNode sourceNode) {
this.context = context;
this.targetNode = targetNode;
this.sourceNode = sourceNode;
this.copyDataPropertiesNode = CopyDataPropertiesNode.create(context);
}
public static JavaScriptNode create(JSContext context, JavaScriptNode targetNode, JavaScriptNode sourceNode, JavaScriptNode excludedNode) {
if (excludedNode == null) {
return RestObjectNodeGen.create(context, targetNode, sourceNode);
} else {
return RestObjectWithExcludedNodeGen.create(context, targetNode, sourceNode, excludedNode);
}
}
@SuppressWarnings("unused")
@Specialization(guards = "isNullOrUndefined(source)")
protected static DynamicObject doNullOrUndefined(DynamicObject restObj, Object source) {
return restObj;
}
@Specialization(guards = {"isJSObject(source)"})
protected final DynamicObject copyDataProperties(DynamicObject restObj, DynamicObject source) {
copyDataPropertiesNode.execute(restObj, source);
return restObj;
}
@Specialization(guards = {"!isJSDynamicObject(source)"})
protected final Object doOther(DynamicObject restObj, Object source,
@Cached("createToObjectNoCheck(context)") JSToObjectNode toObjectNode) {
Object from = toObjectNode.execute(source);
copyDataPropertiesNode.execute(restObj, from);
return restObj;
}
@Override
protected JavaScriptNode copyUninitialized(Set<Class<? extends Tag>> materializedTags) {
return RestObjectNodeGen.create(context, cloneUninitialized(targetNode, materializedTags), cloneUninitialized(sourceNode, materializedTags));
}
}
abstract class RestObjectWithExcludedNode extends JavaScriptNode {
@Child @Executed protected JavaScriptNode targetNode;
@Child @Executed protected JavaScriptNode sourceNode;
@Child @Executed protected JavaScriptNode excludedNode;
@Child private CopyDataPropertiesNode copyDataPropertiesNode;
protected final JSContext context;
protected RestObjectWithExcludedNode(JSContext context, JavaScriptNode targetNode, JavaScriptNode sourceNode, JavaScriptNode excludedNode) {
this.context = context;
this.targetNode = targetNode;
this.sourceNode = sourceNode;
this.excludedNode = JSToObjectArrayNode.create(context, excludedNode);
this.copyDataPropertiesNode = CopyDataPropertiesNode.create(context);
}
@SuppressWarnings("unused")
@Specialization(guards = "isNullOrUndefined(source)")
protected static DynamicObject doNullOrUndefined(DynamicObject restObj, Object source, Object[] excludedItems) {
return restObj;
}
@Specialization(guards = {"isJSObject(source)"})
protected final DynamicObject copyDataProperties(DynamicObject restObj, DynamicObject source, Object[] excludedItems) {
copyDataPropertiesNode.execute(restObj, source, excludedItems);
return restObj;
}
@Specialization(guards = {"!isJSDynamicObject(source)"})
protected final Object doOther(DynamicObject restObj, Object source, Object[] excludedItems,
@Cached("createToObjectNoCheck(context)") JSToObjectNode toObjectNode) {
Object from = toObjectNode.execute(source);
copyDataPropertiesNode.execute(restObj, from, excludedItems);
return restObj;
}
@Override
protected JavaScriptNode copyUninitialized(Set<Class<? extends Tag>> materializedTags) {
return RestObjectWithExcludedNodeGen.create(context, cloneUninitialized(targetNode, materializedTags), cloneUninitialized(sourceNode, materializedTags),
cloneUninitialized(excludedNode, materializedTags));
}
}