Version 5.3.10: Added support for Visual Studio 2013, fixed ErrorDetails line number issue in WindowsScriptEngine (Issue #24), added ScriptEngine.FormatCode and V8Runtime.FormatCode, disabled code formatting by default, fixed script access to nullable values (Issue #30), added ScriptEngine.GetStackTrace() (Issue #27), added V8Runtime.MaxStackUsage and V8ScriptEngine.MaxRuntimeStackUsage (Issue #26), fixed V8 root object marshaling crash when GlobalMembers is in effect, added tests for bug fixes and new APIs. Tested with V8 3.23.13.

This commit is contained in:
ClearScript 2013-11-28 11:15:47 -05:00
Родитель b83270ae12
Коммит 133980c335
46 изменённых файлов: 980 добавлений и 289 удалений

Просмотреть файл

@ -18,6 +18,16 @@
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_BEFORE_TYPEOF_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CLSID/@EntryIndexedValue">CLSID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=COM/@EntryIndexedValue">COM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DOM/@EntryIndexedValue">DOM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=JIT/@EntryIndexedValue">JIT</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=JS/@EntryIndexedValue">JS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=URL/@EntryIndexedValue">URL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VB/@EntryIndexedValue">VB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VBS/@EntryIndexedValue">VBS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>

Просмотреть файл

@ -69,16 +69,16 @@
//-----------------------------------------------------------------------------
#define DEFINE_CALLBACK_MANAGER(NAME, TYPE) \
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, NullMutex)
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, NullMutex)
#define DEFINE_CONCURRENT_CALLBACK_MANAGER(NAME, TYPE) \
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, RecursiveMutex)
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, RecursiveMutex)
#define DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, CALLBACK_TYPE, MUTEX_TYPE) \
struct NAME##CallbackTraits: public CallbackTraits<NAME##CallbackTraits, CALLBACK_TYPE, MUTEX_TYPE> {};
struct NAME##CallbackTraits: public CallbackTraits<NAME##CallbackTraits, CALLBACK_TYPE, MUTEX_TYPE> {};
#define CALLBACK_MANAGER(NAME) \
CallbackManager<NAME##CallbackTraits>
CallbackManager<NAME##CallbackTraits>
//-----------------------------------------------------------------------------
// CallbackTraits

Просмотреть файл

@ -75,16 +75,16 @@
//-----------------------------------------------------------------------------
#define DEFINE_CALLBACK_MANAGER(NAME, TYPE) \
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, NullMutex)
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, NullMutex)
#define DEFINE_CONCURRENT_CALLBACK_MANAGER(NAME, TYPE) \
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, RecursiveMutex)
DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, TYPE, RecursiveMutex)
#define DEFINE_CALLBACK_MANAGER_INTERNAL(NAME, CALLBACK_TYPE, MUTEX_TYPE) \
struct NAME##CallbackTraits: public CallbackTraits<NAME##CallbackTraits, CALLBACK_TYPE, MUTEX_TYPE> {};
struct NAME##CallbackTraits: public CallbackTraits<NAME##CallbackTraits, CALLBACK_TYPE, MUTEX_TYPE> {};
#define CALLBACK_MANAGER(NAME) \
CallbackManager<NAME##CallbackTraits>
CallbackManager<NAME##CallbackTraits>
//-----------------------------------------------------------------------------
// CallbackTraits

Просмотреть файл

@ -63,5 +63,5 @@
#pragma once
#define CLEARSCRIPT_VERSION_STRING "5.3.9.0"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,3,9,0
#define CLEARSCRIPT_VERSION_STRING "5.3.10.0"
#define CLEARSCRIPT_VERSION_COMMA_SEPARATED 5,3,10,0

Просмотреть файл

@ -105,7 +105,7 @@ namespace Microsoft.ClearScript
return result;
}
if ((type == typeof(void)) || (type == typeof(object)))
if ((type == typeof(void)) || (type == typeof(object)) || type.IsNullable())
{
return result;
}

Просмотреть файл

@ -73,5 +73,5 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("ClearScriptTest")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.3.9.0")]
[assembly: AssemblyFileVersion("5.3.9.0")]
[assembly: AssemblyVersion("5.3.10.0")]
[assembly: AssemblyFileVersion("5.3.10.0")]

Просмотреть файл

@ -119,6 +119,17 @@ namespace Microsoft.ClearScript
/// </remarks>
public Type AccessContext { get; set; }
/// <summary>
/// Enables or disables script code formatting.
/// </summary>
/// <remarks>
/// When this property is set to <c>true</c>, the script engine may format script code
/// before executing or compiling it. This is intended to facilitate interactive debugging.
/// The formatting operation currently includes stripping leading and trailing blank lines
/// and removing global indentation.
/// </remarks>
public bool FormatCode { get; set; }
/// <summary>
/// Gets or sets a value that controls whether script code is permitted to use reflection.
/// </summary>
@ -648,6 +659,16 @@ namespace Microsoft.ClearScript
return Evaluate(documentName, discard, code, true);
}
/// <summary>
/// Gets a string representation of the script call stack.
/// </summary>
/// <returns>The script call stack formatted as a string.</returns>
/// <remarks>
/// This method returns an empty string if the script engine is not executing script code.
/// The stack trace text format is defined by the script engine.
/// </remarks>
public abstract string GetStackTrace();
/// <summary>
/// Interrupts script execution and causes the script engine to throw an exception.
/// </summary>

Просмотреть файл

@ -153,8 +153,18 @@ namespace Microsoft.ClearScript.Util
return false;
}
public static bool IsNullable(this Type type)
{
return type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>));
}
public static bool IsAssignableFrom(this Type type, ref object value)
{
if (type.IsNullable())
{
return (value == null) || (Nullable.GetUnderlyingType(type).IsAssignableFrom(ref value));
}
if (value == null)
{
return !type.IsValueType;

Просмотреть файл

@ -22,13 +22,17 @@
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)'=='12.0'">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)'=='11.0'">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

Просмотреть файл

@ -22,13 +22,17 @@
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)'=='12.0'">
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(VisualStudioVersion)'=='11.0'">
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

Просмотреть файл

@ -68,6 +68,7 @@
#include <algorithm>
#include <functional>
#include <string>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@ -113,3 +114,16 @@ using namespace std;
#ifndef DECLSPEC_NORETURN
#define DECLSPEC_NORETURN __declspec(noreturn)
#endif // !DECLSPEC_NORETURN
//-----------------------------------------------------------------------------
#define BEGIN_COMPOUND_MACRO \
do \
{
#define END_COMPOUND_MACRO \
__pragma(warning(push)) \
__pragma(warning(disable:4127)) \
} \
while (false) \
__pragma(warning(pop))

Просмотреть файл

