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"); } } }
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; }
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"); }
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); } }
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; }
public abstract object BindCreatedInstance(StringParser sp, object obj);
// 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(','); } } }
// 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; } }
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); } }
public override JSContext ContextForUnmanagedInstance(StringParser sp) { throw new InvalidOperationException("Normal types cannot have imported constructors"); }
public override object BindCreatedInstance(StringParser sp, object obj) { throw new InvalidOperationException("create not required"); }
// 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; } }
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; } }
// 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"); } }
public abstract object Import(StringParser sp);
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; }
public abstract JSContext ContextForUnmanagedInstance(StringParser sp);
// 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; } }
// XREF1223 public override object Import(StringParser sp) { sp.SkipWS(); if (sp.TryConsumeLit("null")) return null; else return elemInteropOps.Import(sp); }
// 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; } }