Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
8922bba
deps: update npm to 5.5.1
MylesBorins Oct 27, 2017
0ea8ff3
deps: backport 4ca695819 from npm upstream
MylesBorins Oct 27, 2017
237067d
deps: manually add 9.x support to npm
MylesBorins Oct 26, 2017
4fdd76d
http2: fix stream reading resumption
apapirovski Oct 29, 2017
ef238fb
v8: migrate setFlagsFromString to internal/errors
jasnell Oct 26, 2017
07d71c9
async_hooks: enable runtime checks by default
AndreasMadsen Oct 19, 2017
decb9e7
doc: add license information for remark-cli
MylesBorins Oct 31, 2017
ed92e0c
doc: add Gibson Fahnestock to Release team
gibfahn Oct 30, 2017
45873d2
module: revert #3384 DEP0019 EOL
MylesBorins Oct 31, 2017
daa286a
2017-10-31, Version 8.9.0 'Carbon' (LTS) Release
gibfahn Oct 31, 2017
fa9990f
2017-10-31, Version 9.0.0 (Current)
jasnell Sep 1, 2017
a933179
implement intialize(), tear_down(), process_events() for shared lib API
justus-hildebrand Dec 13, 2017
1906ddd
forgot to remove the node_lib include
justus-hildebrand Dec 18, 2017
f685a03
update ReadMe
justus-hildebrand Dec 18, 2017
8b01e1e
Update README.md
justus-hildebrand Dec 18, 2017
819c0f6
added nodelib interface v0.3
Dec 18, 2017
0280f31
Build on Travis (#6)
cmfcmf Dec 18, 2017
42a0104
revert changes made to node.cc and node.h
justus-hildebrand Jan 4, 2018
f4a5f64
Merge branch 'node_lib' of github.com:hpicgs/node into node_lib
justus-hildebrand Jan 4, 2018
d88e1d5
WIP: added more calling convenience
Jan 4, 2018
c9949a5
Renamed nodelib to node_lib
Jan 4, 2018
02493bb
Added Linux build commands to README
luminosuslight Jan 4, 2018
aa2c043
implement Terminate(), RequestTerminate(), RunEventLoop()
justus-hildebrand Jan 5, 2018
6ed7163
Short comments on what the Start() funcs do
justus-hildebrand Jan 5, 2018
2fae0db
Implemented Initialize(), Run() and Evaluate()
cmfcmf Jan 7, 2018
c01f4e5
Replace argc agrv in Initialize() with std::string
luminosuslight Jan 8, 2018
6acebd9
wip
msoechting Jan 8, 2018
4ad8cce
Cleaned code style (no indent for namespaces, left-lean asteriks, uni…
luminosuslight Jan 9, 2018
cc91ae3
Refactored cmd arg generation
luminosuslight Jan 9, 2018
4812646
Fixed cmd args
luminosuslight Jan 9, 2018
9a264ce
Moved code from Initialize() to new functions
luminosuslight Jan 9, 2018
ef6b4e5
Removed unused v8 argc argv
luminosuslight Jan 10, 2018
53f74b8
Implement remaining Call() methods
cmfcmf Jan 10, 2018
d5bb393
Re-add missing node.h include
cmfcmf Jan 14, 2018
d7d4b2b
Make RegisterModule work. Sadly, we can't use std::function|s, becaus…
cmfcmf Jan 14, 2018
f3e7a6d
fix issues from comments on PR #16
justus-hildebrand Jan 15, 2018
7a59273
Fix pointer to stack variable in register module
luminosuslight Jan 15, 2018
9175443
Use UV_RUN_NOWAIT, @justus-hildebrand
cmfcmf Jan 16, 2018
75f39b0
Merge branch 'interface-implementation' of github.com:hpicgs/node int…
cmfcmf Jan 16, 2018
674c0ee
add comments and TODOs for investigation
justus-hildebrand Jan 17, 2018
4e32b91
Implement `Deinitialize()` and `StopEventLoop()`
Jan 19, 2018
734d0d6
Don't read from stdin
cmfcmf Jan 19, 2018
0c575d5
Merge pull request #16 from hpicgs/interface-implementation
Jan 22, 2018
b945ac7
WIP usage
msoechting Jan 22, 2018
78329e0
Update usage documentation
msoechting Jan 22, 2018
6ea63e2
added code docu
Jan 22, 2018
a323279
refactored internals
Jan 24, 2018
6126411
Option to auto-call process.binding() when calling RegisterModule() (…
justus-hildebrand Jan 24, 2018
0ee4348
Rename getters to match style guide
cmfcmf Jan 29, 2018
200c1a9
added error handling via MaybeLocal (#40)
Jan 29, 2018
ee01950
Add support for cmd args (#39)
luminosuslight Jan 29, 2018
d7c8a33
Merge branch 'node_lib' into expose_internals
cmfcmf Jan 29, 2018
22a3107
Update README.md
EmberFlare Jan 29, 2018
5e7adc7
Merge branch 'node_lib' into expose_internals
EmberFlare Jan 29, 2018
e582066
early check for uv_loop_alive(), small refactoring
justus-hildebrand Jan 29, 2018
25211e6
Merge pull request #41 from hpicgs/expose_internals
Jan 30, 2018
6854d8f
changed the way internals are exposed.
Jan 30, 2018
807709d
included feedback from PR
Jan 30, 2018
c51f3f6
Fix method names
luminosuslight Jan 30, 2018
c5c73ff
fix nits
justus-hildebrand Jan 30, 2018
2bb42fb
Merge branch 'node_lib' into tick-event-loop-early-exit
justus-hildebrand Jan 30, 2018
ecee92a
Merge pull request #46 from hpicgs/tick-event-loop-early-exit
luminosuslight Jan 30, 2018
588ab28
moved 'EventLoopIsRunning' back to node::lib
Jan 30, 2018
b607c9f
Merge branch 'node_lib' into expose_internals
justus-hildebrand Jan 30, 2018
5539564
Merge pull request #47 from hpicgs/expose_internals
Jan 31, 2018
40baf2c
Merge branch 'node_lib' into lib-usage-documentation
EmberFlare Jan 31, 2018
e693ecf
added code docu
Jan 22, 2018
0ed0c77
included feedback from PR
Jan 30, 2018
2e6b1ff
fixed merge problems, added more docu for new methods
Jan 31, 2018
c913d75
Merge remote-tracking branch 'origin/interface_docu' into interface_docu
Jan 31, 2018
9c6bf17
Merge pull request #37 from hpicgs/interface_docu
EmberFlare Jan 31, 2018
cac4d43
Merge branch 'node_lib' into lib-usage-documentation
EmberFlare Jan 31, 2018
fd520a7
Merge pull request #35 from hpicgs/lib-usage-documentation
EmberFlare Jan 31, 2018
fe6a38a
Start fixing code style
luminosuslight Feb 1, 2018
334c3a6
Fix more code style, left leaning asterisks
luminosuslight Feb 1, 2018
f45be81
Fix C style cast
luminosuslight Feb 1, 2018
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
213 changes: 153 additions & 60 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4992,9 +4992,73 @@ int Start(int argc, char** argv) {

namespace lib {

struct CmdArgs {
/**
* @brief The CmdArgs class is a container for argc and argv.
*/
class CmdArgs {

public:
/**
* @brief CmdArgs creates valid argc and argv variables from a program name and arguments.
*
* The argv buffer is a contiguous, adjacent char buffer and contains the program name
* as its first item followed by the provided arguments. argc is the number of
* arguments + 1 (the program name).
* The resulting argv buffer should not be modified.
*
* @param program_name the name of the executable
* @param arguments the arguments for the program
*/
CmdArgs(const std::string& program_name, const std::vector<std::string>& arguments)
: argc(0)
, argv(nullptr)
{
size_t total_size = 0;
total_size += program_name.size() + 1;
for (const auto& argument: arguments) {
total_size += argument.size() + 1;
}

std::vector<std::size_t> offsets;
argument_data.reserve(total_size);
offsets.push_back(argument_data.size());
argument_data += program_name;
argument_data += char(0x0);
for (const auto& argument: arguments) {
offsets.push_back(argument_data.size());
argument_data += argument;
argument_data += char(0x0);
}

argument_pointers.resize(offsets.size());
for (std::size_t i=0; i<argument_pointers.size(); ++i) {
argument_pointers[i] = argument_data.data() + offsets[i];
}
argc = argument_pointers.size();
argv = argument_pointers.data();
}

~CmdArgs() = default;

/**
* @brief argc is the number of arguments + 1 (the program name)
*/
int argc;
char** argv;
/**
* @brief argv is an array containing pointers to the arguments (and the program name),
* it should not be modified
*/
const char** argv;

private:
/**
* @brief argument_data contains the program name and the arguments separated by null bytes
*/
std::string argument_data;
/**
* @brief argument_pointers contains pointers to the beginnings of the strings in argument_data
*/
std::vector<const char*> argument_pointers;
};

ArrayBufferAllocator* allocator;
Expand All @@ -5013,8 +5077,8 @@ void deleteCmdArgs() {
if (!cmd_args) {
return;
}
delete[] cmd_args->argv;
delete cmd_args;
cmd_args = nullptr;
}

int _StopEnv() {
Expand Down Expand Up @@ -5058,15 +5122,6 @@ void deinitV8() {

namespace initialize {

void generateCmdArgsFromProgramName(const std::string& program_name) {
deinitialize::deleteCmdArgs();
int argc = 1;
char* program_name_c_string = new char[program_name.length() + 1];
std::strcpy(program_name_c_string, program_name.c_str());
char** argv = new char*(program_name_c_string);
cmd_args = new CmdArgs{argc, argv};
}

void initV8() {
v8_platform.Initialize(v8_thread_pool_size, uv_default_loop());
// Enable tracing when argv has --trace-events-enabled.
Expand Down Expand Up @@ -5180,28 +5235,27 @@ void _StartEnv(int argc,

} // namespace initialize

void Initialize(const std::string& program_name) {
void Initialize(const std::string& program_name, const std::vector<std::string>& node_args) {
//////////
// Start 1
//////////
atexit([] () { uv_tty_reset_mode(); });
PlatformInit();
node::performance::performance_node_start = PERFORMANCE_NOW();

// currently we do not support additional commandline options for node, uv, or v8
// we explicitily only set the first argument to the program name
initialize::generateCmdArgsFromProgramName(program_name);
cmd_args = new CmdArgs(program_name, node_args);

// Hack around with the argv pointer. Used for process.title = "blah".
cmd_args->argv = uv_setup_args(cmd_args->argc, cmd_args->argv);
// Hack around with the argv pointer. Used for process.title = "blah --args".
// argv won't be modified
uv_setup_args(cmd_args->argc, const_cast<char**>(cmd_args->argv));

// This needs to run *before* V8::Initialize(). The const_cast is not
// optional, in case you're wondering.
// Init() puts the v8 specific cmd args in exec_argc and exec_argv, but as we
// don't support these, they are not used.
int exec_argc = 0;
const char** exec_argv = nullptr;
Init(&cmd_args->argc, const_cast<const char**>(cmd_args->argv), &exec_argc, &exec_argv);
Init(&cmd_args->argc, cmd_args->argv, &exec_argc, &exec_argv);

initialize::configureOpenSsl();

Expand Down Expand Up @@ -5242,7 +5296,7 @@ int Deinitialize() {
return exit_code;
}

v8::Local<v8::Value> Run(const std::string& path) {
v8::MaybeLocal<v8::Value> Run(const std::string& path) {
// Read entire file into string. There is most certainly a better way ;)
// https://stackoverflow.com/a/2602258/2560557
std::ifstream t(path);
Expand All @@ -5252,7 +5306,7 @@ v8::Local<v8::Value> Run(const std::string& path) {
return Evaluate(buffer.str());
}

v8::Local<v8::Value> Evaluate(const std::string& java_script_code) {
v8::MaybeLocal<v8::Value> Evaluate(const std::string& java_script_code) {
EscapableHandleScope scope(_environment->isolate());
TryCatch try_catch(_environment->isolate());

Expand All @@ -5264,16 +5318,10 @@ v8::Local<v8::Value> Evaluate(const std::string& java_script_code) {
MaybeLocal<v8::Script> script = v8::Script::Compile(_environment->context(), v8::String::NewFromUtf8(_isolate, java_script_code.c_str())/*, origin*/);
if (script.IsEmpty()) {
ReportException(_environment, try_catch);
exit(3); //TODO jh: don't exit process when function breaks. Handle error differently.
return MaybeLocal<v8::Value>();
}

Local<Value> result = script.ToLocalChecked()->Run();
if (result.IsEmpty()) {
ReportException(_environment, try_catch);
exit(4); //TODO jh: don't exit process when function breaks. Handle error differently.
}

return scope.Escape(result);
return MaybeLocal<v8::Value>(scope.Escape(script.ToLocalChecked()->Run()));
}

void RunEventLoop(const std::function<void()>& callback) {
Expand All @@ -5292,66 +5340,112 @@ void RunEventLoop(const std::function<void()>& callback) {
_event_loop_running = false;
}

v8::Local<v8::Object> GetRootObject() {
v8::MaybeLocal<v8::Object> GetRootObject() {
if (context.IsEmpty()) {
return MaybeLocal<v8::Object>();
}
return context->Global();
}


v8::Local<v8::Value> Call(v8::Local<v8::Object> receiver, v8::Local<v8::Function> function, const std::vector<v8::Local<v8::Value>> & args = {}) {
v8::MaybeLocal<v8::Value> Call(v8::Local<v8::Object> receiver, v8::Local<v8::Function> function, const std::vector<v8::Local<v8::Value>> & args) {
return function->Call(receiver, args.size(), const_cast<v8::Local<v8::Value>*>(&args[0]));
}

v8::Local<v8::Value> Call(v8::Local<v8::Object> receiver, v8::Local<v8::Function> function, std::initializer_list<v8::Local<v8::Value>> args) {
v8::MaybeLocal<v8::Value> Call(v8::Local<v8::Object> receiver, v8::Local<v8::Function> function, std::initializer_list<v8::Local<v8::Value>> args) {
return Call(receiver, function, std::vector<v8::Local<v8::Value>>(args));
}

// TODO: Error handling: Node.js has exceptions disabled.
v8::Local<v8::Value> Call(v8::Local<v8::Object> object, const std::string& function_name, const std::vector<v8::Local<v8::Value>>& args) {
Local<v8::String> v8_function_name = v8::String::NewFromUtf8(_isolate, function_name.c_str());
v8::MaybeLocal<v8::Value> Call(v8::Local<v8::Object> object, const std::string& function_name, const std::vector<v8::Local<v8::Value>>& args) {
MaybeLocal<v8::String> maybe_function_name = v8::String::NewFromUtf8(_isolate, function_name.c_str());
Local<v8::String> v8_function_name;

Local<v8::Value> value = object->Get(v8_function_name);
if (!value->IsFunction()) {
//throw new Exception(":((");
// TODO (js): at least return at this point
if (!maybe_function_name.ToLocal(&v8_function_name)) {
// cannot create v8 string.
return MaybeLocal<v8::Value>();
}

MaybeLocal<v8::Value> maybe_value = object->Get(v8_function_name);
Local<v8::Value> value;

if (!maybe_value.ToLocal(&value)) {
// cannot get member of object
return MaybeLocal<v8::Value>();
} else if (!value->IsFunction()) {
// cannot execute non-function
return MaybeLocal<v8::Value>();
}

return Call(object, v8::Local<v8::Function>::Cast(value), args);
}

v8::Local<v8::Value> Call(v8::Local<v8::Object> object, const std::string & function_name, std::initializer_list<v8::Local<v8::Value>> args) {
v8::MaybeLocal<v8::Value> Call(v8::Local<v8::Object> object, const std::string & function_name, std::initializer_list<v8::Local<v8::Value>> args) {
return Call(object, function_name, std::vector<v8::Local<v8::Value>>(args));
}

// TODO: Node.js has exceptions disabled.
v8::Local<v8::Object> IncludeModule(const std::string& module_name) {
std::vector<v8::Local<v8::Value>> args = {v8::String::NewFromUtf8(_isolate, module_name.c_str())};
v8::MaybeLocal<v8::Object> IncludeModule(const std::string& module_name) {
MaybeLocal<v8::String> maybe_arg = v8::String::NewFromUtf8(_isolate, module_name.c_str());
Local<v8::String> arg;

if (!maybe_arg.ToLocal(&arg)) {
// cannot create v8 string
return MaybeLocal<v8::Object>();
}

Local<v8::Object> root_object;

if (!GetRootObject().ToLocal(&root_object)) {
// cannot get root object
return MaybeLocal<v8::Object>();
}

std::vector<Local<v8::Value>> args = { arg };

MaybeLocal<v8::Value> maybe_module = Call(root_object, "require", args);
Local<v8::Value> module;

if (!maybe_module.ToLocal(&module)) {
// cannot get module
return MaybeLocal<v8::Object>();
}

return MaybeLocal<v8::Object>(Local<v8::Object>::Cast(module));
}

v8::MaybeLocal<v8::Value> GetValue(v8::Local<v8::Object> object, const std::string& value_name) {
MaybeLocal<v8::String> maybe_key = v8::String::NewFromUtf8(_isolate, value_name.c_str());
Local<v8::String> key;

auto module = Call(GetRootObject(), "require", args);
if (module->IsUndefined()) {
//TODO jh: throw new Exception(":(("); // repuire() call failed, but did not throw a JS exception.
// TODO (js): at least return at this point
if (!maybe_key.ToLocal(&key)) {
// cannot create v8::String
return MaybeLocal<v8::Value>();
}

return v8::Local<v8::Object>::Cast(module);
return object->Get(context, key);
}

void RegisterModule(const std::string & name, const addon_context_register_func & callback, void *priv) {
node::node_module* module = new node::node_module();
void RegisterModule(const std::string & name, const addon_context_register_func & callback, void *priv, const std::string & target) {
node::node_module* module = new node::node_module();

module->nm_version = NODE_MODULE_VERSION;
module->nm_flags = NM_F_BUILTIN;
module->nm_filename = __FILE__;
module->nm_context_register_func = callback;
module->nm_modname = name.c_str();
module->nm_priv = priv;
module->nm_version = NODE_MODULE_VERSION;
module->nm_flags = NM_F_BUILTIN;
module->nm_filename = __FILE__;
module->nm_context_register_func = callback;
module->nm_modname = name.c_str();
module->nm_priv = priv;

node_module_register(module);
node_module_register(module);

if(target != "") {
Evaluate("const " + target + " = process.binding('" + name + "')");
}
}

void RegisterModule(const std::string & name,
const std::map<std::string, v8::FunctionCallback> & module_functions) {
const std::map<std::string, v8::FunctionCallback> & module_functions,
const std::string & target) {
auto map_on_heap = new const std::map<std::string, v8::FunctionCallback>(module_functions);
RegisterModule(name, node::lib::_RegisterModuleCallback, const_cast<std::map<std::string, v8::FunctionCallback>*>(map_on_heap));
RegisterModule(name, node::lib::_RegisterModuleCallback, const_cast<std::map<std::string, v8::FunctionCallback>*>(map_on_heap), target);
}

void _RegisterModuleCallback(v8::Local<v8::Object> exports,
Expand All @@ -5375,7 +5469,6 @@ void StopEventLoop() {
return;
}
request_stop = true;
//while (request_stop && _event_loop_running) { }
}

bool ProcessEvents() {
Expand Down
Loading