Quantcast
Channel: ClearScript
Viewing all 2297 articles
Browse latest View live

Edited Issue: [FIXED] Memory leak with shared V8 runtimes [107]

$
0
0
Repeated calls to `V8Runtime.CreateScriptEngine` make the runtime's heap grow even if the engine instances are disposed immediately. This is because the `V8ContextImpl` destructor neglects to to dispose the termination exception.

Commented Issue: [FIXED] Memory leak with shared V8 runtimes [107]

$
0
0
Repeated calls to `V8Runtime.CreateScriptEngine` make the runtime's heap grow even if the engine instances are disposed immediately. This is because the `V8ContextImpl` destructor neglects to to dispose the termination exception.
Comments: Fix posted [here](https://clearscript.codeplex.com/SourceControl/changeset/41036a3cb82a71fc009664ccc9609767bead5aea).

Source code checked in, #41036a3cb82a71fc009664ccc9609767bead5aea

$
0
0
Fixed memory leak with shared V8 runtimes (Issue #107).

Commented Unassigned: cross-engine nested exception fault [108]

$
0
0
got one more cross-engine issue.

an error raised by scriptengine (b) which was invoked by another scriptengine (a), doesn't make it to scriptengine (a) and properly back to the origin calle in the stack scriptengine (b). which means the script execution error occurred as such in scriptengine (b) cant be catched by a try-catch on the host side.

on more weird issue happening along side is that the code block (function|sub) where the error was raised gets executed from the very beginning.

in short the call chain looks like this:
```
engineA.someMethod(
engineB.anotherMethod(
engineA.errorOccuringMethod(
- firstLineCode -
someErrorCode -> causing a rerun of engineA.errorOccuringmethod() then throwing COMException in WindowsScriptEngine.ThrowHostException()
)
)
)
```

here a sample code:

```
var seA = new VBScriptEngine();
seA.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seA.Execute(@"
class aclass

function binvoke(bobj)
bobj.bmethod()
end function

end class
dim avar : set avar = new aclass
");

var seB = new VBScriptEngine();
seB.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seB.Execute(@"
class bclass

function bmethod()
WriteLine(""begin-bmethod"")
err.raise 1, ""source"", ""errdescr""
bmethod = ""retval""
WriteLine(""end-bmethod"")
end function

function go(seA, bobj)
dim i
'for i = 0 to 5
seA.binvoke(bobj)
'next
end function

end class
dim bvar : set bvar = new bclass
");


try
{
seB.Script.bvar.go(seA.Script.avar, seB.Script.bvar);
}
catch (System.Runtime.InteropServices.COMException)
{
throw;
}
catch (Exception)
{
throw;
}
```

you should see 2xtimes "begin-bmethod" in the console output before the debugger stop at WindowsScriptEngine.ThrowHostException()

the expected behaviour would be 1xtime "begin-bmethod" in the console output and break of the debugger in the try-catch block
Comments: Hmm, we're seeing somewhat different behavior. The exception is delivered correctly to the managed caller (as an instance of `ScriptEngineException` with the correct message string), but the failing cross-engine calls are being executed twice, yielding not two but _four_ "begin-bmethod" traces (because `binvoke` is executed twice). We've investigated this briefly and it appears to be due to COM interop bug in the .NET framework. We're looking for a workaround. Thanks for reporting this issue!

Edited Issue: [BUG] Double execution of cross-engine VBScript calls that throw exceptions [108]

$
0
0
got one more cross-engine issue.

an error raised by scriptengine (b) which was invoked by another scriptengine (a), doesn't make it to scriptengine (a) and properly back to the origin calle in the stack scriptengine (b). which means the script execution error occurred as such in scriptengine (b) cant be catched by a try-catch on the host side.

on more weird issue happening along side is that the code block (function|sub) where the error was raised gets executed from the very beginning.

in short the call chain looks like this:
```
engineA.someMethod(
engineB.anotherMethod(
engineA.errorOccuringMethod(
- firstLineCode -
someErrorCode -> causing a rerun of engineA.errorOccuringmethod() then throwing COMException in WindowsScriptEngine.ThrowHostException()
)
)
)
```

here a sample code:

```
var seA = new VBScriptEngine();
seA.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seA.Execute(@"
class aclass

function binvoke(bobj)
bobj.bmethod()
end function

end class
dim avar : set avar = new aclass
");

var seB = new VBScriptEngine();
seB.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seB.Execute(@"
class bclass

function bmethod()
WriteLine(""begin-bmethod"")
err.raise 1, ""source"", ""errdescr""
bmethod = ""retval""
WriteLine(""end-bmethod"")
end function

function go(seA, bobj)
dim i
'for i = 0 to 5
seA.binvoke(bobj)
'next
end function

end class
dim bvar : set bvar = new bclass
");


try
{
seB.Script.bvar.go(seA.Script.avar, seB.Script.bvar);
}
catch (System.Runtime.InteropServices.COMException)
{
throw;
}
catch (Exception)
{
throw;
}
```

you should see 2xtimes "begin-bmethod" in the console output before the debugger stop at WindowsScriptEngine.ThrowHostException()

the expected behaviour would be 1xtime "begin-bmethod" in the console output and break of the debugger in the try-catch block

Commented Issue: [BUG] Double execution of cross-engine VBScript calls that throw exceptions [108]

$
0
0
got one more cross-engine issue.

an error raised by scriptengine (b) which was invoked by another scriptengine (a), doesn't make it to scriptengine (a) and properly back to the origin calle in the stack scriptengine (b). which means the script execution error occurred as such in scriptengine (b) cant be catched by a try-catch on the host side.

on more weird issue happening along side is that the code block (function|sub) where the error was raised gets executed from the very beginning.

in short the call chain looks like this:
```
engineA.someMethod(
engineB.anotherMethod(
engineA.errorOccuringMethod(
- firstLineCode -
someErrorCode -> causing a rerun of engineA.errorOccuringmethod() then throwing COMException in WindowsScriptEngine.ThrowHostException()
)
)
)
```

here a sample code:

```
var seA = new VBScriptEngine();
seA.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seA.Execute(@"
class aclass

function binvoke(bobj)
bobj.bmethod()
end function

end class
dim avar : set avar = new aclass
");

var seB = new VBScriptEngine();
seB.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seB.Execute(@"
class bclass

function bmethod()
WriteLine(""begin-bmethod"")
err.raise 1, ""source"", ""errdescr""
bmethod = ""retval""
WriteLine(""end-bmethod"")
end function

function go(seA, bobj)
dim i
'for i = 0 to 5
seA.binvoke(bobj)
'next
end function

end class
dim bvar : set bvar = new bclass
");


try
{
seB.Script.bvar.go(seA.Script.avar, seB.Script.bvar);
}
catch (System.Runtime.InteropServices.COMException)
{
throw;
}
catch (Exception)
{
throw;
}
```

you should see 2xtimes "begin-bmethod" in the console output before the debugger stop at WindowsScriptEngine.ThrowHostException()

the expected behaviour would be 1xtime "begin-bmethod" in the console output and break of the debugger in the try-catch block
Comments: thanks for the fast reply. after giving a retry, I could find a quick fix for the multiple execution of the code block after error raise. script now seem to stop as expected at the error line. HostItem.cs (:1795) ``` object IReflect.InvokeMember(string name, BindingFlags invokeFlags, Binder binder, object invokeTarget, object[] wrappedArgs, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParams) { if (engine.CurrentScriptFrame.ScriptError != null) { engine.ThrowScriptError(); } return InvokeReflectMember(name, invokeFlags, wrappedArgs, culture, namedParams); } ```

Commented Issue: [BUG] Double execution of cross-engine VBScript calls that throw exceptions [108]

$
0
0
got one more cross-engine issue.

an error raised by scriptengine (b) which was invoked by another scriptengine (a), doesn't make it to scriptengine (a) and properly back to the origin calle in the stack scriptengine (b). which means the script execution error occurred as such in scriptengine (b) cant be catched by a try-catch on the host side.

on more weird issue happening along side is that the code block (function|sub) where the error was raised gets executed from the very beginning.

in short the call chain looks like this:
```
engineA.someMethod(
engineB.anotherMethod(
engineA.errorOccuringMethod(
- firstLineCode -
someErrorCode -> causing a rerun of engineA.errorOccuringmethod() then throwing COMException in WindowsScriptEngine.ThrowHostException()
)
)
)
```

here a sample code:

```
var seA = new VBScriptEngine();
seA.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seA.Execute(@"
class aclass

function binvoke(bobj)
bobj.bmethod()
end function

end class
dim avar : set avar = new aclass
");

var seB = new VBScriptEngine();
seB.Script.WriteLine = new Action<string>((text) => Console.WriteLine(text));
seB.Execute(@"
class bclass

function bmethod()
WriteLine(""begin-bmethod"")
err.raise 1, ""source"", ""errdescr""
bmethod = ""retval""
WriteLine(""end-bmethod"")
end function

function go(seA, bobj)
dim i
'for i = 0 to 5
seA.binvoke(bobj)
'next
end function

end class
dim bvar : set bvar = new bclass
");


try
{
seB.Script.bvar.go(seA.Script.avar, seB.Script.bvar);
}
catch (System.Runtime.InteropServices.COMException)
{
throw;
}
catch (Exception)
{
throw;
}
```

you should see 2xtimes "begin-bmethod" in the console output before the debugger stop at WindowsScriptEngine.ThrowHostException()

the expected behaviour would be 1xtime "begin-bmethod" in the console output and break of the debugger in the try-catch block
Comments: only that my try-catch is not catching the ScriptEngineException

New Post: Header format for V8 debugger

$
0
0
Dear ClearScript team,

I've been dabbling latey with node-inspector to see what would be needed to adapt ClearScript to work with it - aside from some global services, it looks like the header format as defined in (https://clearscript.codeplex.com/SourceControl/latest#ClearScript/V8/V8DebugAgent.cs) does not match what is usually coming from Node.

Specifically, the node debugger (as seen in https://github.com/nodejs/node/commit/8d82ec21308812132a71afe45c5bc517b4a43354, line 72) expects a whitespace after the colon, while ClearScript is not sending one. Is this intended?

Just by changing that (plus a couple of mocked services) I am able to connect with node-inspector and inspect global variables as defined in ClearScript, so I'm hopeful about getting it to work.

Thanks!

New Post: Header format for V8 debugger

$
0
0
Hello!

We'll be happy to adjust the header as long as it doesn't break the Eclipse debugger. Can you detail the changes you made to enable node-inspector?

Thanks!

New Post: Header format for V8 debugger

$
0
0
Hi,

for the moment I haven't changed anything in ClearScript, opting to modify che node debugger instead (that would be, just removing the whitespace in the regular expression here https://github.com/nodejs/node/commit/8d82ec21308812132a71afe45c5bc517b4a43354 at line 72) - I will take time in the next couple of days to play around with the ClearScript source code and see if just modifying the V8DebugAgent.cs gets us all the way.

Regarding the engine itself, all I've done is exposing a mock of the process and global objects with just the bare minimum fields to avoid having an exception in the inspector itself. So far I was able to inspect global variables while the engine is running and perform step-by-step debugging on compiled script(s) - although so far I was not able to have the inspector react to the "debugger symbol reached" event automatically; that is still under investigation.

Since it is of interest for you, I will try and provide an out of the box solution starting from a fork of ClearScript in the next few days. Thanks!

Commented Issue: [FIXED] Memory leak with shared V8 runtimes [107]

$
0
0
Repeated calls to `V8Runtime.CreateScriptEngine` make the runtime's heap grow even if the engine instances are disposed immediately. This is because the `V8ContextImpl` destructor neglects to to dispose the termination exception.
Comments: Thank you so much for resolving this bug. The responsiveness and support for ClearScript has been great thus far. When will this fix be available on Nuget?

Commented Issue: [FIXED] Memory leak with shared V8 runtimes [107]

$
0
0
Repeated calls to `V8Runtime.CreateScriptEngine` make the runtime's heap grow even if the engine instances are disposed immediately. This is because the `V8ContextImpl` destructor neglects to to dispose the termination exception.
Comments: Thanks for your kind words! We don't maintain NuGet packages, and recommend that you contact the owners of the ones you're using. In the past they've released updates soon after we posted new ClearScript versions. We're close to releasing version 5.4.6, but we're waiting for V8 5.1 to hit the stable channel first. In the meantime we encourage you to build ClearScript. The ClearScript [ReadMe](https://clearscript.codeplex.com/SourceControl/latest#ReadMe.txt) contains instructions. Good luck!

Commented Issue: [FIXED] Memory leak with shared V8 runtimes [107]

$
0
0
Repeated calls to `V8Runtime.CreateScriptEngine` make the runtime's heap grow even if the engine instances are disposed immediately. This is because the `V8ContextImpl` destructor neglects to to dispose the termination exception.
Comments: Will do. Thanks

New Post: Header format for V8 debugger

$
0
0
Hi guys,

so, I can confirm that it is possible to connect with node-inspector by adding a space after the colons in the header transmission message, and providing (very simple) "process" and "global" objects. From the ClearScript point of view, two lines of code need to change in (https://clearscript.codeplex.com/SourceControl/latest#ClearScript/V8/V8DebugAgent.cs):

(1)
SendStringAsync(tcpClient, "Type:connect\r\nV8-Version:" + version + "\r\nProtocol-Version:1\r\nEmbedding-Host:" + name + "\r\nContent-Length:0\r\n\r\n", OnConnectionMessageSent);
becomes
SendStringAsync(tcpClient, "Type:connect\r\nV8-Version: " + version + "\r\nProtocol-Version: 1\r\nEmbedding-Host: " + name + "\r\nContent-Length: 0\r\n\r\n", OnConnectionMessageSent);
and (2)
var headerBytes = Encoding.UTF8.GetBytes(MiscHelpers.FormatInvariant("Content-Length:{0}\r\n\r\n", contentBytes.Length));
becomes
var headerBytes = Encoding.UTF8.GetBytes(MiscHelpers.FormatInvariant("Content-Length: {0}\r\n\r\n", contentBytes.Length));
Unfortunately I have no easy way to test if such changes break the Eclipse debugger (although I think that's unlikely, as the Eclipse debugger already works with node). Let me know if you need more information!

New Post: Header format for V8 debugger

$
0
0
Thank you very much for the details! We'll test these changes with Eclipse, and if all goes well, we'll include them in the next point release. Thanks again!

New Post: Pass Javascript Object with Array to the host

$
0
0
Here is my code:
using System;
using Microsoft.ClearScript.V8;
using Newtonsoft.Json;

namespace ConsoleApplication
{
    public class Test
    {
        public void Output(object o)
        {
            Console.WriteLine(JsonConvert.SerializeObject(o));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var engine = new V8ScriptEngine();
            engine.AddHostObject("test", new Test());
            var script = "var o = {Persons: [{Name :\"John\"}, {Name :\"Joe\"}] }; test.Output(o);";
            engine.Execute(script);            
        }
    }
}
I expect that it output

{
"Persons": [
{
  "Name": "John"
},
{
  "Name": "Joe"
}
]
}

but it actually output

{
"Persons": {
"0": {
  "Name": "John"
},
"1": {
  "Name": "Joe"
}
}
}

I understand it use the dynamic V8ScriptItem to convert the javascript object to host object.

But is there a way to keep array of javascript as also a array or list of host object?

New Post: Pass Javascript Object with Array to the host

$
0
0
Hello!

ClearScript doesn't convert script arrays to host arrays automatically. Instead, it lets you access script arrays directly from the host, and vice versa.

Can you say more about your requirements? If you just need to produce the correct JSON for your script object, then you probably want to use JavaScript's JSON object instead of Json.NET. Otherwise you may need to expose an array conversion function and invoke it manually.

Thanks!

New Post: Pass Javascript Object with Array to the host

$
0
0
Thanks!

My requirement can be simplified like my example above, i want to expose Test.Output for the script side to output some debug information.

So I can pass any json object to the Test.Output, so that at the host side, it can Serialize it as string and output to the Console.

As you point out, I can stringify the object as string and pass it to the host side to output to the console, but just want to know if there is a way that I can let the host side serialize it correctly or as I expected before output to the Console.

Thanks again,

New Post: Pass Javascript Object with Array to the host

$
0
0
Hi again,

One thing you could do is modify your Test class so that it converts arrays before passing them to Json.NET:
publicclass Test {
    privatereadonly V8Converter v8Converter = new V8Converter();
    publicvoid Output(object o) {
        Console.WriteLine(JsonConvert.SerializeObject(o, v8Converter));
    }
    privateclass V8Converter : JsonConverter {
        publicoverridebool CanConvert(Type type) {
            return type.Name == "V8ScriptItem";
        }
        publicoverridevoid WriteJson(JsonWriter w, object o, JsonSerializer ser) {
            dynamic dynObj = o;
            if (dynObj.constructor.name == "Array") {
                var length = (int)dynObj.length;
                var array = Enumerable.Range(0, length).Select(i => dynObj[i]).ToArray();
                ser.Serialize(w, array);
            } else {
                var names = (IEnumerable<string>)dynObj.GetDynamicMemberNames();
                var dictionary = names.ToDictionary(name => name, name => dynObj[name]);
                ser.Serialize(w, dictionary);
            }
        }
        publicoverrideobject ReadJson(JsonReader r, Type type, object o, JsonSerializer ser) {
            thrownew NotImplementedException();
        }
    }
}
Checking the script item type this way is a bit hacky, but it works :)

Good luck!

New Post: Pass Javascript Object with Array to the host

Viewing all 2297 articles
Browse latest View live




Latest Images