Skip to content
Open
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
2 changes: 1 addition & 1 deletion Fiddling/Fiddling.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
<PostBuildEvent>copy $(ProjectDir)..\$(V8Platform)\$(Configuration)\v8.dll $(ProjectDir)$(OutDir)
copy $(ProjectDir)..\$(V8Platform)\$(Configuration)\v8_libbase.dll $(ProjectDir)$(OutDir)
copy $(ProjectDir)..\$(V8Platform)\$(Configuration)\v8_libplatform.dll $(ProjectDir)$(OutDir)
copy $(ProjectDir)..\$(V8Platform)\$(Configuration)\zlib.dll $(ProjectDir)$(OutDir)
copy $(ProjectDir)..\$(V8Platform)\$(Configuration)\third_party_*.dll $(ProjectDir)$(OutDir)
copy $(ProjectDir)..\$(V8Platform)\$(Configuration)\icu*.* $(ProjectDir)$(OutDir)
</PostBuildEvent>
</PropertyGroup>
Expand Down
26 changes: 17 additions & 9 deletions Source/Noesis.Javascript/JavaScript.Net.vcxproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\v8-v143-x64.9.8.177.4\build\native\v8-v143-x64.props" Condition="Exists('..\..\packages\v8-v143-x64.9.8.177.4\build\native\v8-v143-x64.props')" />
<Import Project="..\..\packages\v8.redist-v143-x64.9.8.177.4\build\native\v8.redist-v143-x64.props" Condition="Exists('..\..\packages\v8.redist-v143-x64.9.8.177.4\build\native\v8.redist-v143-x64.props')" />
<Import Project="..\..\packages\v8-v143-x86.9.8.177.4\build\native\v8-v143-x86.props" Condition="Exists('..\..\packages\v8-v143-x86.9.8.177.4\build\native\v8-v143-x86.props')" />
<Import Project="..\..\packages\v8.redist-v143-x86.9.8.177.4\build\native\v8.redist-v143-x86.props" Condition="Exists('..\..\packages\v8.redist-v143-x86.9.8.177.4\build\native\v8.redist-v143-x86.props')" />
<Import Project="..\..\packages\v8-v143-x86.13.0.245.25\build\native\v8-v143-x86.props" Condition="Exists('..\..\packages\v8-v143-x86.13.0.245.25\build\native\v8-v143-x86.props')" />
<Import Project="..\..\packages\v8.redist-v143-x86.13.0.245.25\build\native\v8.redist-v143-x86.props" Condition="Exists('..\..\packages\v8.redist-v143-x86.13.0.245.25\build\native\v8.redist-v143-x86.props')" />
<Import Project="..\..\packages\v8-v143-x64.13.0.245.25\build\native\v8-v143-x64.props" Condition="Exists('..\..\packages\v8-v143-x64.13.0.245.25\build\native\v8-v143-x64.props')" />
<Import Project="..\..\packages\v8.redist-v143-x64.13.0.245.25\build\native\v8.redist-v143-x64.props" Condition="Exists('..\..\packages\v8.redist-v143-x64.13.0.245.25\build\native\v8.redist-v143-x64.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
Expand All @@ -28,7 +28,7 @@
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>JavaScriptNet</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
Expand Down Expand Up @@ -97,6 +97,8 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/Zc:__cplusplus /DNOMINMAX %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>v8.dll.lib;v8_libbase.dll.lib;v8_libplatform.dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
Expand All @@ -112,6 +114,8 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/Zc:__cplusplus /DNOMINMAX %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>v8.dll.lib;v8_libbase.dll.lib;v8_libplatform.dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
Expand All @@ -126,6 +130,8 @@
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/Zc:__cplusplus /DNOMINMAX %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>v8.dll.lib;v8_libbase.dll.lib;v8_libplatform.dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
Expand All @@ -140,6 +146,8 @@
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalOptions>/Zc:__cplusplus /DNOMINMAX %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<AdditionalDependencies>v8.dll.lib;v8_libbase.dll.lib;v8_libplatform.dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
Expand Down Expand Up @@ -183,9 +191,9 @@
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\v8.redist-v143-x86.9.8.177.4\build\native\v8.redist-v143-x86.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8.redist-v143-x86.9.8.177.4\build\native\v8.redist-v143-x86.props'))" />
<Error Condition="!Exists('..\..\packages\v8-v143-x86.9.8.177.4\build\native\v8-v143-x86.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8-v143-x86.9.8.177.4\build\native\v8-v143-x86.props'))" />
<Error Condition="!Exists('..\..\packages\v8.redist-v143-x64.9.8.177.4\build\native\v8.redist-v143-x64.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8.redist-v143-x64.9.8.177.4\build\native\v8.redist-v143-x64.props'))" />
<Error Condition="!Exists('..\..\packages\v8-v143-x64.9.8.177.4\build\native\v8-v143-x64.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8-v143-x64.9.8.177.4\build\native\v8-v143-x64.props'))" />
<Error Condition="!Exists('..\..\packages\v8.redist-v143-x64.13.0.245.25\build\native\v8.redist-v143-x64.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8.redist-v143-x64.13.0.245.25\build\native\v8.redist-v143-x64.props'))" />
<Error Condition="!Exists('..\..\packages\v8-v143-x64.13.0.245.25\build\native\v8-v143-x64.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8-v143-x64.13.0.245.25\build\native\v8-v143-x64.props'))" />
<Error Condition="!Exists('..\..\packages\v8.redist-v143-x86.13.0.245.25\build\native\v8.redist-v143-x86.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8.redist-v143-x86.13.0.245.25\build\native\v8.redist-v143-x86.props'))" />
<Error Condition="!Exists('..\..\packages\v8-v143-x86.13.0.245.25\build\native\v8-v143-x86.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\v8-v143-x86.13.0.245.25\build\native\v8-v143-x86.props'))" />
</Target>
</Project>
29 changes: 20 additions & 9 deletions Source/Noesis.Javascript/JavascriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,6 @@ v8::Local<v8::String> ToV8String(Isolate* isolate, System::String^ value) {
return String::NewFromTwoByte(isolate, (uint16_t*)name, v8::NewStringType::kNormal).ToLocalChecked();
}

