1
0
Fork 0
mirror of https://github.com/rubyjs/mini_racer synced 2023-03-27 23:21:28 -04:00

correct attached function calls to properly check for function

This commit is contained in:
Sam 2018-06-26 13:59:29 +10:00
parent 66b28dd2e4
commit dbaaab46b5
3 changed files with 70 additions and 22 deletions

View file

@ -706,7 +706,7 @@ static VALUE convert_result_to_ruby(VALUE self /* context */,
delete result.backtrace;
}
}
// NOTE: this is very important, we can not do an rb_raise from within
// a v8 scope, if we do the scope is never cleaned up properly and we leak
if (!result.parsed) {
@ -743,7 +743,7 @@ static VALUE convert_result_to_ruby(VALUE self /* context */,
}
VALUE ret = Qnil;
// New scope for return value
{
Locker lock(isolate);
@ -935,15 +935,14 @@ gvl_ruby_callback(void* data) {
}
static void ruby_callback(const FunctionCallbackInfo<Value>& args) {
bool has_gvl = (bool)args.GetIsolate()->GetData(IN_GVL);
if(has_gvl) {
gvl_ruby_callback((void*)&args);
} else {
args.GetIsolate()->SetData(IN_GVL, (void*)true);
args.GetIsolate()->SetData(IN_GVL, (void*)true);
rb_thread_call_with_gvl(gvl_ruby_callback, (void*)(&args));
args.GetIsolate()->SetData(IN_GVL, (void*)false);
args.GetIsolate()->SetData(IN_GVL, (void*)false);
}
}
@ -1242,7 +1241,6 @@ static void unblock_function(void *args) {
static VALUE
rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
ContextInfo* context_info;
FunctionCall call;
VALUE *call_argv = NULL;
@ -1284,23 +1282,31 @@ rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
// examples of such usage can be found in
// https://github.com/v8/v8/blob/36b32aa28db5e993312f4588d60aad5c8330c8a5/test/cctest/test-api.cc#L15711
Local<v8::Function> fun = Local<v8::Function>::Cast(context->Global()->Get(
String::NewFromUtf8(isolate, call.function_name)));
call.fun = fun;
int fun_argc = call.argc;
Local<String> fname = String::NewFromUtf8(isolate, call.function_name);
MaybeLocal<v8::Value> val = context->Global()->Get(fname);
if (fun_argc > 0) {
call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
if (!call.argv) {
return Qnil;
}
for(int i=0; i < fun_argc; i++) {
call.argv[i] = convert_ruby_to_v8(isolate, call_argv[i]);
}
}
if (val.IsEmpty() || !val.ToLocalChecked()->IsFunction()) {
return Qnil;
} else {
rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
free(call.argv);
Local<v8::Function> fun = Local<v8::Function>::Cast(val.ToLocalChecked());
call.fun = fun;
int fun_argc = call.argc;
if (fun_argc > 0) {
call.argv = (v8::Local<Value> *) malloc(sizeof(void *) * fun_argc);
if (!call.argv) {
return Qnil;
}
for(int i=0; i < fun_argc; i++) {
call.argv[i] = convert_ruby_to_v8(isolate, call_argv[i]);
}
}
rb_thread_call_without_gvl(nogvl_context_call, &call, unblock_function, &call);
free(call.argv);
}
}
return convert_result_to_ruby(self, call.result);

View file

@ -35,7 +35,7 @@ class MiniRacerFunctionTest < Minitest::Test
context.call('f', 1)
end
assert_equal err.message, 'Error: foo bar'
assert_match /1:23/, err.backtrace[0]
assert_match(/1:23/, err.backtrace[0])
end
def test_args_types

View file

@ -19,6 +19,48 @@ def test
puts "we are done"
end
def test2
context = MiniRacer::Context.new(timeout: 5)
context.attach("marsh", proc do |a, b, c|
return [a,b,c] if a.is_a?(MiniRacer::FailedV8Conversion) || b.is_a?(MiniRacer::FailedV8Conversion) || c.is_a?(MiniRacer::FailedV8Conversion)
a[rand(10000).to_s] = "a"
b[rand(10000).to_s] = "b"
c[rand(10000).to_s] = "c"
[a,b,c]
end)
begin
context.eval("var a = [{},{},{}]; while(true) { a = marsh(a[0],a[1],a[2]); }")
rescue
end
end
def test3
snapshot = MiniRacer::Snapshot.new('Math.sin = 1;')
begin
snapshot.warmup!('var a = Math.sin(1);')
rescue
# do nothing
end
context = MiniRacer::Context.new(snapshot: snapshot)
assert_equal 1, context.eval('Math.sin')
end
test3
# 500.times do
# test2
# end
exit
test
GC.start