Are you the publisher? Claim or contact us about this channel


Embed this content in your HTML

Search

Report adult content:

click to rate:

Account: (login)

More Channels


Showcase


Channel Catalog


Channel Description:

ClearScript is a library that makes it easy to add scripting to your .NET applications. It currently supports JavaScript (via V8 and JScript) and VBScript.

older | 1 | .... | 88 | 89 | (Page 90) | 91 | 92 | .... | 115 | newer

    0 0

    I obtain the window object in DWebBrowserEvents2_Event.NavigateComplete2 event. Following is some stripped down code snippets:
    public void OnNavigateComplete(object pDisp, ref object URL)
    {
        var browser = pDisp as IWebBrowser2;
        var document2 = browser?.Document as IHTMLDocument2;
        var window = document2?.parentWindow as IHTMLWindow2;
    
        var engine = new JScriptEngine("{16d51579-a30b-4c8b-a276-0ff4dc41e755}", null, WindowsScriptEngineFlags.EnableStandardsMode | WindowsScriptEngineFlags.MarshalNullAsDispatch | WindowsScriptEngineFlags.MarshalArraysByValue);
        engine.AddHostObject("window", HostItemFlags.GlobalMembers, window);
    }
    And the JavaScript snippet:

    global is the window object.

    contentPort is a private host object.
    contentPort.addMessageListener(function (msg) {
    
        if (global.document.readyState !== "complete") {
            global.addEventListener('load', function () {
                console.log('message document load');
            }, false);
            console.log("Message received - waiting for document load");
        } else {
            setTimeout(function () {
                console.log('message timeout');
            });
            console.log("Message received");
        }
    }
    The console output displays either "Message received" or "Message received - waiting for document load" but never "message document load" or "message timeout"

    The private host object callback works but the window callbacks do not.

    0 0

    Thanks. Some more questions as we try to replicate your environment:
    1. Where are the browser events coming from? It looks like you're using a native browser control, or perhaps you're working on a plug-in?
    2. Out of curiosity, why does the JavaScript code use global rather than window or simply the root object?

    0 0

    1. The code is part of a BHO. I subscribe to the events in IObjectWithSite.SetSite
    2. For historical reasons. The script is wrapped into a self-executing function which passes window object as the global parameter. You may have noticed that setTimeout is not using global.

    0 0

    Hi frolovm,

    We don't have a BHO test harness, so we're testing with a simple WPF app that uses the WebBrowser XAML control, which exposes the same underlying COM objects.

    We can confirm that passing an external script function to setTimeout appears to succeed but the function is never invoked. However, we can't confirm that it works with ClearScript 5.4.3 either. In fact, with stock 5.4.3 the setTimeout call throws an exception, and with your changes here it appears to behave exactly like 5.4.4.

    You say that you had it working with 5.4.3. Had you by any chance applied any additional changes?

    Interestingly, this works on both 5.4.4 and your modified 5.4.3:
    window.onTimer = function() { /* ... */ };
    setTimeout('onTimer()');
    Thanks!

    0 0

    Hi again,

    Further investigation reveals that the MSHTML+JScript implementation of setTimeout requires that the supplied callback be a function within the DOM's private script collection, so it isn't clear how it ever could have worked with an external function exposed by ClearScript.

    This requirement might be a cross-site security measure. Fortunately, as you can see above, it is relatively easy to work around :)

    Good luck!

    0 0

    Hi Guys, Wondering if ClearScript would work in it's full glory on .Net 4.0..? The reason I am asking is an requirement to get an App that uses ClearScript to work on Windows XP.

    Currently, JINT works fine on .Net 4.0, but I am looking to replace it because of some performance issues with string manipulation.

    Any pointers from this community would be greatly helpful!! Thanks in advance

    0 0

    Hi i2infinity,

    .NET 4.0 is ClearScript's target platform. As for Windows XP, we've done a small bit of testing with the current version (5.4.4), and it appears to work, but no guarantees :)

    Some notes:
    1. You'll need a newer OS to build ClearScript. Visual Studio 2013 (the minimum) doesn't support Windows XP.
    2. We've only tested ClearScript builds generated with Visual Studio 2013.
    3. Don't forget to install the appropriate Visual C++ redistributable package.
    Good luck!

    0 0

    A numeric argument, if it can be converted to an integer without data loss, should match `System.[S]Byte` and `System.[U]Int16` parameters implicitly if the narrowing conversion doesn't result in overflow.
    Comments: Closing resolved issues.

    0 0

    It appears that the for/in loop is not working when JScript engine is initialized with WindowsScriptEngineFlags.EnableStandardsMode flag.

    I tried adding PropertyBag and ExpandoObject as host objects.

    I noticed that there is a ScriptEngineException when executing for/in loop on either of the two objects which has HResult of 0x800a0005 (Invalid procedure call or argument).

    Without WindowsScriptEngineFlags.EnableStandardsMode flag everything works without exceptions.

    I am developing on Windows 10 with ClearScript 5.4.3

    Here is the sample program:

    ```
    static void Main(string[] args)
    {
    var engine = new JScriptEngine(WindowsScriptEngineFlags.EnableStandardsMode);
    engine.AddHostType("Console", typeof(Console));

    dynamic expandoObj = new ExpandoObject();
    expandoObj.testProp = "expando testProp Text";
    engine.AddHostObject("expandoObj", expandoObj);

    var propertyBag = new PropertyBag();
    propertyBag["testProp"] = "property bag testProp Text";
    engine.AddHostObject("propertyBagObj", propertyBag);

    engine.Execute(@"Console.WriteLine('expandoObj.testProp=' + expandoObj.testProp);");
    engine.Execute(@"Console.WriteLine('propertyBagObj.testProp=' + propertyBagObj.testProp);");
    engine.Execute(@"Console.WriteLine('');");
    engine.Execute(@"for (var item in propertyBagObj) Console.WriteLine('propertyBagObj[' + item + ']=' + propertyBagObj[item]);");
    engine.Execute(@"Console.WriteLine('');");
    engine.Execute(@"for (var item in expandoObj) Console.WriteLine('expandoObj[' + item + ']=' + expandoObj[item]);");

    }

    ```

    Comments: Closing resolved issues.

    0 0

    Exposed COM objects that implement `IDispatchEx` should provide full dynamic access (a-la `IPropertyBag`).
    Comments: Closing resolved issues.

    0 0

    I have a need to pass large amounts of data back and forth between JavaScript and C#. Ideally I would like to create a Float32Array in JavaScript and then access it as a native array or byte array in C#. The JavaScript code would calculate values while the C# code would consume them. I can currently brute force this by accessing elements one at a time, but it is way too slow for arrays of 100k or 1M elements.

    V8 has a facility for this via ArrayBuffer::Externalize(). Are there any plans to support this capability in ClearScript? What would be awesome is if I could do something like the following:

    V8ScriptEngine engine = new V8ScriptEngine();
    engine.Execute("var a = new Float32Array(100000);");

    ... do something in JavaScript to set array values

    // access the array and compute the sum of the values
    dynamic a = engine.Script.a;

    // this is how I have to get values today and it is too slow for large arrays
    double total = 0;
    for (int i = 0; i < 100000; i++)
    {
    total += a[i]; // each call dives into V8 to get an indexed value - slow
    }

    // this is what I want to do
    float[] array = (float[]) engine.Script.a.externalize(); // one call to V8
    for (int i = 0; i < 100000; i++)
    {
    total += array[i]; // fast!
    }

    This is also basically what browsers do to process data in WebGL. The JavaScript code calls bufferData() with a Typed Array. See https://msdn.microsoft.com/en-us/library/dn302373(v=vs.85).aspx

    Comments: Closing resolved issues.

    0 0

    Hi!
    We're using ClearScript V8 to render React on the server. Works great, but it slows down a bit when there's a lot of data that needs to be passed to V8. Our current approach is to serialize the object to a JSON string and do: Engine.Evaluate("someFunc(" + json + ")")

    Is there a better way to transfer a large object? I looked at adding it as a host object, but from what I can tell it doesn't become real JavaScript objects. That is, a List won't become an array on the JavaScript side, etc.

    0 0

    I changed the code to expose a Dictionary<string, object> on Engine.Script instead, and iterate over that and convert it to a real JS object. But that turned out to be more than twice as slow as Engine.Evaluate("someFunc(" + json + ")"). I'm guessing it's because I'm crossing the boundary between CLR and V8 a lot by doing that.

    Is there any way to create a real JS object from C# and expose that to the script engine?

    0 0

    Hello!

    You're already doing the right thing by using JSON to minimize hops across the .NET-V8 boundary.

    Your next optimization might be to minimize your use of V8's JavaScript parser. To that end, consider wrapping someFunc in a helper that takes a JSON string and converts it via the JSON object:
    dynamic someFuncHelper = Engine.Evaluate(@"
        (function (json) {
            return someFunc(JSON.parse(json));
        }).valueOf()
    ");
    Then, simply do this:
    // Engine.Evaluate("someFunc(" + json + ")");
    someFuncHelper(json);
    This way you're using an efficient, dedicated JSON parser to convert your object instead of V8's general-purpose JavaScript parser, which is much more complex. Don't forget to cache and reuse someFuncHelper to avoid re-parsing and recompiling the wrapper.

    Good luck!

    0 0

    Thanks for the tip, I'll try it and report back!

    0 0
  • 12/21/15--08:57: Updated Wiki: Home
  • Description

    ClearScript is a library that makes it easy to add scripting to your .NET applications. It currently supports JavaScript (via V8 and JScript) and VBScript.

    Features

    • Simple usage; create a script engine, add your objects and/or types, run scripts
    • Support for several script engines: Google's V8, Microsoft's JScript and VBScript
    • Exposed resources require no modification, decoration, or special coding of any kind
    • Scripts get simple access to most of the features of exposed objects and types:
      • Methods, properties, fields, events
      • (Objects) Indexers, extension methods, conversion operators, explicitly implemented interfaces
      • (Types) Constructors, nested types
    • Full support for generic types and methods, including C#-like type inference and explicit type arguments
    • Scripts can invoke methods with output parameters, optional parameters, and parameter arrays
    • Script delegates enable callbacks into script code
    • Support for exposing all the types defined in one or more assemblies in one step
    • Optional support for importing types and assemblies from script code
    • The host can invoke script functions and access script objects directly
    • Full support for script debugging

    Examples

    using System;
    using Microsoft.ClearScript;
    using Microsoft.ClearScript.JavaScript;
    using Microsoft.ClearScript.V8;
    
    // create a script engineusing (var engine = new V8ScriptEngine())
    {
        // expose a host type
        engine.AddHostType("Console", typeof(Console));
        engine.Execute("Console.WriteLine('{0} is an interesting number.', Math.PI)");
    
        // expose a host object
        engine.AddHostObject("random", new Random());
        engine.Execute("Console.WriteLine(random.NextDouble())");
    
        // expose entire assemblies
        engine.AddHostObject("lib", new HostTypeCollection("mscorlib", "System.Core"));
        engine.Execute("Console.WriteLine(lib.System.DateTime.Now)");
    
        // create a host object from script
        engine.Execute(@"
            birthday = new lib.System.DateTime(2007, 5, 22);
            Console.WriteLine(birthday.ToLongDateString());
        ");
    
        // use a generic class from script
        engine.Execute(@"
            Dictionary = lib.System.Collections.Generic.Dictionary;
            dict = new Dictionary(lib.System.String, lib.System.Int32);
            dict.Add('foo', 123);
        ");
    
        // call a host method with an output parameter
        engine.AddHostObject("host", new HostFunctions());
        engine.Execute(@"
            intVar = host.newVar(lib.System.Int32);
            found = dict.TryGetValue('foo', intVar.out);
            Console.WriteLine('{0} {1}', found, intVar);
        ");
    
        // create and populate a host array
        engine.Execute(@"
            numbers = host.newArr(lib.System.Int32, 20);
            for (var i = 0; i < numbers.Length; i++) { numbers[i] = i; }
            Console.WriteLine(lib.System.String.Join(', ', numbers));
        ");
    
        // create a script delegate
        engine.Execute(@"
            Filter = lib.System.Func(lib.System.Int32, lib.System.Boolean);
            oddFilter = new Filter(function(value) {
                return (value & 1) ? true : false;
            });
        ");
    
        // use LINQ from script
        engine.Execute(@"
            oddNumbers = numbers.Where(oddFilter);
            Console.WriteLine(lib.System.String.Join(', ', oddNumbers));
        ");
    
        // use a dynamic host object
        engine.Execute(@"
            expando = new lib.System.Dynamic.ExpandoObject();
            expando.foo = 123;
            expando.bar = 'qux';
            delete expando.foo;
        ");
    
        // call a script function
        engine.Execute("function print(x) { Console.WriteLine(x); }");
        engine.Script.print(DateTime.Now.DayOfWeek);
    
        // examine a script object
        engine.Execute("person = { name: 'Fred', age: 5 }");
        Console.WriteLine(engine.Script.person.name);
    
        // read a JavaScript typed array
        engine.Execute("values = new Int32Array([1, 2, 3, 4, 5])");
        var values = (ITypedArray<int>)engine.Script.values;
        Console.WriteLine(string.Join(", ", values.ToArray()));
    }

    0 0

    Using JSON.parse instead of embedding the JSON in the call expression didn't make a difference in performance unfortunately.

    Are there any plans on integrating ClearScript with Chakra now that Chakra is going open source?

    0 0

    Hi again,

    A test that generates large JSON structures (source code here) reveals that V8's JSON parser is 3-4 times as fast as its JavaScript parser, at least when it comes to processing JSON. Consider also that JavaScript parsers are not 100% JSON-compliant (link).

    Of course, this test uses very large JSON blocks (~7.5 million characters each) and may not be representative of your application. By using a trivial someFunc, it does isolate the performance of object transfer and conversion. Is it possible that your performance issues are within your someFunc implementation?

    We're looking at adding support for the Edge version of Chakra, but that's at a very early stage.

    Cheers!

    0 0

    Hi,

    I've created a fork named StandardsPlusMode. It is based on 5.4.3 version of ClearScript. I've made changes to it to enable the latest Javascript features in the JScriptEngine. This is the code I use in the BHO and it allows me to use the window object and all callbacks work.

    The same changes integrated in 5.4.4 version of ClearScript break callbacks.

    Instantiate with the following code:
    var engine = new JScriptEngine("{16d51579-a30b-4c8b-a276-0ff4dc41e755}", null, WindowsScriptEngineFlags.EnableStandardsPlusMode);

    0 0

    Hi frolovm,

    Thanks for sharing your changes. We've reproduced the issue and are investigating.

    Apparently the limitation mentioned above applies only to legacy JScript, whereas Chakra's requirements are somewhat different. It looks like ClearScript 5.4.3 satisfied those requirements, but 5.4.4 doesn't. ClearScript doesn't support Chakra, but we'd like to get to the bottom of this.

    Thanks again!

older | 1 | .... | 88 | 89 | (Page 90) | 91 | 92 | .... | 115 | newer