Exemplo n.º 1
0
        public ActionResult Index()
        {
            var engine = new V8.Net.V8Engine();

            ViewBag.Result = engine.Execute("2*3", "V8.NET ASP Test").AsString;
            return(View());
        }
Exemplo n.º 2
0
 public string GetData(int value)
 {
     // V8Engine.ASPBINSubFolderName = "V8.NET"; // It is already "V8.NET" by default, so just delete this line if not needed.  Please see integration steps at the top for more details.
     var engine = new V8Engine();
     Handle result = engine.Execute("'You entered: '+" + value, "V8.NET Web Service Test");
     return result.AsString;
 }
        /// <summary>
        /// JavaScript callback. Returns absolute path to the file that is referenced from the file in the
        /// editor. Implementation copied from the Emmet project source code.
        /// </summary>
        public InternalHandle LocateFile(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            if (args.Length != 2)
            {
                this.TraceError("IEmmetFile locateFile called with invalid number of arguments.");
                return engine.CreateValue(false);
            }

            string editorFile = args[0].AsString;
            string targetFile = args[1].AsString;

            if (targetFile.StartsWith("HTTP", System.StringComparison.InvariantCultureIgnoreCase))
                return engine.CreateValue(targetFile);

            string folder = Path.GetDirectoryName(editorFile);
            do
            {
                string retVal = Path.Combine(folder, targetFile);
                if (File.Exists(retVal))
                    return engine.CreateValue(retVal);
            }
            while (folder.Length > 3);

            return engine.CreateValue(string.Empty);
        }
Exemplo n.º 4
0
 public void InitEngine()
 {
     engine.Dispose();
     engine = new V8Engine();
     commands = new Command(this);
     engine.GlobalObject.SetProperty("Plugin", this, "Plugin", null, ScriptMemberSecurity.Locked);
     engine.GlobalObject.SetProperty("Command", commands, "Command", true, ScriptMemberSecurity.Locked);
 }
        /// <summary>
        /// JavaScript callback. Returns character indexes of selected text: object with <code>start</code>
        /// and <code>end</code> properties.If there's no selection, should return object with
        /// <code>start</code> and <code>end</code> properties referring to current caret position.
        /// </summary>
        public InternalHandle GetSelectionRange(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            var selection = _editor.GetSelectionRange();
            ObjectHandle retVal = engine.CreateObject();
            retVal.SetProperty("start", engine.CreateValue(selection.Start));
            retVal.SetProperty("end", engine.CreateValue(selection.End));

            return retVal;
        }
        public void Compile_CompilesEmmetEngineScript()
        {
            // Arrange
            V8Engine engine = new V8Engine();
            EngineCompiler compiler = new EngineCompiler(engine);

            // Act
            compiler.CompileCore();

            // Assert
            ObjectHandle emmet = engine.DynamicGlobalObject.window.emmet;
            emmet.Should().NotBeNull();
        }
Exemplo n.º 7
0
        private void InitializeEngine()
        {
            this.Trace("Started initializing Emmet engine.");

            _engine = new V8Engine();
            var compiler = new EngineCompiler(_engine);

            compiler.CompileCore();
            compiler.RegisterCallbacks(_editor);
            if (null != _extensionsDir)
                compiler.LoadExtensions(_extensionsDir);

            this.Trace("Emmet engine successfully initialized.");
        }
