Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Source/Noesis.Javascript/JavascriptContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ public ref class JavascriptContext: public System::IDisposable
////////////////////////////////////////////////////////////
// Data members
////////////////////////////////////////////////////////////

protected:
// By entering an isolate before using a context, we can have multiple
// contexts used simultaneously in different threads.
Expand Down
93 changes: 93 additions & 0 deletions Source/Noesis.Javascript/JavascriptFunction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "JavascriptFunction.h"
#include "JavascriptInterop.h"
#include "JavascriptContext.h"

////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Noesis { namespace Javascript {

////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////

JavascriptFunction::JavascriptFunction( v8::Handle<v8::Object> iFunction, JavascriptContext^ context)
{
if (!iFunction->IsFunction())
throw gcnew System::ArgumentException("Trying to use non-function as function");

if(!context)
throw gcnew System::ArgumentException("Must provide a JavascriptContext");

mFuncHandle = new Persistent<Function>();
*mFuncHandle = Persistent<Function>::New(Handle<Function>::Cast(iFunction));
mContext = context;
}

JavascriptFunction::~JavascriptFunction()
{
if(mFuncHandle)
{
JavascriptScope scope(mContext);
mFuncHandle->Dispose();
delete mFuncHandle;
mFuncHandle = nullptr;
}
System::GC::SuppressFinalize(this);
}

JavascriptFunction::!JavascriptFunction()
{
if(mFuncHandle)
{
JavascriptScope scope(mContext);
mFuncHandle->Dispose();
delete mFuncHandle;
mFuncHandle = nullptr;
}
}

System::Object^ JavascriptFunction::Call(... cli::array<System::Object^>^ args)
{
JavascriptScope scope(mContext);
HandleScope handleScope;

Handle<v8::Object> global = (*mFuncHandle)->CreationContext()->Global();

int argc = args->Length;
Handle<v8::Value> *argv = new Handle<v8::Value>[argc];
for (int i = 0; i < argc; i++)
{
argv[i] = JavascriptInterop::ConvertToV8(args[i]);
}

Local<Value> retVal = (*mFuncHandle)->Call(global, argc, argv);

delete [] argv;
return JavascriptInterop::ConvertFromV8(retVal);
}

bool JavascriptFunction::operator==( JavascriptFunction^ func1, JavascriptFunction^ func2 )
{
if(ReferenceEquals(func2, nullptr)) {
return false;
}
Handle<Function> jsFuncPtr1 = *(func1->mFuncHandle);
Handle<Function> jsFuncPtr2 = *(func2->mFuncHandle);

return jsFuncPtr1->Equals(jsFuncPtr2);
}

bool JavascriptFunction::Equals( JavascriptFunction^ other )
{
return this == other;
}

bool JavascriptFunction::Equals(Object^ other )
{
JavascriptFunction^ otherFunc = dynamic_cast<JavascriptFunction^>(other);
return (otherFunc && this->Equals(otherFunc));
}

} } // namespace Noesis::Javascript

////////////////////////////////////////////////////////////////////////////////////////////////////
45 changes: 45 additions & 0 deletions Source/Noesis.Javascript/JavascriptFunction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

//////////////////////////////////////////////////////////////////////////

#include <v8.h>

#include "JavascriptContext.h"

using namespace v8;

//////////////////////////////////////////////////////////////////////////

namespace Noesis { namespace Javascript {

//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
// JavascriptFunction
//
// Wraps around JS function object and allow calling it in later time
//////////////////////////////////////////////////////////////////////////
public ref class JavascriptFunction
{
public:
JavascriptFunction(v8::Handle<v8::Object> iFunction, JavascriptContext^ context);
~JavascriptFunction();
!JavascriptFunction();

System::Object^ Call(... cli::array<System::Object^>^ args);

static bool operator== (JavascriptFunction^ func1, JavascriptFunction^ func2);
bool Equals(JavascriptFunction^ other);

virtual bool Equals(Object^ other) override;

private:
v8::Persistent<v8::Function>* mFuncHandle;
JavascriptContext^ mContext;
};

//////////////////////////////////////////////////////////////////////////

} } // namespace Noesis::Javascript

