#include <map>
#include "pl_stats.h"
#include "pl_console.h"
#include "pl_eventloop.h"
#include "pl_v8.h"
#include "ppport.h"
#define PL_GC_RUNS 2
using
namespace
v8;
static
const
char
* ToCString(
const
String::Utf8Value& value)
{
return
*value ? *value :
"<string conversion failed>"
;
}
static
void
ReportException(pTHX_ V8Context* ctx, TryCatch* try_catch)
{
SV* buffer = newSVpvs(
""
);
Isolate* isolate = ctx->isolate;
HandleScope handle_scope(isolate);
String::Utf8Value exception(isolate, try_catch->Exception());
const
char
* exception_string = ToCString(exception);
Local<Message> message = try_catch->Message();
if
(message.IsEmpty()) {
Perl_sv_catpvf(aTHX_ buffer,
"%s\n"
, exception_string);
}
else
{
Local<Context> context(isolate->GetCurrentContext());
Local<Value> stack_trace_string;
bool
has_stack_trace = (
try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
stack_trace_string->IsString() &&
Local<String>::Cast(stack_trace_string)->Length() > 0);
if
(!has_stack_trace) {
String::Utf8Value filename(isolate, message->GetScriptOrigin().ResourceName());
const
char
* filename_string = ToCString(filename);
int
linenum = message->GetLineNumber(context).FromJust();
Perl_sv_catpvf(aTHX_ buffer,
"%s:%i: "
, filename_string, linenum);
}
Perl_sv_catpvf(aTHX_ buffer,
"error: %s\n"
, exception_string);
#if 0
String::Utf8Value sourceline(
isolate, message->GetSourceLine(context).ToLocalChecked());
const
char
* sourceline_string = ToCString(sourceline);
Perl_sv_catpvf(aTHX_ buffer,
"%s\n"
, sourceline_string);
int
start = message->GetStartColumn(context).FromJust();
for
(
int
i = 0; i < start; i++) {
Perl_sv_catpvf(aTHX_ buffer,
" "
);
}
int
end = message->GetEndColumn(context).FromJust();
for
(
int
i = start; i < end; i++) {
Perl_sv_catpvf(aTHX_ buffer,
"^"
);
}
Perl_sv_catpvf(aTHX_ buffer,
"\n"
);
#endif
if
(has_stack_trace) {
String::Utf8Value stack_trace(isolate, stack_trace_string);
const
char
* stack_trace_string = ToCString(stack_trace);
Perl_sv_catpvf(aTHX_ buffer,
"%s\n"
, stack_trace_string);
}
}
STRLEN blen = 0;
char
* bstr = SvPV(buffer, blen);
pl_show_error(ctx,
"%s"
, bstr);
}
SV* pl_eval(pTHX_ V8Context* ctx,
const
char
* code,
const
char
* file)
{
SV* ret = &PL_sv_undef;
HandleScope handle_scope(ctx->isolate);
Local<Context> context = Local<Context>::New(ctx->isolate, *ctx->persistent_context);
Context::Scope context_scope(context);
ScriptOrigin* origin = 0;
TryCatch try_catch(ctx->isolate);
bool
ok =
true
;
do
{
if
(file) {
Local<String> name;
ok = String::NewFromUtf8(ctx->isolate, file, NewStringType::kNormal).ToLocal(&name);
if
(!ok) {
break
;
}
origin =
new
ScriptOrigin(name);
if
(!origin) {
break
;
}
}
Local<String> source;
ok = String::NewFromUtf8(ctx->isolate, code, NewStringType::kNormal).ToLocal(&source);
if
(!ok) {
break
;
}
Perf perf;
pl_stats_start(aTHX_ ctx, &perf);
Local<Script> script;
ok = Script::Compile(context, source, origin).ToLocal(&script);
pl_stats_stop(aTHX_ ctx, &perf,
"compile"
);
if
(!ok) {
break
;
}
pl_stats_start(aTHX_ ctx, &perf);
Local<Value> result;
ok = script->Run(context).ToLocal(&result);
pl_stats_stop(aTHX_ ctx, &perf,
"run"
);
if
(!ok) {
break
;
}
Local<Object> object = Local<Object>::Cast(result);
ret = pl_v8_to_perl(aTHX_ ctx, object);
eventloop_run(ctx);
}
while
(0);
if
(!ok) {
if
(try_catch.HasCaught()) {
ReportException(aTHX_ ctx, &try_catch);
#if 0
String::Utf8Value error(ctx->isolate, try_catch.Exception());
pl_show_error(ctx, *error);
#endif
}
}
delete
origin;
return
ret;
}
int
pl_run_function(V8Context* ctx, Persistent<Function>& func)
{
dTHX;
HandleScope handle_scope(ctx->isolate);
Local<Context> context = Local<Context>::New(ctx->isolate, *ctx->persistent_context);
Context::Scope context_scope(context);
TryCatch try_catch(ctx->isolate);
Local<Value> result;
bool
ok =
true
;
do
{
Local<Value> global = context->Global();
Local<Function> v8_func = Local<Function>::New(ctx->isolate, func);
ok = v8_func->Call(context, global, 0, 0).ToLocal(&result);
if
(!ok) {
break
;
}
}
while
(0);
if
(!ok) {
if
(try_catch.HasCaught()) {
ReportException(aTHX_ ctx, &try_catch);
#if 0
String::Utf8Value error(ctx->isolate, try_catch.Exception());
pl_show_error(ctx, *error);
#endif
}
}
return
ok;
}