node: do not print SyntaxError hints to stderr
Try embedding the ` ... ^` lines inside the `SyntaxError` (or any other native error) object before giving up and printing them to the stderr. fix #6920 fix #1310
This commit is contained in:
parent
6cbfcdad46
commit
f1de13b8ab
@ -224,6 +224,7 @@ inline Environment::Environment(v8::Local<v8::Context> context)
|
|||||||
isolate_data_(IsolateData::GetOrCreate(context->GetIsolate())),
|
isolate_data_(IsolateData::GetOrCreate(context->GetIsolate())),
|
||||||
using_smalloc_alloc_cb_(false),
|
using_smalloc_alloc_cb_(false),
|
||||||
using_domains_(false),
|
using_domains_(false),
|
||||||
|
printed_error_(false),
|
||||||
context_(context->GetIsolate(), context) {
|
context_(context->GetIsolate(), context) {
|
||||||
// We'll be creating new objects so make sure we've entered the context.
|
// We'll be creating new objects so make sure we've entered the context.
|
||||||
v8::HandleScope handle_scope(isolate());
|
v8::HandleScope handle_scope(isolate());
|
||||||
@ -330,6 +331,14 @@ inline void Environment::set_using_domains(bool value) {
|
|||||||
using_domains_ = value;
|
using_domains_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool Environment::printed_error() const {
|
||||||
|
return printed_error_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Environment::set_printed_error(bool value) {
|
||||||
|
printed_error_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) {
|
inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) {
|
||||||
return CONTAINER_OF(handle, Environment, cares_timer_handle_);
|
return CONTAINER_OF(handle, Environment, cares_timer_handle_);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,7 @@ namespace node {
|
|||||||
V(ipv6_string, "IPv6") \
|
V(ipv6_string, "IPv6") \
|
||||||
V(issuer_string, "issuer") \
|
V(issuer_string, "issuer") \
|
||||||
V(mark_sweep_compact_string, "mark-sweep-compact") \
|
V(mark_sweep_compact_string, "mark-sweep-compact") \
|
||||||
|
V(message_string, "message") \
|
||||||
V(method_string, "method") \
|
V(method_string, "method") \
|
||||||
V(mode_string, "mode") \
|
V(mode_string, "mode") \
|
||||||
V(modulus_string, "modulus") \
|
V(modulus_string, "modulus") \
|
||||||
@ -115,6 +116,7 @@ namespace node {
|
|||||||
V(onstop_string, "onstop") \
|
V(onstop_string, "onstop") \
|
||||||
V(path_string, "path") \
|
V(path_string, "path") \
|
||||||
V(port_string, "port") \
|
V(port_string, "port") \
|
||||||
|
V(processed_string, "processed") \
|
||||||
V(rdev_string, "rdev") \
|
V(rdev_string, "rdev") \
|
||||||
V(rename_string, "rename") \
|
V(rename_string, "rename") \
|
||||||
V(rss_string, "rss") \
|
V(rss_string, "rss") \
|
||||||
@ -127,6 +129,7 @@ namespace node {
|
|||||||
V(smalloc_p_string, "_smalloc_p") \
|
V(smalloc_p_string, "_smalloc_p") \
|
||||||
V(sni_context_err_string, "Invalid SNI context") \
|
V(sni_context_err_string, "Invalid SNI context") \
|
||||||
V(sni_context_string, "sni_context") \
|
V(sni_context_string, "sni_context") \
|
||||||
|
V(stack_string, "stack") \
|
||||||
V(status_code_string, "statusCode") \
|
V(status_code_string, "statusCode") \
|
||||||
V(status_message_string, "statusMessage") \
|
V(status_message_string, "statusMessage") \
|
||||||
V(subject_string, "subject") \
|
V(subject_string, "subject") \
|
||||||
@ -302,6 +305,9 @@ class Environment {
|
|||||||
inline bool using_domains() const;
|
inline bool using_domains() const;
|
||||||
inline void set_using_domains(bool value);
|
inline void set_using_domains(bool value);
|
||||||
|
|
||||||
|
inline bool printed_error() const;
|
||||||
|
inline void set_printed_error(bool value);
|
||||||
|
|
||||||
// Strings are shared across shared contexts. The getters simply proxy to
|
// Strings are shared across shared contexts. The getters simply proxy to
|
||||||
// the per-isolate primitive.
|
// the per-isolate primitive.
|
||||||
#define V(PropertyName, StringValue) \
|
#define V(PropertyName, StringValue) \
|
||||||
@ -343,6 +349,7 @@ class Environment {
|
|||||||
bool using_smalloc_alloc_cb_;
|
bool using_smalloc_alloc_cb_;
|
||||||
bool using_domains_;
|
bool using_domains_;
|
||||||
QUEUE gc_tracker_queue_;
|
QUEUE gc_tracker_queue_;
|
||||||
|
bool printed_error_;
|
||||||
|
|
||||||
#define V(PropertyName, TypeName) \
|
#define V(PropertyName, TypeName) \
|
||||||
v8::Persistent<TypeName> PropertyName ## _;
|
v8::Persistent<TypeName> PropertyName ## _;
|
||||||
|
196
src/node.cc
196
src/node.cc
@ -1275,80 +1275,120 @@ ssize_t DecodeWrite(char *buf,
|
|||||||
return StringBytes::Write(buf, buflen, val, encoding, NULL);
|
return StringBytes::Write(buf, buflen, val, encoding, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayExceptionLine(Handle<Message> message) {
|
void AppendExceptionLine(Environment* env,
|
||||||
// Prevent re-entry into this function. For example, if there is
|
Handle<Value> er,
|
||||||
// a throw from a program in vm.runInThisContext(code, filename, true),
|
Handle<Message> message) {
|
||||||
// then we want to show the original failure, not the secondary one.
|
if (message.IsEmpty())
|
||||||
static bool displayed_error = false;
|
|
||||||
|
|
||||||
if (displayed_error)
|
|
||||||
return;
|
return;
|
||||||
displayed_error = true;
|
|
||||||
|
|
||||||
uv_tty_reset_mode();
|
HandleScope scope(env->isolate());
|
||||||
|
Local<Object> err_obj;
|
||||||
|
if (!er.IsEmpty() && er->IsObject()) {
|
||||||
|
err_obj = er.As<Object>();
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
// Do it only once per message
|
||||||
|
if (!err_obj->GetHiddenValue(env->processed_string()).IsEmpty())
|
||||||
if (!message.IsEmpty()) {
|
return;
|
||||||
// Print (filename):(line number): (message).
|
err_obj->SetHiddenValue(env->processed_string(), True(env->isolate()));
|
||||||
String::Utf8Value filename(message->GetScriptResourceName());
|
|
||||||
const char* filename_string = *filename;
|
|
||||||
int linenum = message->GetLineNumber();
|
|
||||||
fprintf(stderr, "%s:%i\n", filename_string, linenum);
|
|
||||||
// Print line of source code.
|
|
||||||
String::Utf8Value sourceline(message->GetSourceLine());
|
|
||||||
const char* sourceline_string = *sourceline;
|
|
||||||
|
|
||||||
// Because of how node modules work, all scripts are wrapped with a
|
|
||||||
// "function (module, exports, __filename, ...) {"
|
|
||||||
// to provide script local variables.
|
|
||||||
//
|
|
||||||
// When reporting errors on the first line of a script, this wrapper
|
|
||||||
// function is leaked to the user. There used to be a hack here to
|
|
||||||
// truncate off the first 62 characters, but it caused numerous other
|
|
||||||
// problems when vm.runIn*Context() methods were used for non-module
|
|
||||||
// code.
|
|
||||||
//
|
|
||||||
// If we ever decide to re-instate such a hack, the following steps
|
|
||||||
// must be taken:
|
|
||||||
//
|
|
||||||
// 1. Pass a flag around to say "this code was wrapped"
|
|
||||||
// 2. Update the stack frame output so that it is also correct.
|
|
||||||
//
|
|
||||||
// It would probably be simpler to add a line rather than add some
|
|
||||||
// number of characters to the first line, since V8 truncates the
|
|
||||||
// sourceline to 78 characters, and we end up not providing very much
|
|
||||||
// useful debugging info to the user if we remove 62 characters.
|
|
||||||
|
|
||||||
int start = message->GetStartColumn();
|
|
||||||
int end = message->GetEndColumn();
|
|
||||||
|
|
||||||
fprintf(stderr, "%s\n", sourceline_string);
|
|
||||||
// Print wavy underline (GetUnderline is deprecated).
|
|
||||||
for (int i = 0; i < start; i++) {
|
|
||||||
fputc((sourceline_string[i] == '\t') ? '\t' : ' ', stderr);
|
|
||||||
}
|
|
||||||
for (int i = start; i < end; i++) {
|
|
||||||
fputc('^', stderr);
|
|
||||||
}
|
|
||||||
fputc('\n', stderr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char arrow[1024];
|
||||||
|
|
||||||
|
// Print (filename):(line number): (message).
|
||||||
|
String::Utf8Value filename(message->GetScriptResourceName());
|
||||||
|
const char* filename_string = *filename;
|
||||||
|
int linenum = message->GetLineNumber();
|
||||||
|
// Print line of source code.
|
||||||
|
String::Utf8Value sourceline(message->GetSourceLine());
|
||||||
|
const char* sourceline_string = *sourceline;
|
||||||
|
|
||||||
|
// Because of how node modules work, all scripts are wrapped with a
|
||||||
|
// "function (module, exports, __filename, ...) {"
|
||||||
|
// to provide script local variables.
|
||||||
|
//
|
||||||
|
// When reporting errors on the first line of a script, this wrapper
|
||||||
|
// function is leaked to the user. There used to be a hack here to
|
||||||
|
// truncate off the first 62 characters, but it caused numerous other
|
||||||
|
// problems when vm.runIn*Context() methods were used for non-module
|
||||||
|
// code.
|
||||||
|
//
|
||||||
|
// If we ever decide to re-instate such a hack, the following steps
|
||||||
|
// must be taken:
|
||||||
|
//
|
||||||
|
// 1. Pass a flag around to say "this code was wrapped"
|
||||||
|
// 2. Update the stack frame output so that it is also correct.
|
||||||
|
//
|
||||||
|
// It would probably be simpler to add a line rather than add some
|
||||||
|
// number of characters to the first line, since V8 truncates the
|
||||||
|
// sourceline to 78 characters, and we end up not providing very much
|
||||||
|
// useful debugging info to the user if we remove 62 characters.
|
||||||
|
|
||||||
|
int start = message->GetStartColumn();
|
||||||
|
int end = message->GetEndColumn();
|
||||||
|
|
||||||
|
int off = snprintf(arrow,
|
||||||
|
sizeof(arrow),
|
||||||
|
"%s:%i\n%s\n",
|
||||||
|
filename_string,
|
||||||
|
linenum,
|
||||||
|
sourceline_string);
|
||||||
|
assert(off >= 0);
|
||||||
|
|
||||||
|
// Print wavy underline (GetUnderline is deprecated).
|
||||||
|
for (int i = 0; i < start; i++) {
|
||||||
|
assert(static_cast<size_t>(off) < sizeof(arrow));
|
||||||
|
arrow[off++] = (sourceline_string[i] == '\t') ? '\t' : ' ';
|
||||||
|
}
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
assert(static_cast<size_t>(off) < sizeof(arrow));
|
||||||
|
arrow[off++] = '^';
|
||||||
|
}
|
||||||
|
assert(static_cast<size_t>(off) < sizeof(arrow) - 1);
|
||||||
|
arrow[off++] = '\n';
|
||||||
|
arrow[off] = '\0';
|
||||||
|
|
||||||
|
Local<String> arrow_str = String::NewFromUtf8(env->isolate(), arrow);
|
||||||
|
Local<Value> msg;
|
||||||
|
Local<Value> stack;
|
||||||
|
|
||||||
|
// Allocation failed, just print it out
|
||||||
|
if (arrow_str.IsEmpty() || err_obj.IsEmpty() || !err_obj->IsNativeError())
|
||||||
|
goto print;
|
||||||
|
|
||||||
|
msg = err_obj->Get(env->message_string());
|
||||||
|
stack = err_obj->Get(env->stack_string());
|
||||||
|
|
||||||
|
if (msg.IsEmpty() || stack.IsEmpty())
|
||||||
|
goto print;
|
||||||
|
|
||||||
|
err_obj->Set(env->message_string(),
|
||||||
|
String::Concat(arrow_str, msg->ToString()));
|
||||||
|
err_obj->Set(env->stack_string(),
|
||||||
|
String::Concat(arrow_str, stack->ToString()));
|
||||||
|
return;
|
||||||
|
|
||||||
|
print:
|
||||||
|
if (env->printed_error())
|
||||||
|
return;
|
||||||
|
env->set_printed_error(true);
|
||||||
|
uv_tty_reset_mode();
|
||||||
|
fprintf(stderr, "\n%s", arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ReportException(Handle<Value> er, Handle<Message> message) {
|
static void ReportException(Environment* env,
|
||||||
HandleScope scope(node_isolate);
|
Handle<Value> er,
|
||||||
|
Handle<Message> message) {
|
||||||
|
HandleScope scope(env->isolate());
|
||||||
|
|
||||||
DisplayExceptionLine(message);
|
AppendExceptionLine(env, er, message);
|
||||||
|
|
||||||
Local<Value> trace_value;
|
Local<Value> trace_value;
|
||||||
|
|
||||||
if (er->IsUndefined() || er->IsNull()) {
|
if (er->IsUndefined() || er->IsNull())
|
||||||
trace_value = Undefined(node_isolate);
|
trace_value = Undefined(env->isolate());
|
||||||
} else {
|
else
|
||||||
trace_value =
|
trace_value = er->ToObject()->Get(env->stack_string());
|
||||||
er->ToObject()->Get(FIXED_ONE_BYTE_STRING(node_isolate, "stack"));
|
|
||||||
}
|
|
||||||
|
|
||||||
String::Utf8Value trace(trace_value);
|
String::Utf8Value trace(trace_value);
|
||||||
|
|
||||||
@ -1364,8 +1404,8 @@ static void ReportException(Handle<Value> er, Handle<Message> message) {
|
|||||||
|
|
||||||
if (er->IsObject()) {
|
if (er->IsObject()) {
|
||||||
Local<Object> err_obj = er.As<Object>();
|
Local<Object> err_obj = er.As<Object>();
|
||||||
message = err_obj->Get(FIXED_ONE_BYTE_STRING(node_isolate, "message"));
|
message = err_obj->Get(env->message_string());
|
||||||
name = err_obj->Get(FIXED_ONE_BYTE_STRING(node_isolate, "name"));
|
name = err_obj->Get(FIXED_ONE_BYTE_STRING(env->isolate(), "name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.IsEmpty() ||
|
if (message.IsEmpty() ||
|
||||||
@ -1386,14 +1426,16 @@ static void ReportException(Handle<Value> er, Handle<Message> message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ReportException(const TryCatch& try_catch) {
|
static void ReportException(Environment* env, const TryCatch& try_catch) {
|
||||||
ReportException(try_catch.Exception(), try_catch.Message());
|
ReportException(env, try_catch.Exception(), try_catch.Message());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Executes a str within the current v8 context.
|
// Executes a str within the current v8 context.
|
||||||
Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
|
static Local<Value> ExecuteString(Environment* env,
|
||||||
HandleScope scope(node_isolate);
|
Handle<String> source,
|
||||||
|
Handle<Value> filename) {
|
||||||
|
HandleScope scope(env->isolate());
|
||||||
TryCatch try_catch;
|
TryCatch try_catch;
|
||||||
|
|
||||||
// try_catch must be nonverbose to disable FatalException() handler,
|
// try_catch must be nonverbose to disable FatalException() handler,
|
||||||
@ -1402,13 +1444,13 @@ Local<Value> ExecuteString(Handle<String> source, Handle<Value> filename) {
|
|||||||
|
|
||||||
Local<v8::Script> script = v8::Script::Compile(source, filename);
|
Local<v8::Script> script = v8::Script::Compile(source, filename);
|
||||||
if (script.IsEmpty()) {
|
if (script.IsEmpty()) {
|
||||||
ReportException(try_catch);
|
ReportException(env, try_catch);
|
||||||
exit(3);
|
exit(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
Local<Value> result = script->Run();
|
Local<Value> result = script->Run();
|
||||||
if (result.IsEmpty()) {
|
if (result.IsEmpty()) {
|
||||||
ReportException(try_catch);
|
ReportException(env, try_catch);
|
||||||
exit(4);
|
exit(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2025,7 +2067,7 @@ void FatalException(Handle<Value> error, Handle<Message> message) {
|
|||||||
if (!fatal_exception_function->IsFunction()) {
|
if (!fatal_exception_function->IsFunction()) {
|
||||||
// failed before the process._fatalException function was added!
|
// failed before the process._fatalException function was added!
|
||||||
// this is probably pretty bad. Nothing to do but report and exit.
|
// this is probably pretty bad. Nothing to do but report and exit.
|
||||||
ReportException(error, message);
|
ReportException(env, error, message);
|
||||||
exit(6);
|
exit(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2040,12 +2082,12 @@ void FatalException(Handle<Value> error, Handle<Message> message) {
|
|||||||
|
|
||||||
if (fatal_try_catch.HasCaught()) {
|
if (fatal_try_catch.HasCaught()) {
|
||||||
// the fatal exception function threw, so we must exit
|
// the fatal exception function threw, so we must exit
|
||||||
ReportException(fatal_try_catch);
|
ReportException(env, fatal_try_catch);
|
||||||
exit(7);
|
exit(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false == caught->BooleanValue()) {
|
if (false == caught->BooleanValue()) {
|
||||||
ReportException(error, message);
|
ReportException(env, error, message);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2705,10 +2747,10 @@ void Load(Environment* env) {
|
|||||||
// are not safe to ignore.
|
// are not safe to ignore.
|
||||||
try_catch.SetVerbose(false);
|
try_catch.SetVerbose(false);
|
||||||
|
|
||||||
Local<String> script_name = FIXED_ONE_BYTE_STRING(node_isolate, "node.js");
|
Local<String> script_name = FIXED_ONE_BYTE_STRING(env->isolate(), "node.js");
|
||||||
Local<Value> f_value = ExecuteString(MainSource(), script_name);
|
Local<Value> f_value = ExecuteString(env, MainSource(), script_name);
|
||||||
if (try_catch.HasCaught()) {
|
if (try_catch.HasCaught()) {
|
||||||
ReportException(try_catch);
|
ReportException(env, try_catch);
|
||||||
exit(10);
|
exit(10);
|
||||||
}
|
}
|
||||||
assert(f_value->IsFunction());
|
assert(f_value->IsFunction());
|
||||||
|
@ -190,7 +190,6 @@ enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
|
|||||||
enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v,
|
enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v,
|
||||||
enum encoding _default = BINARY);
|
enum encoding _default = BINARY);
|
||||||
NODE_EXTERN void FatalException(const v8::TryCatch& try_catch);
|
NODE_EXTERN void FatalException(const v8::TryCatch& try_catch);
|
||||||
void DisplayExceptionLine(v8::Handle<v8::Message> message);
|
|
||||||
|
|
||||||
NODE_EXTERN v8::Local<v8::Value> Encode(const void *buf, size_t len,
|
NODE_EXTERN v8::Local<v8::Value> Encode(const void *buf, size_t len,
|
||||||
enum encoding encoding = BINARY);
|
enum encoding encoding = BINARY);
|
||||||
|
@ -453,7 +453,7 @@ class ContextifyScript : public BaseObject {
|
|||||||
|
|
||||||
if (v8_script.IsEmpty()) {
|
if (v8_script.IsEmpty()) {
|
||||||
if (display_errors) {
|
if (display_errors) {
|
||||||
DisplayExceptionLine(try_catch.Message());
|
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||||
}
|
}
|
||||||
try_catch.ReThrow();
|
try_catch.ReThrow();
|
||||||
return;
|
return;
|
||||||
@ -622,7 +622,7 @@ class ContextifyScript : public BaseObject {
|
|||||||
if (result.IsEmpty()) {
|
if (result.IsEmpty()) {
|
||||||
// Error occurred during execution of the script.
|
// Error occurred during execution of the script.
|
||||||
if (display_errors) {
|
if (display_errors) {
|
||||||
DisplayExceptionLine(try_catch.Message());
|
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||||
}
|
}
|
||||||
try_catch.ReThrow();
|
try_catch.ReThrow();
|
||||||
return false;
|
return false;
|
||||||
|
@ -155,6 +155,10 @@ inline static void ThrowUVException(int errorno,
|
|||||||
v8::ThrowException(UVException(errorno, syscall, message, path));
|
v8::ThrowException(UVException(errorno, syscall, message, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppendExceptionLine(Environment* env,
|
||||||
|
v8::Handle<v8::Value> er,
|
||||||
|
v8::Handle<v8::Message> message);
|
||||||
|
|
||||||
NO_RETURN void FatalError(const char* location, const char* message);
|
NO_RETURN void FatalError(const char* location, const char* message);
|
||||||
|
|
||||||
v8::Local<v8::Object> BuildStatsObject(Environment* env, const uv_stat_t* s);
|
v8::Local<v8::Object> BuildStatsObject(Environment* env, const uv_stat_t* s);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
[eval]
|
[eval]
|
||||||
|
|
||||||
[eval]:1
|
[eval]:1
|
||||||
with(this){__filename}
|
with(this){__filename}
|
||||||
^^^^
|
^^^^
|
||||||
@ -12,7 +11,6 @@ SyntaxError: Strict mode code may not include a with statement
|
|||||||
at node.js:*:*
|
at node.js:*:*
|
||||||
42
|
42
|
||||||
42
|
42
|
||||||
|
|
||||||
[eval]:1
|
[eval]:1
|
||||||
throw new Error("hello")
|
throw new Error("hello")
|
||||||
^
|
^
|
||||||
@ -24,7 +22,6 @@ Error: hello
|
|||||||
at evalScript (node.js:*:*)
|
at evalScript (node.js:*:*)
|
||||||
at startup (node.js:*:*)
|
at startup (node.js:*:*)
|
||||||
at node.js:*:*
|
at node.js:*:*
|
||||||
|
|
||||||
[eval]:1
|
[eval]:1
|
||||||
throw new Error("hello")
|
throw new Error("hello")
|
||||||
^
|
^
|
||||||
@ -37,7 +34,6 @@ Error: hello
|
|||||||
at startup (node.js:*:*)
|
at startup (node.js:*:*)
|
||||||
at node.js:*:*
|
at node.js:*:*
|
||||||
100
|
100
|
||||||
|
|
||||||
[eval]:1
|
[eval]:1
|
||||||
var x = 100; y = x;
|
var x = 100; y = x;
|
||||||
^
|
^
|
||||||
@ -49,12 +45,10 @@ ReferenceError: y is not defined
|
|||||||
at evalScript (node.js:*:*)
|
at evalScript (node.js:*:*)
|
||||||
at startup (node.js:*:*)
|
at startup (node.js:*:*)
|
||||||
at node.js:*:*
|
at node.js:*:*
|
||||||
|
|
||||||
[eval]:1
|
[eval]:1
|
||||||
var ______________________________________________; throw 10
|
var ______________________________________________; throw 10
|
||||||
^
|
^
|
||||||
10
|
10
|
||||||
|
|
||||||
[eval]:1
|
[eval]:1
|
||||||
var ______________________________________________; throw 10
|
var ______________________________________________; throw 10
|
||||||
^
|
^
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
before
|
before
|
||||||
|
|
||||||
*test*message*throw_custom_error.js:31
|
*test*message*throw_custom_error.js:31
|
||||||
throw ({ name: 'MyCustomError', message: 'This is a custom message' });
|
throw ({ name: 'MyCustomError', message: 'This is a custom message' });
|
||||||
^
|
^
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
before
|
before
|
||||||
|
|
||||||
*test*message*throw_in_line_with_tabs.js:32
|
*test*message*throw_in_line_with_tabs.js:32
|
||||||
throw ({ foo: 'bar' });
|
throw ({ foo: 'bar' });
|
||||||
^
|
^
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
before
|
before
|
||||||
|
|
||||||
*test*message*throw_non_error.js:31
|
*test*message*throw_non_error.js:31
|
||||||
throw ({ foo: 'bar' });
|
throw ({ foo: 'bar' });
|
||||||
^
|
^
|
||||||
|
49
test/simple/test-vm-syntax-error-stderr.js
Normal file
49
test/simple/test-vm-syntax-error-stderr.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright Joyent, Inc. and other Node contributors.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
var common = require('../common');
|
||||||
|
var assert = require('assert');
|
||||||
|
var path = require('path');
|
||||||
|
var child_process = require('child_process');
|
||||||
|
|
||||||
|
var wrong_script = path.join(common.fixturesDir, 'cert.pem');
|
||||||
|
|
||||||
|
var p = child_process.spawn(process.execPath, [
|
||||||
|
'-e',
|
||||||
|
'try { require(process.argv[1]); } catch (e) { console.log(e.stack); }',
|
||||||
|
wrong_script
|
||||||
|
]);
|
||||||
|
|
||||||
|
p.stderr.on('data', function(data) {
|
||||||
|
assert(false, 'Unexpected stderr data: ' + data);
|
||||||
|
});
|
||||||
|
|
||||||
|
var output = '';
|
||||||
|
|
||||||
|
p.stdout.on('data', function(data) {
|
||||||
|
output += data;
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('exit', function() {
|
||||||
|
assert(/BEGIN CERT/.test(output));
|
||||||
|
assert(/^\s+\^/m.test(output));
|
||||||
|
assert(/Unexpected identifier/.test(output));
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user