diff --git a/CMakeLists.txt b/CMakeLists.txt index ff8732156..7e9ec4742 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -327,6 +327,7 @@ if (JSONRPC) add_subdirectory(libweb3jsonrpc) endif() +add_subdirectory(libethconsole) add_subdirectory(secp256k1) add_subdirectory(libp2p) add_subdirectory(libdevcrypto) diff --git a/cmake/EthDependencies.cmake b/cmake/EthDependencies.cmake index 2dfb80ac3..1edc33b65 100644 --- a/cmake/EthDependencies.cmake +++ b/cmake/EthDependencies.cmake @@ -47,6 +47,10 @@ find_package (LevelDB REQUIRED) message(" - LevelDB header: ${LEVELDB_INCLUDE_DIRS}") message(" - LevelDB lib: ${LEVELDB_LIBRARIES}") +find_package (v8 REQUIRED) +message(" - v8 header: ${V8_INCLUDE_DIRS}") +message(" - v8 lib : ${V8_LIBRARIES}") + # TODO the Jsoncpp package does not yet check for correct version number find_package (Jsoncpp 0.60 REQUIRED) message(" - Jsoncpp header: ${JSONCPP_INCLUDE_DIRS}") diff --git a/cmake/Findv8.cmake b/cmake/Findv8.cmake new file mode 100644 index 000000000..49c797586 --- /dev/null +++ b/cmake/Findv8.cmake @@ -0,0 +1,69 @@ +# Find v8 +# +# Find the v8 includes and library +# +# if you nee to add a custom library search path, do it via via CMAKE_PREFIX_PATH +# +# This module defines +# V8_INCLUDE_DIRS, where to find header, etc. +# V8_LIBRARIES, the libraries needed to use v8. +# V8_FOUND, If false, do not try to use v8. + +# only look in default directories +find_path( + V8_INCLUDE_DIR + NAMES v8.h + DOC "v8 include dir" +) + +find_library( + V8_LIBRARY + NAMES v8 + DOC "v8 library" +) + +find_library( + V8_BASE_LIBRARY + NAMES v8_base + DOC "v8 library" +) + +find_library( + V8_LIBBASE_LIBRARY + NAMES v8_libbase + DOC "v8 library" +) + +find_library( + V8_LIBPLATFORM_LIBRARY + NAMES v8_libplatform + DOC "v8 library" +) + +string(REPLACE "/include" "" V8_INCLUDE_DIR_LOCATION ${V8_INCLUDE_DIR}) + +set(V8_INCLUDE_DIRS ${V8_INCLUDE_DIR} ${V8_INCLUDE_DIR_LOCATION}) +set(V8_LIBRARIES ${V8_LIBRARY} ${V8_BASE_LIBRARY} ${V8_LIBBASE_LIBRARY} ${V8_LIBPLATFORM_LIBRARY}) + +# debug library on windows +# same naming convention as in qt (appending debug library with d) +# boost is using the same "hack" as us with "optimized" and "debug" +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + + find_library( + V8_LIBRARY_DEBUG + NAMES v8d + DOC "v8 debug library" + ) + + set(V8_LIBRARIES optimized ${V8_LIBRARIES} debug ${V8_LIBRARY_DEBUG}) + +endif() + +# handle the QUIETLY and REQUIRED arguments and set V8_FOUND to TRUE +# if all listed variables are TRUE, hide their existence from configuration view +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(v8 DEFAULT_MSG + V8_INCLUDE_DIR V8_LIBRARY) +mark_as_advanced (V8_INCLUDE_DIR V8_LIBRARY) + diff --git a/libdevcore/CommonIO.cpp b/libdevcore/CommonIO.cpp index a1a1056cb..cf98254c4 100644 --- a/libdevcore/CommonIO.cpp +++ b/libdevcore/CommonIO.cpp @@ -30,7 +30,7 @@ string dev::memDump(bytes const& _bytes, unsigned _width, bool _html) { stringstream ret; if (_html) - ret << "
";
+		ret << "
";
 	for (unsigned i = 0; i < _bytes.size(); i += _width)
 	{
 		ret << hex << setw(4) << setfill('0') << i << " ";
diff --git a/libethconsole/CMakeLists.txt b/libethconsole/CMakeLists.txt
new file mode 100644
index 000000000..d62da84ff
--- /dev/null
+++ b/libethconsole/CMakeLists.txt
@@ -0,0 +1,28 @@
+cmake_policy(SET CMP0015 NEW)
+# this policy was introduced in cmake 3.0
+# remove if, once 3.0 will be used on unix
+if (${CMAKE_MAJOR_VERSION} GREATER 2)
+	# old policy do not use MACOSX_RPATH
+	cmake_policy(SET CMP0042 OLD)
+endif()
+
+set(CMAKE_AUTOMOC OFF)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++")
+
+aux_source_directory(. SRC_LIST)
+
+include_directories(BEFORE ..)
+include_directories(${V8_INCLUDE_DIRS})
+
+set(EXECUTABLE ethconsole)
+
+file(GLOB HEADERS "*.h")
+
+add_library(${EXECUTABLE} SHARED ${SRC_LIST} ${HEADERS})
+
+target_link_libraries(${EXECUTABLE} ${V8_LIBRARIES})
+
+install( TARGETS ${EXECUTABLE} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib )
+install( FILES ${HEADERS} DESTINATION include/${EXECUTABLE} )
+
diff --git a/libethconsole/JSScope.cpp b/libethconsole/JSScope.cpp
new file mode 100644
index 000000000..10795e9b0
--- /dev/null
+++ b/libethconsole/JSScope.cpp
@@ -0,0 +1,5 @@
+//
+// Created by Marek Kotewicz on 27/04/15.
+//
+
+#include "JSScope.h"
diff --git a/libethconsole/JSScope.h b/libethconsole/JSScope.h
new file mode 100644
index 000000000..18d6c863c
--- /dev/null
+++ b/libethconsole/JSScope.h
@@ -0,0 +1,25 @@
+//
+// Created by Marek Kotewicz on 27/04/15.
+//
+
+#pragma once
+
+namespace dev
+{
+namespace eth
+{
+
+class JSScope
+{
+public:
+	JSScope()
+	{ };
+
+	virtual ~JSScope()
+	{ };
+
+	virtual const char* evaluate(const char* _cstr) const = 0;
+};
+
+}
+}
diff --git a/libethconsole/JSV8ScopeBase.cpp b/libethconsole/JSV8ScopeBase.cpp
new file mode 100644
index 000000000..9e3516812
--- /dev/null
+++ b/libethconsole/JSV8ScopeBase.cpp
@@ -0,0 +1,87 @@
+//
+// Created by Marek Kotewicz on 27/04/15.
+//
+
+#include 
+#include 
+#include "JSV8ScopeBase.h"
+
+using namespace dev;
+using namespace dev::eth;
+
+JSV8Env JSV8ScopeBase::s_env = JSV8Env();
+
+class ShellArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
+public:
+	virtual void* Allocate(size_t length) {
+		void* data = AllocateUninitialized(length);
+		return data == NULL ? data : memset(data, 0, length);
+	}
+	virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
+	virtual void Free(void* data, size_t) { free(data); }
+};
+
+JSV8Env::JSV8Env()
+{
+	static bool initialized = false;
+	if (initialized)
+		return;
+	initialized = true;
+	v8::V8::InitializeICU();
+	m_platform = v8::platform::CreateDefaultPlatform();
+	v8::V8::InitializePlatform(m_platform);
+	v8::V8::Initialize();
+	ShellArrayBufferAllocator array_buffer_allocator;
+	v8::V8::SetArrayBufferAllocator(&array_buffer_allocator);
+}
+
+JSV8Env::~JSV8Env()
+{
+	v8::V8::Dispose();
+	v8::V8::ShutdownPlatform();
+	delete m_platform;
+}
+
+JSV8ScopeBase::JSV8ScopeBase():
+		m_isolate(v8::Isolate::New()),
+		m_scope(new JSV8DumbScope(m_isolate))
+{ }
+
+JSV8ScopeBase::~JSV8ScopeBase()
+{
+	delete m_scope;
+	m_isolate->Dispose();
+}
+
+const char* JSV8ScopeBase::evaluate(const char* _cstr) const
+{
+	v8::HandleScope handleScope(m_isolate);
+//	v8::TryCatch tryCatch;
+	v8::Local source = v8::String::NewFromUtf8(m_scope->context()->GetIsolate(), _cstr);
+	v8::Local name(v8::String::NewFromUtf8(m_scope->context()->GetIsolate(), "(shell)"));
+	v8::ScriptOrigin origin(name);
+	v8::Handle script = v8::Script::Compile(source, &origin);
+	if (script.IsEmpty())
+	{
+		// TODO: handle exceptions
+		return "";
+	}
+
+	v8::Handle result = script->Run();
+	return formatValue(result);
+}
+
+const char* JSV8ScopeBase::formatValue(v8::Handle const &_value) const
+{
+	if (_value.IsEmpty())
+	{
+		// TODO: handle exceptions
+		return "";
+	}
+	else if (_value->IsUndefined())
+	{
+		return "undefined";
+	}
+	v8::String::Utf8Value str(_value);
+	return *str ? *str : "";
+}
diff --git a/libethconsole/JSV8ScopeBase.h b/libethconsole/JSV8ScopeBase.h
new file mode 100644
index 000000000..2f7d46c79
--- /dev/null
+++ b/libethconsole/JSV8ScopeBase.h
@@ -0,0 +1,69 @@
+//
+// Created by Marek Kotewicz on 27/04/15.
+//
+
+#pragma once
+
+#include 
+#include "JSScope.h"
+
+namespace dev
+{
+namespace eth
+{
+
+class JSV8Env
+{
+public:
+	JSV8Env();
+	~JSV8Env();
+
+private:
+	v8::Platform* m_platform;
+};
+
+v8::Handle CreateShellContext(v8::Isolate* isolate)
+{
+	v8::Handle global = v8::ObjectTemplate::New(isolate);
+	return v8::Context::New(isolate, NULL, global);
+}
+
+class JSV8DumbScope
+{
+public:
+	JSV8DumbScope(v8::Isolate* _isolate):
+			m_isolateScope(_isolate),
+			m_handleScope(_isolate),
+			m_context(CreateShellContext(_isolate)),
+			m_contextScope(m_context)
+	{}
+
+	v8::Handle  const& context() const { return m_context; }
+
+private:
+	v8::Isolate::Scope m_isolateScope;
+	v8::HandleScope m_handleScope;
+	v8::Handle  m_context;
+	v8::Context::Scope m_contextScope;
+};
+
+class JSV8ScopeBase : public JSScope
+{
+public:
+	JSV8ScopeBase();
+
+	virtual ~JSV8ScopeBase();
+
+	const char* evaluate(const char* _cstr) const;
+
+private:
+	static JSV8Env s_env;
+	v8::Isolate* m_isolate;
+	JSV8DumbScope* m_scope;
+
+	virtual const char* formatValue(v8::Handle  const &_value) const;
+};
+
+}
+}
+
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a97bb86fc..2413fc0a9 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -25,6 +25,8 @@ add_subdirectory(libethereum)
 add_subdirectory(libevm)
 add_subdirectory(libnatspec)
 add_subdirectory(libp2p)