//////////////////////////////////////////////////////////////////////////
3 changes: 3 additions & 0 deletions Source/Noesis.Javascript/JavascriptInterop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "SystemInterop.h"
#include "JavascriptException.h"
#include "JavascriptExternal.h"
#include "JavascriptFunction.h"

#include <string>

Expand Down Expand Up @@ -81,6 +82,8 @@ JavascriptInterop::ConvertFromV8(Handle<Value> iValue)
return ConvertArrayFromV8(iValue);
if (iValue->IsDate())
return ConvertDateFromV8(iValue);
if (iValue->IsFunction())
return gcnew JavascriptFunction(iValue->ToObject(), JavascriptContext::GetCurrent());
if (iValue->IsObject())
{
Handle<Object> object = iValue->ToObject();
Expand Down
2 changes: 2 additions & 0 deletions Source/Noesis.Javascript/Noesis.Javascript.VS2012.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,15 @@
<ClCompile Include="JavascriptContext.cpp" />
<ClCompile Include="JavascriptException.cpp" />
<ClCompile Include="JavascriptExternal.cpp" />
<ClCompile Include="JavascriptFunction.cpp" />
<ClCompile Include="JavascriptInterop.cpp" />
<ClCompile Include="SystemInterop.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="JavascriptContext.h" />
<ClInclude Include="JavascriptException.h" />
<ClInclude Include="JavascriptExternal.h" />
<ClInclude Include="JavascriptFunction.h" />
<ClInclude Include="JavascriptInterop.h" />
<ClInclude Include="SystemInterop.h" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
<ClCompile Include="SystemInterop.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AssemblyInfo.cpp">
<ClCompile Include="JavascriptFunction.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
Expand All @@ -42,6 +45,9 @@
<ClInclude Include="SystemInterop.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="JavascriptFunction.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="key.snk" />
Expand Down
4 changes: 1 addition & 3 deletions Tests/Noesis.Javascript.Tests/IsolationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Noesis.Javascript.Tests
public class IsolationTests
{
[Test]
public string RunIsolatesTest()
public void RunIsolatesTest()
{

Stopwatch timer = new Stopwatch();
Expand All @@ -24,8 +24,6 @@ public string RunIsolatesTest()
thread.Join();

Assert.That(timer.ElapsedMilliseconds, Is.LessThan(1500), "It took too long, they must not be running in parallel.");

return null;
}

static void RunInstance()
Expand Down
23 changes: 23 additions & 0 deletions Tests/Noesis.Javascript.Tests/JavascriptFunctionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using NUnit.Framework;

namespace Noesis.Javascript.Tests
{
[TestFixture]
public class JavascriptFunctionTests
{
[Test]
public void GetFunctionFromJsContext()
{
JavascriptContext context = new JavascriptContext();
context.Run("a = function(a,b) {return a+b;}");

JavascriptFunction funcObj = context.GetParameter("a") as JavascriptFunction;

Assert.That(funcObj, Is.Not.Null);

object result = funcObj.Call(1, 2);

Assert.That(result, Is.EqualTo(3));
}
}
}
6 changes: 2 additions & 4 deletions Tests/Noesis.Javascript.Tests/MemoryLeakTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Noesis.Javascript.Tests
public class MemoryLeakTests
{
[Test]
public string RunMemoryLeakTest()
public void RunMemoryLeakTest()
{
MemoryUsageLoadInstance();
long mem = Process.GetCurrentProcess().PrivateMemorySize64;
Expand All @@ -21,9 +21,7 @@ public string RunMemoryLeakTest()
GC.Collect();
decimal diffMBytes = (Process.GetCurrentProcess().PrivateMemorySize64 - mem) / 1048576m;

if (diffMBytes >= 1) // Allow 1 MB
return String.Format("{0:0.00}MB left allocated", diffMBytes);
return null;
Assert.That(diffMBytes, Is.LessThan(1), "{0:0.00}MB left allocated", diffMBytes);
}

private static void MemoryUsageLoadInstance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
<Compile Include="ExceptionTests.cs" />
<Compile Include="IsolationTests.cs" />
<Compile Include="MemoryLeakTests.cs" />
<Compile Include="JavascriptFunctionTests.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
Expand Down Expand Up @@ -151,6 +152,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="RegressionTests\" />
<Folder Include="UnitTest\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Expand Down