Exemplo n.º 8
0
        // TODO: This is shared in both templates - consider putting elsewhere.
        internal static HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount, params JSFunction[] functions)
        {
            // ... get a handle to the native "this" object ...

            InternalHandle hThis = _this;

            V8Engine engine = hThis.Engine;

            // ... wrap the arguments ...

            InternalHandle[] _args = new InternalHandle[argCount];
            int i;

            for (i = 0; i < argCount; i++)
            {
                _args[i] = args[i]; // (since these will be disposed immediately after, the "first" flag is not required [this also prevents it from getting passed on])
            }
            // (note: the underlying native handles for '_this' and any arguments will be disposed automatically upon return, unless the user calls 'KeepAlive()' on them)

            InternalHandle result = null;

            // ... call all function types (multiple custom derived function types are allowed, but only one of each type) ...
            foreach (var callback in functions)
            {
                result = callback(engine, isConstructCall, hThis, _args);

                if (!result.IsEmpty)
                {
                    break;
                }
            }

            var obj = result.Object;

            // ... make sure the user is not returning a 'V8ManagedObject' instance associated with the new object (the property interceptors will never work) ...

            if (isConstructCall && obj != null && obj is V8ManagedObject && obj.InternalHandle == hThis)
            {
                throw new InvalidOperationException("You've attempted to return the type '" + obj.GetType().Name
                                                    + "' which is of type V8ManagedObject in a construction call (using 'new' in JavaScript) to wrap the new native object given to the constructor.  The native V8 engine"
                                                    + " only supports interceptor hooks for objects generated from ObjectTemplate instances.  You will need to first derive/implement from V8NativeObject/IV8NativeObject"
                                                    + " for your custom object(s), or rewrite your object to use V8NativeObject directly instead and use the 'SetAccessor()' handle method.");
            }

            return(result);
        }
        public void LoadExtensions_PointedToPreferencesFile_LoadsCustomSnippets()
        {
            // Arrange
            V8Engine engine = new V8Engine();
            EngineCompiler compiler = new EngineCompiler(engine);

            // Act
            compiler.CompileCore();
            compiler.LoadExtensions(TestContext.TestDeploymentDir);

            // Assert
            string script = "window.emmet.resources.fuzzyFindSnippet('css', 'section')";
            Handle result = engine.Execute(script);

            // preferences.json file contains "section" abbreviation for css. If we are able to find it then
            // our extension has been loaded correctly. 
            result.IsObject.Should().BeTrue();
        }
        /// <summary>
        /// JavaScript callback. Creates selection from <code>start</code> to <code>end</code> character
        /// indexes. If <code>end</code> is omitted, this method should place caret and <code>start</code>
        /// index.
        /// </summary>
        public InternalHandle CreateSelection(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            if (args.Length == 2)
            {
                int start = args[0].AsInt32;
                int end = args[0].AsInt32;
                _editor.CreateSelection(start, end);
            }
            else
            {
                return SetCarretPos(engine, isConstructCall, self, args);
            }

            return engine.CreateValue(true);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Looks for tab stops in the specified content and returns a processed version with expanded
        /// placeholders and tab stops found.
        /// </summary>
        /// <param name="engine">V8 instance with Emmet engine compiled in it.</param>
        /// <param name="content">Expanded abbreviation content.</param>
        /// <exception cref="Exception{EmmetEngineExceptionArgs}">
        /// Indicates that Emmet engine has failed to parse the specified content.
        /// </exception>
        public static TabStopsParser ParseContent(V8Engine engine, string content)
        {
            ObjectHandle tabStopsUtil = engine.DynamicGlobalObject.window.emmet.tabStops;
            Handle extractResult = tabStopsUtil.Call("extract", null, engine.CreateValue(content));

            if (extractResult.IsError)
            {
                var ex = new EmmetEngineExceptionArgs(
                    "Error while trying to extract tab stops.",
                    extractResult);
                throw new Exception<EmmetEngineExceptionArgs>(ex);
            }

            TabStopsParser retVal = new TabStopsParser();
            ObjectHandle tabStopsObj = (ObjectHandle)extractResult;
            retVal.Content = tabStopsObj.GetProperty(@"text").AsString;
            ObjectHandle tabStopsList = tabStopsObj.GetProperty(@"tabstops");

            // Tab stops should be added before modifying document so that editor can track their position.
            int tabStopsCount = tabStopsList.ArrayLength;

            if (tabStopsCount > 0)
            {
                retVal.TabStops = new Range[tabStopsCount];
                retVal.TabStopGroups = new int[tabStopsCount];

                for (int i = 0; i < tabStopsCount; i++)
                {
                    ObjectHandle tabStopObj = tabStopsList.GetProperty(i.ToString());
                    int start = tabStopObj.GetProperty("start").AsInt32;
                    int end = tabStopObj.GetProperty("end").AsInt32;
                    int group = tabStopObj.GetProperty("group").AsInt32;

                    retVal.TabStops[i] = new Range(start, end);
                    retVal.TabStopGroups[i] = group;
                }
            }

            return retVal;
        }
Exemplo n.º 12
0
        /// <summary>
        /// JavaScript callback. Reads the specified file content and returns it as string.
        /// </summary>
        public InternalHandle Read(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            if (args.Length != 3)
            {
                this.TraceError("IEmmetFile read called with invalid number of arguments.");
                return engine.CreateValue(false);
            }

            string targetFilePath = args[0].AsString;
            int chunkSize = args[1].AsInt32;
            ObjectHandle callback = args[2];

            if (!File.Exists(targetFilePath))
            {
                this.TraceError($"Emmet requested file {targetFilePath} that does not exist.");
                callback.StaticCall(engine.CreateValue(true), engine.CreateNullValue());

                return engine.CreateValue(false);
            }

            char[] buf = new char[chunkSize];
            FileStream stream = File.OpenRead(targetFilePath);
            using (StreamReader reader = new StreamReader(stream))
            {
                chunkSize = reader.ReadBlock(buf, 0, chunkSize);
            }

            string retVal = new string(buf, 0, chunkSize);
            callback.StaticCall(engine.CreateValue(false), engine.CreateValue(retVal));

            return engine.CreateValue(true);
        }
Exemplo n.º 13
0
        internal void _Initialize(V8Engine v8EngineProxy, NativeObjectTemplateProxy *nativeObjectTemplateProxy, bool registerPropertyInterceptors = true)
        {
            if (v8EngineProxy == null)
            {
                throw new ArgumentNullException("v8EngineProxy");
            }

            if (nativeObjectTemplateProxy == null)
            {
                throw new ArgumentNullException("nativeObjectTemplateProxy");
            }

            _Engine = v8EngineProxy;

            _NativeObjectTemplateProxy = nativeObjectTemplateProxy;

            if (registerPropertyInterceptors)
            {
                RegisterNamedPropertyInterceptors();
                RegisterIndexedPropertyInterceptors();
            }

            OnInitialized();
        }
 /// <summary>
 /// JavaScript callback. Returns current editor's syntax mode.
 /// </summary>
 public InternalHandle GetSyntax(
     V8Engine engine,
     bool isConstructCall,
     InternalHandle self,
     params InternalHandle[] args)
 {
     return engine.CreateValue(_syntax);
 }
Exemplo n.º 15
0
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
            AppDomain.CurrentDomain.UnhandledException   += CurrentDomain_UnhandledException;

            try
            {
                Console.WriteLine("V8.Net Version: " + V8Engine.Version);

                Console.Write(Environment.NewLine + "Creating a V8Engine instance ...");
                _JSServer = new V8Engine();
                _JSServer.SetFlagsFromCommandLine(args);
                Console.WriteLine(" Done!");

                Console.Write("Testing marshalling compatibility...");
                _JSServer.RunMarshallingTests();
                Console.WriteLine(" Pass!");

                _TitleUpdateTimer           = new System.Timers.Timer(500);
                _TitleUpdateTimer.AutoReset = true;
                _TitleUpdateTimer.Elapsed  += (_o, _e) =>
                {
                    if (!_JSServer.IsDisposed)
                    {
                        Console.Title = "V8.Net Console - " + (IntPtr.Size == 4 ? "32-bit" : "64-bit") + " mode (Handles: " + _JSServer.TotalHandles
                                        + " / Pending Disposal: " + _JSServer.TotalHandlesPendingDisposal
                                        + " / Cached: " + _JSServer.TotalHandlesCached
                                        + " / In Use: " + (_JSServer.TotalHandlesInUse) + ")";
                    }
                    else
                    {
                        Console.Title = "V8.Net Console - Shutting down...";
                    }
                };
                _TitleUpdateTimer.Start();

                ((Action)(() =>
                {
                    _JSServer.DynamicGlobalObject.mo = _JSServer.CreateObjectTemplate().CreateObject(); // (need to keep a reference to the object so the GC doesn't claim it)
                }))();

                Console.WriteLine(Environment.NewLine + @"Ready - just enter script to execute. Type '\' or '\help' for a list of console specific commands.");

                string input, lcInput;

                while (true)
                {
                    var ok = ((Func <bool>)(() => // (this forces a scope to close so the GC can collect objects while in debug mode)
                    {
                        try
                        {
                            Console.Write(Environment.NewLine + "> ");

                            input = Console.ReadLine();
                            lcInput = input.Trim().ToLower();

                            if (lcInput == @"\help" || lcInput == @"\")
                            {
                                Console.WriteLine(@"Special console commands (all commands are triggered via a preceding '\' character so as not to confuse it with script code):");
                                Console.WriteLine(@"\init - Setup environment for testing (adds 'dump()' and 'assert()'.");
                                Console.WriteLine(@"\flags --flag1 --flag2 --etc... - Sets one or more flags (use '\flags --help' for more details).");
                                Console.WriteLine(@"\cls - Clears the screen.");
                                Console.WriteLine(@"\gc - Triggers garbage collection (for testing purposes).");
                                Console.WriteLine(@"\v8gc - Triggers garbage collection in V8 (for testing purposes).");
                                Console.WriteLine(@"\gctest - Runs a simple GC test against V8.NET and the native V8 engine.");
                                Console.WriteLine(@"\handles - Dumps the current list of known handles.");
                                Console.WriteLine(@"\speedtest - Runs a simple test script to test V8.NET performance with the V8 engine.");
                                Console.WriteLine(@"\exit - Exits the console.");
                            }
                            else if (lcInput == @"\init")
                            {
                                Console.WriteLine(Environment.NewLine + "Creating a global 'dump(obj)' function to dump properties of objects (one level only) ...");
                                _JSServer.ConsoleExecute(@"dump = function(o) { var s=''; if (typeof(o)=='undefined') return 'undefined';"
                                                         + @" if (typeof o.valueOf=='undefined') return ""'valueOf()' is missing on '""+(typeof o)+""' - if you are inheriting from V8ManagedObject, make sure you are not blocking the property."";"
                                                         + @" if (typeof o.toString=='undefined') return ""'toString()' is missing on '""+o.valueOf()+""' - if you are inheriting from V8ManagedObject, make sure you are not blocking the property."";"
                                                         + @" for (var p in o) {var ov='', pv=''; try{ov=o.valueOf();}catch(e){ov='{error: '+e.message+': '+dump(o)+'}';} try{pv=o[p];}catch(e){pv=e.message;} s+='* '+ov+'.'+p+' = ('+pv+')\r\n'; } return s; }");

                                Console.WriteLine(Environment.NewLine + "Creating a global 'assert(msg, a,b)' function for property value assertion ...");
                                _JSServer.ConsoleExecute(@"assert = function(msg,a,b) { msg += ' ('+a+'==='+b+'?)'; if (a === b) return msg+' ... Ok.'; else throw msg+' ... Failed!'; }");
                            }
                            else if (lcInput == @"\cls")
                            {
                                Console.Clear();
                            }
                            else if (lcInput == @"\flags" || lcInput.StartsWith(@"\flags "))
                            {
                                string flags = lcInput.Substring(6).Trim();
                                if (flags.Length > 0)
                                {
                                    _JSServer.SetFlagsFromString(flags);
                                }
                                else
                                {
                                    Console.WriteLine(@"You did not specify any options.");
                                }
                            }
                            else if (lcInput == @"\exit")
                            {
                                Console.WriteLine("User requested exit, disposing the engine instance ...");
                                _JSServer.Dispose();
                                Console.WriteLine("Engine disposed successfully. Press any key to continue ...");
                                Console.ReadKey();
                                Console.WriteLine("Goodbye. :)");
                                return(false);
                            }
                            else if (lcInput == @"\gc")
                            {
                                Console.Write(Environment.NewLine + "Forcing garbage collection ... ");
                                GC.AddMemoryPressure(100000000000);
                                GC.Collect(3, GCCollectionMode.Forced);
                                GC.WaitForPendingFinalizers();
                                GC.RemoveMemoryPressure(100000000000);
                                Console.WriteLine("Done.\r\n");
                                Console.WriteLine("Currently Used Memory: " + GC.GetTotalMemory(true));
                            }
                            else if (lcInput == @"\v8gc")
                            {
                                Console.Write(Environment.NewLine + "Forcing V8 garbage collection ... ");
                                _JSServer.ForceV8GarbageCollection();
                                Console.WriteLine("Done.\r\n");
                            }
                            else if (lcInput == @"\handles")
                            {
                                Console.Write(Environment.NewLine + "Active handles list ... " + Environment.NewLine);

                                foreach (var h in _JSServer.Handles_Active)
                                {
                                    Console.WriteLine(" * " + h.Description.Replace(Environment.NewLine, "\\r\\n"));
                                }

                                Console.Write(Environment.NewLine + "Managed side dispose-ready handles or non-tracked internal handles (usually due to a GC attempt) ... " + Environment.NewLine);

                                foreach (var h in _JSServer.Handles_ManagedSideDisposed)
                                {
                                    Console.WriteLine(" * " + h.Description.Replace(Environment.NewLine, "\\r\\n"));
                                }

                                Console.Write(Environment.NewLine + "Native side V8 handles now marked as disposing (in the queue) ... " + Environment.NewLine);

                                foreach (var h in _JSServer.Handles_Disposing)
                                {
                                    Console.WriteLine(" * " + h.Description.Replace(Environment.NewLine, "\\r\\n"));
                                }

                                Console.Write(Environment.NewLine + "Native side V8 handles that are now disposed (cached) for reuse ... " + Environment.NewLine);

                                foreach (var h in _JSServer.Handles_DisposedAndCached)
                                {
                                    Console.WriteLine(" * " + h.Description.Replace(Environment.NewLine, "\\r\\n"));
                                }

                                Console.WriteLine(Environment.NewLine + "Done." + Environment.NewLine);
                            }
                            else if (lcInput == @"\gctest")
                            {
                                Console.WriteLine("\r\nTesting garbage collection ... ");

                                int objectId = -1;

                                InternalHandle internalHandle = ((Func <V8Engine, InternalHandle>)((engine) =>
                                {
                                    V8NativeObject tempObj;

                                    Console.WriteLine("Setting 'tempObj' to a new managed object ...");

                                    engine.DynamicGlobalObject.tempObj = tempObj = engine.CreateObject <V8NativeObject>();
                                    InternalHandle ih = InternalHandle.GetUntrackedHandleFromObject(tempObj);

                                    objectId = tempObj.ID;

                                    Console.WriteLine("Generation of test instance before collect: " + GC.GetGeneration(tempObj));

                                    Console.WriteLine("Releasing the object on the managed side ...");
                                    tempObj = null;

                                    return(ih);
                                }))(_JSServer);

                                // (we wait for the object to be sent for disposal by the worker)

                                GC.Collect();
                                GC.WaitForPendingFinalizers();

                                var testobj = _JSServer.GetObjectByID(objectId);
                                if (testobj != null)
                                {
                                    Console.WriteLine("Generation of test instance after collect: " + GC.GetGeneration(testobj));
                                }
                                else
                                {
                                    Console.WriteLine("Generation of test instance after collect: Object null for ID: " + objectId);
                                }
                                testobj = null;

                                int i;

                                for (i = 0; i < 3000 && !internalHandle.IsDisposed; i++)
                                {
                                    System.Threading.Thread.Sleep(1); // (just wait for the worker)
                                }
                                if (!internalHandle.IsDisposed)
                                {
                                    throw new Exception("The temp object's handle is still not pending disposal ... something is wrong.");
                                }

                                Console.WriteLine("Success!");
                                //Console.WriteLine("Success! The test object's handle is going through the disposal process.");
                                ////Console.WriteLine("Clearing the handle object reference next ...");

                                //// object handles will finally be disposed when the native V8 GC calls back regarding them ...

                                //Console.WriteLine("Waiting on the worker to make the object weak on the native V8 side ... ");

                                //for (i = 0; i < 6000 && !internalHandle.IsNativeDisposed; i++)
                                //    System.Threading.Thread.Sleep(1);

                                //if (!internalHandle.IsNativeDisposed)
                                //    throw new Exception("Object is not weak yet ... something is wrong.");

                                //Console.WriteLine("The native side object is now weak and ready to be collected by V8.");

                                //Console.WriteLine("Forcing V8 garbage collection ... ");
                                //_JSServer.DynamicGlobalObject.tempObj = null;
                                //for (i = 0; i < 3000 && !internalHandle.IsDisposed; i++)
                                //{
                                //    _JSServer.ForceV8GarbageCollection();
                                //    System.Threading.Thread.Sleep(1);
                                //}

                                //Console.WriteLine("Looking for object ...");

                                //if (!internalHandle.IsDisposed) throw new Exception("Managed object's handle did not dispose.");
                                //// (note: this call is only valid as long as no more objects are created before this point)
                                //Console.WriteLine("Success! The managed V8NativeObject native handle is now disposed.");
                                //Console.WriteLine("\r\nDone.\r\n");
                            }
                            else if (lcInput == @"\speedtest")
                            {
                                var timer = new Stopwatch();
                                long startTime, elapsed;
                                long count;
                                double result1, result2, result3, result4;
#if DEBUG
                                Console.WriteLine(Environment.NewLine + "WARNING: You are running in debug mode, so the speed will be REALLY slow compared to release.");
#endif
                                Console.WriteLine(Environment.NewLine + "Running the speed tests ... ");

                                timer.Start();

                                //??Console.WriteLine(Environment.NewLine + "Running the property access speed tests ... ");
                                Console.WriteLine("(Note: 'V8NativeObject' objects are always faster than using the 'V8ManagedObject' objects because native objects store values within the V8 engine and managed objects store theirs on the .NET side.)");

#if DEBUG
                                count = 20000000;
#else
                                count = 200000000;
#endif

                                Console.WriteLine("\r\nTesting native property write speed ... ");
                                startTime = timer.ElapsedMilliseconds;
                                _JSServer.Execute("o={i:0}; for (o.i=0; o.i<" + count + "; o.i++) n = 0;", throwExceptionOnError: true); // (o={i:0}; is used in case the global object is managed, which will greatly slow down the loop)
                                elapsed = timer.ElapsedMilliseconds - startTime;
                                result1 = (double)elapsed / count;
                                Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result1.ToString("0.0#########") + " ms each pass.");

                                Console.WriteLine("\r\nTesting native property read speed ... ");
                                startTime = timer.ElapsedMilliseconds;
                                _JSServer.Execute("for (o.i=0; o.i<" + count + "; o.i++) n;", throwExceptionOnError: true);
                                elapsed = timer.ElapsedMilliseconds - startTime;
                                result2 = (double)elapsed / count;
                                Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result2.ToString("0.0#########") + " ms each pass.");

#if DEBUG
                                count = 10000;
#else
                                count = 2000000;
#endif

                                Console.WriteLine("\r\nTesting property write speed on a managed object (with interceptors) ... ");
                                var o = _JSServer.CreateObjectTemplate().CreateObject(); // (need to keep a reference to the object so the GC doesn't claim it)
                                _JSServer.DynamicGlobalObject.mo = o;
                                startTime = timer.ElapsedMilliseconds;
                                _JSServer.Execute("o={i:0}; for (o.i=0; o.i<" + count + "; o.i++) mo.n = 0;", throwExceptionOnError: true);
                                elapsed = timer.ElapsedMilliseconds - startTime;
                                result3 = (double)elapsed / count;
                                Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result3.ToString("0.0#########") + " ms each pass.");

                                Console.WriteLine("\r\nTesting property read speed on a managed object (with interceptors) ... ");
                                startTime = timer.ElapsedMilliseconds;
                                _JSServer.Execute("for (o.i=0; o.i<" + count + "; o.i++) mo.n;", throwExceptionOnError: true);
                                elapsed = timer.ElapsedMilliseconds - startTime;
                                result4 = (double)elapsed / count;
                                Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result4.ToString("0.0#########") + " ms each pass.");

                                Console.WriteLine("\r\nUpdating native properties is {0:N2}x faster than managed ones.", result3 / result1);
                                Console.WriteLine("\r\nReading native properties is {0:N2}x faster than managed ones.", result4 / result2);

                                Console.WriteLine("\r\nDone.\r\n");

                                GC.KeepAlive(o);
                            }
                            else if (lcInput.StartsWith(@"\"))
                            {
                                Console.WriteLine(@"Invalid console command. Type '\help' to see available commands.");
                            }
                            else
                            {
                                Console.WriteLine();

                                try
                                {
                                    var result = _JSServer.Execute(input, "V8.NET Console", false, 5000);

                                    Console.WriteLine(result.AsString);

                                    if (result.WasTerminated)
                                    {
                                        Console.WriteLine("The script took longer than 5 seconds to run and was aborted.");
                                    }

                                    result.Dispose();
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine();
                                    Console.WriteLine();
                                    Console.WriteLine(Exceptions.GetFullErrorMessage(ex));
                                    Console.WriteLine();
                                    Console.WriteLine("Error!  Press any key to continue ...");
                                    Console.ReadKey();
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine();
                            Console.WriteLine();
                            Console.WriteLine(Exceptions.GetFullErrorMessage(ex));
                            Console.WriteLine();
                            Console.WriteLine("Error!  Press any key to continue ...");
                            Console.ReadKey();
                        }

                        return(true);
                    }))();
                    if (!ok)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine(Exceptions.GetFullErrorMessage(ex));
                Console.WriteLine();
                Console.WriteLine("Error!  Press any key to exit ...");
                Console.ReadKey();
            }

            if (_TitleUpdateTimer != null)
            {
                _TitleUpdateTimer.Dispose();
            }
        }
Exemplo n.º 16
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="engine">The engine to use for compilation.</param>
 public EngineCompiler(V8Engine engine)
 {
     _engine = engine;
 }
 /// <summary>
 /// JavaScript callback. Returns current editor's file path.
 /// </summary>
 public InternalHandle GetFilePath(
     V8Engine engine,
     bool isConstructCall,
     InternalHandle self,
     params InternalHandle[] args)
 {
     // As of version 1.3 this callback is required only for actions with external images that we don't
     // support.
     return engine.CreateNullValue();
 }
Exemplo n.º 18
0
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
            AppDomain.CurrentDomain.UnhandledException   += CurrentDomain_UnhandledException;

            try
            {
                Console.Write(Environment.NewLine + "Creating a V8Engine instance ...");
                _JSServer = new V8Engine();
                Console.WriteLine(" Done!");

                Console.Write("Testing marshalling compatibility...");
                _JSServer.RunMarshallingTests();
                Console.WriteLine(" Pass!");

                _TitleUpdateTimer           = new System.Timers.Timer(500);
                _TitleUpdateTimer.AutoReset = true;
                _TitleUpdateTimer.Elapsed  += (_o, _e) =>
                {
                    if (!_JSServer.IsDisposed)
                    {
                        Console.Title = "V8.Net Console - " + (IntPtr.Size == 4 ? "32-bit" : "64-bit") + " mode (Handles: " + _JSServer.TotalHandles
                                        + " / Pending Native GC: " + _JSServer.TotalHandlesPendingDisposal
                                        + " / Cached: " + _JSServer.TotalHandlesCached
                                        + " / In Use: " + (_JSServer.TotalHandles - _JSServer.TotalHandlesCached) + ")";
                    }
                    else
                    {
                        Console.Title = "V8.Net Console - Shutting down...";
                    }
                };
                _TitleUpdateTimer.Start();

                {
                    Console.WriteLine(Environment.NewLine + "Creating some global CLR types ...");

                    // (Note: It's not required to explicitly register a type, but it is recommended for more control.)

                    _JSServer.RegisterType(typeof(Object), "Object", true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(Type), "Type", true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(String), "String", true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(Boolean), "Boolean", true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(Array), "Array", true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(System.Collections.ArrayList), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(char), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(int), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(Int16), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(Int32), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(Int64), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(UInt16), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(UInt32), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(UInt64), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(Enumerable), null, true, ScriptMemberSecurity.Locked);
                    _JSServer.RegisterType(typeof(System.IO.File), null, true, ScriptMemberSecurity.Locked);

                    ObjectHandle hSystem = _JSServer.CreateObject();
                    _JSServer.DynamicGlobalObject.System = hSystem;
                    hSystem.SetProperty(typeof(Object)); // (Note: No optional parameters used, so this will simply lookup and apply the existing registered type details above.)
                    hSystem.SetProperty(typeof(String));
                    hSystem.SetProperty(typeof(Boolean));
                    hSystem.SetProperty(typeof(Array));
                    _JSServer.GlobalObject.SetProperty(typeof(Type));
                    _JSServer.GlobalObject.SetProperty(typeof(System.Collections.ArrayList));
                    _JSServer.GlobalObject.SetProperty(typeof(char));
                    _JSServer.GlobalObject.SetProperty(typeof(int));
                    _JSServer.GlobalObject.SetProperty(typeof(Int16));
                    _JSServer.GlobalObject.SetProperty(typeof(Int32));
                    _JSServer.GlobalObject.SetProperty(typeof(Int64));
                    _JSServer.GlobalObject.SetProperty(typeof(UInt16));
                    _JSServer.GlobalObject.SetProperty(typeof(UInt32));
                    _JSServer.GlobalObject.SetProperty(typeof(UInt64));
                    _JSServer.GlobalObject.SetProperty(typeof(Enumerable));
                    _JSServer.GlobalObject.SetProperty(typeof(Environment));
                    _JSServer.GlobalObject.SetProperty(typeof(System.IO.File));

                    _JSServer.GlobalObject.SetProperty(typeof(Uri), V8PropertyAttributes.Locked, null, true, ScriptMemberSecurity.Locked); // (Note: Not yet registered, but will auto register!)
                    _JSServer.GlobalObject.SetProperty("uri", new Uri("http://www.example.com"));

                    _JSServer.GlobalObject.SetProperty(typeof(GenericTest <int, string>), V8PropertyAttributes.Locked, null, true, ScriptMemberSecurity.Locked);
                    _JSServer.GlobalObject.SetProperty(typeof(GenericTest <string, int>), V8PropertyAttributes.Locked, null, true, ScriptMemberSecurity.Locked);

                    Console.WriteLine(Environment.NewLine + "Creating a global 'dump(obj)' function to dump properties of objects (one level only) ...");
                    _JSServer.ConsoleExecute(@"dump = function(o) { var s=''; if (typeof(o)=='undefined') return 'undefined';"
                                             + @" if (typeof o.valueOf=='undefined') return ""'valueOf()' is missing on '""+(typeof o)+""' - if you are inheriting from V8ManagedObject, make sure you are not blocking the property."";"
                                             + @" if (typeof o.toString=='undefined') return ""'toString()' is missing on '""+o.valueOf()+""' - if you are inheriting from V8ManagedObject, make sure you are not blocking the property."";"
                                             + @" for (var p in o) {var ov='', pv=''; try{ov=o.valueOf();}catch(e){ov='{error: '+e.message+': '+dump(o)+'}';} try{pv=o[p];}catch(e){pv=e.message;} s+='* '+ov+'.'+p+' = ('+pv+')\r\n'; } return s; }");

                    Console.WriteLine(Environment.NewLine + "Creating a global 'assert(msg, a,b)' function for property value assertion ...");
                    _JSServer.ConsoleExecute(@"assert = function(msg,a,b) { msg += ' ('+a+'==='+b+'?)'; if (a === b) return msg+' ... Ok.'; else throw msg+' ... Failed!'; }");

                    Console.WriteLine(Environment.NewLine + "Creating a global 'Console' object ...");
                    _JSServer.GlobalObject.SetProperty(typeof(Console), V8PropertyAttributes.Locked, null, true, ScriptMemberSecurity.Locked);
                    //??_JSServer.CreateObject<JS_Console>();

                    Console.WriteLine(Environment.NewLine + "Creating a new global type 'TestEnum' ...");
                    _JSServer.GlobalObject.SetProperty(typeof(TestEnum), V8PropertyAttributes.Locked, null, true, ScriptMemberSecurity.Locked);

                    Console.WriteLine(Environment.NewLine + "Creating a new global type 'SealedObject' as 'Sealed_Object' ...");
                    Console.WriteLine("(represents a 3rd-party inaccessible V8.NET object.)");
                    _JSServer.GlobalObject.SetProperty(typeof(SealedObject), V8PropertyAttributes.Locked, null, true);

                    Console.WriteLine(Environment.NewLine + "Creating a new wrapped and locked object 'sealedObject' ...");
                    _JSServer.GlobalObject.SetProperty("sealedObject", new SealedObject(null, null), null, true, ScriptMemberSecurity.Locked);

                    Console.WriteLine(Environment.NewLine + "Dumping global properties ...");
                    _JSServer.VerboseConsoleExecute(@"dump(this)");

                    Console.WriteLine(Environment.NewLine + "Here is a contrived example of calling and passing CLR methods/types ...");
                    _JSServer.VerboseConsoleExecute(@"r = Enumerable.Range(1,Int32('10'));");
                    _JSServer.VerboseConsoleExecute(@"a = System.String.Join$1([Int32], ', ', r);");

                    Console.WriteLine(Environment.NewLine + "Example of changing 'System.String.Empty' member security attributes to 'NoAccess'...");
                    _JSServer.GetTypeBinder(typeof(String)).ChangeMemberSecurity("Empty", ScriptMemberSecurity.NoAcccess);
                    _JSServer.VerboseConsoleExecute(@"System.String.Empty;");
                    Console.WriteLine("(Note: Access denied is only for static types - bound instances are more dynamic, and will hide properties instead [name/index interceptors are not available on V8 Function objects])");

                    Console.WriteLine(Environment.NewLine + "Finally, how to view method signatures...");
                    _JSServer.VerboseConsoleExecute(@"dump(System.String.Join);");

                    var funcTemp = _JSServer.CreateFunctionTemplate <SamplePointFunctionTemplate>("SamplePointFunctionTemplate");
                }

                Console.WriteLine(Environment.NewLine + @"Ready - just enter script to execute. Type '\' or '\help' for a list of console specific commands.");

                string input, lcInput;

                while (true)
                {
                    try
                    {
                        Console.Write(Environment.NewLine + "> ");

                        input   = Console.ReadLine();
                        lcInput = input.Trim().ToLower();

                        if (lcInput == @"\help" || lcInput == @"\")
                        {
                            Console.WriteLine(@"Special console commands (all commands are triggered via a preceding '\' character so as not to confuse it with script code):");
                            Console.WriteLine(@"\cls - Clears the screen.");
                            Console.WriteLine(@"\test - Starts the test process.");
                            Console.WriteLine(@"\gc - Triggers garbage collection (for testing purposes).");
                            Console.WriteLine(@"\v8gc - Triggers garbage collection in V8 (for testing purposes).");
                            Console.WriteLine(@"\gctest - Runs a simple GC test against V8.NET and the native V8 engine.");
                            Console.WriteLine(@"\speedtest - Runs a simple test script to test V8.NET performance with the V8 engine.");
                            Console.WriteLine(@"\mtest - Runs a simple test script to test V8.NET integration/marshalling compatibility with the V8 engine on your system.");
                            Console.WriteLine(@"\newenginetest - Creates 3 new engines (each time) and runs simple expressions in each one (note: new engines are never removed once created).");
                            Console.WriteLine(@"\exit - Exists the console.");
                        }
                        else if (lcInput == @"\cls")
                        {
                            Console.Clear();
                        }
                        else if (lcInput == @"\test")
                        {
                            try
                            {
                                /* This command will serve as a means to run fast tests against various aspects of V8.NET from the JavaScript side.
                                 * This is preferred over unit tests because 1. it takes a bit of time for the engine to initialize, 2. internal feedback
                                 * can be sent to the console from the environment, and 3. serves as a nice implementation example.
                                 * The unit testing project will serve to test basic engine instantiation and solo utility classes.
                                 * In the future, the following testing process may be redesigned to be runnable in both unit tests and console apps.
                                 */

                                Console.WriteLine("\r\n===============================================================================");
                                Console.WriteLine("Setting up the test environment ...\r\n");

                                {
                                    // ... create a function template in order to generate our object! ...
                                    // (note: this is not using ObjectTemplate because the native V8 does not support class names for those objects [class names are object type names])

                                    Console.Write("\r\nCreating a FunctionTemplate instance ...");
                                    var funcTemplate = _JSServer.CreateFunctionTemplate(typeof(V8DotNetTesterWrapper).Name);
                                    Console.WriteLine(" Ok.");

                                    // ... use the template to generate our object ...

                                    Console.Write("\r\nRegistering the custom V8DotNetTester function object ...");
                                    var testerFunc = funcTemplate.GetFunctionObject <V8DotNetTesterFunction>();
                                    _JSServer.DynamicGlobalObject.V8DotNetTesterWrapper = testerFunc;
                                    Console.WriteLine(" Ok.  'V8DotNetTester' is now a type [Function] in the global scope.");

                                    Console.Write("\r\nCreating a V8DotNetTester instance from within JavaScript ...");
                                    // (note: Once 'V8DotNetTester' is constructed, the 'Initialize()' override will be called immediately before returning,
                                    // but you can return "engine.GetObject<V8DotNetTester>(_this.Handle, true, false)" to prevent it.)
                                    _JSServer.VerboseConsoleExecute("testWrapper = new V8DotNetTesterWrapper();");
                                    _JSServer.VerboseConsoleExecute("tester = testWrapper.tester;");
                                    Console.WriteLine(" Ok.");

                                    // ... Ok, the object exists, BUT, it is STILL not yet part of the global object, so we add it next ...

                                    Console.Write("\r\nRetrieving the 'tester' property on the global object for the V8DotNetTester instance ...");
                                    var handle = _JSServer.GlobalObject.GetProperty("tester");
                                    var tester = (V8DotNetTester)_JSServer.DynamicGlobalObject.tester;
                                    Console.WriteLine(" Ok.");

                                    Console.WriteLine("\r\n===============================================================================");
                                    Console.WriteLine("Dumping global properties ...\r\n");

                                    _JSServer.VerboseConsoleExecute("dump(this)");

                                    Console.WriteLine("\r\n===============================================================================");
                                    Console.WriteLine("Dumping tester properties ...\r\n");

                                    _JSServer.VerboseConsoleExecute("dump(tester)");

                                    // ... example of adding a functions via script (note: V8Engine.GlobalObject.Properties will have 'Test' set) ...

                                    Console.WriteLine("\r\n===============================================================================");
                                    Console.WriteLine("Ready to run the tester, press any key to proceed ...\r\n");
                                    Console.ReadKey();

                                    tester.Execute();

                                    Console.WriteLine("\r\nReleasing managed tester object ...\r\n");
                                    tester.Handle.ReleaseManagedObject();
                                }

                                Console.WriteLine("\r\n===============================================================================\r\n");
                                Console.WriteLine("Test completed successfully! Any errors would have interrupted execution.");
                                Console.WriteLine("Note: The 'dump(obj)' function is available to use for manual inspection.");
                                Console.WriteLine("Press any key to dump the global properties ...");
                                Console.ReadKey();
                                _JSServer.VerboseConsoleExecute("dump(this);");
                            }
                            catch
                            {
                                Console.WriteLine("\r\nTest failed.\r\n");
                                throw;
                            }
                        }
                        else if (lcInput == @"\gc")
                        {
                            Console.Write("\r\nForcing garbage collection ... ");
                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                            Console.WriteLine("Done.\r\n");
                        }
                        else if (lcInput == @"\v8gc")
                        {
                            Console.Write("\r\nForcing V8 garbage collection ... ");
                            _JSServer.ForceV8GarbageCollection();
                            Console.WriteLine("Done.\r\n");
                        }
                        else if (lcInput == @"\gctest")
                        {
                            Console.WriteLine("\r\nTesting garbage collection ... ");

                            V8NativeObject tempObj;
                            InternalHandle internalHandle = InternalHandle.Empty;
                            int            i;

                            {
                                Console.WriteLine("Setting 'this.tempObj' to a new managed object ...");

                                tempObj        = _JSServer.CreateObject <V8NativeObject>();
                                internalHandle = tempObj.Handle;
                                Handle testHandle = internalHandle;
                                _JSServer.DynamicGlobalObject.tempObj = tempObj;

                                // ... because we have a strong reference to the handle in 'testHandle', the managed and native objects are safe; however,
                                // this block has the only strong reference, so once the reference goes out of scope, the managed GC should attempt to
                                // collect it, which will mark the handle as ready for collection (but it will not be destroyed just yet until V8 is ready) ...

                                Console.WriteLine("Clearing managed references and running the garbage collector ...");
                                testHandle = null;
                            }

                            GC.Collect();
                            GC.WaitForPendingFinalizers();
                            // (we wait for the 'testHandle' handle object to be collected, which will dispose the handle)
                            // (note: we do not call 'Set()' on 'internalHandle' because the "Handle" type takes care of the disposal)

                            for (i = 0; i < 3000 && internalHandle.ReferenceCount > 1; i++)
                            {
                                System.Threading.Thread.Sleep(1); // (just wait for the worker)
                            }
                            if (internalHandle.ReferenceCount > 1)
                            {
                                throw new Exception("Handle is still not ready for GC ... something is wrong.");
                            }

                            Console.WriteLine("Success! The managed handle instance is pending disposal.");
                            Console.WriteLine("Clearing the handle object reference next ...");

                            // ... because we still have a reference to 'tempObj' at this point, the managed and native objects are safe; however, this
                            // block scope has the only strong reference to the managed object keeping everything alive (including the underlying handle),
                            // so once the reference goes out of scope, the managed GC will collect it, which will mark the managed object as ready for
                            // collection. Once both the managed object and handle are marked, this in turn marks the native handle as weak. When the native
                            // V8 engine's garbage collector is ready to dispose of the handle, as call back is triggered and the native object and
                            // handles will finally be removed ...

                            tempObj = null;

                            Console.WriteLine("Forcing CLR garbage collection ... ");
                            GC.Collect();
                            GC.WaitForPendingFinalizers();

                            Console.WriteLine("Waiting on the worker to make the object weak on the native V8 side ... ");

                            for (i = 0; i < 6000 && !internalHandle.IsNativelyWeak; i++)
                            {
                                System.Threading.Thread.Sleep(1);
                            }

                            if (!internalHandle.IsNativelyWeak)
                            {
                                throw new Exception("Object is not weak yet ... something is wrong.");
                            }

                            Console.WriteLine("The native side object is now weak and ready to be collected by V8.");

                            Console.WriteLine("Forcing V8 garbage collection ... ");
                            _JSServer.DynamicGlobalObject.tempObj = null;
                            for (i = 0; i < 3000 && !internalHandle.IsDisposed; i++)
                            {
                                _JSServer.ForceV8GarbageCollection();
                                System.Threading.Thread.Sleep(1);
                            }

                            Console.WriteLine("Looking for object ...");

                            if (!internalHandle.IsDisposed)
                            {
                                throw new Exception("Managed object was not garbage collected.");
                            }
                            // (note: this call is only valid as long as no more objects are created before this point)
                            Console.WriteLine("Success! The managed V8NativeObject instance is disposed.");
                            Console.WriteLine("\r\nDone.\r\n");
                        }
                        else if (lcInput == @"\speedtest")
                        {
                            var    timer = new Stopwatch();
                            long   startTime, elapsed;
                            long   count;
                            double result1, result2, result3, result4;

                            Console.WriteLine(Environment.NewLine + "Running the speed tests ... ");

                            timer.Start();

                            //??Console.WriteLine(Environment.NewLine + "Running the property access speed tests ... ");
                            Console.WriteLine("(Note: 'V8NativeObject' objects are always faster than using the 'V8ManagedObject' objects because native objects store values within the V8 engine and managed objects store theirs on the .NET side.)");

                            count = 200000000;

                            Console.WriteLine("\r\nTesting global property write speed ... ");
                            startTime = timer.ElapsedMilliseconds;
                            _JSServer.Execute("o={i:0}; for (o.i=0; o.i<" + count + "; o.i++) n = 0;"); // (o={i:0}; is used in case the global object is managed, which will greatly slow down the loop)
                            elapsed = timer.ElapsedMilliseconds - startTime;
                            result1 = (double)elapsed / count;
                            Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result1.ToString("0.0#########") + " ms each pass.");

                            Console.WriteLine("\r\nTesting global property read speed ... ");
                            startTime = timer.ElapsedMilliseconds;
                            _JSServer.Execute("for (o.i=0; o.i<" + count + "; o.i++) n;");
                            elapsed = timer.ElapsedMilliseconds - startTime;
                            result2 = (double)elapsed / count;
                            Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result2.ToString("0.0#########") + " ms each pass.");

                            count = 200000;

                            Console.WriteLine("\r\nTesting property write speed on a managed object (with interceptors) ... ");
                            _JSServer.DynamicGlobalObject.mo = _JSServer.CreateObjectTemplate().CreateObject();
                            startTime = timer.ElapsedMilliseconds;
                            _JSServer.Execute("o={i:0}; for (o.i=0; o.i<" + count + "; o.i++) mo.n = 0;");
                            elapsed = timer.ElapsedMilliseconds - startTime;
                            result3 = (double)elapsed / count;
                            Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result3.ToString("0.0#########") + " ms each pass.");

                            Console.WriteLine("\r\nTesting property read speed on a managed object (with interceptors) ... ");
                            startTime = timer.ElapsedMilliseconds;
                            _JSServer.Execute("for (o.i=0; o.i<" + count + "; o.i++) mo.n;");
                            elapsed = timer.ElapsedMilliseconds - startTime;
                            result4 = (double)elapsed / count;
                            Console.WriteLine(count + " loops @ " + elapsed + "ms total = " + result4.ToString("0.0#########") + " ms each pass.");

                            Console.WriteLine("\r\nUpdating native properties is {0:N2}x faster than managed ones.", result3 / result1);
                            Console.WriteLine("\r\nReading native properties is {0:N2}x faster than managed ones.", result4 / result2);

                            Console.WriteLine("\r\nDone.\r\n");
                        }
                        else if (lcInput == @"\exit")
                        {
                            Console.WriteLine("User requested exit, disposing the engine instance ...");
                            _JSServer.Dispose();
                            Console.WriteLine("Engine disposed successfully. Press any key to continue ...");
                            Console.ReadKey();
                            Console.WriteLine("Goodbye. :)");
                            break;
                        }
                        else if (lcInput == @"\mtest")
                        {
                            Console.WriteLine("Loading and marshalling native structs with test data ...");

                            _JSServer.RunMarshallingTests();

                            Console.WriteLine("Success! The marshalling between native and managed side is working as expected.");
                        }
                        else if (lcInput == @"\newenginetest")
                        {
                            Console.WriteLine("Creating 3 more engines ...");

                            var engine1 = new V8Engine();
                            var engine2 = new V8Engine();
                            var engine3 = new V8Engine();

                            Console.WriteLine("Running test expressions ...");

                            var resultHandle = engine1.Execute("1 + 2");
                            var result       = resultHandle.AsInt32;
                            Console.WriteLine("Engine 1: 1+2=" + result);
                            resultHandle.Dispose();

                            resultHandle = engine2.Execute("2+3");
                            result       = resultHandle.AsInt32;
                            Console.WriteLine("Engine 2: 2+3=" + result);
                            resultHandle.Dispose();

                            resultHandle = engine3.Execute("3 + 4");
                            result       = resultHandle.AsInt32;
                            Console.WriteLine("Engine 3: 3+4=" + result);
                            resultHandle.Dispose();

                            Console.WriteLine("Done.");
                        }
                        else if (lcInput == @"\memleaktest")
                        {
                            string script = @"
for (var i=0; i < 1000; i++) {
// if the loop is empty no memory leak occurs.
// if any of the following 3 method calls are uncommented then a bad memory leak occurs.
//SomeMethods.StaticDoNothing();
//shared.StaticDoNothing();
shared.InstanceDoNothing();
}
";
                            _JSServer.GlobalObject.SetProperty(typeof(SomeMethods), recursive: true, memberSecurity: ScriptMemberSecurity.ReadWrite);
                            var sm = new SomeMethods();
                            _JSServer.GlobalObject.SetProperty("shared", sm, recursive: true);
                            var hScript = _JSServer.Compile(script, null, true);
                            int i       = 0;
                            try
                            {
                                while (true)
                                {
                                    // putting a using statement on the returned handle stops the memory leak when running just the for loop.
                                    // using a compiled script seems to reduce garbage collection, but does not affect the memory leak
                                    using (var h = _JSServer.Execute(hScript, true))
                                    {
                                    } // end using handle returned by execute
                                    _JSServer.DoIdleNotification();
                                    Thread.Sleep(1);
                                    i++;
                                    if (i % 1000 == 0)
                                    {
                                        GC.Collect();
                                        GC.WaitForPendingFinalizers();
                                        _JSServer.ForceV8GarbageCollection();
                                        i = 0;
                                    }
                                } // end infinite loop
                            }
                            catch (OutOfMemoryException ex)
                            {
                                Console.WriteLine(ex);
                                Console.ReadKey();
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                                Console.ReadKey();
                            }
                            //?catch
                            //{
                            //    Console.WriteLine("We caught something");
                            //    Console.ReadKey();
                            //}
                        }
                        else if (lcInput.StartsWith(@"\"))
                        {
                            Console.WriteLine(@"Invalid console command. Type '\help' to see available commands.");
                        }
                        else
                        {
                            Console.WriteLine();

                            try
                            {
                                var result = _JSServer.Execute(input, "V8.NET Console");
                                Console.WriteLine(result.AsString);
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine();
                                Console.WriteLine();
                                Console.WriteLine(Exceptions.GetFullErrorMessage(ex));
                                Console.WriteLine();
                                Console.WriteLine("Error!  Press any key to continue ...");
                                Console.ReadKey();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine();
                        Console.WriteLine();
                        Console.WriteLine(Exceptions.GetFullErrorMessage(ex));
                        Console.WriteLine();
                        Console.WriteLine("Error!  Press any key to continue ...");
                        Console.ReadKey();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine(Exceptions.GetFullErrorMessage(ex));
                Console.WriteLine();
                Console.WriteLine("Error!  Press any key to exit ...");
                Console.ReadKey();
            }

            if (_TitleUpdateTimer != null)
            {
                _TitleUpdateTimer.Dispose();
            }
        }
Exemplo n.º 19
0
        /// <summary>
        /// JavaScript callback. Creates absolute path by concatenating two arguments.
        /// </summary>
        public InternalHandle CreatePath(
            V8Engine engine,
            bool isConstructorCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            if (args.Length != 2)
            {
                this.TraceError("IEmmetFile createPath called with invalid number of arguments.");
                return engine.CreateValue(false);
            }

            string parent = args[0].AsString;
            string fileName = args[1].AsString;

            if (Path.HasExtension(parent))
                parent = Path.GetDirectoryName(parent);

            return engine.CreateValue(Path.Combine(parent, fileName));
        }
        /// <summary>
        /// JavaScript callback. Returns current selection.
        /// </summary>
        public InternalHandle GetSelection(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            string selection = _editor.GetSelection();
            if (string.IsNullOrEmpty(selection))
                return engine.CreateValue(string.Empty);

            return engine.CreateValue(selection);
        }
Exemplo n.º 21
0
        private void InitEntityContext(Entity entity)
        {
            // Remove previous context if any.
            entityContexts.Remove(entity.Guid);

            logger.Debug("Entered initEntityContext with entity [{0}]", entity.Guid);

            string serverScript = (string)entity["scripting"]["serverScript"].Value;
            if (serverScript == null)
                return;

            logger.Debug("Creating the context. Server script is {0}", serverScript);

            V8Engine engine;
            try
            {
                engine = new V8Engine();
            }
            catch (Exception e)
            {
                logger.ErrorException("Exception during context creation", e);
                return;
            }

            logger.Debug("Adding context to the list");

            entityContexts.Add(entity.Guid, engine);

            logger.Debug("Creating context wrapper");

            // This object should be used to assign event handlers, e.g. script.onNewObject = function (newObject) {...}
            var context = new V8NetContext(engine);

            logger.Debug("Creating script object");

            context.Execute("script = {}");

            logger.Debug("About to enter context scope");

            engine.WithContextScope = () =>
            {
                logger.Debug("Configuring the context");

                // Register global objects.
                // FIXME: Potential security issue. Users can access .Type in script which allows to create any object and
                // thus run arbitrary code on the server.
                foreach (var entry in registeredGlobalObjects)
                    engine.GlobalObject.SetProperty(entry.Key, entry.Value, null, true, V8PropertyAttributes.Locked);

                logger.Debug("Calling context callbacks");

                // Invoke new context handlers.
                newContextHandlers.ForEach(handler => handler(context));

                logger.Debug("Executing serverScript");

                // Execute server script.
                engine.Execute(serverScript);
            };
        }
Exemplo n.º 22
0
 public JSProperty(V8Engine engine, object value, V8PropertyAttributes attributes = V8PropertyAttributes.None)
     : this(InternalHandle.Empty, attributes)
 {
     _Value.Set(engine != null ? engine.CreateValue(value) : InternalHandle.Empty);
 }
Exemplo n.º 23
0
        /// <summary>
        /// JavaScript callback. Saves the specified content to the file with the specified name.
        /// </summary>
        public InternalHandle Save(
            V8Engine engine,
            bool isConstructorCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            if (args.Length != 2)
            {
                this.TraceError("IEmmetFile save called with invalid number of arguments.");
                return engine.CreateValue(false);
            }

            string filePath = args[0].AsString;
            string content = args[1].AsString;

            File.WriteAllText(filePath, content);

            return engine.CreateValue(true);
        }
Exemplo n.º 24
0
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged
        /// resources.
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);

            if (null != _engine)
            {
                _engine.Dispose();
                _engine = null;
            }
        }
        /// <summary>
        /// JavaScript callback. Returns the content of the current line.
        /// </summary>
        public InternalHandle GetCurrentLine(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            string txt = _editor.GetCurrentLine();

            return engine.CreateValue(txt);
        }
        /// <summary>
        /// JavaScript callback. Set new caret position.
        /// </summary>
        public InternalHandle SetCarretPos(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            _editor.SetCaretPosition(args[0].AsInt32);

            return engine.CreateValue(true);
        }
Exemplo n.º 27
0
        /// <summary>
        /// JavaScript callback. Returns file extension in lower case.
        /// </summary>
        public InternalHandle GetExtension(
            V8Engine engine,
            bool isConstructorCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            if (args.Length != 1)
            {
                this.TraceError("IEmmetFile getExt called with invalid number of arguments.");
                return engine.CreateValue(false);
            }

            string filePath = args[0].AsString;

            return engine.CreateValue(Path.GetExtension(filePath).ToLowerInvariant());
        }
Exemplo n.º 28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ScriptingPluginInitializer.V8NetContext"/> class.
 /// </summary>
 /// <param name="aEngine">Associated V8Engine.</param>
 public V8NetContext(V8Engine aEngine)
 {
     engine = aEngine;
 }
 /// <summary>
 /// JavaScript callback. Returns current output profile name (see profile module). In most cases,
 /// this method should return <code>null</code> and let Emmet guess best profile name for current
 /// syntax and user data. In case you’re using advanced editor with access to syntax scopes (like
 /// Sublime Text 2), you can return syntax name for current scope. For example, you may return
 /// `line` profile when editor caret is inside string of programming language.
 /// </summary>
 public InternalHandle GetProfileName(
     V8Engine engine,
     bool isConstructCall,
     InternalHandle self,
     params InternalHandle[] args)
 {
     // Let Emmet engine detect profile
     return engine.CreateNullValue();
 }
        /// <summary>
        /// JavaScript callback. Replace editor's content or it's part (from <code>start</code> to
        /// <code>end</code> index). If <code>value</code> contains <code>caret_placeholder</code>, the editor
        /// will put caret into this position. If you skip <code>start</code> and <code>end</code> arguments,
        /// the whole target's content will be replaced with <code>value</code>.
        /// If you pass <code>start</code> argument only, the <code>value</code> will be placed at
        /// <code>start</code> string index of current content.
        /// If you pass <code>start</code> and <code>end</code> arguments, the corresponding substring of
        /// current target's content will be replaced with <code>value</code>.
        /// </summary>
        public InternalHandle ReplaceContent(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            string rawContent = args[0].AsString;
            int regionStart = args.Length > 1 ? args[1].AsInt32 : -1;
            int regionLength = args.Length > 2 ? args[2].AsInt32 - regionStart : 0;
            bool indentContent = args.Length == 4 ? args[3].AsBoolean : true;

            this.Trace($"Received new content for the editor: {rawContent}");

            // Extract tab stops placeholders from the specified content.
            var tabStops = TabStopsParser.ParseContent(engine, rawContent);

            _editor.ReplaceContentRange(tabStops.Content, regionStart, regionStart + regionLength);

            if (null != tabStops.TabStops)
            {
                Range[] tabStopRanges = tabStops.TabStops;

                // Tab stop offsets are relative to the newly generated content ranges, we need to convert
                // them to the document-wide offsets.
                if (regionStart > 0)
                {
                    tabStopRanges = tabStopRanges.Select(
                        item => new Range(item.Start + regionStart, item.End + regionStart)).ToArray();
                }

                _editor.TrackTabStops(tabStopRanges, tabStops.TabStopGroups);
            }

            if (indentContent)
                _editor.FormatRegion(regionStart, regionStart + tabStops.Content.Length);

            return engine.CreateValue(true);
        }
        /// <summary>
        /// JavaScript callback. Asks user to enter something.
        /// </summary>
        public InternalHandle Prompt(
            V8Engine engine,
            bool isConstructCall,
            InternalHandle self,
            params InternalHandle[] args)
        {
            string input = _editor.Prompt();
            if (string.IsNullOrWhiteSpace(input))
                return engine.CreateNullValue();

            return engine.CreateValue(input);
        }
 /// <summary>
 /// JavaScript callbacks. Returns the content of the current editor window.
 /// </summary>
 public InternalHandle GetContent(
     V8Engine engine,
     bool isConstructCall,
     InternalHandle self,
     params InternalHandle[] args)
 {
     return engine.CreateValue(_editor.GetContent());
 }
Exemplo n.º 33
0
        // --------------------------------------------------------------------------------------------------------------------

        internal Handle(V8Engine engine)
        {
            _Engine = engine;
            _ID     = -1;
        }