Beispiel #1
0
 private static Type ConsumeType(StringParser sp)
 {
     sp.SkipWS();
     sp.ConsumeChar('[');
     var assmName = sp.ConsumeUntilChar(']');
     sp.ConsumeChar(']');
     var typeName = sp.ConsumeUntilChar('<');
     var args = default(List<Type>);
     if (sp.TryConsumeChar('<'))
     {
         args = new List<Type>();
         while (true)
         {
             if (sp.Failed)
                 break;
             args.Add(ConsumeType(sp));
             sp.SkipWS();
             if (sp.TryConsumeChar('>'))
                 break;
             sp.ConsumeChar(',');
         }
     }
     if (sp.Failed)
         throw new InvalidOperationException("syntax error in qualified type name");
     var assm = default(Assembly);
     try
     {
         assm = Assembly.Load(assmName);
     }
     catch (FileNotFoundException)
     {
         throw new InvalidOperationException("no such assembly");
     }
     var hkType = assm.GetType(typeName);
     if (hkType == null)
         throw new InvalidOperationException("no such type");
     if (args == null)
         return hkType;
     else
     {
         try
         {
             return hkType.MakeGenericType(args.ToArray());
         }
         catch (InvalidOperationException)
         {
             throw new InvalidOperationException("type is not higher-kinded");
         }
         catch (ArgumentException)
         {
             throw new InvalidOperationException("mismatched type arity");
         }
     }
 }
Beispiel #2
0
 private object[] ConsumeArgs(List<Type> argTypes, string args)
 {
     var argObjects = new object[argTypes.Count];
     var sp = new StringParser(args);
     sp.SkipWS();
     sp.ConsumeChar('(');
     for (var i = 0; i < argTypes.Count; i++)
     {
         if (i > 0)
         {
             sp.SkipWS();
             sp.ConsumeChar(',');
         }
         sp.SkipWS();
         if (sp.Failed)
             throw new InvalidOperationException("syntax error in arguments");
         var ops = FindInteropOps(argTypes[i]);
         argObjects[i] = ops.Import(sp);
     }
     sp.ConsumeChar(')');
     return argObjects;
 }
Beispiel #3
0
        private object Eval
            (Action<StringBuilder, Dictionary<Type, int>> expr, Func<StringParser, object> import)
        {
            var sb1 = new StringBuilder();
            var toBeLoaded = new Dictionary<Type, int>();
            sb1.Append("(function(){try{");
            if (import != null)
            {
                sb1.Append("return ");
                expr(sb1, toBeLoaded);
                sb1.Append(';');
            }
            else
            {
                expr(sb1, toBeLoaded);
                sb1.Append("return \"undefined\"");
            }
            sb1.Append("}catch(e){return ");
            sb1.Append(database.RootExpression);
            sb1.Append(".ImportException(");
            sb1.Append(TypeIndex(toBeLoaded, typeof(JSObject)));
            sb1.Append(",e);}})()");

            var sb2 = default(StringBuilder);
            if (toBeLoaded.Count > 0)
            {
                sb2 = new StringBuilder();
                AppendLoadRequiredTypes(sb2, toBeLoaded);
            }

            var res = default(string);
            bridge.InJavaScriptContext
                (() =>
                 {
                     if (sb2 != null)
                     {
                         Log("! " + sb2.ToString());
                         bridge.EvalStatementString(sb2.ToString());
                     }
                     Log("> " + sb1.ToString());
                     res = bridge.EvalExpressionString(sb1.ToString());
                     Log("< " + res);
                 });

            var sp = new StringParser(res);
            sp.SkipWS();
            if (sp.TryConsumeChar('~'))
                throw MakeInvalidCastException();
            else if (sp.TryConsumeChar('!'))
            {
                var ops = FindInteropOps(typeof(Exception));
                throw (Exception)ops.Import(sp);
            }
            else if (sp.TryConsumeChar('#'))
            {
                var ops = FindInteropOps(typeof (JSObject));
                var underlyingException = (JSObject)ops.Import(sp);
                throw MakeJSException(underlyingException);
            }
            else if (import != null)
                return import(sp);
            else if (sp.TryConsumeLit("undefined"))
                return null;
            else
                throw new InvalidOperationException("unexpected result of statement execution");
        }
Beispiel #4
0
 public override JSContext ContextForUnmanagedInstance(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         throw new InvalidOperationException("constructor returned null");
     else if (sp.TryConsumeLit("undefined"))
         throw new InvalidOperationException("constructor returned undefined");
     else
     {
         var id = sp.ConsumeId();
         sp.SkipWS();
         var qnm = default(string);
         if (sp.TryConsumeLit("null"))
             qnm = null;
         else
             qnm = sp.ConsumeEscapedString();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
         if (qnm != null)
         {
             var rttype = QualifiedNameToType(qnm);
             if (!type.IsAssignableFrom(rttype))
                 throw outer.MakeInvalidCastException();
         }
         return new JSContext(outer, type, null, id);
     }
 }