static JavascriptContext::JavascriptContext()
{
UnmanagedInitialisation();
}


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

Expand Down Expand Up @@ -151,6 +146,11 @@ void JavascriptContext::FatalErrorCallbackMember(const char* location, const cha

JavascriptContext::JavascriptContext()
{
// Certain static operations like setting flags cannot be performed after V8 has been initialized. Since we allow setting flags by
// a static method we can't do the unmanaged initialization in the static constructor, because that would always run before any other
// static method. Instead we call it here. The internal checks in UnmanagedInitialisation make this thread safe.
UnmanagedInitialisation();

// Unfortunately the fatal error handler is not installed early enough to catch
// out-of-memory errors while creating new isolates
// (see my post Catching V8::FatalProcessOutOfMemory while creating an isolate (SetFatalErrorHandler does not work)).
Expand Down Expand Up @@ -213,6 +213,8 @@ void JavascriptContext::SetFatalErrorHandler(FatalErrorHandler^ handler)

void JavascriptContext::SetFlags(System::String^ flags)
{
if (initialized)
throw gcnew System::InvalidOperationException("Flags can only be set once before the first context and therefore V8 is initialized.");
std::string convertedFlags = msclr::interop::marshal_as<std::string>(flags);
v8::V8::SetFlagsFromString(convertedFlags.c_str(), (int)convertedFlags.length());
}
Expand Down Expand Up @@ -262,7 +264,7 @@ JavascriptContext::SetParameter(System::String^ iName, System::Object^ iObject,
if (options != SetParameterOptions::None) {
Local<v8::Object> obj = value.As<v8::Object>();
if (!obj.IsEmpty()) {
Local<v8::External> wrap = obj->GetInternalField(0).As<v8::External>();
Local<v8::External> wrap = obj->GetInternalField(0).As<v8::Value>().As<v8::External>();
if (!wrap.IsEmpty()) {
JavascriptExternal* external = static_cast<JavascriptExternal*>(wrap->Value());
external->SetOptions(options);
Expand Down Expand Up @@ -291,7 +293,8 @@ void JavascriptContext::SetConstructor(System::String^ name, System::Type^ assoc
Local<String> className = ToV8String(isolate, name);
Local<FunctionTemplate> functionTemplate = JavascriptInterop::GetFunctionTemplateFromSystemDelegate(constructor);
functionTemplate->SetClassName(className);
JavascriptInterop::InitObjectWrapperTemplate(functionTemplate->InstanceTemplate());
auto instanceTemplate = functionTemplate->InstanceTemplate();
JavascriptInterop::InitObjectWrapperTemplate(instanceTemplate);
mTypeToConstructorMapping[associatedType] = System::IntPtr(new Persistent<FunctionTemplate>(isolate, functionTemplate));
Local<Context>::New(isolate, *mContext)->Global()->Set(context, className, functionTemplate->GetFunction(context).ToLocalChecked());
}
Expand Down Expand Up @@ -493,7 +496,9 @@ JavascriptContext::Exit(v8::Locker *locker, JavascriptContext^ old_context)
void
JavascriptContext::Collect()
{
while(!this->isolate->IdleNotificationDeadline(1)) {};
// The method used originally here does not exist anymore and this is the best guess for a replacement.
// Since this isn't used in internal tests anywhere it can't be checked for validity.
this->isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -523,7 +528,8 @@ JavascriptContext::GetObjectWrapperConstructorTemplate(System::Type ^type)
System::IntPtr ptrToConstructor;
if (!mTypeToConstructorMapping->TryGetValue(type, ptrToConstructor)) {
Local<FunctionTemplate> constructor = FunctionTemplate::New(GetCurrentIsolate());
JavascriptInterop::InitObjectWrapperTemplate(constructor->InstanceTemplate());
auto instanceTemplate = constructor->InstanceTemplate();
JavascriptInterop::InitObjectWrapperTemplate(instanceTemplate);
mTypeToConstructorMapping[type] = System::IntPtr(new Persistent<FunctionTemplate>(isolate, constructor));
return constructor;
}
Expand All @@ -538,6 +544,11 @@ System::String^ JavascriptContext::V8Version::get()
return gcnew System::String(v8::V8::GetVersion());
}

bool JavascriptContext::IsV8Initialized::get()
{
return initialized;
}

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

Local<Script>
Expand Down
8 changes: 6 additions & 2 deletions Source/Noesis.Javascript/JavascriptContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,6 @@ public ref class JavascriptContext: public System::IDisposable
// Constructor
////////////////////////////////////////////////////////////
public:
static JavascriptContext();

JavascriptContext();

~JavascriptContext();
Expand All @@ -151,6 +149,12 @@ public ref class JavascriptContext: public System::IDisposable
virtual System::Object^ Run(System::String^ iScript, System::String^ iScriptResourceName);

property static System::String^ V8Version { System::String^ get(); }

/// <summary>
/// Returns true if the unmanaged initialization of V8 has already occurred in this process. This property helps with not calling certain
/// operations (e.g. setting engine flags by using SetFlags) that only work before the V8 platform is initialized in this process.
/// </summary>
property static bool IsV8Initialized { bool get(); }

System::Collections::Generic::List<JavascriptStackFrame^>^ GetCurrentStack(int maxDepth);

Expand Down
34 changes: 24 additions & 10 deletions Source/Noesis.Javascript/JavascriptExternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ void JavascriptExternal::IteratorCallback(const v8::FunctionCallbackInfo<Value>&
iterator->Set(String::NewFromUtf8(isolate, "next").ToLocalChecked(), functionTemplate);
auto iteratorInstance = iterator->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();

auto internalField = Local<External>::Cast(iArgs.Holder()->GetInternalField(0));
auto internalField = iArgs.This()->GetInternalField(0).As<Value>().As<External>();
auto external = (JavascriptExternal*)internalField->Value();
auto enumerable = (System::Collections::IEnumerable^)external->GetObject();
auto enumerator = enumerable->GetEnumerator();
Expand All @@ -405,17 +405,31 @@ void JavascriptExternal::IteratorNextCallback(const v8::FunctionCallbackInfo<Val
{
auto isolate = iArgs.GetIsolate();

auto internalField = Local<External>::Cast(iArgs.Holder()->GetInternalField(0));
auto internalField = iArgs.This()->GetInternalField(0).As<Value>().As<External>();
auto external = (JavascriptExternal*)internalField->Value();
auto enumerator = (System::Collections::IEnumerator^) external->GetObject();
auto done = !enumerator->MoveNext();

auto resultTemplate = ObjectTemplate::New(isolate);
auto result = resultTemplate->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "done").ToLocalChecked(), JavascriptInterop::ConvertToV8(done));
if (!done)
result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "value").ToLocalChecked(), JavascriptInterop::ConvertToV8(enumerator->Current));
iArgs.GetReturnValue().Set(result);

try
{
// MoveNext might throw in which case we need to schedule a JS exception with the isolate otherwise the JS code
// can't catch that error and the script execution terminates immediately instead.
auto done = !enumerator->MoveNext();
auto resultTemplate = ObjectTemplate::New(isolate);
auto result = resultTemplate->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "done").ToLocalChecked(), JavascriptInterop::ConvertToV8(done));
if (!done)
result->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "value").ToLocalChecked(), JavascriptInterop::ConvertToV8(enumerator->Current));
iArgs.GetReturnValue().Set(result);
}
catch (System::Exception ^exception)
{
// If we catch a .NET exception we schedule it with the isolate and set the resulting object as the return value
// of the callback. This automatically causes the iterator protocol to be fulfilled correctly. We must set the
// JS exception object as the return value to get correct source and line information in addition to the
// stacktrace.
auto result = isolate->ThrowException(JavascriptInterop::ConvertToV8(exception));
iArgs.GetReturnValue().Set(result);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
Loading