JavaScript exception propagation

211 views
Skip to first unread message

Anton Korenyushkin

unread,
Feb 13, 2009, 7:33:49 AM2/13/09
to v8-users
Hello,

I'm desperately trying to implement 'load' function that would
propagate exceptions thrown during loading. The problem is that I
failed to understand how to re-throw an exception back into
JavaScript. To be specific, here is a minimal example (derived from
shell.cc):

$ cat main.cc

#include <v8.h>
#include <cstdio>
#include <cassert>

using namespace v8;


Handle<String> ReadFile(const char* name) {
FILE* file = fopen(name, "rb");
if (file == NULL) return Handle<String>();

fseek(file, 0, SEEK_END);
int size = ftell(file);
rewind(file);

char* chars = new char[size + 1];
chars[size] = '\0';
for (int i = 0; i < size;) {
int read = fread(&chars[i], 1, size - i, file);
i += read;
}
fclose(file);
Handle<String> result = String::New(chars, size);
delete[] chars;
return result;
}


Handle<Value> Load(const Arguments& args) {
HandleScope handle_scope;
assert(args.Length() == 1);
String::Utf8Value utf8value(args[0]);
Handle<String> str = ReadFile(*utf8value);

// TryCatch try_catch;
Local<Script> script = Script::Compile(str, args[0]);
if (script.IsEmpty()) {
// ThrowException(handle_scope.Close(try_catch.Exception()));
return Handle<Value>();
}

Local<Value> value = script->Run();
if (value.IsEmpty()) {
// ThrowException(handle_scope.Close(try_catch.Exception()));
return Handle<Value>();
}
return handle_scope.Close(value);
}


int main(int argc, char* argv[]) {
if (argc != 2) {
printf("Usage: %s <js file>\n", argv[0]);
return 1;
}

HandleScope handle_scope;
Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("load"), FunctionTemplate::New(Load));
Handle<v8::Context> context = Context::New(NULL, global);
Context::Scope context_scope(context);

Handle<String> str = ReadFile(argv[1]);
assert(!str.IsEmpty());

TryCatch try_catch;
Local<Script> script = Script::Compile(str, String::New(argv[1]));
if (script.IsEmpty()) {
printf("Compile error\n");
return 0;
}

Local<Value> value = script->Run();
if (value.IsEmpty()) {
String::Utf8Value
utf8value_err(try_catch.Exception());
String::Utf8Value
utf8value_file(try_catch.Message()->GetScriptResourceName
());
printf("Run error: %s in file %s line %d\n",
*utf8value_err,
*utf8value_file,
try_catch.Message()->GetLineNumber());
return 0;
}
String::Utf8Value utf8value(value);
printf("%s\n", *utf8value);
return 0;
}
$ ##########################################
$ cat throw.js
throw 42;
$ ##########################################
$ cat catch.js
try {
load('throw.js');
} catch (err) {
result = err;
}
result
$ ##########################################
$ cat load.js
load('throw.js')
$ ##########################################
$ g++ -g3 main.cc -lv8_g -lpthread
$ ./a.out throw.js
Run error: 42 in file throw.js line 1
$ ./a.out catch.js
42
$ ./a.out load.js
undefined
$


I want the output of './a.out load.js' to be 'Run error: 42 in file
throw.js line 1' but exception disappears. I tried to re-throw it
manually (see 3 commented lines in Load()) but it produced errors
hinting that Exception() became invalid. What am I missing?

Ondrej Zara

unread,
Feb 13, 2009, 8:33:05 AM2/13/09
to v8-u...@googlegroups.com
Hi Anton,

I am not sure if this helps, but the "test-api.cc" contains this
interesting code sample:


v8::Locker nested_locker;
v8::HandleScope scope;
v8::Handle<Value> exception;
{ v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(code);
CHECK(value.IsEmpty());
CHECK(try_catch.HasCaught());
// Make sure to wrap the exception in a new handle because
// the handle returned from the TryCatch is destroyed
// when the TryCatch is destroyed.
exception = Local<Value>::New(try_catch.Exception());
}
return v8::ThrowException(exception);



So maybe you can try wrapping your exception in a similar way prior to
re-throwing it?



Ondrej




2009/2/13 Anton Korenyushkin <koreny...@gmail.com>:

Anton Korenyushkin

unread,
Feb 13, 2009, 9:03:52 AM2/13/09
to v8-u...@googlegroups.com
Wow! It did help! I didn't even think it was so easy.

Thank you, Ondrej.
--
Best regards,
Anton Korenyushkin
Reply all
Reply to author
Forward
0 new messages