Beispiel #5
0
 public override object BindCreatedInstance(StringParser sp, object obj)
 {
     if (outer.objectToDisconnect.ContainsKey(obj))
         throw new InvalidOperationException("object already associated with unmanaged instance");
     sp.SkipWS();
     var id = sp.ConsumeId();
     if (sp.Failed)
         throw new InvalidOperationException("invalid response");
     outer.proxyToIdCache.Add(obj, id);
     outer.objectToDisconnect.Add(obj, () => Disconnect(id, obj));
     return obj;
 }
Beispiel #6
0
 public abstract object BindCreatedInstance(StringParser sp, object obj);
Beispiel #7
0
 // XREF1451
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         return null;
     else
     {
         sp.ConsumeChar('[');
         sp.SkipWS();
         if (sp.TryConsumeChar(']'))
             return Array.CreateInstance(elemInteropOps.type, 0);
         var objs = new List<object>();
         while (true)
         {
             if (sp.Failed)
                 throw new InvalidOperationException("invalid response");
             objs.Add(elemInteropOps.Import(sp));
             sp.SkipWS();
             if (sp.TryConsumeChar(']'))
             {
                 var res = Array.CreateInstance(elemInteropOps.type, objs.Count);
                 for (var i = 0; i < objs.Count; i++)
                     res.SetValue(objs[i], i);
                 return res;
             }
             sp.ConsumeChar(',');
         }
     }
 }
Beispiel #8
0
 // XREF1093
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         return null;
     else
     {
         var key = sp.ConsumeEscapedString();
         sp.SkipWS();
         var qnm = default(string);
         if (!sp.TryConsumeLit("null"))
             qnm = sp.ConsumeEscapedString();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
         var obj = default(object);
         var tkp = new TypeAndKeyPair { type = rootType, key = key };
         if (outer.keyToObjectCache.TryGetValue(tkp, out obj))
         {
             if (!type.IsAssignableFrom(obj.GetType()))
                 throw outer.MakeInvalidCastException();
         }
         else
         {
             if (qnm == null)
                 obj = outer.CreateDefaultInstance(type, key, 0);
             else
             {
                 var rttype = QualifiedNameToType(qnm);
                 if (!type.IsAssignableFrom(rttype))
                     throw outer.MakeInvalidCastException();
                 obj = outer.CreateDefaultInstance(rttype, key, 0);
             }
             outer.keyToObjectCache.Add(tkp, obj);
             var top = new TypeAndObjectPair { type = rootType, obj = obj };
             outer.objectToKeyCache.Add(top, key);
             // obj is always new
             outer.objectToDisconnect.Add(obj, () => Disconnect(tkp, top));
         }
         return obj;
     }
 }
Beispiel #9
0
 public override JSContext ContextForUnmanagedInstance(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         throw new InvalidOperationException("constructor returned null");
     else
     {
         var key = sp.ConsumeEscapedString();
         sp.SkipWS();
         var qnm = default(string);
         if (!sp.TryConsumeLit("null"))
             qnm = sp.ConsumeEscapedString();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
         var tkp = new TypeAndKeyPair { type = rootType, key = key };
         if (outer.keyToObjectCache.ContainsKey(tkp))
             throw new InvalidOperationException("constructor reused key from existing object");
         if (qnm != null)
         {
             var rttype = QualifiedNameToType(qnm);
             if (!type.IsAssignableFrom(rttype))
                 throw outer.MakeInvalidCastException();
         }
         return new JSContext(outer, type, key, 0);
     }
 }
Beispiel #10
0
 public override JSContext ContextForUnmanagedInstance(StringParser sp)
 {
     throw new InvalidOperationException("Normal types cannot have imported constructors");
 }
Beispiel #11
0
 public override object BindCreatedInstance(StringParser sp, object obj)
 {
     throw new InvalidOperationException("create not required");
 }
Beispiel #12
0
 // XREF1009
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         return null;
     else
     {
         var id = sp.ConsumeId();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
         var obj = default(object);
         if (!outer.idToObjectCache.TryGetValue(id, out obj))
             throw outer.MakeInvalidCastException();
         if (!type.IsAssignableFrom(obj.GetType()))
             throw outer.MakeInvalidCastException();
         return obj;
     }
 }
Beispiel #13
0
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         return null;
     else
     {
         var res = sp.ConsumeEscapedString();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
         return res;
     }
 }
