/// <summary> /// Make glue object implementing interface cl that will /// call the supplied JS function when called. /// </summary> /// <remarks> /// Make glue object implementing interface cl that will /// call the supplied JS function when called. /// Only interfaces were all methods have the same signature is supported. /// </remarks> /// <returns> /// The glue object or null if <tt>cl</tt> is not interface or /// has methods with different signatures. /// </returns> internal static object Create(Context cx, Type cl, ScriptableObject @object) { if (!cl.IsInterface) { throw new ArgumentException(); } Scriptable topScope = ScriptRuntime.GetTopCallScope(cx); ClassCache cache = ClassCache.Get(topScope); Rhino.InterfaceAdapter adapter; adapter = (Rhino.InterfaceAdapter)cache.GetInterfaceAdapter(cl); ContextFactory cf = cx.GetFactory(); if (adapter == null) { MethodInfo[] methods = cl.GetMethods(); if (@object is Callable) { // Check if interface can be implemented by a single function. // We allow this if the interface has only one method or multiple // methods with the same name (in which case they'd result in // the same function to be invoked anyway). int length = methods.Length; if (length == 0) { throw Context.ReportRuntimeError1("msg.no.empty.interface.conversion", cl.FullName); } if (length > 1) { string methodName = methods[0].Name; for (int i = 1; i < length; i++) { if (!methodName.Equals(methods[i].Name)) { throw Context.ReportRuntimeError1("msg.no.function.interface.conversion", cl.FullName); } } } } adapter = new Rhino.InterfaceAdapter(cf, cl); cache.CacheInterfaceAdapter(cl, adapter); } return VMBridge.instance.NewInterfaceProxy(adapter.proxyHelper, cf, adapter, @object, topScope); }
public static object DoTopCall(Callable callable, Context cx, Scriptable scope, Scriptable thisObj, object[] args) { if (scope == null) { throw new ArgumentException(); } if (cx.topCallScope != null) { throw new InvalidOperationException(); } object result; cx.topCallScope = ScriptableObject.GetTopLevelScope(scope); cx.useDynamicScope = cx.HasFeature(Context.FEATURE_DYNAMIC_SCOPE); ContextFactory f = cx.GetFactory(); try { result = f.DoTopCall(callable, cx, scope, thisObj, args); } finally { cx.topCallScope = null; // Cleanup cached references cx.cachedXMLLib = null; if (cx.currentActivationCall != null) { // Function should always call exitActivationFunction // if it creates activation record throw new InvalidOperationException(); } } return result; }
/// <summary> /// The spawn function runs a given function or script in a different /// thread. /// </summary> /// <remarks> /// The spawn function runs a given function or script in a different /// thread. /// js> function g() { a = 7; } /// js> a = 3; /// 3 /// js> spawn(g) /// Thread[Thread-1,5,main] /// js> a /// 3 /// </remarks> public static object Spawn(Context cx, Scriptable thisObj, object[] args, Function funObj) { Scriptable scope = funObj.GetParentScope(); Runner runner; if (args.Length != 0 && args[0] is Function) { object[] newArgs = null; if (args.Length > 1 && args[1] is Scriptable) { newArgs = cx.GetElements((Scriptable)args[1]); } if (newArgs == null) { newArgs = ScriptRuntime.emptyArgs; } runner = new Runner(scope, (Function)args[0], newArgs); } else { if (args.Length != 0 && args[0] is Script) { runner = new Runner(scope, (Script)args[0]); } else { throw ReportRuntimeError("msg.spawn.args"); } } runner.factory = cx.GetFactory(); Sharpen.Thread thread = new Sharpen.Thread(runner); thread.Start(); return thread; }