diff --git a/Android.common.mk b/Android.common.mk index 87cb883c5e2d..41ef951d2a4c 100644 --- a/Android.common.mk +++ b/Android.common.mk @@ -34,6 +34,7 @@ LOCAL_C_INCLUDES += \ LOCAL_SRC_FILES := \ src/node.cc \ + src/node_androidlog.cc \ src/node_buffer.cc \ src/node_constants.cc \ src/node_crypto.cc \ diff --git a/Android.mk b/Android.mk index aa3fa256baf6..e13f89990fbc 100644 --- a/Android.mk +++ b/Android.mk @@ -21,6 +21,8 @@ include $(LOCAL_PATH)/Android.common.mk # to override exit handling in node.cc LOCAL_CFLAGS += -DNODE_LIBRARY +LOCAL_LDLIBS += -llog + include $(BUILD_STATIC_LIBRARY) $(call import-module,deps/http_parser) diff --git a/Application.mk b/Application.mk index 47f54d945612..509710cfe1a4 100644 --- a/Application.mk +++ b/Application.mk @@ -1,3 +1,4 @@ APP_PROJECT_PATH :=. APP_BUILD_SCRIPT :=$(APP_PROJECT_PATH)/Android.exe.mk APP_PLATFORM := android-9 +APP_ABI := armeabi-v7a diff --git a/lib/console.js b/lib/console.js index ac8912f828ea..d793d7a762f0 100644 --- a/lib/console.js +++ b/lib/console.js @@ -21,24 +21,61 @@ var util = require('util'); -exports.log = function() { - process.stdout.write(util.format.apply(this, arguments) + '\n'); + +var os = require('os'); +var isandroid = (os.platform() == 'android'); +if (isandroid) { + var binding = process.binding('androidlog'); +} + +if (!isandroid) { + exports.log = function() { + process.stdout.write(util.format.apply(this, arguments) + '\n'); + }; +} else { + exports.log = function() { + binding.debug(util.format.apply(this, arguments)); + }; }; -exports.info = exports.log; +if (!isandroid) { + exports.info = exports.log; +} else { + exports.info = function() { + binding.info(util.format.apply(this, arguments)); + }; +}; -exports.warn = function() { - process.stderr.write(util.format.apply(this, arguments) + '\n'); +if (!isandroid) { + exports.warn = function() { + process.stderr.write(util.format.apply(this, arguments) + '\n'); + }; +} else { + exports.warn = function() { + binding.warn(util.format.apply(this, arguments)); + }; }; -exports.error = exports.warn; +if (!isandroid) { + exports.error = exports.warn; +} else { + exports.error = function() { + binding.error(util.format.apply(this, arguments)); + }; +}; -exports.dir = function(object) { - process.stdout.write(util.inspect(object) + '\n'); +if (!isandroid) { + exports.dir = function(object) { + process.stdout.write(util.inspect(object) + '\n'); + }; +} else { + exports.dir = function(object) { + binding.verbose(util.inspect(object)); + }; }; diff --git a/node.gyp b/node.gyp index 0677cfefcde2..3249209e878c 100644 --- a/node.gyp +++ b/node.gyp @@ -73,6 +73,7 @@ 'src/cares_wrap.cc', 'src/handle_wrap.cc', 'src/node.cc', + 'src/node_androidlog.cc' 'src/node_buffer.cc', 'src/node_constants.cc', 'src/node_extensions.cc', @@ -94,6 +95,7 @@ # headers to make for a more pleasant IDE experience 'src/handle_wrap.h', 'src/node.h', + 'src/node_androidlog.h' 'src/node_buffer.h', 'src/node_constants.h', 'src/node_crypto.h', diff --git a/src/node.cc b/src/node.cc index 4d2fd74a36f9..bedfbc635ca3 100644 --- a/src/node.cc +++ b/src/node.cc @@ -79,6 +79,17 @@ typedef int mode_t; # include # include #endif + +#ifdef ANDROID +#include +#define DEBUG_TAG "node.js" +#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, DEBUG_TAG,__VA_ARGS__) +#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , DEBUG_TAG,__VA_ARGS__) +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , DEBUG_TAG,__VA_ARGS__) +#define LOGW(...) __android_log_print(ANDROID_LOG_WARN , DEBUG_TAG,__VA_ARGS__) +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , DEBUG_TAG,__VA_ARGS__) +#endif + #include #include #include @@ -835,6 +846,7 @@ void MakeCallback(Handle object, Local callback_v = object->Get(String::New(method)); if (!callback_v->IsFunction()) { fprintf(stderr, "method = %s", method); + LOGE("method = %s", method); } assert(callback_v->IsFunction()); Local callback = Local::Cast(callback_v); @@ -903,10 +915,14 @@ enum encoding ParseEncoding(Handle encoding_v, enum encoding _default) { } else if (strcasecmp(*encoding, "raw") == 0) { fprintf(stderr, "'raw' (array of integers) has been removed. " "Use 'binary'.\n"); + LOGE("'raw' (array of integers) has been removed. " + "Use 'binary'.\n"); return BINARY; } else if (strcasecmp(*encoding, "raws") == 0) { fprintf(stderr, "'raws' encoding has been renamed to 'binary'. " "Please update your code.\n"); + LOGE("'raws' encoding has been renamed to 'binary'. " + "Please update your code.\n"); return BINARY; } else { return _default; @@ -942,6 +958,8 @@ ssize_t DecodeBytes(v8::Handle val, enum encoding encoding) { if (val->IsArray()) { fprintf(stderr, "'raw' encoding (array of integers) has been removed. " "Use 'binary'.\n"); + LOGE("'raw' encoding (array of integers) has been removed. " + "Use 'binary'.\n"); assert(0); return -1; } @@ -975,6 +993,8 @@ ssize_t DecodeWrite(char *buf, if (val->IsArray()) { fprintf(stderr, "'raw' encoding (array of integers) has been removed. " "Use 'binary'.\n"); + LOGE("'raw' encoding (array of integers) has been removed. " + "Use 'binary'.\n"); assert(0); return -1; } @@ -1018,6 +1038,7 @@ void DisplayExceptionLine (TryCatch &try_catch) { uv_tty_reset_mode(); fprintf(stderr, "\n"); + LOGE("\n"); if (!message.IsEmpty()) { // Print (filename):(line number): (message). @@ -1025,6 +1046,7 @@ void DisplayExceptionLine (TryCatch &try_catch) { const char* filename_string = *filename; int linenum = message->GetLineNumber(); fprintf(stderr, "%s:%i\n", filename_string, linenum); + LOGE("%s:%i\n", filename_string, linenum); // Print line of source code. String::Utf8Value sourceline(message->GetSourceLine()); const char* sourceline_string = *sourceline; @@ -1050,6 +1072,7 @@ void DisplayExceptionLine (TryCatch &try_catch) { int offset = linenum == 1 ? 62 : 0; fprintf(stderr, "%s\n", sourceline_string + offset); + LOGE("%s\n", sourceline_string + offset); // Print wavy underline (GetUnderline is deprecated). int start = message->GetStartColumn(); for (int i = offset; i < start; i++) { @@ -1058,8 +1081,10 @@ void DisplayExceptionLine (TryCatch &try_catch) { int end = message->GetEndColumn(); for (int i = start; i < end; i++) { fprintf(stderr, "^"); + LOGE("^"); } fprintf(stderr, "\n"); + LOGE("\n"); } } @@ -1075,6 +1100,7 @@ static void ReportException(TryCatch &try_catch, bool show_line) { // range errors have a trace member set to undefined if (trace.length() > 0 && !try_catch.StackTrace()->IsUndefined()) { fprintf(stderr, "%s\n", *trace); + LOGE("%s\n", *trace); } else { // this really only happens for RangeErrors, since they're the only // kind that won't have all this info in the trace, or when non-Error @@ -1087,11 +1113,13 @@ static void ReportException(TryCatch &try_catch, bool show_line) { if (isErrorObject) { String::Utf8Value name(er->ToObject()->Get(String::New("name"))); fprintf(stderr, "%s: ", *name); + LOGE("%s: ", *name); } String::Utf8Value msg(!isErrorObject ? er->ToString() : er->ToObject()->Get(String::New("message"))->ToString()); fprintf(stderr, "%s\n", *msg); + LOGE("%s\n", *msg); } fflush(stderr); @@ -1553,8 +1581,10 @@ Handle DLOpen(const v8::Arguments& args) { void OnFatalError(const char* location, const char* message) { if (location) { fprintf(stderr, "FATAL ERROR: %s %s\n", location, message); + LOGE("FATAL ERROR: %s %s\n", location, message); } else { fprintf(stderr, "FATAL ERROR: %s\n", message); + LOGE("FATAL ERROR: %s\n", message); } BREAK_AND_EXIT(1); } @@ -1758,6 +1788,7 @@ static Handle EnvSetter(Local property, int r = _putenv(pair); if (r) { fprintf(stderr, "error putenv: '%s'\n", pair); + LOGE("error putenv: '%s'\n", pair); } delete [] pair; #endif @@ -1802,6 +1833,7 @@ static Handle EnvDeleter(Local property, int r = _putenv(pair); if (r) { fprintf(stderr, "error unsetenv: '%s'\n", pair); + LOGE("error unsetenv: '%s'\n", pair); } delete [] pair; #endif @@ -2093,6 +2125,24 @@ static void PrintHelp() { "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n" "\n" "Documentation can be found at http://nodejs.org/\n"); + LOGV("Usage: node [options] [ -e script | script.js ] [arguments] \n" + " node debug script.js [arguments] \n" + "\n" + "Options:\n" + " -v, --version print node's version\n" + " -e, --eval script evaluate script\n" + " --v8-options print v8 command line options\n" + " --vars print various compiled-in variables\n" + " --max-stack-size=val set max v8 stack size (bytes)\n" + "\n" + "Enviromental variables:\n" + "NODE_PATH ':'-separated list of directories\n" + " prefixed to the module search path.\n" + "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n" + " global contexts.\n" + "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n" + "\n" + "Documentation can be found at http://nodejs.org/\n"); } NodeOptions::NodeOptions() { @@ -2122,13 +2172,16 @@ void NodeOptions::ParseArgs(int argc, char **argv) { #ifndef NODE_LIBRARY } else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) { printf("%s\n", NODE_VERSION); + LOGV("%s\n", NODE_VERSION); exit(0); } else if (strcmp(arg, "--vars") == 0) { #ifdef NODE_PREFIX printf("NODE_PREFIX: %s\n", NODE_PREFIX); + LOGV("NODE_PREFIX: %s\n", NODE_PREFIX); #endif #ifdef NODE_CFLAGS printf("NODE_CFLAGS: %s\n", NODE_CFLAGS); + LOGV("NODE_CFLAGS: %s\n", NODE_CFLAGS); #endif exit(0); } else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { @@ -2145,6 +2198,7 @@ void NodeOptions::ParseArgs(int argc, char **argv) { } else if (strcmp(arg, "--eval") == 0 || strcmp(arg, "-e") == 0) { if (argc <= i + 1) { fprintf(stderr, "Error: --eval requires an argument\n"); + LOGE("Error: --eval requires an argument\n"); EXIT(1); } argv[i] = const_cast(""); @@ -2180,8 +2234,11 @@ void NodeOptions::ParseDebugOpt(const char* arg) { return; fprintf(stderr, "Bad debug option.\n"); - if (p) fprintf(stderr, "Debug port must be in range 1025 to 65535.\n"); - + LOGE("Bad debug option.\n"); + if (p) { + fprintf(stderr, "Debug port must be in range 1025 to 65535.\n"); + LOGE("Debug port must be in range 1025 to 65535.\n"); + } PrintHelp(); EXIT(1); } @@ -2225,6 +2282,7 @@ static void EnableDebug(bool wait_connect) { // Print out some information. fprintf(stderr, "debugger listening on port %d\n", options.debug_port); + LOGE("debugger listening on port %d\n", options.debug_port); fflush(stderr); debugger_running = true; @@ -2240,6 +2298,7 @@ void EnableDebugSignalHandler(int signal) { if (!debugger_running) { fprintf(stderr, "Hit SIGUSR1 - starting debugger agent.\n"); + LOGE("Hit SIGUSR1 - starting debugger agent.\n"); EnableDebug(false); } } @@ -2282,6 +2341,7 @@ DWORD WINAPI EnableDebugThreadProc(void* arg) { if (!debugger_running) { for (int i = 0; i < 1; i++) { fprintf(stderr, "Starting debugger agent.\r\n"); + LOGE("Starting debugger agent.\r\n"); fflush(stderr); EnableDebug(false); } @@ -2619,12 +2679,16 @@ void Isolate::Dispose() { int Isolate::Stop(int signum) { /* trigger the event loop to wake up, and (in the callback) * break out of the loop */ + LOGD("Stopping signum %d", signum); uv_async_send(&stop_watcher); + LOGD("Loop broken"); /* forcibly terminate any ongoing javascript execution, forcing * execution to return back to the event loop */ if(signum == SIGKILL || signum == SIGABRT) { + LOGD("Trying kill"); term_signal = signum; V8::TerminateExecution(isolate); + LOGD("Terminated"); } return exit_status; } diff --git a/src/node_androidlog.cc b/src/node_androidlog.cc new file mode 100644 index 000000000000..c98cfafee57b --- /dev/null +++ b/src/node_androidlog.cc @@ -0,0 +1,126 @@ +// Copyright Natsume23 +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include +#include + +#include + +#include + +#define DEBUG +#ifdef DEBUG +# ifdef ANDROID +# include +# define DEBUG_TAG "node.js" +# define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, DEBUG_TAG, __VA_ARGS__) +# define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, __VA_ARGS__) +# define LOGI(...) __android_log_print(ANDROID_LOG_INFO, DEBUG_TAG, __VA_ARGS__) +# define LOGW(...) __android_log_print(ANDROID_LOG_WARN, DEBUG_TAG, __VA_ARGS__) +# define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, DEBUG_TAG, __VA_ARGS__) +# else +# define LOGV(...) fprintf(stdout, __VA_ARGS__) +# define LOGD(...) fprintf(stdout, __VA_ARGS__) +# define LOGI(...) fprintf(stdout, __VA_ARGS__) +# define LOGW(...) fprintf(stderr, __VA_ARGS__) +# define LOGE(...) fprintf(stderr, __VA_ARGS__) +# endif +#else +# define LOGV(...) +# define LOGD(...) +# define LOGI(...) +# define LOGW(...) +# define LOGE(...) +#endif + +namespace node { + +using namespace v8; + +const char* ToCString(const v8::String::Utf8Value& value) { + return *value ? *value : ""; +} + + +static Handle Verbose(const Arguments& args) { + HandleScope scope; + + if (args.Length() > 0) { + v8::String::Utf8Value msg(args[0]); + LOGV(ToCString(msg)); + } + return scope.Close(Undefined()); +} + +static Handle Debug(const Arguments& args) { + HandleScope scope; + + if (args.Length() > 0) { + v8::String::Utf8Value msg(args[0]); + LOGD(ToCString(msg)); + } + return scope.Close(Undefined()); +} + +static Handle Info(const Arguments& args) { + HandleScope scope; + + if (args.Length() > 0) { + v8::String::Utf8Value msg(args[0]); + LOGI(ToCString(msg)); + } + return scope.Close(Undefined()); +} + +static Handle Warn(const Arguments& args) { + HandleScope scope; + + if (args.Length() > 0) { + v8::String::Utf8Value msg(args[0]); + LOGW(ToCString(msg)); + } + return scope.Close(Undefined()); +} + +static Handle Error(const Arguments& args) { + HandleScope scope; + + if (args.Length() > 0) { + v8::String::Utf8Value msg(args[0]); + LOGE(ToCString(msg)); + } + return scope.Close(Undefined()); +} + +void Androidlog::Initialize(v8::Handle target) { + HandleScope scope; + + NODE_SET_METHOD(target, "log", Verbose); + NODE_SET_METHOD(target, "verbose", Verbose); + NODE_SET_METHOD(target, "debug", Debug); + NODE_SET_METHOD(target, "info", Info); + NODE_SET_METHOD(target, "warn", Warn); + NODE_SET_METHOD(target, "error", Error); +} + +} // namespace node + +NODE_MODULE(node_androidlog, node::Androidlog::Initialize) diff --git a/src/node_androidlog.h b/src/node_androidlog.h new file mode 100644 index 000000000000..d2f16649bd48 --- /dev/null +++ b/src/node_androidlog.h @@ -0,0 +1,38 @@ +// Copyright Natsume23 +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef node_androidlog_h +#define node_androidlog_h + +#include +#include + +namespace node { + +class Androidlog { +public: + static void Initialize (v8::Handle target); +}; + + +} // namespace node + +#endif // node_androidlog_h diff --git a/src/node_extensions.h b/src/node_extensions.h index 39ddf1748fa2..92cee90c9959 100644 --- a/src/node_extensions.h +++ b/src/node_extensions.h @@ -21,6 +21,7 @@ NODE_EXT_LIST_START +NODE_EXT_LIST_ITEM(node_androidlog) NODE_EXT_LIST_ITEM(node_buffer) #if HAVE_OPENSSL NODE_EXT_LIST_ITEM(node_crypto) diff --git a/wscript b/wscript index 02ede45ad282..1ecc9cdd1a19 100644 --- a/wscript +++ b/wscript @@ -861,6 +861,7 @@ def build(bld): node.chmod = 0755 node.source = """ src/node.cc + src/node_androidlog.cc src/node_buffer.cc src/node_javascript.cc src/node_extensions.cc