package org.dynjs.runtime.linker.js.shadow; import org.dynjs.runtime.*; import org.dynjs.runtime.linker.js.ReferenceBaseFilter; import org.dynjs.runtime.linker.js.ReferenceStrictnessFilter; import org.projectodd.rephract.builder.LinkBuilder; import org.projectodd.rephract.guards.Guard; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import static java.lang.invoke.MethodHandles.lookup; import static java.lang.invoke.MethodType.methodType; /** * @author Bob McWhirter */ public class ShadowObjectPropertySetLink extends AbstractShadowObjectLink implements Guard { public ShadowObjectPropertySetLink(LinkBuilder builder, ShadowObjectManager shadowManager) throws Exception { super(builder, shadowManager); this.builder = builder.guardWith( this ); } public boolean guard(Object receiver, Object context, String propertyName, Object value) { if (!(receiver instanceof Reference)) { return false; } Object primary = ((Reference) receiver).getBase(); if (primary instanceof JSObject || primary instanceof EnvironmentRecord || primary == Types.UNDEFINED) { return false; } if ( this.primary != null ) { if ( this.primary != primary ) { return false; } if ( ! this.propertyName.equals( propertyName ) ) { return false; } } this.primary = primary; this.propertyName = propertyName; return true; } @Override public MethodHandle guardMethodHandle(MethodType inputType) throws Exception { return lookup() .findVirtual(ShadowObjectPropertySetLink.class, "guard", methodType(boolean.class, Object.class, Object.class, String.class, Object.class )) .bindTo(this); } public MethodHandle target() throws Exception { return builder //.convert(void.class, Reference.class, Object.class, String.class, Object.class) .permute(0, 1, 2, 3, 0) //.convert(void.class, Reference.class, Object.class, String.class, Object.class, Reference.class) .filter(0, ReferenceBaseFilter.INSTANCE) .filter(0, new ShadowFilter(this.shadowManager, true)) .filter(4, ReferenceStrictnessFilter.INSTANCE) .convert(void.class, JSObject.class, ExecutionContext.class, String.class, Object.class, boolean.class) .invoke(lookup().findVirtual(JSObject.class, "put", methodType(void.class, ExecutionContext.class, String.class, Object.class, boolean.class))) .target(); } }