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:
parent
66b28dd2e4
commit
dbaaab46b5
3 changed files with 70 additions and 22 deletions
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue