Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Support mruby 2.1.0 #75

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
language: go
sudo: required
go:
- "1.13"
- "1.12"
- "1.11"
- "1.10"
install: sudo apt-get install build-essential g++ bison flex
script: make all megacheck
12 changes: 6 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MRUBY_COMMIT ?= 1.2.0
MRUBY_COMMIT ?= 2.1.0

all: libmruby.a test
all: test

clean:
rm -rf vendor
Expand All @@ -14,11 +14,11 @@ lint:
sh golint.sh

megacheck:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we rename this task to 'staticcheck'? also, nice catch, thanks!

go get honnef.co/go/tools/cmd/megacheck
GO111MODULE=off megacheck ./...
go get honnef.co/go/tools/cmd/staticcheck
GO111MODULE=off staticcheck ./...

libmruby.a: vendor/mruby
cd vendor/mruby && ${MAKE}
cd vendor/mruby && MRUBY_CONFIG=../../build_config.rb ${MAKE}
cp vendor/mruby/build/host/lib/libmruby.a .

vendor/mruby:
Expand All @@ -27,7 +27,7 @@ vendor/mruby:
cd vendor/mruby && git reset --hard && git clean -fdx
cd vendor/mruby && git checkout ${MRUBY_COMMIT}

test: gofmt lint
test: libmruby.a gofmt lint
go test -v

