/// <summary> /// Enumerates all scripts in the the container, and execute the /// scripts that have the highest reference count first. /// </summary> protected void ExecuteScripts() { foreach (JistScript script in scriptContainer.Scripts.OrderByDescending(i => i.ReferenceCount)) { try { ExecuteScript(script); RaisePercentChangedEvent("Execute"); } catch (Exception ex) { ScriptLog.ErrorFormat(script.FilePathOrUri, "Execution error: " + ex.Message); } } }
/// <summary> /// Executes a script, and returns it's completion value. /// </summary> public JsValue ExecuteScript(JistScript script) { if (script == null || string.IsNullOrEmpty(script.Script) == true) { return(JsValue.Undefined); } try { return(jsEngine.Execute(script.Script).GetCompletionValue()); } catch (Exception ex) { ScriptLog.ErrorFormat(script.FilePathOrUri, "Execution error: " + ex.Message); return(JsValue.Undefined); } }
/// <summary> /// Loads a script from file into a reference-counted object, and inserts it into /// the script container. /// /// Scripts are /not/ executed by the javascript engine at this point. /// </summary> public JistScript LoadScript(string ScriptPath, bool IncreaseRefCount = true) { JistScript content; /* * if this script has already been called for, return the called object * with an incremented ref count */ if (scriptContainer.Scripts.Count(i => i.FilePathOrUri.Equals(ScriptPath, StringComparison.InvariantCultureIgnoreCase)) > 0) { content = scriptContainer.Scripts.FirstOrDefault(i => i.FilePathOrUri.Equals(ScriptPath, StringComparison.InvariantCultureIgnoreCase)); if (IncreaseRefCount) { content.ReferenceCount++; } return(null); } content = new JistScript(); content.FilePathOrUri = ScriptPath; content.ReferenceCount = 1; try { content.Script = File.ReadAllText(Path.Combine(scriptsDir, content.FilePathOrUri)); } catch (Exception ex) { ScriptLog.ErrorFormat("engine", "Cannot load {0}: {1}", ScriptPath, ex.Message); return(null); } /* * Script must be added to the content list before preprocessing * this is to prevent cyclic references between @imports, used as an include guard */ scriptContainer.PreprocessScript(content); scriptContainer.Scripts.Add(content); return(content); }
/// <summary> /// Creates Javascript function delegates for the type specified, and /// optionally by the object instance. /// /// Instance may be null, however only static methods will be regarded /// in this manner, since there is no 'this' pointer. /// </summary> public void CreateScriptFunctions(Type type, object instance) { Delegate functionDelegate = null; Type delegateSignature = null; string functionName = null; JavascriptFunctionAttribute jsAttribute = null; /* * If the class provides functionality for scripts, * add it into the providedpackages array. */ foreach (JavascriptProvidesAttribute attrib in type.GetCustomAttributes(true).OfType <JavascriptProvidesAttribute>()) { if (!providedPackages.Contains(attrib.PackageName)) { providedPackages.Add(attrib.PackageName); } } /* * look for JS methods in the type */ foreach (var jsFunction in type.GetMethods().Where(i => i.GetCustomAttributes(true).OfType <JavascriptFunctionAttribute>().Any())) { if (instance == null && jsFunction.IsStatic == false || (jsAttribute = jsFunction.GetCustomAttributes(true).OfType <JavascriptFunctionAttribute>().FirstOrDefault()) == null) { continue; } foreach (string func in jsAttribute.FunctionNames) { functionName = func ?? jsFunction.Name; try { /* * A delegate signature type matching every single parameter type, * and the return type must be appended as the very last item * in the array. */ delegateSignature = Expression.GetDelegateType(jsFunction.GetParameters().Select(i => i.ParameterType) .Concat(new[] { jsFunction.ReturnType }).ToArray()); if (instance != null) { functionDelegate = Delegate.CreateDelegate(delegateSignature, instance, jsFunction); } else { functionDelegate = Delegate.CreateDelegate(delegateSignature, jsFunction); } lock (syncRoot) jsEngine.SetValue(functionName, functionDelegate); } catch (Exception ex) { ScriptLog.ErrorFormat("engine", "Error whilst creating javascript function for {0}: {1}", functionName, ex.ToString()); continue; } } } }