Example #1
0
        /// <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));
        }
        /// <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);
        }
        /// <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));
        }
Example #4
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()));
        }
Example #5
0
        public bool Invoke(string method, params object[] args)
        {
            try
            {
                InternalHandle h = engine.GlobalObject.GetProperty(method);
                if (h.IsError)
                {
                    Logger.LogError("[V8] Failed to invoke " + method);
                    return(false);
                }
                if (h.IsFunction)
                {
                    InternalHandle[] handles = new InternalHandle[args.Length];
                    for (int i = 0; i < args.Length; ++i)
                    {
                        handles.SetValue(engine.CreateValue(args[i]), i);
                    }

                    h.Call(handles);
                    return(true);
                }
            }
            catch (Exception ex)
            {
                Logger.LogError("[V8] Plugin error: " + pluginInfo.Name + " (" + pluginInfo.Author + ")\nJavascript error:\n " + ex.Message + "\n----\nStack trace:\n" + ex.StackTrace);
                Logger.LogError("[V8] Invoking method: " + method + "\nParams (" + args.Length + "):");
                for (int i = 0; i < args.Length; ++i)
                {
                    Logger.LogError(i + "=>" + args[i].GetType());
                }
                return(false);
            }
            return(false);
        }
 /// <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));
 }
 /// <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()));
 }
Example #8
0
        public void UpdateKeyboardState(KeyboardDevice currentKeyboard)
        {
            if (v8.IsDisposed)
            {
                return;
            }

            // Copy keyboard state
            //TODO: copy state quicker. Should be able to transfer over in O(1)
            InternalHandle[] keyboard = new InternalHandle[(int)Key.LastKey];
            for (int i = 0; i < keyboard.Length; i++)
            {
                int k = currentKeyboard[(Key)i] ? 1 : 0;
                keyboard[i] = v8.CreateValue(k);
            }

            v8.GlobalObject.SetProperty("Keyboard", v8.CreateArray(keyboard));
        }
Example #9
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));
        }
        /// <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));
        }
        /// <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));
        }
Example #12
0
        /// <summary>
        /// Loads JavaScript extensions and preferences from the specified directory.
        /// </summary>
        /// <param name="extensionsDirectory">Pathname of the extensions directory.</param>
        public void LoadExtensions(string extensionsDirectory)
        {
            List <InternalHandle> extensions = new List <InternalHandle>();
            var          files = Directory.EnumerateFiles(extensionsDirectory, "*.*");
            ObjectHandle emmet = _engine.DynamicGlobalObject.window.emmet;

            foreach (string filePath in files)
            {
                if (0 != string.Compare(Path.GetFileName(filePath), PreferencesFileName, true))
                {
                    extensions.Add(_engine.CreateValue(filePath));
                    continue;
                }

                string content   = File.ReadAllText(filePath);
                Handle parameter = _engine.CreateValue(content);
                Handle result    = emmet.Call("loadUserData", emmet, parameter);

                if (result.IsError)
                {
                    this.TraceError($"Failed to load Emmet preferences from {filePath}: {result.AsString}");
                }
                else
                {
                    this.Trace($"Successfully loaded Emmet preferences from {filePath}");
                }
            }

            if (extensions.Count > 0)
            {
                var    parameter = _engine.CreateArray(extensions.ToArray());
                Handle result    = emmet.Call("loadExtensions", emmet, parameter);

                if (result.IsError)
                {
                    this.TraceError($"Failed to load Emmet extensions: {result.AsString}");
                }
                else
                {
                    this.Trace($"Successfully loaded {extensions.Count} Emmet extensions");
                }
            }
        }
Example #13
0
 public InternalHandle TestJSFunction1(V8Engine engine, bool isConstructCall, InternalHandle _this, params InternalHandle[] args)
 {
     // ... there can be two different returns based on the call mode! ...
     // (tip: if a new object is created and returned instead (such as V8ManagedObject or an object derived from it), then that object will be the new object (instead of "_this"))
     if (isConstructCall)
     {
         var obj = engine.GetObject(_this);
         obj.AsDynamic.x  = args[0];
         ((dynamic)obj).y = 0; // (native objects in this case will always be V8NativeObject dynamic objects)
         obj.SetProperty(0, engine.CreateValue(100));
         obj.SetProperty("1", engine.CreateValue(100.2));
         obj.SetProperty("2", engine.CreateValue("300"));
         obj.SetProperty(4, engine.CreateValue(new DateTime(2013, 1, 2, 3, 4, 5, DateTimeKind.Utc)));
         return(_this);
     }
     else
     {
         return(args.Length > 0 ? args[0] : InternalHandle.Empty);
     }
 }
        public InternalHandle setInterval(V8Engine engine,
                                          bool isConstructCall,
                                          InternalHandle _this,
                                          params InternalHandle[] args)
        {
            if (isConstructCall)
            {
                return(_this);
            }
            else
            {
                if (args != null && args.Length == 2)
                {
                    InternalHandle timerCallback = args[0];
                    InternalHandle milliseconds  = args[1];

                    if (milliseconds != null && milliseconds.IsInt32 && timerCallback != null && timerCallback.IsFunction)
                    {
                        int    ms             = milliseconds.AsInt32;
                        string sourceFragment = timerCallback.Value.ToString();

                        System.Timers.Timer tmr = new System.Timers.Timer();
                        tmr.Interval = milliseconds.AsInt32;

                        tmr.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) =>
                        {
                            if (!engine.IsDisposed)
                            {
                                try
                                {
                                    engine.Execute("____$=" + sourceFragment + ";____$();", ScriptingEngine.SOURCE_NAME, false);
                                }
                                catch { }
                            }
                            else
                            {
                                tmr.Stop();
                            }
                        };

                        tmr.Start();

                        timers.Add(tmr);

                        Handle timerHandle = engine.CreateValue(timers.Count - 1);

                        return(timerHandle);
                    }
                }
            }

            return(InternalHandle.Empty);
        }