Beispiel #14
0
 // XREF1319
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     var v = default(double);
     if (sp.TryConsumeLit("true"))
         v = 1.0;
     else if (sp.TryConsumeLit("false"))
         v = 0.0;
     else if (sp.TryConsumeLit("NaN"))
         v = double.NaN;
     else
     {
         v = sp.ConsumeDouble();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
     }
     switch (type.FullName)
     {
         case "System.SByte":
             return (sbyte)v;
         case "System.Boolean":
             return v == 0.0 ? false : true;
         case "System.Char":
             return (char)v;
         case "System.Int16":
             return (short)v;
         case "System.Int32":
             return (int)v;
         case "System.Int64":
             return (long)v;
         case "System.Byte":
             return (byte)v;
         case "System.UInt16":
             return (ushort)v;
         case "System.UInt32":
             return (uint)v;
         case "System.UInt64":
             return (ulong)v;
         case "System.Single":
             return (float)v;
         case "System.Double":
             return v;
         default:
             throw new InvalidOperationException("not a primitive number type");
     }
 }
Beispiel #15
0
 public abstract object Import(StringParser sp);
Beispiel #16
0
 public override object BindCreatedInstance(StringParser sp, object obj)
 {
     if (outer.objectToDisconnect.ContainsKey(obj))
         throw new InvalidOperationException("object already associated with unmanaged instance");
     sp.SkipWS();
     var key = sp.ConsumeEscapedString();
     if (sp.Failed)
         throw new InvalidOperationException("invalid response");
     var tkp = new TypeAndKeyPair { type = rootType, key = key };
     outer.keyToObjectCache.Add(tkp, obj);
     var top = new TypeAndObjectPair { type = rootType, obj = obj };
     outer.objectToKeyCache.Add(top, key);
     outer.objectToDisconnect.Add(obj, () => Disconnect(tkp, top));
     return obj;
 }
Beispiel #17
0
 public abstract JSContext ContextForUnmanagedInstance(StringParser sp);
Beispiel #18
0
 // XREF1051
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         return null;
     else if (sp.TryConsumeLit("undefined"))
     {
         var obj = outer.CreateDefaultInstance(type, null, -1);
         // Remember this object is associated with 'undefined'
         outer.proxyToIdCache.Add(obj, -1);
         // obj is always new
         outer.objectToDisconnect.Add(obj, () => Disconnect(-1, obj));
         return obj;
     }
     else
     {
         var id = sp.ConsumeId();
         sp.SkipWS();
         var qnm = default(string);
         if (sp.TryConsumeLit("null"))
             qnm = null;
         else
             qnm = sp.ConsumeEscapedString();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
         var obj = default(object);
         if (qnm == null)
             obj = outer.CreateDefaultInstance(type, null, id);
         else
         {
             var rttype = QualifiedNameToType(qnm);
             if (!type.IsAssignableFrom(rttype))
                 throw outer.MakeInvalidCastException();
             obj = outer.CreateDefaultInstance(rttype, null, id);
         }
         outer.proxyToIdCache.Add(obj, id);
         // obj is always new
         outer.objectToDisconnect.Add(obj, () => Disconnect(id, obj));
         return obj;
     }
 }
Beispiel #19
0
 // XREF1223
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         return null;
     else
         return elemInteropOps.Import(sp);
 }
Beispiel #20
0
 // XREF1039
 public override object Import(StringParser sp)
 {
     sp.SkipWS();
     if (sp.TryConsumeLit("null"))
         return null;
     else
     {
         var id = sp.ConsumeId();
         if (sp.Failed)
             throw new InvalidOperationException("invalid response");
         UniversalDelegate f = argObjects =>
                               {
                                   if (argObjects == null || argObjects.Length != argInteropOps.Length)
                                       throw new InvalidOperationException
                                           ("invalid universal delegate arguments array");
                                   Action<StringBuilder, Dictionary<Type, int>> makeCall =
                                       (sb, toBeLoaded) =>
                                       {
                                           sb.Append(outer.database.RootExpression);
                                           sb.Append(".CallUnmanaged(");
                                           sb.Append(id);
                                           sb.Append(",[");
                                           for (var i = 0; i < argInteropOps.Length; i++)
                                           {
                                               if (i > 0)
                                                   sb.Append(',');
                                               argInteropOps[i].AppendExport
                                                   (sb, toBeLoaded, argObjects[i]);
                                           }
                                           sb.Append("],");
                                           sb.Append(captureThis ? "true" : "false");
                                           sb.Append(',');
                                           sb.Append(inlineParamsArray ? "true" : "false");
                                           sb.Append(')');
                                           if (resInteropOps == null)
                                               sb.Append(';');
                                       };
                                   if (resInteropOps == null)
                                       return outer.Eval(makeCall, null);
                                   else
                                       return outer.Eval
                                           (resInteropOps.WrapImport(makeCall), resInteropOps.Import);
                               };
         var shimType = outer.database.FindDelegateShim(type);
         var shim = Activator.CreateInstance(shimType, f);
         var g = Delegate.CreateDelegate(type, shim, "Invoke");
         outer.objectToDisconnect.Add(g, () => DisconnectImported(id));
         return g;
     }
 }