+add_subdirectory(libethconsole)
+
 if (SOLIDITY)
 	add_subdirectory(libsolidity)
 endif ()
@@ -40,6 +42,7 @@ include_directories(BEFORE ..)
 include_directories(${Boost_INCLUDE_DIRS})
 include_directories(${CRYPTOPP_INCLUDE_DIRS})
 include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
+include_directories(${V8_INCLUDE_DIRS})
 
 # search for test names and create ctest tests
 enable_testing()
@@ -65,6 +68,7 @@ target_link_libraries(testeth ${CURL_LIBRARIES})
 target_link_libraries(testeth ethereum)
 target_link_libraries(testeth ethcore)
 target_link_libraries(testeth secp256k1)
+target_link_libraries(testeth ethconsole)
 if (SOLIDITY)
 	target_link_libraries(testeth solidity)
 endif ()
diff --git a/test/libethconsole/CMakeLists.txt b/test/libethconsole/CMakeLists.txt
new file mode 100644
index 000000000..610c58889
--- /dev/null
+++ b/test/libethconsole/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_policy(SET CMP0015 NEW)
+
+aux_source_directory(. SRCS)
+
+add_sources(${SRCS})
+
+
diff --git a/test/libethconsole/JSV8ScopeBase.cpp b/test/libethconsole/JSV8ScopeBase.cpp
new file mode 100644
index 000000000..5bd7bf6a5
--- /dev/null
+++ b/test/libethconsole/JSV8ScopeBase.cpp
@@ -0,0 +1,21 @@
+//
+// Created by Marek Kotewicz on 27/04/15.
+//
+
+#include 
+#include "../../libethconsole/JSV8ScopeBase.h"
+
+using namespace std;
+using namespace dev;
+using namespace dev::eth;
+
+BOOST_AUTO_TEST_SUITE(jsscope)
+
+BOOST_AUTO_TEST_CASE(common)
+{
+	JSV8ScopeBase scope;
+	string result = scope.evaluate("1 + 1");
+	BOOST_CHECK_EQUAL(result, "2");
+}
+
+BOOST_AUTO_TEST_SUITE_END()