prepare / espresso Goto Github PK
View Code? Open in Web Editor NEW☕ Bridge your C# soul to the power of Javascript (V8 Javascript Engine / NodeJs)
License: MIT License
☕ Bridge your C# soul to the power of Javascript (V8 Javascript Engine / NodeJs)
License: MIT License
Any attempt to run JsEngine.CompileScript results in a System.AccessViolationException being thrown from JsScript.cs:24 (jsscript_compile)
Are you compiling all of nodejs, but only exporting the V8 functions you need?
The reason why I ask is because I think this could potential allow running javascript code in .NET that actually utilize network/file and node_modules.
file src/node_main_instance.cc
about line 14
#if HAVE_INSPECTOR
#include "inspector/worker_inspector.h" // ParentInspectorHandle
#endif
//////////////////////////////////
//#espresso ,#1
#include "../src/libespresso/bridge2.h"
void DoEngineSetupCallback(JsEngine* engine, JsContext* jsContext);
void DoEngineClosingCallback(JsEngine* engine,
JsContext* jsContext,
int exitCode);
//////////////////////////////////
namespace node {
using v8::Context;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Locker;
patch 1: src/node_main_instance.cc
about line 135
int NodeMainInstance::Run(const EnvSerializeInfo* env_info) {
Locker locker(isolate_);
Isolate::Scope isolate_scope(isolate_);
HandleScope handle_scope(isolate_);
int exit_code = 0;
DeleteFnPtr<Environment, FreeEnvironment> env =
CreateMainEnvironment(&exit_code, env_info);
CHECK_NOT_NULL(env);
{
Context::Scope context_scope(env->context());
if (exit_code == 0) {
/////////////////////////////
//#espresso ,#2
JsEngine* jsEngine = JsEngine::NewFromExistingIsolate(isolate_);
v8::Persistent<Context>* pcontext =
new v8::Persistent<Context>(isolate_, env->context());
JsContext* jscontext =
JsContext::NewFromExistingContext(0, jsEngine, pcontext);
DoEngineSetupCallback(jsEngine, jscontext);
////////////////////////////////
LoadEnvironment(env.get(), StartExecutionCallback{
});
exit_code = SpinEventLoop(env.get()).FromMaybe(1);
//////////////////////////////////
////#espresso ,#3
DoEngineClosingCallback(jsEngine, jscontext, exit_code);
////////////////////////////////
}
patch 2&3: src/node_main_instance.cc
When you build the ND version again, you may also want to add this change to JsEngine.NativeMethods:
dpwhittaker@53388e3#diff-5d67ff4aeda70590cede90599ce6f971
This allowed me to add --inspect as a node parameter and connect the chrome debugger to javascript in initial testing.
If there is another way to do this, let me know.
see detail ... https://nodejs.org/api/n-api.html
file src/node_main_instance.cc
about line 14
#if HAVE_INSPECTOR
#include "inspector/worker_inspector.h" // ParentInspectorHandle
#endif
//////////////////////////////////
//#espresso ,#1
#include "../src/libespresso/bridge2.h"
void DoEngineSetupCallback(JsEngine* engine, JsContext* jsContext);
void DoEngineClosingCallback(JsEngine* engine,
JsContext* jsContext,
int exitCode);
//////////////////////////////////
namespace node {
using v8::Context;
using v8::HandleScope;
patch 1: src/node_main_instance.cc
about line 151
void NodeMainInstance::Run(int* exit_code, Environment* env) {
if (*exit_code == 0) {
/////////////////////////////
//#espresso ,#2
JsEngine* jsEngine = JsEngine::NewFromExistingIsolate(isolate_);
v8::Persistent<Context>* pcontext =
new v8::Persistent<Context>(isolate_, env->context());
JsContext* jscontext =
JsContext::NewFromExistingContext(0, jsEngine, pcontext);
DoEngineSetupCallback(jsEngine, jscontext);
////////////////////////////////
LoadEnvironment(env, StartExecutionCallback{});
*exit_code = SpinEventLoop(env).FromMaybe(1);
//////////////////////////////////
////#espresso ,#3
DoEngineClosingCallback(jsEngine, jscontext, *exit_code);
///////////////////////////////
}
ResetStdio();
patch 2&3: src/node_main_instance.cc
Would it be possible to implement and expose suitable send and receive functions so that a user of the non-ND version of Espresso could access Inspector Protocol for debugging purposes.
My ideal would obviously be to be able to use ChromeDevTools in the same way that ND users can as seen in #39 however I'd be happy to start with very basic access to allow me to build a basic debugger.
The documentation at https://v8.dev/docs/inspector seems to imply that this should be fairly straight-forwards, however I haven't written any C++ for many years, so have no idea how to go about this myself.
I also believe that there's a good chance that if we could set up a suitable Inspector Protocol redirector, it could be integrated with Visual Studio's javascript/NodeJs debugging facility without too much work. Ref https://code.visualstudio.com/docs/nodejs/nodejs-debugging and I'd be happy to have a try at that.
patches are located here => Espresso\node_patches\node10.15.3_modified
... about line 120
// This is used to load built-in modules. Instead of using
// __attribute__((constructor)), we call the _register_<modname>
// function for each built-in modules explicitly in
// node::RegisterBuiltinModules(). This is only forward declaration.
// The definitions are in each module's implementation when calling
// the NODE_BUILTIN_MODULE_CONTEXT_AWARE.
#define V(modname) void _register_##modname();
NODE_BUILTIN_MODULES(V)
#undef V
//////////////////////////////////
//#espresso ,#1
#include "../src/libespresso/bridge2.h"
void DoEngineSetupCallback(JsEngine* engine, JsContext* jsContext);
//////////////////////////////////
patch 1: src/node.cc
... about line 2847
inline int Start(Isolate* isolate, IsolateData* isolate_data,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args) {
HandleScope handle_scope(isolate);
Local<Context> context = NewContext(isolate);
Context::Scope context_scope(context);
Environment env(isolate_data, context, v8_platform.GetTracingAgentWriter());
env.Start(args, exec_args, v8_is_profiling);
////////////////////////////////
//#espresso ,#2
JsEngine* jsEngine = JsEngine::NewFromExistingIsolate(isolate);
v8::Persistent<Context>* pcontext =
new v8::Persistent<Context>(isolate, context);
JsContext* jscontext = JsContext::NewFromExistingContext(0, jsEngine, pcontext);
DoEngineSetupCallback(jsEngine, jscontext);
////////////////////////////////
const char* path = args.size() > 1 ? args[1].c_str() : nullptr;
StartInspector(&env, path, env.options()->debug_options);
patch2: src/node.cc
see screen snapshot patches here, https://github.com/CompilerLab/Espresso/issues/12
temp release for x86, see https://github.com/prepare/espresso_release_tmp
same steps as previous version
(see https://github.com/prepare/Espresso/tree/v_9_3_0)
In this version you can use http2 with node9.3.0.
pic 1: http2 protocol example, on node v9.3.0
pic2: (1) console screen, (2) http2 server says 'Hello World' to Firefox
see more at https://nodejs.org/api/http2.html
patches are located here => Espresso\node_patches\node11.12.0_modified
... about line 116
#include <string>
#include <vector>
//////////////////////////////////
//#espresso ,#1
#include "../src/libespresso/bridge2.h"
void DoEngineSetupCallback(JsEngine* engine, JsContext* jsContext);
void DoEngineClosingCallback(JsEngine* engine, JsContext* jsContext,int exitCode);
//////////////////////////////////
namespace node {
using options_parser::kAllowedInEnvironment;
using options_parser::kDisallowedInEnvironment;
patch 1: src/node.cc
... about line 778
inline int StartNodeWithIsolate(Isolate* isolate,
IsolateData* isolate_data,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args) {
HandleScope handle_scope(isolate);
Local<Context> context = NewContext(isolate);
Context::Scope context_scope(context);
int exit_code = 0;
Environment env(
isolate_data,
context,
static_cast<Environment::Flags>(Environment::kIsMainThread |
Environment::kOwnsProcessState |
Environment::kOwnsInspector));
env.InitializeLibuv(per_process::v8_is_profiling);
env.ProcessCliArgs(args, exec_args);
////////////////////////////////
//#espresso ,#2
JsEngine* jsEngine = JsEngine::NewFromExistingIsolate(isolate);
v8::Persistent<Context>* pcontext =
new v8::Persistent<Context>(isolate, context);
JsContext* jscontext = JsContext::NewFromExistingContext(0, jsEngine, pcontext);
DoEngineSetupCallback(jsEngine, jscontext);
////////////////////////////////
#if HAVE_INSPECTOR && NODE_USE_V8_PLATFORM
CHECK(!env.inspector_agent()->IsListening());
patch2: src/node.cc
about line 856
env.set_trace_sync_io(false);
exit_code = EmitExit(&env);
////////////////////////////////
//#espresso ,#3
DoEngineClosingCallback(jsEngine, jscontext,exit_code);
////////////////////////////////
WaitForInspectorDisconnect(&env);
exit:
env.set_can_call_into_js(false);
env.stop_sub_worker_contexts();
uv_tty_reset_mode();
env.RunCleanup();
RunAtExit(&env);
patch3: src/node.cc
see #40 (comment)
Repro: https://github.com/dpwhittaker/Espresso
dpwhittaker@e4d020d
I added a test 3 to TestEspressoCore. Attempting to send an array of anything (test covers strings, also tried CLR objects) results in a segfault. Looks like the native side allocates an array of JsValue pointers, but does not allocate a JsValue for each entry. I allocated it on the CLR side (with new JsValue()), and stuck it in the keepAlive to keep it around (I know there's a memory leak there, just trying to make anything work), but still end up with an array of null's on the Javascript side.
I was unable to access the dropbox link with the precompiled dll's, so I built it myself. I also had some issues running the patcher on our locked-down PCs, so I believe I replicated the steps correctly, but I may have built node incorrectly. So please verify that this issue exists with the way you build node. It would be appreciated if the complete nuget package was built and regularly published to nuget.org or github releases to avoid these questions on whether all the dependencies were built correctly. If this test works fine on your box, please republish the node dll's (github releases is highly recommended).
I'm having trouble debugging into the Native side on node, so I'm having trouble tracking the issue past the C# code. Any help you can provide would be appreciated.
Hi!
Is there any howTo or something similar for this?
I can't get it to run....
If i just try the TestEspressoCore it gives following Error:
Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'libespr': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at Espresso.NativeV8JsInterOp.V8Init()
at Espresso.JsBridge.V8Init() in C:\_Daten\Repos\Github\Espresso\src\0_Start\JsBridge.cs:line 18
at TestEspressoCore.Program.Main(String[] args) in C:\_Daten\Repos\Github\Espresso\Tests\TestEspressoCore\Program.cs:line 13
If i try to compile libespr i'll get:
Cannot open include file: 'v8.h': No such file or directory
A little startup Help would be great!!
Is it possible to run complex JS code like MathJax in C# using Espresso?
Would it be possible to add 64-bit binaries of libespr.dll to the native folder? Our project needs > 2GB of ram, so it has to be built in 64-bit, but we'd like to interface with V8. We started with VroomJS, but it's on a pretty old version of v8, so we'd like to use this version if possible, but the instructions for building libespr are a little slim. I'll grab the node source and see if I can piece it together, but it would make the library more useful if they were included.
We have another issue showing up. It manifests as an access violation in JsContext::CreateWrapperForManagedObject. objTemplate->NewInstance on line 103 returns null, but this value is not checked for. I have not been able to create a simple repro to cause the issue yet, but wanted to go ahead and log the issue in case it sparked any ideas.
The building steps of this might be easier if we have an automate build script.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.