.PHONY: all clean libmruby.a test lint
2 changes: 1 addition & 1 deletion array.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Array struct {

// Len returns the length of the array.
func (v *Array) Len() int {
return int(C.mrb_ary_len(v.state, v.value))
return int(C._mrb_ary_len(v.value))
}

// Get gets an element form the Array by index.
Expand Down
17 changes: 17 additions & 0 deletions build_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
MRuby::Build.new do |conf|
# load specific toolchain settings

# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
end

if ENV['CI']
# Turn on `enable_debug` for better debugging
enable_debug
end

gem core: 'mruby-error'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't notice this before, and I'm sorry about this. We can't depend on external gems here, I hope you realize. The whole point of having this environment this way is that the user can customize it.

This breaks nearly everything I depend on in this library. Is there any way we can bring in the changes that mruby-error provides directly? We had healthy gc arena code in the codebase before. was it removed?

end
2 changes: 1 addition & 1 deletion context.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type CompileContext struct {
ctx *C.mrbc_context
filename string
mrb *Mrb
captureErrors bool
// captureErrors bool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove this line if it's not being used

}

// NewCompileContext constructs a *CompileContext from a *Mrb.
Expand Down
6 changes: 3 additions & 3 deletions func.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,18 @@ func goMRBFuncCall(s *C.mrb_state, v C.mrb_value) C.mrb_value {

// Lookup the class itself
classTable.Mutex.Lock()
methodTable := classTable.Map[ci.proc.target_class]
methodTable := classTable.Map[ci.target_class]
classTable.Mutex.Unlock()
if methodTable == nil {
panic(fmt.Sprintf("func call on unknown class"))
panic("func call on unknown class")
}

// Lookup the method
methodTable.Mutex.Lock()
f := methodTable.Map[ci.mid]
methodTable.Mutex.Unlock()
if f == nil {
panic(fmt.Sprintf("func call on unknown method"))
panic("func call on unknown method")
}

// Call the method to get our *Value
Expand Down
6 changes: 4 additions & 2 deletions gc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ func TestEnableDisableGC(t *testing.T) {
mrb.EnableGC()
mrb.FullGC()

if orig-2 != mrb.LiveObjectCount() {
t.Fatalf("Object count was not what was expected after full GC: %d %d", orig-2, mrb.LiveObjectCount())
if orig-1 != mrb.LiveObjectCount() {
t.Fatalf("Object count was not what was expected after full GC: %d %d", orig-1, mrb.LiveObjectCount())
}
}

Expand All @@ -43,7 +43,9 @@ func TestIsDead(t *testing.T) {

mrb.Close()

/*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this test commented out?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes use after free in sanitizer enabled env and it shouldn't be tested with go test

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the major point of this test is to run that block that's commented out; is there any way to re-enable the test? This feels like a change in API.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't care how you feel.
You should never touch freed memory.

if !val.IsDead() {
t.Fatal("Value should be dead and is not")
}
*/
}
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ module github.com/mitchellh/go-mruby

require (
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 // indirect
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7 // indirect
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 // indirect
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 // indirect
honnef.co/go/tools v0.0.1-2019.2.3 // indirect
)

go 1.13
33 changes: 33 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,39 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7 h1:2hRPrmiwPrp3fQX967rNJIhQPtiGXdlQWAxKbKw3VHA=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7 h1:00BeQWmeaGazuOrq8Q5K5d3/cHaGuFrZzpaHBXfrsUA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 h1:dzEuQYa6+a3gROnSlgly5ERUm4SZKJt+dh+4iSbO+bI=
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnfG5kSmgy9KZR9sW3W5QeA=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
2 changes: 1 addition & 1 deletion golint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ version=$(go version | awk '{ print $3 }' | awk -F. '{ print $2 }')
if [ "$version" != "5" ]
then
echo "Installing golint into your GOPATH..."
go get github.com/golang/lint/...
go get golang.org/x/lint/golint
echo "Checking with golint..."
golint ./...
fi
88 changes: 56 additions & 32 deletions gomruby.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,46 +46,66 @@ static inline mrb_func_t _go_mrb_func_t() {
//-------------------------------------------------------------------
// Helpers to deal with calling into Ruby (C)
//-------------------------------------------------------------------
// These are some really horrible C macros that are used to wrap
// various mruby C API function calls so that we catch the exceptions.
// If we let exceptions through then the longjmp will cause a Go stack
// split.
#define GOMRUBY_EXC_PROTECT_START \
struct mrb_jmpbuf *prev_jmp = mrb->jmp; \
struct mrb_jmpbuf c_jmp; \
mrb_value result = mrb_nil_value(); \
MRB_TRY(&c_jmp) { \
mrb->jmp = &c_jmp;

#define GOMRUBY_EXC_PROTECT_END \
mrb->jmp = prev_jmp; \
} MRB_CATCH(&c_jmp) { \
mrb->jmp = prev_jmp; \
result = mrb_nil_value();\
} MRB_END_EXC(&c_jmp); \
mrb_gc_protect(mrb, result); \
return result;

static mrb_value load_string_cb(mrb_state *mrb, mrb_value in) {
return mrb_load_string(mrb, (const char*)mrb_cptr(in));
}

static mrb_value _go_mrb_load_string(mrb_state *mrb, const char *s) {
GOMRUBY_EXC_PROTECT_START
result = mrb_load_string(mrb, s);
GOMRUBY_EXC_PROTECT_END
mrb_bool state;
mrb_value result = mrb_protect(mrb, load_string_cb, mrb_cptr_value(mrb, (void*)s), &state);
if (state) {
mrb->exc = mrb_obj_ptr(result);
}
return result;
}

struct yield_data {
mrb_value block;
mrb_int argc;
const mrb_value *argv;
};

static mrb_value yield_argv_cb(mrb_state *mrb, mrb_value in) {
struct yield_data *d = (struct yield_data*)mrb_cptr(in);
return mrb_yield_argv(mrb, d->block, d->argc, d->argv);
}

static mrb_value _go_mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv) {
GOMRUBY_EXC_PROTECT_START
result = mrb_yield_argv(mrb, b, argc, argv);
GOMRUBY_EXC_PROTECT_END
struct yield_data d = { b, argc, argv };
mrb_bool state;
mrb_value result = mrb_protect(mrb, yield_argv_cb, mrb_cptr_value(mrb, &d), &state);
if (state) {
mrb->exc = mrb_obj_ptr(result);
}
return result;
}

static mrb_value _go_mrb_call(mrb_state *mrb, mrb_value b, mrb_sym method, mrb_int argc, const mrb_value *argv, mrb_value *block) {
GOMRUBY_EXC_PROTECT_START
if (block != NULL) {
result = mrb_funcall_with_block(mrb, b, method, argc, argv, *block);
struct call_data {
mrb_value self;
mrb_sym method;
mrb_int argc;
const mrb_value *argv;
const mrb_value *block;
};

static mrb_value mrb_call_cb(mrb_state *mrb, mrb_value in) {
struct call_data *d = (struct call_data*)mrb_cptr(in);
if (d->block != NULL) {
return mrb_funcall_with_block(mrb, d->self, d->method, d->argc, d->argv, *d->block);
} else {
result = mrb_funcall_argv(mrb, b, method, argc, argv);
return mrb_funcall_argv(mrb, d->self, d->method, d->argc, d->argv);
}
GOMRUBY_EXC_PROTECT_END
}

static mrb_value _go_mrb_call(mrb_state *mrb, mrb_value self, mrb_sym method, mrb_int argc, const mrb_value *argv, const mrb_value *block) {
struct call_data d = { self, method, argc, argv, block };
mrb_bool state;
mrb_value result = mrb_protect(mrb, mrb_call_cb, mrb_cptr_value(mrb, &d), &state);
if (state) {
mrb->exc = mrb_obj_ptr(result);
}
return result;
}

//-------------------------------------------------------------------
Expand All @@ -100,7 +120,7 @@ static inline int _go_mrb_get_args_all(mrb_state *s) {
mrb_value *argv;
mrb_value block;
mrb_bool append;
int argc, i;
mrb_int argc, i;

mrb_get_args(s, "*&?", &argv, &argc, &block, &append);

Expand Down Expand Up @@ -268,4 +288,8 @@ static inline mrb_value _go_mrb_gv_get(mrb_state *m, mrb_sym sym) {
return mrb_gv_get(m, sym);
}

static inline mrb_int _mrb_ary_len(mrb_value ary) {
return RARRAY_LEN(ary);
}

#endif
4 changes: 4 additions & 0 deletions mruby_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,10 @@ func TestMrbStackedException(t *testing.T) {
}

mrb.Close()

// TODO(take-cheeze): Test below
return
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's make sure we pass all tests before merge.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to fix mruby itself to make this work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need this functionality for my own projects that depend on go-mruby. What changed between 1.2 and 2.1 that caused this to break?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


mrb = NewMrb()

evalFunc := func(m *Mrb, self *MrbValue) (Value, Value) {
Expand Down
13 changes: 8 additions & 5 deletions value.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func (v *MrbValue) GCProtect() {
// when this value is a proc.
func (v *MrbValue) SetProcTargetClass(c *Class) {
proc := C._go_mrb_proc_ptr(v.value)
proc.target_class = c.class
proc.e = *(*[8]byte)(unsafe.Pointer(&c.class))
}

// Type returns the ValueType of the MrbValue. See the constants table.
Expand Down Expand Up @@ -260,10 +260,13 @@ func newExceptionValue(s *C.mrb_state) *Exception {

// Retrieve and convert backtrace to []string (avoiding reflection in Decode)
var backtrace []string
mrbBacktrace := newValue(s, C.mrb_exc_backtrace(s, value)).Array()
for i := 0; i < mrbBacktrace.Len(); i++ {
ln, _ := mrbBacktrace.Get(i)
backtrace = append(backtrace, ln.String())
stk := newValue(s, C.mrb_exc_backtrace(s, value))
if stk.Type() != TypeNil {
mrbBacktrace := stk.Array()
for i := 0; i < mrbBacktrace.Len(); i++ {
ln, _ := mrbBacktrace.Get(i)
backtrace = append(backtrace, ln.String())
}
}

// Extract file + line from first backtrace line
Expand Down
12 changes: 8 additions & 4 deletions value_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ type ValueType uint32
const (
// TypeFalse is `false`
TypeFalse ValueType = iota
// TypeFree is ?
TypeFree
// TypeTrue is `true`
TypeTrue
// TypeFloat is any floating point number such as 1.2, etc.
TypeFloat
// TypeFixnum is fixnums, or integers for this case.
TypeFixnum
// TypeSymbol is for entities in ruby that look like `:this`
TypeSymbol
// TypeUndef is a value internal to ruby for uninstantiated vars.
TypeUndef
// TypeFloat is any floating point number such as 1.2, etc.
TypeFloat
// TypeCptr is a void*
TypeCptr
// TypeFree is ?
TypeFree
// TypeObject is a standard ruby object, base class of most instantiated objects.
TypeObject
// TypeClass is the base class of all classes.
Expand Down Expand Up @@ -51,6 +51,10 @@ const (
TypeData
// TypeFiber is for members of the Fiber class
TypeFiber
// TypeIStruct is ?
TypeIStruct
// TypeBreak is ?
TypeBreak
// TypeMaxDefine is ?
TypeMaxDefine
// TypeNil is nil
Expand Down