@ -220,7 +220,7 @@ V8Value HostObjectHelpers::Invoke(void* pvObject, const vector<V8Value>& args, b
{
try
{
auto argCount = (int)args.size();
auto argCount = static_cast<int>(args.size());
auto exportedArgs = gcnew array<Object^>(argCount);
for (auto index = 0; index < argCount; index++)
@ -242,7 +242,7 @@ V8Value HostObjectHelpers::InvokeMethod(void* pvObject, const wchar_t* pName, co
{
try
{
auto argCount = (int)args.size();
auto argCount = static_cast<int>(args.size());
auto exportedArgs = gcnew array<Object^>(argCount);
for (auto index = 0; index < argCount; index++)

Просмотреть файл

@ -94,9 +94,9 @@ using namespace Microsoft::ClearScript::Util;
//-----------------------------------------------------------------------------
#define BEGIN_LOCK_SCOPE(OBJECT) \
{ \
msclr::lock t_Lock(OBJECT);
{ \
msclr::lock t_Lock(OBJECT);
#define END_LOCK_SCOPE \
IGNORE_UNUSED(t_Lock); \
}
IGNORE_UNUSED(t_Lock); \
}

Просмотреть файл

@ -153,9 +153,9 @@ private:
//-----------------------------------------------------------------------------
#define BEGIN_MUTEX_SCOPE(MUTEX) \
{ \
MutexLock<decltype(MUTEX)> t_MutexLock(MUTEX);
{ \
MutexLock<decltype(MUTEX)> t_MutexLock(MUTEX);
#define END_MUTEX_SCOPE \
IGNORE_UNUSED(t_MutexLock); \
}
IGNORE_UNUSED(t_MutexLock); \
}

Просмотреть файл

@ -120,12 +120,12 @@ private:
//-----------------------------------------------------------------------------
#define BEGIN_ADDREF_SCOPE \
{ \
AddRefScope t_AddRefScope(GetRefCount());
{ \
AddRefScope t_AddRefScope(GetRefCount());
#define END_ADDREF_SCOPE \
IGNORE_UNUSED(t_AddRefScope); \
}
IGNORE_UNUSED(t_AddRefScope); \
}
//-----------------------------------------------------------------------------
// SharedPtr

Просмотреть файл

@ -71,6 +71,9 @@ public:
static V8Context* Create(const SharedPtr<V8Isolate>& spIsolate, const wchar_t* pName, bool enableDebugging, bool disableGlobalMembers, int debugPort);
virtual size_t GetMaxIsolateStackUsage() = 0;
virtual void SetMaxIsolateStackUsage(size_t value) = 0;
typedef void LockCallbackT(void* pvArg);
virtual void CallWithLock(LockCallbackT* pCallback, void* pvArg) = 0;

Просмотреть файл

@ -152,50 +152,50 @@ static void* UnwrapHostObject(const FunctionCallbackInfo<T>& args)
//-----------------------------------------------------------------------------
#define BEGIN_ISOLATE_SCOPE \
{ \
V8IsolateImpl::Scope t_IsolateScope(m_spIsolateImpl);
{ \
V8IsolateImpl::Scope t_IsolateScope(m_spIsolateImpl);
#define END_ISOLATE_SCOPE \
IGNORE_UNUSED(t_IsolateScope); \
}
IGNORE_UNUSED(t_IsolateScope); \
}
#define BEGIN_CONTEXT_SCOPE \
{ \
Scope t_ContextScope(this);
{ \
Scope t_ContextScope(this);
#define END_CONTEXT_SCOPE \
IGNORE_UNUSED(t_ContextScope); \
}
IGNORE_UNUSED(t_ContextScope); \
}
#define BEGIN_CONTEXT_SCOPE_NOTHROW \
{ \
Context::Scope t_ContextScopeNoThrow(m_hContext);
{ \
Context::Scope t_ContextScopeNoThrow(m_hContext);
#define END_CONTEXT_SCOPE_NOTHROW \
IGNORE_UNUSED(t_ContextScopeNoThrow); \
}
IGNORE_UNUSED(t_ContextScopeNoThrow); \
}
#define BEGIN_VERIFY_SCOPE \
{ \
TryCatch t_TryCatch;
#define BEGIN_EXECUTION_SCOPE \
{ \
V8IsolateImpl::ExecutionScope t_IsolateExecutionScope(m_spIsolateImpl); \
TryCatch t_TryCatch;
#define END_VERIFY_SCOPE \
IGNORE_UNUSED(t_TryCatch); \
}
#define END_EXECUTION_SCOPE \
IGNORE_UNUSED(t_TryCatch); \
IGNORE_UNUSED(t_IsolateExecutionScope); \
}
#define VERIFY(RESULT) \
Verify(t_TryCatch, RESULT)
Verify(t_TryCatch, RESULT)
#define VERIFY_CHECKPOINT() \
Verify(t_TryCatch)
Verify(t_TryCatch)
#define CALLBACK_RETURN(RESULT) \
do \
{ \
info.GetReturnValue().Set(RESULT); \
return; \
} \
while (false)
BEGIN_COMPOUND_MACRO \
info.GetReturnValue().Set(RESULT); \
return; \
END_COMPOUND_MACRO
//-----------------------------------------------------------------------------
@ -255,6 +255,20 @@ V8ContextImpl::V8ContextImpl(V8IsolateImpl* pIsolateImpl, const wchar_t* pName,
//-----------------------------------------------------------------------------
size_t V8ContextImpl::GetMaxIsolateStackUsage()
{
return m_spIsolateImpl->GetMaxStackUsage();
}
//-----------------------------------------------------------------------------
void V8ContextImpl::SetMaxIsolateStackUsage(size_t value)
{
m_spIsolateImpl->SetMaxStackUsage(value);
}
//-----------------------------------------------------------------------------
void V8ContextImpl::CallWithLock(LockCallbackT* pCallback, void* pvArg)
{
VerifyNotOutOfMemory();
@ -298,12 +312,12 @@ void V8ContextImpl::SetGlobalProperty(const wchar_t* pName, const V8Value& value
V8Value V8ContextImpl::Execute(const wchar_t* pDocumentName, const wchar_t* pCode, bool /* discard */)
{
BEGIN_CONTEXT_SCOPE
BEGIN_VERIFY_SCOPE
BEGIN_EXECUTION_SCOPE
auto hScript = VERIFY(Script::Compile(String::New(pCode), String::New(pDocumentName)));
return ExportValue(VERIFY(hScript->Run()));
END_VERIFY_SCOPE
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -312,12 +326,12 @@ V8Value V8ContextImpl::Execute(const wchar_t* pDocumentName, const wchar_t* pCod
V8ScriptHolder* V8ContextImpl::Compile(const wchar_t* pDocumentName, const wchar_t* pCode)
{
BEGIN_CONTEXT_SCOPE
BEGIN_VERIFY_SCOPE
BEGIN_EXECUTION_SCOPE
auto hScript = VERIFY(Script::New(String::New(pCode), String::New(pDocumentName)));
return new V8ScriptHolderImpl(m_spIsolateImpl, ::PtrFromScriptHandle(CreatePersistent(hScript)));
END_VERIFY_SCOPE
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -333,12 +347,12 @@ bool V8ContextImpl::CanExecute(V8ScriptHolder* pHolder)
V8Value V8ContextImpl::Execute(V8ScriptHolder* pHolder)
{
BEGIN_CONTEXT_SCOPE
BEGIN_VERIFY_SCOPE
BEGIN_EXECUTION_SCOPE
auto hScript = ::ScriptHandleFromPtr(pHolder->GetScript());
return ExportValue(VERIFY(hScript->Run()));
END_VERIFY_SCOPE
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -390,9 +404,11 @@ void V8ContextImpl::ReleaseV8Object(void* pvObject)
V8Value V8ContextImpl::GetV8ObjectProperty(void* pvObject, const wchar_t* pName)
{
BEGIN_CONTEXT_SCOPE
BEGIN_EXECUTION_SCOPE
return ExportValue(::ObjectHandleFromPtr(pvObject)->Get(String::New(pName)));
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -401,9 +417,11 @@ V8Value V8ContextImpl::GetV8ObjectProperty(void* pvObject, const wchar_t* pName)
void V8ContextImpl::SetV8ObjectProperty(void* pvObject, const wchar_t* pName, const V8Value& value)
{
BEGIN_CONTEXT_SCOPE
BEGIN_EXECUTION_SCOPE
::ObjectHandleFromPtr(pvObject)->Set(String::New(pName), ImportValue(value));
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -434,9 +452,11 @@ void V8ContextImpl::GetV8ObjectPropertyNames(void* pvObject, vector<wstring>& na
V8Value V8ContextImpl::GetV8ObjectProperty(void* pvObject, int index)
{
BEGIN_CONTEXT_SCOPE
BEGIN_EXECUTION_SCOPE
return ExportValue(::ObjectHandleFromPtr(pvObject)->Get(index));
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -445,9 +465,11 @@ V8Value V8ContextImpl::GetV8ObjectProperty(void* pvObject, int index)
void V8ContextImpl::SetV8ObjectProperty(void* pvObject, int index, const V8Value& value)
{
BEGIN_CONTEXT_SCOPE
BEGIN_EXECUTION_SCOPE
::ObjectHandleFromPtr(pvObject)->Set(index, ImportValue(value));
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -478,7 +500,7 @@ void V8ContextImpl::GetV8ObjectPropertyIndices(void* pvObject, vector<int>& indi
V8Value V8ContextImpl::InvokeV8Object(void* pvObject, const vector<V8Value>& args, bool asConstructor)
{
BEGIN_CONTEXT_SCOPE
BEGIN_VERIFY_SCOPE
BEGIN_EXECUTION_SCOPE
auto hObject = ::ObjectHandleFromPtr(pvObject);
@ -487,12 +509,12 @@ V8Value V8ContextImpl::InvokeV8Object(void* pvObject, const vector<V8Value>& arg
if (asConstructor)
{
return ExportValue(VERIFY(hObject->CallAsConstructor((int)importedArgs.size(), importedArgs.data())));
return ExportValue(VERIFY(hObject->CallAsConstructor(static_cast<int>(importedArgs.size()), importedArgs.data())));
}
return ExportValue(VERIFY(hObject->CallAsFunction(hObject, (int)importedArgs.size(), importedArgs.data())));
return ExportValue(VERIFY(hObject->CallAsFunction(hObject, static_cast<int>(importedArgs.size()), importedArgs.data())));
END_VERIFY_SCOPE
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -501,7 +523,7 @@ V8Value V8ContextImpl::InvokeV8Object(void* pvObject, const vector<V8Value>& arg
V8Value V8ContextImpl::InvokeV8ObjectMethod(void* pvObject, const wchar_t* pName, const vector<V8Value>& args)
{
BEGIN_CONTEXT_SCOPE
BEGIN_VERIFY_SCOPE
BEGIN_EXECUTION_SCOPE
auto hObject = ::ObjectHandleFromPtr(pvObject);
@ -523,9 +545,9 @@ V8Value V8ContextImpl::InvokeV8ObjectMethod(void* pvObject, const wchar_t* pName
ImportValues(args, importedArgs);
auto hMethod = VERIFY(hValue->ToObject());
return ExportValue(VERIFY(hMethod->CallAsFunction(hObject, (int)importedArgs.size(), importedArgs.data())));
return ExportValue(VERIFY(hMethod->CallAsFunction(hObject, static_cast<int>(importedArgs.size()), importedArgs.data())));
END_VERIFY_SCOPE
END_EXECUTION_SCOPE
END_CONTEXT_SCOPE
}
@ -608,7 +630,7 @@ void V8ContextImpl::GetV8ObjectPropertyNames(Handle<Object> hObject, vector<wstr
auto hNames = hObject->GetPropertyNames();
if (!hNames.IsEmpty())
{
auto nameCount = (int)hNames->Length();
auto nameCount = static_cast<int>(hNames->Length());
names.reserve(nameCount);
for (auto index = 0; index < nameCount; index++)
@ -616,7 +638,7 @@ void V8ContextImpl::GetV8ObjectPropertyNames(Handle<Object> hObject, vector<wstr
auto hName = hNames->Get(index);
if (!hName.IsEmpty())
{
wstring name(*String::Value(hName->ToString()));
wstring name(*String::Value(hName));
int propertyIndex;
if (!HostObjectHelpers::TryParseInt32(name.c_str(), propertyIndex))
@ -637,7 +659,7 @@ void V8ContextImpl::GetV8ObjectPropertyIndices(Handle<Object> hObject, vector<in
auto hNames = hObject->GetPropertyNames();
if (!hNames.IsEmpty())
{
auto nameCount = (int)hNames->Length();
auto nameCount = static_cast<int>(hNames->Length());
indices.reserve(nameCount);
for (auto index = 0; index < nameCount; index++)
@ -645,7 +667,7 @@ void V8ContextImpl::GetV8ObjectPropertyIndices(Handle<Object> hObject, vector<in
auto hName = hNames->Get(index);
if (!hName.IsEmpty())
{
wstring name(*String::Value(hName->ToString()));
wstring name(*String::Value(hName));
int propertyIndex;
if (HostObjectHelpers::TryParseInt32(name.c_str(), propertyIndex))
@ -716,7 +738,7 @@ void V8ContextImpl::QueryGlobalProperty(Local<String> hName, const PropertyCallb
if (pContextImpl != nullptr)
{
const vector<Persistent<Object>>& stack = pContextImpl->m_GlobalMembersStack;
if (stack.size() > 0)
if ((stack.size() > 0) && !hName->Equals(pContextImpl->m_hHostObjectCookieName))
{
for (auto it = stack.rbegin(); it != stack.rend(); it++)
{
@ -802,7 +824,7 @@ void V8ContextImpl::GetGlobalPropertyNames(const PropertyCallbackInfo<Array>& in
sort(names.begin(), names.end());
auto newEnd = unique(names.begin(), names.end());
auto nameCount = (int)(newEnd - names.begin());
auto nameCount = static_cast<int>(newEnd - names.begin());
auto hImportedNames = Array::New(nameCount);
for (auto index = 0; index < nameCount; index++)
@ -951,7 +973,7 @@ void V8ContextImpl::GetGlobalPropertyIndices(const PropertyCallbackInfo<Array>&
sort(indices.begin(), indices.end());
auto newEnd = unique(indices.begin(), indices.end());
auto indexCount = (int)(newEnd - indices.begin());
auto indexCount = static_cast<int>(newEnd - indices.begin());
auto hImportedIndices = Array::New(indexCount);
for (auto index = 0; index < indexCount; index++)
@ -1064,7 +1086,7 @@ void V8ContextImpl::GetHostObjectPropertyNames(const PropertyCallbackInfo<Array>
{
vector<wstring> names;
HostObjectHelpers::GetPropertyNames(::UnwrapHostObject(info), names);
auto nameCount = (int)names.size();
auto nameCount = static_cast<int>(names.size());
auto hImportedNames = Array::New(nameCount);
for (auto index = 0; index < nameCount; index++)
@ -1126,7 +1148,7 @@ void V8ContextImpl::QueryHostObjectProperty(unsigned __int32 index, const Proper
for (auto it = indices.begin(); it < indices.end(); it++)
{
if (*it == (int)index)
if (*it == static_cast<int>(index))
{
CALLBACK_RETURN(None);
}
@ -1164,7 +1186,7 @@ void V8ContextImpl::GetHostObjectPropertyIndices(const PropertyCallbackInfo<Arra
{
vector<int> indices;
HostObjectHelpers::GetPropertyIndices(::UnwrapHostObject(info), indices);
auto indexCount = (int)indices.size();
auto indexCount = static_cast<int>(indices.size());
auto hImportedIndices = Array::New(indexCount);
for (auto index = 0; index < indexCount; index++)
@ -1378,7 +1400,7 @@ void V8ContextImpl::ImportValues(const vector<V8Value>& values, vector<Handle<Va
{
importedValues.clear();
auto valueCount = (int)values.size();
auto valueCount = static_cast<int>(values.size());
importedValues.reserve(valueCount);
for (auto index = 0; index < valueCount; index++)
@ -1399,128 +1421,169 @@ void V8ContextImpl::Verify(const TryCatch& tryCatch)
}
auto hException = tryCatch.Exception();
wstring message = *String::Value(hException);
wstring stackTrace;
auto hStackTrace = tryCatch.StackTrace();
if (!hStackTrace.IsEmpty())
wstring message;
bool stackOverflow;
String::Value value(hException);
if (value.length() > 0)
{
stackTrace = *String::Value(hStackTrace);
message = *value;
stackOverflow = (_wcsicmp(message.c_str(), L"RangeError: Maximum call stack size exceeded") == 0);
}
else
{
// It is unclear why V8 sometimes generates blank exceptions, although it probably has
// to do with memory pressure. It seems to happen only during stack overflow recovery.
message = L"Unknown error; potential stack overflow detected";
stackOverflow = true;
}
auto hMessage = tryCatch.Message();
if (!hMessage.IsEmpty())
#ifdef _DEBUG
if (stackOverflow)
{
if (message.length() < 1)
// Stack overflow conditions require extreme care, as V8's behavior can be erratic
// until the stack is unwound a bit. Much of the code below can trigger unexpected
// fatal errors in this context, so it makes sense to bypass it. On the other hand,
// losing error information is also undesirable, and the detection code above is far
// from robust. These sanity checks are intended to mitigate this fragility.
_ASSERTE(hException->IsObject());
_ASSERTE(wstring(*String::Value(hException->ToObject()->GetConstructorName())) == L"RangeError");
}
#endif // _DEBUG
wstring stackTrace;
V8Value innerException(V8Value::Undefined);
if (stackOverflow)
{
stackTrace = message;
}
else
{
auto hStackTrace = tryCatch.StackTrace();
if (!hStackTrace.IsEmpty())
{
message = *String::Value(hMessage->Get());
stackTrace = *String::Value(hStackTrace);
}
stackTrace = message;
auto hStackTrace = hMessage->GetStackTrace();
int frameCount = !hStackTrace.IsEmpty() ? hStackTrace->GetFrameCount() : 0;
if (frameCount < 1)
auto hMessage = tryCatch.Message();
if (!hMessage.IsEmpty())
{
auto hScriptResourceName = hMessage->GetScriptResourceName();
if (!hScriptResourceName.IsEmpty() && !hScriptResourceName->IsNull() && !hScriptResourceName->IsUndefined())
if (message.length() < 1)
{
auto hScriptName = hScriptResourceName->ToString();
if (!hScriptName.IsEmpty() && (hScriptName->Length() > 0))
message = *String::Value(hMessage->Get());
}
stackTrace = message;
auto hStackTrace = hMessage->GetStackTrace();
int frameCount = !hStackTrace.IsEmpty() ? hStackTrace->GetFrameCount() : 0;
if (frameCount < 1)
{
auto hScriptResourceName = hMessage->GetScriptResourceName();
if (!hScriptResourceName.IsEmpty() && !hScriptResourceName->IsNull() && !hScriptResourceName->IsUndefined())
{
stackTrace += L"\n at ";
stackTrace += *String::Value(hScriptName);
auto hScriptName = hScriptResourceName->ToString();
if (!hScriptName.IsEmpty() && (hScriptName->Length() > 0))
{
stackTrace += L"\n at ";
stackTrace += *String::Value(hScriptName);
}
else
{
stackTrace += L"\n at <anonymous>";
}
}
else
{
stackTrace += L"\n at <anonymous>";
}
stackTrace += L':';
stackTrace += to_wstring(hMessage->GetLineNumber());
stackTrace += L':';
stackTrace += to_wstring(hMessage->GetStartColumn() + 1);
auto hSourceLine = hMessage->GetSourceLine();
if (!hSourceLine.IsEmpty() && (hSourceLine->Length() > 0))
{
stackTrace += L" -> ";
stackTrace += *String::Value(hSourceLine);
}
}
else
{
stackTrace += L"\n at <anonymous>";
}
for (int index = 0; index < frameCount; index++)
{
auto hFrame = hStackTrace->GetFrame(index);
stackTrace += L"\n at ";
stackTrace += L':';
stackTrace += to_wstring(hMessage->GetLineNumber());
stackTrace += L':';
stackTrace += to_wstring(hMessage->GetStartColumn() + 1);
auto hFunctionName = hFrame->GetFunctionName();
if (!hFunctionName.IsEmpty() && (hFunctionName->Length() > 0))
{
if (hFrame->IsConstructor())
{
stackTrace += L"new ";
}
auto hSourceLine = hMessage->GetSourceLine();
if (!hSourceLine.IsEmpty() && (hSourceLine->Length() > 0))
{
stackTrace += L" -> ";
stackTrace += *String::Value(hSourceLine);
stackTrace += *String::Value(hFunctionName);
stackTrace += L" (";
}
auto hScriptName = hFrame->GetScriptName();
if (!hScriptName.IsEmpty() && (hScriptName->Length() > 0))
{
stackTrace += *String::Value(hScriptName);
}
else
{
stackTrace += L"<anonymous>";
}
stackTrace += L':';
auto lineNumber = hFrame->GetLineNumber();
if (lineNumber != Message::kNoLineNumberInfo)
{
stackTrace += to_wstring(lineNumber);
}
stackTrace += L':';
auto column = hFrame->GetColumn();
if (column != Message::kNoColumnInfo)
{
stackTrace += to_wstring(column);
}
if (!hFunctionName.IsEmpty() && (hFunctionName->Length() > 0))
{
stackTrace += L')';
}
if (index == 0)
{
auto hSourceLine = hMessage->GetSourceLine();
if (!hSourceLine.IsEmpty() && (hSourceLine->Length() > 0))
{
stackTrace += L" -> ";
stackTrace += *String::Value(hSourceLine);
}
}
}
}
}
else
if (hException->IsObject())
{
for (int index = 0; index < frameCount; index++)
{
auto hFrame = hStackTrace->GetFrame(index);
stackTrace += L"\n at ";
auto hFunctionName = hFrame->GetFunctionName();
if (!hFunctionName.IsEmpty() && (hFunctionName->Length() > 0))
{
if (hFrame->IsConstructor())
{
stackTrace += L"new ";
}
stackTrace += *String::Value(hFunctionName);
stackTrace += L" (";
}
auto hScriptName = hFrame->GetScriptName();
if (!hScriptName.IsEmpty() && (hScriptName->Length() > 0))
{
stackTrace += *String::Value(hScriptName);
}
else
{
stackTrace += L"<anonymous>";
}
stackTrace += L':';
auto lineNumber = hFrame->GetLineNumber();
if (lineNumber != Message::kNoLineNumberInfo)
{
stackTrace += to_wstring(lineNumber);
}
stackTrace += L':';
auto column = hFrame->GetColumn();
if (column != Message::kNoColumnInfo)
{
stackTrace += to_wstring(column);
}
if (!hFunctionName.IsEmpty() && (hFunctionName->Length() > 0))
{
stackTrace += L')';
}
if (index == 0)
{
auto hSourceLine = hMessage->GetSourceLine();
if (!hSourceLine.IsEmpty() && (hSourceLine->Length() > 0))
{
stackTrace += L" -> ";
stackTrace += *String::Value(hSourceLine);
}
}
}
innerException = ExportValue(hException->ToObject()->Get(m_hInnerExceptionName));
}
}
V8Value innerException(V8Value::Undefined);
if (hException->IsObject())
{
innerException = ExportValue(hException->ToObject()->Get(m_hInnerExceptionName));
}
throw V8Exception(V8Exception::Type_General, m_Name.c_str(), message.c_str(), stackTrace.c_str(), innerException);
}
}

Просмотреть файл

@ -73,6 +73,9 @@ public:
V8ContextImpl(V8IsolateImpl* pIsolateImpl, const wchar_t* pName, bool enableDebugging, bool disableGlobalMembers, int debugPort);
size_t GetMaxIsolateStackUsage();
void SetMaxIsolateStackUsage(size_t value);
void CallWithLock(LockCallbackT* pCallback, void* pvArg);
V8Value GetRootObject();
void SetGlobalProperty(const wchar_t* pName, const V8Value& value, bool globalMembers);

Просмотреть файл

@ -94,6 +94,20 @@ namespace V8 {
//-------------------------------------------------------------------------
UIntPtr V8ContextProxyImpl::MaxRuntimeStackUsage::get()
{
return (UIntPtr)GetContext()->GetMaxIsolateStackUsage();
}
//-------------------------------------------------------------------------
void V8ContextProxyImpl::MaxRuntimeStackUsage::set(UIntPtr value)
{
GetContext()->SetMaxIsolateStackUsage(static_cast<size_t>(value));
}
//-------------------------------------------------------------------------
void V8ContextProxyImpl::InvokeWithLock(Action^ gcAction)
{
try

Просмотреть файл

@ -75,6 +75,12 @@ namespace V8 {
V8ContextProxyImpl(V8IsolateProxy^ gcIsolateProxy, String^ gcName, Boolean enableDebugging, Boolean disableGlobalMembers, Int32 debugPort);
property UIntPtr MaxRuntimeStackUsage
{
virtual UIntPtr get() override;
virtual void set(UIntPtr value) override;
}
virtual void InvokeWithLock(Action^ gcAction) override;
virtual Object^ GetRootItem() override;
virtual void AddGlobalItem(String^ gcName, Object^ gcItem, Boolean globalMembers) override;

Просмотреть файл

@ -71,6 +71,9 @@ public:
static V8Isolate* Create(const wchar_t* pName, const V8IsolateConstraints* pConstraints, bool enableDebugging, int debugPort);
virtual size_t GetMaxStackUsage() = 0;
virtual void SetMaxStackUsage(size_t value) = 0;
virtual V8ScriptHolder* Compile(const wchar_t* pDocumentName, const wchar_t* pCode) = 0;
virtual void GetHeapInfo(V8IsolateHeapInfo& heapInfo) = 0;
virtual void CollectGarbage(bool exhaustive) = 0;

Просмотреть файл

@ -82,20 +82,20 @@ static Persistent<Script> ScriptHandleFromPtr(void* pvScript)
//-----------------------------------------------------------------------------
#define BEGIN_ISOLATE_ENTRY_SCOPE \
{ \
Isolate::Scope t_IsolateEntryScope(m_pIsolate);
{ \
Isolate::Scope t_IsolateEntryScope(m_pIsolate);
#define END_ISOLATE_ENTRY_SCOPE \
IGNORE_UNUSED(t_IsolateEntryScope); \
}
IGNORE_UNUSED(t_IsolateEntryScope); \
}
#define BEGIN_ISOLATE_SCOPE \
{ \
Scope t_IsolateScope(this);
{ \
Scope t_IsolateScope(this);
#define END_ISOLATE_SCOPE \
IGNORE_UNUSED(t_IsolateScope); \
}
IGNORE_UNUSED(t_IsolateScope); \
}
//-----------------------------------------------------------------------------
@ -103,10 +103,18 @@ DEFINE_CONCURRENT_CALLBACK_MANAGER(DebugMessageDispatcher, void())
//-----------------------------------------------------------------------------
V8IsolateImpl::V8IsolateImpl(const wchar_t* pName, const V8IsolateConstraints* pConstraints, bool enableDebugging, int debugPort):
static const size_t s_StackBreathingRoom = static_cast<size_t>(16 * 1024);
static size_t* const s_pMinStackLimit = reinterpret_cast<size_t*>(sizeof(size_t));
//-----------------------------------------------------------------------------
V8IsolateImpl::V8IsolateImpl(const wchar_t* pName, const V8IsolateConstraints* pConstraints, bool enableDebugging, int debugPort) :
m_pIsolate(Isolate::New()),
m_DebuggingEnabled(false),
m_DebugMessageDispatchCount(0),
m_MaxStackUsage(0),
m_ExecutionLevel(0),
m_pStackLimit(nullptr),
m_IsOutOfMemory(false)
{
BEGIN_ADDREF_SCOPE
@ -126,7 +134,7 @@ V8IsolateImpl::V8IsolateImpl(const wchar_t* pName, const V8IsolateConstraints* p
constraints.set_max_young_space_size(pConstraints->GetMaxYoungSpaceSize());
constraints.set_max_old_space_size(pConstraints->GetMaxOldSpaceSize());
constraints.set_max_executable_size(pConstraints->GetMaxExecutableSize());
ASSERT_EVAL(SetResourceConstraints(&constraints));
ASSERT_EVAL(SetResourceConstraints(m_pIsolate, &constraints));
}
END_ISOLATE_ENTRY_SCOPE
@ -232,6 +240,20 @@ void V8IsolateImpl::DisableDebugging()
//-----------------------------------------------------------------------------
size_t V8IsolateImpl::GetMaxStackUsage()
{
return m_MaxStackUsage;
}
//-----------------------------------------------------------------------------
void V8IsolateImpl::SetMaxStackUsage(size_t value)
{
m_MaxStackUsage = value;
}
//-----------------------------------------------------------------------------
V8ScriptHolder* V8IsolateImpl::Compile(const wchar_t* pDocumentName, const wchar_t* pCode)
{
BEGIN_ISOLATE_SCOPE
@ -348,3 +370,72 @@ void V8IsolateImpl::ProcessDebugMessages()
END_ISOLATE_SCOPE
}
//-----------------------------------------------------------------------------
void V8IsolateImpl::EnterExecutionScope(size_t* pStackMarker)
{
_ASSERTE(m_pIsolate == Isolate::GetCurrent());
_ASSERTE(Locker::IsLocked(m_pIsolate));
if (m_ExecutionLevel == 0)
{
// entering top-level execution scope
_ASSERTE(m_pStackLimit == nullptr);
// is a stack usage limit specified?
size_t maxStackUsage = m_MaxStackUsage;
if (maxStackUsage > 0)
{
// yes; ensure minimum breathing room
maxStackUsage = max(maxStackUsage, s_StackBreathingRoom);
// calculate stack address limit
size_t* pStackLimit = pStackMarker - (maxStackUsage / sizeof(size_t));
if ((pStackLimit < s_pMinStackLimit) || (pStackLimit > pStackMarker))
{
// underflow; use minimum non-null stack address
pStackLimit = s_pMinStackLimit;
}
else
{
// check stack address limit sanity
_ASSERTE((pStackMarker - pStackLimit) >= (s_StackBreathingRoom / sizeof(size_t)));
}
// set and record stack address limit
ResourceConstraints constraints;
constraints.set_stack_limit(reinterpret_cast<uint32_t*>(pStackLimit));
ASSERT_EVAL(SetResourceConstraints(m_pIsolate, &constraints));
m_pStackLimit = pStackLimit;
}
}
else if ((m_pStackLimit != nullptr) && (pStackMarker < m_pStackLimit))
{
// stack usage limit exceeded (host-side detection)
throw V8Exception(V8Exception::Type_General, m_Name.c_str(), L"The V8 runtime has exceeded its stack usage limit", nullptr, V8Value(V8Value::Undefined));
}
m_ExecutionLevel++;
}
//-----------------------------------------------------------------------------
void V8IsolateImpl::ExitExecutionScope()
{
_ASSERTE(m_pIsolate == Isolate::GetCurrent());
_ASSERTE(Locker::IsLocked(m_pIsolate));
if (--m_ExecutionLevel == 0)
{
// exiting top-level execution scope
if (m_pStackLimit != nullptr)
{
// V8 has no API for removing a stack address limit
ResourceConstraints constraints;
constraints.set_stack_limit(reinterpret_cast<uint32_t*>(s_pMinStackLimit));
ASSERT_EVAL(SetResourceConstraints(m_pIsolate, &constraints));
m_pStackLimit = nullptr;
}
}
}

Просмотреть файл

@ -98,6 +98,29 @@ public:
HandleScope m_HandleScope;
};
class ExecutionScope
{
PROHIBIT_COPY(ExecutionScope)
PROHIBIT_HEAP(ExecutionScope)
public:
explicit ExecutionScope(V8IsolateImpl* pIsolateImpl):
m_pIsolateImpl(pIsolateImpl)
{
m_pIsolateImpl->EnterExecutionScope(reinterpret_cast<size_t*>(&pIsolateImpl));
}
~ExecutionScope()
{
m_pIsolateImpl->ExitExecutionScope();
}
private:
V8IsolateImpl* m_pIsolateImpl;
};
V8IsolateImpl(const wchar_t* pName, const V8IsolateConstraints* pConstraints, bool enableDebugging, int debugPort);
Local<Context> CreateContext(ExtensionConfiguration* pExtensionConfiguation = nullptr, Handle<ObjectTemplate> hGlobalTemplate = Handle<ObjectTemplate>(), Handle<Value> hGlobalObject = Handle<Value>())
@ -187,6 +210,9 @@ public:
void EnableDebugging(int debugPort);
void DisableDebugging();
size_t GetMaxStackUsage();
void SetMaxStackUsage(size_t value);
V8ScriptHolder* Compile(const wchar_t* pDocumentName, const wchar_t* pCode);
void GetHeapInfo(V8IsolateHeapInfo& heapInfo);
void CollectGarbage(bool exhaustive);
@ -203,6 +229,9 @@ private:
void DispatchDebugMessages();
void ProcessDebugMessages();
void EnterExecutionScope(size_t* pStackMarker);
void ExitExecutionScope();
wstring m_Name;
Isolate* m_pIsolate;
list<V8ContextImpl*> m_ContextPtrs;
@ -212,5 +241,9 @@ private:
Debug::DebugMessageDispatchHandler m_pDebugMessageDispatcher;
atomic<size_t> m_DebugMessageDispatchCount;
atomic<size_t> m_MaxStackUsage;
size_t m_ExecutionLevel;
size_t* m_pStackLimit;
atomic<bool> m_IsOutOfMemory;
};

Просмотреть файл

@ -93,6 +93,20 @@ namespace V8 {
//-------------------------------------------------------------------------
UIntPtr V8IsolateProxyImpl::MaxStackUsage::get()
{
return (UIntPtr)GetIsolate()->GetMaxStackUsage();
}
//-------------------------------------------------------------------------
void V8IsolateProxyImpl::MaxStackUsage::set(UIntPtr value)
{
GetIsolate()->SetMaxStackUsage(static_cast<size_t>(value));
}
//-------------------------------------------------------------------------
V8Script^ V8IsolateProxyImpl::Compile(String^ gcDocumentName, String^ gcCode)
{
try

Просмотреть файл

@ -75,6 +75,12 @@ namespace V8 {
V8IsolateProxyImpl(String^ gcName, V8RuntimeConstraints^ gcConstraints, Boolean enableDebugging, Int32 debugPort);
property UIntPtr MaxStackUsage
{
virtual UIntPtr get() override;
virtual void set(UIntPtr value) override;
}
virtual V8Script^ Compile(String^ gcDocumentName, String^ gcCode) override;
virtual V8RuntimeHeapInfo^ GetHeapInfo() override;
virtual void CollectGarbage(bool exhaustive) override;

Просмотреть файл

@ -125,7 +125,7 @@ namespace V8 {
{
vector<wstring> names;
V8ObjectHelpers::GetPropertyNames(GetHolder(), names);
auto nameCount = (int)names.size();
auto nameCount = static_cast<int>(names.size());
auto gcNames = gcnew array<String^>(nameCount);
for (auto index = 0; index < nameCount; index++)
@ -191,7 +191,7 @@ namespace V8 {
{
vector<int> indices;
V8ObjectHelpers::GetPropertyIndices(GetHolder(), indices);
auto indexCount = (int)indices.size();
auto indexCount = static_cast<int>(indices.size());
auto gcIndices = gcnew array<int>(indexCount);
for (auto index = 0; index < indexCount; index++)

Просмотреть файл

@ -1,6 +1,6 @@
Index: src/utils.h
===================================================================
--- src/utils.h (revision 17421)
--- src/utils.h (revision 18109)
+++ src/utils.h (working copy)
@@ -109,7 +109,7 @@
// These are kind of 2's complement reciprocal of the divisors.
@ -13,9 +13,9 @@ Index: src/utils.h
// lithium-codegen-arm.cc : LCodeGen::TryEmitSignedIntegerDivisionByConstant().
Index: tools/gyp/v8.gyp
===================================================================
--- tools/gyp/v8.gyp (revision 17421)
--- tools/gyp/v8.gyp (revision 18109)
+++ tools/gyp/v8.gyp (working copy)
@@ -33,6 +33,7 @@
@@ -34,6 +34,7 @@
'targets': [
{
'target_name': 'v8',

Просмотреть файл

@ -70,6 +70,8 @@ namespace Microsoft.ClearScript.V8
return CreateImpl<V8ContextProxy>(isolateProxy, name, enableDebugging, disableGlobalMembers, debugPort);
}
public abstract UIntPtr MaxRuntimeStackUsage { get; set; }
public abstract void InvokeWithLock(Action action);
public abstract object GetRootItem();

Просмотреть файл

@ -59,6 +59,8 @@
// fitness for a particular purpose and non-infringement.
//
using System;
namespace Microsoft.ClearScript.V8
{
internal abstract class V8IsolateProxy : V8Proxy
@ -68,6 +70,8 @@ namespace Microsoft.ClearScript.V8
return CreateImpl<V8IsolateProxy>(name, constraints, enableDebugging, debugPort);
}
public abstract UIntPtr MaxStackUsage { get; set; }
public abstract V8Script Compile(string documentName, string code);
public abstract V8RuntimeHeapInfo GetHeapInfo();

Просмотреть файл

@ -216,6 +216,44 @@ namespace Microsoft.ClearScript.V8
get { return name; }
}
/// <summary>
/// Enables or disables script code formatting.
/// </summary>
/// <remarks>
/// When this property is set to <c>true</c>, the V8 runtime may format script code before
/// executing or compiling it. This is intended to facilitate interactive debugging. The
/// formatting operation currently includes stripping leading and trailing blank lines and
/// removing global indentation.
/// </remarks>
public bool FormatCode { get; set; }
/// <summary>
/// Gets or sets the maximum amount by which the stack is permitted to grow during script execution.
/// </summary>
/// <remarks>
/// This property is specified in bytes. When it is set to the default value, no stack
/// usage limit is enforced, and unchecked recursion or other stack usage may lead to
/// unrecoverable errors and process termination.
/// <para>
/// Note that the V8 runtime does not monitor stack usage while a host call is in progress.
/// Monitoring is resumed when control returns to the runtime.
/// </para>
/// </remarks>
public UIntPtr MaxStackUsage
{
get
{
VerifyNotDisposed();
return proxy.MaxStackUsage;
}
set
{
VerifyNotDisposed();
proxy.MaxStackUsage = value;
}
}
/// <summary>
/// Creates a new V8 script engine instance.
/// </summary>
@ -321,7 +359,7 @@ namespace Microsoft.ClearScript.V8
public V8ScriptEngine CreateScriptEngine(string engineName, V8ScriptEngineFlags flags, int debugPort)
{
VerifyNotDisposed();
return new V8ScriptEngine(this, engineName, null, flags, debugPort);
return new V8ScriptEngine(this, engineName, null, flags, debugPort) { FormatCode = FormatCode };
}
/// <summary>
@ -344,7 +382,7 @@ namespace Microsoft.ClearScript.V8
{
VerifyNotDisposed();
var uniqueName = name + ":" + documentNameManager.GetUniqueName(documentName, "Script Document");
return proxy.Compile(uniqueName, MiscHelpers.FormatCode(code));
return proxy.Compile(uniqueName, FormatCode ? MiscHelpers.FormatCode(code) : code);
}
/// <summary>

Просмотреть файл

@ -62,6 +62,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.ClearScript.Util;
using Microsoft.ClearScript.Windows;
@ -307,6 +308,16 @@ namespace Microsoft.ClearScript.V8
throw new Error('Function expected');
}
return method.apply(target, convertArgs(args));
},
getStackTrace: function () {
try {
throw new Error('[stack trace]');
}
catch (exception) {
return exception.stack;
}
return '';
}
};
})();
@ -321,6 +332,33 @@ namespace Microsoft.ClearScript.V8
#region public members
/// <summary>
/// Gets or sets the maximum amount by which the V8 runtime is permitted to grow the stack during script execution.
/// </summary>
/// <remarks>
/// This property is specified in bytes. When it is set to the default value, no stack
/// usage limit is enforced, and unchecked recursion or other stack usage may lead to
/// unrecoverable errors and process termination.
/// <para>
/// Note that the V8 runtime does not monitor stack usage while a host call is in progress.
/// Monitoring is resumed when control returns to the runtime.
/// </para>
/// </remarks>
public UIntPtr MaxRuntimeStackUsage
{
get
{
VerifyNotDisposed();
return proxy.MaxRuntimeStackUsage;
}
set
{
VerifyNotDisposed();
proxy.MaxRuntimeStackUsage = value;
}
}
/// <summary>
/// Creates a compiled script.
/// </summary>
@ -344,7 +382,7 @@ namespace Microsoft.ClearScript.V8
return ScriptInvoke(() =>
{
var uniqueName = documentNameManager.GetUniqueName(documentName, "Script Document");
return proxy.Compile(uniqueName, MiscHelpers.FormatCode(code));
return proxy.Compile(uniqueName, FormatCode ? MiscHelpers.FormatCode(code) : code);
});
}
@ -473,6 +511,21 @@ namespace Microsoft.ClearScript.V8
});
}
/// <summary>
/// Gets a string representation of the script call stack.
/// </summary>
/// <returns>The script call stack formatted as a string.</returns>
/// <remarks>
/// This method returns an empty string if the script engine is not executing script code.
/// The stack trace text format is defined by the script engine.
/// </remarks>
public override string GetStackTrace()
{
string stackTrace = Script.EngineInternal.getStackTrace();
var lines = stackTrace.Split('\n');
return string.Join("\n", lines.Skip(2));
}
/// <summary>
/// Interrupts script execution and causes the script engine to throw an exception.
/// </summary>
@ -630,7 +683,7 @@ namespace Microsoft.ClearScript.V8
stateObjects[0] = new WeakReference(this);
stateObjects[1] = timer;
timer.Change(continuationInterval, Timeout.Infinite);
return proxy.Execute(uniqueName, MiscHelpers.FormatCode(code), discard);
return proxy.Execute(uniqueName, FormatCode ? MiscHelpers.FormatCode(code) : code, discard);
}
});
}

Просмотреть файл

@ -88,7 +88,7 @@ namespace Microsoft.ClearScript.Windows
{
try
{
var stackTrace = GetStackTrace();
var stackTrace = engine.GetStackTraceInternal();
if (!string.IsNullOrWhiteSpace(stackTrace))
{
return message + "\n" + stackTrace;
@ -109,75 +109,6 @@ namespace Microsoft.ClearScript.Windows
return message;
}
private string GetStackTrace()
{
var stackTrace = string.Empty;
IEnumDebugStackFrames enumFrames;
engine.activeScript.EnumStackFrames(out enumFrames);
while (true)
{
DebugStackFrameDescriptor descriptor;
uint countFetched;
enumFrames.Next(1, out descriptor, out countFetched);
if (countFetched < 1)
{
break;
}
try
{
string description;
descriptor.Frame.GetDescriptionString(true, out description);
IDebugCodeContext codeContext;
descriptor.Frame.GetCodeContext(out codeContext);
IDebugDocumentContext documentContext;
codeContext.GetDocumentContext(out documentContext);
IDebugDocument document;
documentContext.GetDocument(out document);
var documentText = (IDebugDocumentText)document;
string documentName;
document.GetName(DocumentNameType.Title, out documentName);
uint position;
uint length;
documentText.GetPositionOfContext(documentContext, out position, out length);
var pBuffer = Marshal.AllocCoTaskMem((int)(sizeof(char) * length));
try
{
uint lengthReturned = 0;
documentText.GetText(position, pBuffer, IntPtr.Zero, ref lengthReturned, length);
var codeLine = Marshal.PtrToStringUni(pBuffer, (int)lengthReturned);
uint lineNumber;
uint offsetInLine;
documentText.GetLineOfPosition(position, out lineNumber, out offsetInLine);
stackTrace += MiscHelpers.FormatInvariant(" at {0} ({1}:{2}:{3}) -> {4}\n", description, documentName, lineNumber, offsetInLine, codeLine);
}
finally
{
Marshal.FreeCoTaskMem(pBuffer);
}
}
finally
{
if (descriptor.FinalObject != null)
{
Marshal.ReleaseComObject(descriptor.FinalObject);
}
}
}
return stackTrace;
}
private string GetErrorLocation(object error)
{
var scriptError = error as IActiveScriptError;
@ -198,7 +129,7 @@ namespace Microsoft.ClearScript.Windows
if (lineNumber > 0)
{
uint linePosition;
document.GetPositionOfLine(--lineNumber, out linePosition);
document.GetPositionOfLine(lineNumber, out linePosition);
position = (int)linePosition + offsetInLine;
}
else

Просмотреть файл

@ -185,7 +185,7 @@ namespace Microsoft.ClearScript.Windows
private void Parse(string documentName, string code, ScriptTextFlags flags, IntPtr pVarResult, out EXCEPINFO excepInfo, bool discard)
{
var formattedCode = MiscHelpers.FormatCode(code);
var formattedCode = FormatCode ? MiscHelpers.FormatCode(code) : code;
DebugDocument debugDocument;
var sourceContext = CreateDebugDocument(documentName, formattedCode, discard, out debugDocument);
@ -227,6 +227,82 @@ namespace Microsoft.ClearScript.Windows
return sourceContext;
}
private string GetStackTraceInternal()
{
Debug.Assert(engineFlags.HasFlag(WindowsScriptEngineFlags.EnableDebugging));
var stackTrace = string.Empty;
IEnumDebugStackFrames enumFrames;
activeScript.EnumStackFrames(out enumFrames);
while (true)
{
DebugStackFrameDescriptor descriptor;
uint countFetched;
enumFrames.Next(1, out descriptor, out countFetched);
if (countFetched < 1)
{
break;
}
try
{
string description;
descriptor.Frame.GetDescriptionString(true, out description);
IDebugCodeContext codeContext;
descriptor.Frame.GetCodeContext(out codeContext);
IDebugDocumentContext documentContext;
codeContext.GetDocumentContext(out documentContext);
if (documentContext == null)
{
stackTrace += MiscHelpers.FormatInvariant(" at {0}\n", description);
}
else
{
IDebugDocument document;
documentContext.GetDocument(out document);
var documentText = (IDebugDocumentText)document;
string documentName;
document.GetName(DocumentNameType.Title, out documentName);
uint position;
uint length;
documentText.GetPositionOfContext(documentContext, out position, out length);
var pBuffer = Marshal.AllocCoTaskMem((int)(sizeof(char) * length));
try
{
uint lengthReturned = 0;
documentText.GetText(position, pBuffer, IntPtr.Zero, ref lengthReturned, length);
var codeLine = Marshal.PtrToStringUni(pBuffer, (int)lengthReturned);
uint lineNumber;
uint offsetInLine;
documentText.GetLineOfPosition(position, out lineNumber, out offsetInLine);
stackTrace += MiscHelpers.FormatInvariant(" at {0} ({1}:{2}:{3}) -> {4}\n", description, documentName, lineNumber, offsetInLine, codeLine);
}
finally
{
Marshal.FreeCoTaskMem(pBuffer);
}
}
}
finally
{
if (descriptor.FinalObject != null)
{
Marshal.ReleaseComObject(descriptor.FinalObject);
}
}
}
return stackTrace.TrimEnd('\n');
}
private void VerifyNotDisposed()
{
if (disposed)
@ -256,6 +332,24 @@ namespace Microsoft.ClearScript.Windows
}
}
/// <summary>
/// Gets a string representation of the script call stack.
/// </summary>
/// <returns>The script call stack formatted as a string.</returns>
/// <remarks>
/// This method returns an empty string if the script engine is not executing script code.
/// The stack trace text format is defined by the script engine.
/// <para>
/// The <see cref="WindowsScriptEngine"/> version of this method returns the empty string
/// if script debugging features have not been enabled for the instance.
/// </para>
/// </remarks>
public override string GetStackTrace()
{
VerifyNotDisposed();
return engineFlags.HasFlag(WindowsScriptEngineFlags.EnableDebugging) ? ScriptInvoke(() => GetStackTraceInternal()) : string.Empty;
}
/// <summary>
/// Interrupts script execution and causes the script engine to throw an exception.
/// </summary>

Двоичные данные
ClearScript/doc/Reference.chm

Двоичный файл не отображается.

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.3.9.0")]
[assembly: AssemblyFileVersion("5.3.9.0")]
[assembly: AssemblyVersion("5.3.10.0")]
[assembly: AssemblyFileVersion("5.3.10.0")]

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.3.9.0")]
[assembly: AssemblyFileVersion("5.3.9.0")]
[assembly: AssemblyVersion("5.3.10.0")]
[assembly: AssemblyFileVersion("5.3.10.0")]

Просмотреть файл

@ -293,8 +293,74 @@ namespace Microsoft.ClearScript.Test
Assert.AreEqual(456, engine.Evaluate("expando.property('bar')"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_Nullable_Field()
{
engine.Script.test = new NullableTest();
Assert.IsNull(engine.Evaluate("test.Field"));
Assert.IsTrue((bool)engine.Evaluate("test.Field === null"));
engine.Execute("test.Field = 123");
Assert.AreEqual(123, engine.Evaluate("test.Field"));
Assert.IsTrue((bool)engine.Evaluate("test.Field === 123"));
engine.Execute("test.Field = null");
Assert.IsNull(engine.Evaluate("test.Field"));
Assert.IsTrue((bool)engine.Evaluate("test.Field === null"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_Nullable_Property()
{
engine.Script.test = new NullableTest();
Assert.IsNull(engine.Evaluate("test.Property"));
Assert.IsTrue((bool)engine.Evaluate("test.Property === null"));
engine.Execute("test.Property = 123");
Assert.AreEqual(123, engine.Evaluate("test.Property"));
Assert.IsTrue((bool)engine.Evaluate("test.Property === 123"));
engine.Execute("test.Property = null");
Assert.IsNull(engine.Evaluate("test.Property"));
Assert.IsTrue((bool)engine.Evaluate("test.Property === null"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_Nullable_ArgBinding()
{
var test = new NullableTest();
engine.Script.test = test;
Assert.IsNull(engine.Evaluate("test.Method(null)"));
Assert.AreEqual(test.Method(5), engine.Evaluate("test.Method(5)"));
Assert.AreEqual(test.Method(5.1), engine.Evaluate("test.Method(5.1)"));
}
[TestMethod, TestCategory("BugFix")]
public void BugFix_GlobalObjectCrash()
{
engine.AddHostObject("random", HostItemFlags.GlobalMembers, new Random());
Assert.AreEqual("[object global]", engine.ExecuteCommand("this"));
}
// ReSharper restore InconsistentNaming
#endregion
#region miscellaneous
public class NullableTest
{
public int? Field;
public double? Property;
public object Method(int? value)
{
return value.HasValue ? (value + 1) : null;
}
public object Method(double? value)
{
return value.HasValue ? (value * 2.0) : null;
}
}
#endregion
}
}

Просмотреть файл

@ -927,6 +927,43 @@ namespace Microsoft.ClearScript.Test
Assert.AreEqual(Math.Sqrt(7), engine.Evaluate("testObject.Item.get(123, '456', 789.987, -0.12345)"));
}
[TestMethod, TestCategory("JScriptEngine")]
public void JScriptEngine_FormatCode()
{
try
{
engine.Execute("a", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains("(a:3:11)"));
}
engine.FormatCode = true;
try
{
engine.Execute("b", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains("(b:0:6)"));
}
}
[TestMethod, TestCategory("JScriptEngine")]
public void JScriptEngine_GetStackTrace()
{
engine.AddHostObject("qux", new Func<object>(() => engine.GetStackTrace()));
engine.Execute(@"
function baz() { return qux(); }
function bar() { return baz(); }
function foo() { return bar(); }
");
Assert.AreEqual(" at baz (Script Document:1:33) -> return qux()\n at bar (Script Document:2:33) -> return baz()\n at foo (Script Document:3:33) -> return bar()\n at JScript global code (Script Document [2] [temp]:0:0) -> foo()", engine.Evaluate("foo()"));
Assert.AreEqual(" at baz (Script Document:1:33) -> return qux()\n at bar (Script Document:2:33) -> return baz()\n at foo (Script Document:3:33) -> return bar()", engine.Script.foo());
}
// ReSharper restore InconsistentNaming
#endregion

Просмотреть файл

@ -100,7 +100,7 @@ namespace Microsoft.ClearScript.Test
return hashCode * Math.E / Math.PI;
}
public static void AssertException<T>(Action action) where T : Exception
public static void AssertException<T>(Action action, bool checkScriptStackTrace = true) where T : Exception
{
var gotException = false;
@ -111,12 +111,12 @@ namespace Microsoft.ClearScript.Test
catch (T exception)
{
gotException = true;
AssertValidExceptionChain(exception);
AssertValidExceptionChain(exception, checkScriptStackTrace);
}
catch (Exception exception)
{
gotException = exception.GetBaseException() is T;
AssertValidExceptionChain(exception);
AssertValidExceptionChain(exception, checkScriptStackTrace);
}
Assert.IsTrue(gotException, "Expected " + typeof(T).Name + " was not thrown.");
@ -131,30 +131,33 @@ namespace Microsoft.ClearScript.Test
Assert.IsFalse(string.IsNullOrWhiteSpace(exception.StackTrace));
}
public static void AssertValidException(IScriptEngineException exception)
public static void AssertValidException(IScriptEngineException exception, bool checkScriptStackTrace = true)
{
AssertValidException((Exception)exception);
if ((exception is ScriptEngineException) && !exception.IsFatal && (exception.HResult != RawCOMHelpers.HResult.CLEARSCRIPT_E_SCRIPTITEMEXCEPTION))
{
Assert.IsTrue(exception.ErrorDetails.StartsWith(exception.Message, StringComparison.Ordinal));
Assert.IsTrue(exception.ErrorDetails.Contains("\n at "));
if (checkScriptStackTrace)
{
Assert.IsTrue(exception.ErrorDetails.Contains("\n at "));
}
}
}
public static void AssertValidException(ScriptEngine engine, IScriptEngineException exception)
public static void AssertValidException(ScriptEngine engine, IScriptEngineException exception, bool checkScriptStackTrace = true)
{
AssertValidException(exception);
AssertValidException(exception, checkScriptStackTrace);
Assert.AreEqual(engine.Name, exception.EngineName);
}
private static void AssertValidExceptionChain(Exception exception)
private static void AssertValidExceptionChain(Exception exception, bool checkScriptStackTrace)
{
while (exception != null)
{
var scriptError = exception as IScriptEngineException;
if (scriptError != null)
{
AssertValidException(scriptError);
AssertValidException(scriptError, checkScriptStackTrace);
}
else
{

Просмотреть файл

@ -69,5 +69,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("(c) Microsoft Corporation")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("5.3.9.0")]
[assembly: AssemblyFileVersion("5.3.9.0")]
[assembly: AssemblyVersion("5.3.10.0")]
[assembly: AssemblyFileVersion("5.3.10.0")]

Просмотреть файл

@ -269,7 +269,10 @@ namespace Microsoft.ClearScript.Test
Action innerTest = () =>
{
using (var scriptEngine = new VBScriptEngine(WindowsScriptEngineFlags.EnableDebugging))
// The Visual Studio 2013 debugging stack fails to release the engine properly,
// resulting in test failure. Visual Studio 2012 does not have this bug.
using (var scriptEngine = new VBScriptEngine())
{
scriptEngine.AddHostObject("bag", bag);
Assert.AreEqual(2, bag.EngineCount);
@ -290,7 +293,10 @@ namespace Microsoft.ClearScript.Test
var innerBag = new PropertyBag();
Action innerTest = () =>
{
using (var scriptEngine = new VBScriptEngine(WindowsScriptEngineFlags.EnableDebugging))
// The Visual Studio 2013 debugging stack fails to release the engine properly,
// resulting in test failure. Visual Studio 2012 does not have this bug.
using (var scriptEngine = new VBScriptEngine())
{
scriptEngine.AddHostObject("bag", outerBag);
outerBag.Add("innerBag", innerBag);

Просмотреть файл

@ -1127,6 +1127,108 @@ namespace Microsoft.ClearScript.Test
Assert.AreEqual(Math.Sqrt(7), engine.Evaluate("testObject.Item.get(123, '456', 789.987, -0.12345)"));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_FormatCode()
{
try
{
engine.Execute("a", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains(" a:4:10 "));
}
engine.FormatCode = true;
try
{
engine.Execute("b", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains(" b:1:5 "));
}
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_GetStackTrace()
{
engine.AddHostObject("qux", new Func<object>(() => engine.GetStackTrace()));
engine.Execute(@"
function baz() { return qux(); }
function bar() { return baz(); }
function foo() { return bar(); }
");
Assert.AreEqual(" at baz (Script Document:2:41)\n at bar (Script Document:3:41)\n at foo (Script Document:4:41)\n at Script Document [2] [temp]:1:1", engine.Evaluate("foo()"));
Assert.AreEqual(" at baz (Script Document:2:41)\n at bar (Script Document:3:41)\n at foo (Script Document:4:41)", engine.Script.foo());
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_MaxRuntimeStackUsage()
{
using (var runtime = new V8Runtime())
{
using (var engine1 = runtime.CreateScriptEngine())
{
using (var engine2 = runtime.CreateScriptEngine())
{
var value = (UIntPtr)123456;
engine1.MaxRuntimeStackUsage = value;
Assert.AreEqual(value, engine1.MaxRuntimeStackUsage);
Assert.AreEqual(value, engine2.MaxRuntimeStackUsage);
Assert.AreEqual(value, runtime.MaxStackUsage);
value = (UIntPtr)654321;
runtime.MaxStackUsage = value;
Assert.AreEqual(value, engine1.MaxRuntimeStackUsage);
Assert.AreEqual(value, engine2.MaxRuntimeStackUsage);
Assert.AreEqual(value, runtime.MaxStackUsage);
}
}
}
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_MaxRuntimeStackUsage_ScriptOnly()
{
engine.MaxRuntimeStackUsage = (UIntPtr)(16 * 1024);
TestUtil.AssertException<ScriptEngineException>(() => engine.Execute("(function () { arguments.callee(); })()"), false);
Assert.AreEqual(Math.PI, engine.Evaluate("Math.PI"));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_MaxRuntimeStackUsage_HostBounce()
{
engine.MaxRuntimeStackUsage = (UIntPtr)(16 * 1024);
dynamic foo = engine.Evaluate("(function () { arguments.callee(); })");
engine.Script.bar = new Action(() => foo());
TestUtil.AssertException<ScriptEngineException>(() => engine.Execute("bar()"), false);
Assert.AreEqual(Math.PI, engine.Evaluate("Math.PI"));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_MaxRuntimeStackUsage_Alternating()
{
engine.MaxRuntimeStackUsage = (UIntPtr)(16 * 1024);
dynamic foo = engine.Evaluate("(function () { bar(); })");
engine.Script.bar = new Action(() => foo());
TestUtil.AssertException<ScriptEngineException>(() => foo(), false);
Assert.AreEqual(Math.PI, engine.Evaluate("Math.PI"));
}
[TestMethod, TestCategory("V8ScriptEngine")]
public void V8ScriptEngine_MaxRuntimeStackUsage_Expansion()
{
engine.MaxRuntimeStackUsage = (UIntPtr)(16 * 1024);
TestUtil.AssertException<ScriptEngineException>(() => engine.Execute("count = 0; (function () { count++; arguments.callee(); })()"), false);
var count1 = engine.Script.count;
engine.MaxRuntimeStackUsage = (UIntPtr)(64 * 1024);
TestUtil.AssertException<ScriptEngineException>(() => engine.Execute("count = 0; (function () { count++; arguments.callee(); })()"), false);
var count2 = engine.Script.count;
Assert.IsTrue(count2 >= (count1 * 2));
}
// ReSharper restore InconsistentNaming
#endregion

Просмотреть файл

@ -863,6 +863,43 @@ namespace Microsoft.ClearScript.Test
Assert.AreEqual(Math.Sqrt(7), engine.Evaluate("testObject.Item.get(clng(123), \"456\", 789.987, -0.12345)"));
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_FormatCode()
{
try
{
engine.Execute("a", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains("(a:3:11)"));
}
engine.FormatCode = true;
try
{
engine.Execute("b", "\n\n\n x = 3.a");
}
catch (ScriptEngineException exception)
{
Assert.IsTrue(exception.ErrorDetails.Contains("(b:0:6)"));
}
}
[TestMethod, TestCategory("VBScriptEngine")]
public void VBScriptEngine_GetStackTrace()
{
engine.AddHostObject("qux", new Func<object>(() => engine.GetStackTrace()));
engine.Execute(@"
function baz():baz = qux():end function
function bar():bar = baz():end function
function foo():foo = bar():end function
");
Assert.AreEqual(" at baz (Script Document [3]:1:31) -> baz = qux()\n at bar (Script Document [3]:2:31) -> bar = baz()\n at foo (Script Document [3]:3:31) -> foo = bar()\n at VBScript global code (Script Document [4] [temp]:0:0) -> foo()", engine.Evaluate("foo()"));
Assert.AreEqual(" at baz (Script Document [3]:1:31) -> baz = qux()\n at bar (Script Document [3]:2:31) -> bar = baz()\n at foo (Script Document [3]:3:31) -> foo = bar()", engine.Script.foo());
}
// ReSharper restore InconsistentNaming
#endregion

Просмотреть файл

@ -20,9 +20,9 @@ See ClearScript\doc for information about using ClearScript.
II. Building ClearScript
------------------------
The provided project and solution files require Visual Studio 2012. They
produce architecture-neutral managed libraries that target .NET Framework 4.0.
ClearScript has been tested with .NET Framework 4.5 as well. It does not
The provided project and solution files support Visual Studio 2012 and 2013.
They produce architecture-neutral managed libraries that target .NET Framework
4.0. ClearScript has been tested with .NET Framework 4.5 as well. It does not
support older environments. The output directory is bin\[Debug|Release].
There are two ways to build ClearScript - with and without V8 support.
@ -66,6 +66,10 @@ build, and import V8:
You are now ready to build the full ClearScript solution using Visual Studio.
NOTE: The first time you open the solution, Visual Studio may prompt you to
upgrade one or more projects to the latest platform toolset or .NET Framework.
We recommend that you select "Cancel" or "Don't Upgrade".
OPTIONAL: The ClearScript distribution includes a copy of the ClearScript
Library Reference in Compiled HTML (.CHM) format. If you'd like to rebuild this
file, use Sandcastle Help File Builder (SHFB, http://shfb.codeplex.com) with
@ -90,11 +94,19 @@ Once you've built ClearScript, here's how to add it to your application:
ClearScriptV8-64.dll
v8-ia32.dll
v8-x64.dll
For ASP.NET projects, we recommend that you add these assemblies as content
files at the root of your web application and set their "Copy to Output
Directory" properties to "Do not copy".
In addition, if Visual Studio is not installed on the deployment machine,
4. IMPORTANT: If Visual Studio is not installed on your deployment machine,
you must install 32-bit and 64-bit Visual C++ Redistributable packages:
Visual Studio 2012:
http://www.microsoft.com/en-us/download/details.aspx?id=30679
Visual Studio 2013:
http://www.microsoft.com/en-us/download/details.aspx?id=40784
-------------------------------------
IV. Debugging with ClearScript and V8

Просмотреть файл

@ -5,8 +5,8 @@ setlocal
:: process arguments
::-----------------------------------------------------------------------------
set testedRevision=17421
set testedVersion=3.22.23
set testedRevision=18109
set testedVersion=3.23.13
set gyprev=1685
set pythonrev=89111
@ -162,7 +162,14 @@ cd ..
:Build
:SetMSVSVersion
if "%VisualStudioVersion%"=="12.0" goto UseMSVS2013
set GYP_MSVS_VERSION=2012
goto SetMSVSVersionDone
:UseMSVS2013
set GYP_MSVS_VERSION=2013
:SetMSVSVersionDone
set PYTHONHOME=
set PYTHONPATH=

Просмотреть файл

@ -1 +1 @@
<# var version = new Version(5, 3, 9, 0); #>
<# var version = new Version(5, 3, 10, 0); #>