Example #15
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. 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 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));
        }
Example #18
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);
        }
        /// <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));
        }
Example #20
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));
        }
Example #21
0
        static void Main(string[] args)
        {
            V8Engine v8Engine = new V8Engine();

            var result = v8Engine.Execute(
                @"var gs = (function () {  // NOTE: 'result' WILL ALWAYS BE 'undefined' BECAUSE OF 'var' before 'gs'.
                    var myClassObject = function() {};
                    myClassObject.prototype.getCompanyInfo = function (a, b, c) {
                        var staff = [
                            {
                                'name': 'John',
                                'address': '1 Walk Way',
                                'dob': 'July '+a+', 1970'
                            },
                            {
                                'name': 'Peter',
                                'address': '241 Otoforwan Rd',
                                'dob': 'January '+b+', 1953'
                            },
                            {
                                'name': 'Marry',
                                'address': '1 Contrary Lane',
                                'dob': 'August '+c+', 1984'
                            }
                        ];
                        var result = {
                            'isEnabled': true,
                            'staff': staff
                        };
                        return result;
                    };
                    return new myClassObject();
                })();"
                );

            //create parameter
            Handle day1 = v8Engine.CreateValue("1");
            Handle day2 = v8Engine.CreateValue("2");
            Handle day3 = v8Engine.CreateValue("3");

            var     gs           = v8Engine.GlobalObject.GetProperty("gs");
            var     resultHandle = gs.Call("getCompanyInfo", null, day1, day2, day3); // NOTE: The object context is already known, so pass 'null' for '_this'.
            Company completion   = v8Engine.GetObject <Company>(resultHandle);

            //examine result
            var    test0              = resultHandle.GetProperty("isEnable");
            Handle test1              = resultHandle.GetProperty("staff"); // NOTE: "ObjectHandle" is a special handle for objects (which also obviously includes arrays, etc.).
            var    arrayLength        = test1._.ArrayLength;
            Handle arrayItem1         = test1._.GetProperty(0);
            var    arrayItem1_name    = arrayItem1._.GetProperty("name");
            var    arrayItem1_address = arrayItem1._.GetProperty("address");
            var    arrayItem1_dob     = (~arrayItem1).GetProperty("dob");
            Handle arrayItem2         = test1._.GetProperty(1); // (arrays are treated same as objects here)
            Handle arrayItem3         = test1._.GetProperty(2); // (arrays are treated same as objects here)

            //  ==================================================================== OR  ====================================================================

            v8Engine.RegisterType <Company2>(null, true, ScriptMemberSecurity.Locked); // (this line is NOT required, but allows more control over the settings)
            v8Engine.GlobalObject.SetProperty(typeof(Company2));                       // <= THIS IS IMPORTANT! It sets the type on the global object (though you can put this anywhere like any property)

            var gs2 = v8Engine.Execute(
                @"(function () {
                    var myClassObject = function() {};
                    myClassObject.prototype.getCompanyInfo = function (a, b, c) {
                        return new Company2(a, b, c);
                    };
                    return new myClassObject();
                })();"
                );

            var resultHandle2             = gs2.Call("getCompanyInfo", null, day1, day2, day3); // NOTE: The object context is already known, so pass 'null' for '_this'.
            var objectBindingModeIfNeeded = resultHandle2.BindingMode;
            var ci2 = (Company2)resultHandle2.BoundObject;                                      // (when a CLR class is bound, it is tracked by the handle in a special way)

            //  =============================================================================================================================================
            // Take your pick. ;)

            System.Console.WriteLine("Script executions completed. Press any key to exit.");
            System.Console.ReadKey(true);
        }
 /// <summary>
 /// Name of the X3D Browser
 /// </summary>
 public InternalHandle GetName(V8Engine engine, bool isConstructCall, InternalHandle _this, params InternalHandle[] args)
 {
     return(engine.CreateValue(AppInfo));
 }