rucy 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.doc/ext/rucy/class.cpp +36 -1
- data/.doc/ext/rucy/exception.cpp +31 -0
- data/.doc/ext/rucy/tester.cpp +3 -3
- data/.doc/ext/rucy/value.cpp +19 -3
- data/.github/workflows/release-gem.yml +2 -49
- data/.github/workflows/tag.yml +5 -28
- data/.github/workflows/test.yml +1 -37
- data/ChangeLog.md +14 -0
- data/Gemfile.lock +13 -8
- data/VERSION +1 -1
- data/ext/rucy/class.cpp +40 -1
- data/ext/rucy/exception.cpp +32 -0
- data/ext/rucy/extconf.rb +2 -1
- data/ext/rucy/tester.cpp +3 -3
- data/ext/rucy/value.cpp +24 -6
- data/include/rucy/exception.h +5 -1
- data/include/rucy/extension.h.erb +11 -7
- data/include/rucy/value.h.erb +23 -3
- data/rucy.gemspec +2 -2
- data/src/exception.cpp +14 -0
- data/src/ios/exception.mm +2 -0
- data/src/osx/exception.mm +31 -0
- data/src/rucy.cpp +0 -15
- data/src/value.cpp.erb +39 -10
- data/test/test_class.rb +13 -0
- data/test/test_exception.rb +6 -0
- data/test/test_value.rb +15 -6
- metadata +7 -6
- data/.github/workflows/utils.rb +0 -127
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bad5f79df70e83f98dcc1571f7a43a25855b1bde8387063728ac2b9b4beeacde
|
|
4
|
+
data.tar.gz: 233f871a156d7391412515bb7f40c0f813489cf9c920a0a7d594bcd0a7ee0e79
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 378c52e7c4e79fac2e80f0b7a0c3d60fd9ee908dd4338343e64ba82cd1b7127faf98eede21d355b0067f01325b2e38028eee012c3c41ca3d55cc09171db71a70
|
|
7
|
+
data.tar.gz: a204c450f186c05448ae3ffc1c15415d28fa4458ea6378d1b1f00fc93d50642ae80d202348ef27ab4dccdb40da48dfed2798abcc6c238d7e63bc67f750e673ec
|
data/.doc/ext/rucy/class.cpp
CHANGED
|
@@ -49,7 +49,7 @@ class RubyBase : public ClassWrapper<T>
|
|
|
49
49
|
|
|
50
50
|
#define THIS(type) to<type*>(self)
|
|
51
51
|
|
|
52
|
-
#define CHECK(type)
|
|
52
|
+
#define CHECK(type) RUCY_CHECK_PTR(type, self)
|
|
53
53
|
|
|
54
54
|
#define CALL(obj, fun) RUCY_CALL_SUPER(obj, fun)
|
|
55
55
|
|
|
@@ -97,6 +97,38 @@ VALUE base_new_raw(VALUE self)
|
|
|
97
97
|
return value(new Base);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
static Base* base_raw_ref = NULL;
|
|
101
|
+
|
|
102
|
+
static
|
|
103
|
+
VALUE base_set_raw_ref(VALUE self, VALUE obj)
|
|
104
|
+
{
|
|
105
|
+
if (base_raw_ref)
|
|
106
|
+
invalid_state_error(__FILE__, __LINE__);
|
|
107
|
+
|
|
108
|
+
// holds the c++ object without holding the ruby one, like a native handle
|
|
109
|
+
// that retains before the wrapper is set up
|
|
110
|
+
base_raw_ref = to<Base*>(obj);
|
|
111
|
+
base_raw_ref->Xot::RefCountable<>::retain();
|
|
112
|
+
return obj;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static
|
|
116
|
+
VALUE base_clear_raw_ref(VALUE self)
|
|
117
|
+
{
|
|
118
|
+
if (base_raw_ref)
|
|
119
|
+
base_raw_ref->Xot::RefCountable<>::release();
|
|
120
|
+
base_raw_ref = NULL;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static
|
|
124
|
+
VALUE base_call_raw_ref_name_overridable(VALUE self)
|
|
125
|
+
{
|
|
126
|
+
if (!base_raw_ref)
|
|
127
|
+
invalid_state_error(__FILE__, __LINE__);
|
|
128
|
+
|
|
129
|
+
return value(base_raw_ref->name_overridable());
|
|
130
|
+
}
|
|
131
|
+
|
|
100
132
|
|
|
101
133
|
/*
|
|
102
134
|
alloc function.
|
|
@@ -168,6 +200,9 @@ Init_class ()
|
|
|
168
200
|
rb_define_method(cBase, "call_name", RUBY_METHOD_FUNC(call_name), 0);
|
|
169
201
|
rb_define_method(cBase, "call_name_overridable", RUBY_METHOD_FUNC(call_name_overridable), 0);
|
|
170
202
|
rb_define_singleton_method(cBase, "new_raw", RUBY_METHOD_FUNC(base_new_raw), 0);
|
|
203
|
+
rb_define_singleton_method(cBase, "set_raw_ref", RUBY_METHOD_FUNC(base_set_raw_ref), 1);
|
|
204
|
+
rb_define_singleton_method(cBase, "clear_raw_ref", RUBY_METHOD_FUNC(base_clear_raw_ref), 0);
|
|
205
|
+
rb_define_singleton_method(cBase, "call_raw_ref_name_overridable", RUBY_METHOD_FUNC(base_call_raw_ref_name_overridable), 0);
|
|
171
206
|
|
|
172
207
|
cSub = rb_define_class_under(mTester, "Sub", cBase);
|
|
173
208
|
rb_define_alloc_func(cSub, sub_alloc);
|
data/.doc/ext/rucy/exception.cpp
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
#include "defs.h"
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
#ifdef OSX
|
|
5
|
+
#include <objc/runtime.h>
|
|
6
|
+
#include <objc/message.h>
|
|
7
|
+
#include <objc/objc-exception.h>
|
|
8
|
+
#include <CoreFoundation/CoreFoundation.h>
|
|
9
|
+
#undef nil// hides Rucy::nil()
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
|
|
4
13
|
using namespace Rucy;
|
|
5
14
|
|
|
6
15
|
|
|
@@ -81,6 +90,25 @@ VALUE throw_cstring(VALUE self)
|
|
|
81
90
|
throw "cstring";
|
|
82
91
|
}
|
|
83
92
|
|
|
93
|
+
#ifdef OSX
|
|
94
|
+
/*
|
|
95
|
+
throw NSException. this file is c++, so go through the objc runtime.
|
|
96
|
+
*/
|
|
97
|
+
static
|
|
98
|
+
VALUE throw_objc_exception(VALUE self)
|
|
99
|
+
{
|
|
100
|
+
typedef id (*Fun) (id, SEL, id, id, id);
|
|
101
|
+
|
|
102
|
+
CFStringRef name = CFSTR("TesterException");
|
|
103
|
+
CFStringRef reason = CFSTR("throw_objc_exception");
|
|
104
|
+
id exception = ((Fun) objc_msgSend)(
|
|
105
|
+
(id) objc_getClass("NSException"),
|
|
106
|
+
sel_registerName("exceptionWithName:reason:userInfo:"),
|
|
107
|
+
(id) name, (id) reason, NULL);
|
|
108
|
+
objc_exception_throw(exception);
|
|
109
|
+
}
|
|
110
|
+
#endif
|
|
111
|
+
|
|
84
112
|
|
|
85
113
|
void
|
|
86
114
|
Init_exception ()
|
|
@@ -96,4 +124,7 @@ Init_exception ()
|
|
|
96
124
|
rb_define_method(mTester, "throw_custom_exception", RUBY_METHOD_FUNC(throw_custom_exception), 0);
|
|
97
125
|
rb_define_method(mTester, "throw_std_string", RUBY_METHOD_FUNC(throw_std_string), 0);
|
|
98
126
|
rb_define_method(mTester, "throw_cstring", RUBY_METHOD_FUNC(throw_cstring), 0);
|
|
127
|
+
#ifdef OSX
|
|
128
|
+
rb_define_method(mTester, "throw_objc_exception", RUBY_METHOD_FUNC(throw_objc_exception), 0);
|
|
129
|
+
#endif
|
|
99
130
|
}
|
data/.doc/ext/rucy/tester.cpp
CHANGED
|
@@ -23,9 +23,9 @@ log (const char* str)
|
|
|
23
23
|
*/
|
|
24
24
|
VALUE all_logs(VALUE self)
|
|
25
25
|
{
|
|
26
|
-
|
|
27
|
-
for (size_t i = 0; i < logs.size(); ++i) a.
|
|
28
|
-
return
|
|
26
|
+
Value a = array(NULL, logs.size());
|
|
27
|
+
for (size_t i = 0; i < logs.size(); ++i) a.push(logs[i].c_str());
|
|
28
|
+
return a;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/*
|
data/.doc/ext/rucy/value.cpp
CHANGED
|
@@ -5,9 +5,9 @@ using namespace Rucy;
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
static
|
|
8
|
-
VALUE
|
|
8
|
+
VALUE value_to_schar(VALUE self, VALUE num)
|
|
9
9
|
{
|
|
10
|
-
return value(to<char>(num));
|
|
10
|
+
return value(to<signed char>(num));
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
static
|
|
@@ -97,6 +97,19 @@ VALUE array_value(VALUE self)
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
static
|
|
101
|
+
VALUE value_is_frozen(VALUE self, VALUE obj)
|
|
102
|
+
{
|
|
103
|
+
return value(obj.is_frozen());
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static
|
|
107
|
+
VALUE value_check_frozen(VALUE self, VALUE obj)
|
|
108
|
+
{
|
|
109
|
+
obj.check_frozen();
|
|
110
|
+
return obj;
|
|
111
|
+
}
|
|
112
|
+
|
|
100
113
|
|
|
101
114
|
void
|
|
102
115
|
Init_value ()
|
|
@@ -104,7 +117,7 @@ Init_value ()
|
|
|
104
117
|
Module mRucy = rb_define_module("Rucy");
|
|
105
118
|
Module mTester = rb_define_module_under(mRucy, "Tester");
|
|
106
119
|
|
|
107
|
-
rb_define_method(mTester, "
|
|
120
|
+
rb_define_method(mTester, "value_to_schar", RUBY_METHOD_FUNC(value_to_schar), 1);
|
|
108
121
|
rb_define_method(mTester, "value_to_uchar", RUBY_METHOD_FUNC(value_to_uchar), 1);
|
|
109
122
|
rb_define_method(mTester, "value_to_short", RUBY_METHOD_FUNC(value_to_short), 1);
|
|
110
123
|
rb_define_method(mTester, "value_to_ushort", RUBY_METHOD_FUNC(value_to_ushort), 1);
|
|
@@ -119,4 +132,7 @@ Init_value ()
|
|
|
119
132
|
|
|
120
133
|
rb_define_method(mTester, "nil_value", RUBY_METHOD_FUNC(nil_value), -1);
|
|
121
134
|
rb_define_method(mTester, "array_value", RUBY_METHOD_FUNC(array_value), -1);
|
|
135
|
+
|
|
136
|
+
rb_define_method(mTester, "value_is_frozen", RUBY_METHOD_FUNC(value_is_frozen), 1);
|
|
137
|
+
rb_define_method(mTester, "value_check_frozen", RUBY_METHOD_FUNC(value_check_frozen), 1);
|
|
122
138
|
}
|
|
@@ -9,52 +9,5 @@ permissions:
|
|
|
9
9
|
|
|
10
10
|
jobs:
|
|
11
11
|
release:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
steps:
|
|
15
|
-
- name: ruby 3.2
|
|
16
|
-
uses: ruby/setup-ruby@v1
|
|
17
|
-
with:
|
|
18
|
-
ruby-version: 3.2
|
|
19
|
-
|
|
20
|
-
- name: checkout
|
|
21
|
-
uses: actions/checkout@v4
|
|
22
|
-
|
|
23
|
-
- name: setup gems
|
|
24
|
-
run: bundle install
|
|
25
|
-
|
|
26
|
-
- name: setup dependencies
|
|
27
|
-
run: "ruby -I.github/workflows -rutils -e 'setup_dependencies'"
|
|
28
|
-
|
|
29
|
-
- name: packages
|
|
30
|
-
run: bundle exec rake packages
|
|
31
|
-
|
|
32
|
-
- name: setup zig
|
|
33
|
-
if: github.event.repository.name == 'reflex-terminal'
|
|
34
|
-
uses: mlugg/setup-zig@v2
|
|
35
|
-
with:
|
|
36
|
-
version: 0.16.0
|
|
37
|
-
|
|
38
|
-
- name: test
|
|
39
|
-
run: bundle exec rake test
|
|
40
|
-
|
|
41
|
-
- name: create gem
|
|
42
|
-
id: gem
|
|
43
|
-
run: |
|
|
44
|
-
bundle exec rake gem
|
|
45
|
-
echo path=$(ruby -e 'print Dir.glob("*.gem").first') >> $GITHUB_OUTPUT
|
|
46
|
-
|
|
47
|
-
- name: create github release
|
|
48
|
-
env:
|
|
49
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
50
|
-
run: ruby -I.github/workflows -rutils -e 'release(*ARGV)' ./${{ steps.gem.outputs.path }}
|
|
51
|
-
|
|
52
|
-
- name: upload to rubygems
|
|
53
|
-
env:
|
|
54
|
-
GEM_HOST_API_KEY: ${{ secrets.RUBYGEMS_AUTH_TOKEN }}
|
|
55
|
-
run: |
|
|
56
|
-
mkdir -p $HOME/.gem
|
|
57
|
-
touch $HOME/.gem/credentials
|
|
58
|
-
chmod 0600 $HOME/.gem/credentials
|
|
59
|
-
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
|
60
|
-
bundle exec rake upload
|
|
12
|
+
uses: xord/xot/.github/workflows/release-gem.yml@master
|
|
13
|
+
secrets: inherit
|
data/.github/workflows/tag.yml
CHANGED
|
@@ -1,35 +1,12 @@
|
|
|
1
1
|
name: Tag
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: [Test]
|
|
6
|
+
types: [completed]
|
|
5
7
|
branches: [master]
|
|
6
8
|
|
|
7
9
|
jobs:
|
|
8
10
|
tag:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
steps:
|
|
12
|
-
- name: ruby 3.2
|
|
13
|
-
uses: ruby/setup-ruby@v1
|
|
14
|
-
with:
|
|
15
|
-
ruby-version: 3.2
|
|
16
|
-
|
|
17
|
-
- name: checkout
|
|
18
|
-
uses: actions/checkout@v4
|
|
19
|
-
with:
|
|
20
|
-
fetch-depth: 0
|
|
21
|
-
token: ${{ secrets.PAT }}
|
|
22
|
-
|
|
23
|
-
- name: setup dependencies
|
|
24
|
-
run: "ruby -I.github/workflows -rutils -e 'setup_dependencies only: :xot'"
|
|
25
|
-
|
|
26
|
-
- name: setup user name and email
|
|
27
|
-
run: |
|
|
28
|
-
git config --global user.email "xordog@gmail.com"
|
|
29
|
-
git config --global user.name "xord"
|
|
30
|
-
|
|
31
|
-
- name: tag versions
|
|
32
|
-
run: "ruby -I.github/workflows -rutils -e 'tag_versions'"
|
|
33
|
-
|
|
34
|
-
- name: push tags
|
|
35
|
-
run: git push origin --tags
|
|
11
|
+
uses: xord/xot/.github/workflows/tag.yml@master
|
|
12
|
+
secrets: inherit
|
data/.github/workflows/test.yml
CHANGED
|
@@ -7,40 +7,4 @@ on:
|
|
|
7
7
|
|
|
8
8
|
jobs:
|
|
9
9
|
test:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
steps:
|
|
13
|
-
- name: ruby 3.2
|
|
14
|
-
uses: ruby/setup-ruby@v1
|
|
15
|
-
with:
|
|
16
|
-
ruby-version: 3.2
|
|
17
|
-
|
|
18
|
-
- name: checkout
|
|
19
|
-
uses: actions/checkout@v4
|
|
20
|
-
|
|
21
|
-
- name: setup gems
|
|
22
|
-
run: bundle install
|
|
23
|
-
|
|
24
|
-
- name: setup dependencies
|
|
25
|
-
run: "ruby -I.github/workflows -rutils -e 'setup_dependencies'"
|
|
26
|
-
|
|
27
|
-
- name: packages
|
|
28
|
-
run: bundle exec rake verbose packages
|
|
29
|
-
|
|
30
|
-
- name: setup zig
|
|
31
|
-
if: github.event.repository.name == 'reflex-terminal'
|
|
32
|
-
uses: mlugg/setup-zig@v2
|
|
33
|
-
with:
|
|
34
|
-
version: 0.16.0
|
|
35
|
-
|
|
36
|
-
- name: vendor
|
|
37
|
-
run: bundle exec rake vendor
|
|
38
|
-
|
|
39
|
-
- name: lib
|
|
40
|
-
run: bundle exec rake verbose lib
|
|
41
|
-
|
|
42
|
-
- name: ext
|
|
43
|
-
run: bundle exec rake verbose ext
|
|
44
|
-
|
|
45
|
-
- name: test
|
|
46
|
-
run: bundle exec rake verbose test
|
|
10
|
+
uses: xord/xot/.github/workflows/test.yml@master
|
data/ChangeLog.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# rucy ChangeLog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## [v0.5.0] - 2026-11-04
|
|
5
|
+
|
|
6
|
+
- [BREAKING] Rename RUCY_CHECK_OBJ to RUCY_CHECK_PTR and RUCY_CHECK_OBJECT to RUCY_CHECK_OBJ
|
|
7
|
+
- [BREAKING] Take signed char instead of char in value_to
|
|
8
|
+
- [BREAKING] Remove the hint_memory_usage callback
|
|
9
|
+
- Tag the strings handed over from C++ as UTF-8, not as ASCII-8BIT
|
|
10
|
+
- Add Value::freeze, Value::is_frozen and Value::check_frozen
|
|
11
|
+
- Keep a Ruby exception alive while it is thrown and caught in C++
|
|
12
|
+
- Put the name and reason of an Objective-C exception into NativeError
|
|
13
|
+
|
|
14
|
+
- Fix a crash when a C++ object outlives its Ruby object
|
|
15
|
+
- Fix a crash when the GC runs while an array is made from C++ values
|
|
16
|
+
|
|
17
|
+
|
|
4
18
|
## [v0.4.0] - 2026-08-04
|
|
5
19
|
|
|
6
20
|
- Add Rucy::yield and route extension block yields through it
|
data/Gemfile.lock
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
GEM
|
|
2
2
|
remote: https://rubygems.org/
|
|
3
3
|
specs:
|
|
4
|
-
power_assert (3.0
|
|
5
|
-
rake (13.
|
|
6
|
-
test-unit (3.7.
|
|
4
|
+
power_assert (3.1.0)
|
|
5
|
+
rake (13.4.2)
|
|
6
|
+
test-unit (3.7.8)
|
|
7
7
|
power_assert
|
|
8
|
-
yard (0.9.
|
|
8
|
+
yard (0.9.45)
|
|
9
9
|
|
|
10
10
|
PLATFORMS
|
|
11
|
-
|
|
12
|
-
arm64-darwin-23
|
|
13
|
-
arm64-darwin-24
|
|
11
|
+
ruby
|
|
14
12
|
|
|
15
13
|
DEPENDENCIES
|
|
16
14
|
rake
|
|
17
15
|
test-unit
|
|
18
16
|
yard
|
|
19
17
|
|
|
18
|
+
CHECKSUMS
|
|
19
|
+
bundler (4.0.20) sha256=7978a8ac648767f5e635bc522445b79e80a52b907a39a36c2d8085ed6bc762ae
|
|
20
|
+
power_assert (3.1.0) sha256=fefe98ed5d3140628138f3f9f9194d6ece01f1320e69700d3c928adca7518251
|
|
21
|
+
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
|
|
22
|
+
test-unit (3.7.8) sha256=689d1ca53f4d46f678b4e5d68d8e4294f87fc5e8b9238cc4de7c5727e8d65943
|
|
23
|
+
yard (0.9.45) sha256=52e211493f7cb8a3ebf7e104a25a1e73937a3103092545d34cb88fafebb3dc51
|
|
24
|
+
|
|
20
25
|
BUNDLED WITH
|
|
21
|
-
|
|
26
|
+
4.0.20
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.5.0
|
data/ext/rucy/class.cpp
CHANGED
|
@@ -49,7 +49,7 @@ class RubyBase : public ClassWrapper<T>
|
|
|
49
49
|
|
|
50
50
|
#define THIS(type) to<type*>(self)
|
|
51
51
|
|
|
52
|
-
#define CHECK(type)
|
|
52
|
+
#define CHECK(type) RUCY_CHECK_PTR(type, self)
|
|
53
53
|
|
|
54
54
|
#define CALL(obj, fun) RUCY_CALL_SUPER(obj, fun)
|
|
55
55
|
|
|
@@ -103,6 +103,41 @@ RUCY_DEF0(base_new_raw)
|
|
|
103
103
|
}
|
|
104
104
|
RUCY_END
|
|
105
105
|
|
|
106
|
+
static Base* base_raw_ref = NULL;
|
|
107
|
+
|
|
108
|
+
static
|
|
109
|
+
RUCY_DEF1(base_set_raw_ref, obj)
|
|
110
|
+
{
|
|
111
|
+
if (base_raw_ref)
|
|
112
|
+
invalid_state_error(__FILE__, __LINE__);
|
|
113
|
+
|
|
114
|
+
// holds the c++ object without holding the ruby one, like a native handle
|
|
115
|
+
// that retains before the wrapper is set up
|
|
116
|
+
base_raw_ref = to<Base*>(obj);
|
|
117
|
+
base_raw_ref->Xot::RefCountable<>::retain();
|
|
118
|
+
return obj;
|
|
119
|
+
}
|
|
120
|
+
RUCY_END
|
|
121
|
+
|
|
122
|
+
static
|
|
123
|
+
RUCY_DEF0(base_clear_raw_ref)
|
|
124
|
+
{
|
|
125
|
+
if (base_raw_ref)
|
|
126
|
+
base_raw_ref->Xot::RefCountable<>::release();
|
|
127
|
+
base_raw_ref = NULL;
|
|
128
|
+
}
|
|
129
|
+
RUCY_END
|
|
130
|
+
|
|
131
|
+
static
|
|
132
|
+
RUCY_DEF0(base_call_raw_ref_name_overridable)
|
|
133
|
+
{
|
|
134
|
+
if (!base_raw_ref)
|
|
135
|
+
invalid_state_error(__FILE__, __LINE__);
|
|
136
|
+
|
|
137
|
+
return value(base_raw_ref->name_overridable());
|
|
138
|
+
}
|
|
139
|
+
RUCY_END
|
|
140
|
+
|
|
106
141
|
|
|
107
142
|
/*
|
|
108
143
|
alloc function.
|
|
@@ -181,6 +216,10 @@ Init_class ()
|
|
|
181
216
|
cBase.define_method("call_name", call_name);
|
|
182
217
|
cBase.define_method("call_name_overridable", call_name_overridable);
|
|
183
218
|
cBase.define_singleton_method("new_raw", base_new_raw);
|
|
219
|
+
cBase.define_singleton_method("set_raw_ref", base_set_raw_ref);
|
|
220
|
+
cBase.define_singleton_method("clear_raw_ref", base_clear_raw_ref);
|
|
221
|
+
cBase.define_singleton_method(
|
|
222
|
+
"call_raw_ref_name_overridable", base_call_raw_ref_name_overridable);
|
|
184
223
|
|
|
185
224
|
cSub = mTester.define_class("Sub", cBase);
|
|
186
225
|
cSub.define_alloc_func(sub_alloc);
|
data/ext/rucy/exception.cpp
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
#include "defs.h"
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
#ifdef OSX
|
|
5
|
+
#include <objc/runtime.h>
|
|
6
|
+
#include <objc/message.h>
|
|
7
|
+
#include <objc/objc-exception.h>
|
|
8
|
+
#include <CoreFoundation/CoreFoundation.h>
|
|
9
|
+
#undef nil// hides Rucy::nil()
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
|
|
4
13
|
using namespace Rucy;
|
|
5
14
|
|
|
6
15
|
|
|
@@ -89,6 +98,26 @@ RUCY_DEF0(throw_cstring)
|
|
|
89
98
|
}
|
|
90
99
|
RUCY_END
|
|
91
100
|
|
|
101
|
+
#ifdef OSX
|
|
102
|
+
/*
|
|
103
|
+
throw NSException. this file is c++, so go through the objc runtime.
|
|
104
|
+
*/
|
|
105
|
+
static
|
|
106
|
+
RUCY_DEF0(throw_objc_exception)
|
|
107
|
+
{
|
|
108
|
+
typedef id (*Fun) (id, SEL, id, id, id);
|
|
109
|
+
|
|
110
|
+
CFStringRef name = CFSTR("TesterException");
|
|
111
|
+
CFStringRef reason = CFSTR("throw_objc_exception");
|
|
112
|
+
id exception = ((Fun) objc_msgSend)(
|
|
113
|
+
(id) objc_getClass("NSException"),
|
|
114
|
+
sel_registerName("exceptionWithName:reason:userInfo:"),
|
|
115
|
+
(id) name, (id) reason, NULL);
|
|
116
|
+
objc_exception_throw(exception);
|
|
117
|
+
}
|
|
118
|
+
RUCY_END
|
|
119
|
+
#endif
|
|
120
|
+
|
|
92
121
|
|
|
93
122
|
void
|
|
94
123
|
Init_exception ()
|
|
@@ -104,4 +133,7 @@ Init_exception ()
|
|
|
104
133
|
mTester.define_method("throw_custom_exception", throw_custom_exception);
|
|
105
134
|
mTester.define_method("throw_std_string", throw_std_string);
|
|
106
135
|
mTester.define_method("throw_cstring", throw_cstring);
|
|
136
|
+
#ifdef OSX
|
|
137
|
+
mTester.define_method("throw_objc_exception", throw_objc_exception);
|
|
138
|
+
#endif
|
|
107
139
|
}
|
data/ext/rucy/extconf.rb
CHANGED
data/ext/rucy/tester.cpp
CHANGED
|
@@ -23,9 +23,9 @@ log (const char* str)
|
|
|
23
23
|
*/
|
|
24
24
|
RUCY_DEF0(all_logs)
|
|
25
25
|
{
|
|
26
|
-
|
|
27
|
-
for (size_t i = 0; i < logs.size(); ++i) a.
|
|
28
|
-
return
|
|
26
|
+
Value a = array(NULL, logs.size());
|
|
27
|
+
for (size_t i = 0; i < logs.size(); ++i) a.push(logs[i].c_str());
|
|
28
|
+
return a;
|
|
29
29
|
}
|
|
30
30
|
RUCY_END
|
|
31
31
|
|
data/ext/rucy/value.cpp
CHANGED
|
@@ -5,9 +5,9 @@ using namespace Rucy;
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
static
|
|
8
|
-
RUCY_DEF1(
|
|
8
|
+
RUCY_DEF1(value_to_schar, num)
|
|
9
9
|
{
|
|
10
|
-
return value(to<char>(num));
|
|
10
|
+
return value(to<signed char>(num));
|
|
11
11
|
}
|
|
12
12
|
RUCY_END
|
|
13
13
|
|
|
@@ -110,6 +110,21 @@ RUCY_DEFN(array_value)
|
|
|
110
110
|
}
|
|
111
111
|
RUCY_END
|
|
112
112
|
|
|
113
|
+
static
|
|
114
|
+
RUCY_DEF1(value_is_frozen, obj)
|
|
115
|
+
{
|
|
116
|
+
return value(obj.is_frozen());
|
|
117
|
+
}
|
|
118
|
+
RUCY_END
|
|
119
|
+
|
|
120
|
+
static
|
|
121
|
+
RUCY_DEF1(value_check_frozen, obj)
|
|
122
|
+
{
|
|
123
|
+
obj.check_frozen();
|
|
124
|
+
return obj;
|
|
125
|
+
}
|
|
126
|
+
RUCY_END
|
|
127
|
+
|
|
113
128
|
|
|
114
129
|
void
|
|
115
130
|
Init_value ()
|
|
@@ -117,7 +132,7 @@ Init_value ()
|
|
|
117
132
|
Module mRucy = define_module("Rucy");
|
|
118
133
|
Module mTester = mRucy.define_module("Tester");
|
|
119
134
|
|
|
120
|
-
mTester.define_method("
|
|
135
|
+
mTester.define_method("value_to_schar", value_to_schar);
|
|
121
136
|
mTester.define_method("value_to_uchar", value_to_uchar);
|
|
122
137
|
mTester.define_method("value_to_short", value_to_short);
|
|
123
138
|
mTester.define_method("value_to_ushort", value_to_ushort);
|
|
@@ -126,10 +141,13 @@ Init_value ()
|
|
|
126
141
|
mTester.define_method("value_to_long", value_to_long);
|
|
127
142
|
mTester.define_method("value_to_ulong", value_to_ulong);
|
|
128
143
|
|
|
129
|
-
mTester.define_method("true_to_value",
|
|
144
|
+
mTester.define_method( "true_to_value", true_to_value);
|
|
130
145
|
mTester.define_method("false_to_value", false_to_value);
|
|
131
|
-
mTester.define_method("null_to_value",
|
|
146
|
+
mTester.define_method( "null_to_value", NULL_to_value);
|
|
132
147
|
|
|
133
|
-
mTester.define_method("nil_value",
|
|
148
|
+
mTester.define_method( "nil_value", nil_value);
|
|
134
149
|
mTester.define_method("array_value", array_value);
|
|
150
|
+
|
|
151
|
+
mTester.define_method("value_is_frozen", value_is_frozen);
|
|
152
|
+
mTester.define_method("value_check_frozen", value_check_frozen);
|
|
135
153
|
}
|
data/include/rucy/exception.h
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
#include <stdexcept>
|
|
8
|
+
#include <exception>
|
|
8
9
|
#include <xot/exception.h>
|
|
9
10
|
#include <rucy/value.h>
|
|
10
11
|
|
|
@@ -30,7 +31,7 @@ namespace Rucy
|
|
|
30
31
|
|
|
31
32
|
private:
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
GlobalValue val;
|
|
34
35
|
|
|
35
36
|
};// RubyException
|
|
36
37
|
|
|
@@ -98,6 +99,9 @@ namespace Rucy
|
|
|
98
99
|
const char* file, int line, const char* format = NULL, ...);
|
|
99
100
|
|
|
100
101
|
|
|
102
|
+
Xot::String get_unknown_exception_message (std::exception_ptr exception);
|
|
103
|
+
|
|
104
|
+
|
|
101
105
|
}// Rucy
|
|
102
106
|
|
|
103
107
|
|
|
@@ -256,7 +256,8 @@
|
|
|
256
256
|
catch (...) \
|
|
257
257
|
{ \
|
|
258
258
|
RUCY_GOTO_RAISE(rb_exc_new2( \
|
|
259
|
-
Rucy::native_error_class(),
|
|
259
|
+
Rucy::native_error_class(), \
|
|
260
|
+
Rucy::get_unknown_exception_message(std::current_exception()).c_str())); \
|
|
260
261
|
}
|
|
261
262
|
|
|
262
263
|
#define RUCY_GOTO_RAISE(exception) \
|
|
@@ -290,7 +291,7 @@
|
|
|
290
291
|
}
|
|
291
292
|
|
|
292
293
|
|
|
293
|
-
#define
|
|
294
|
+
#define RUCY_CHECK_PTR(native_class, obj) \
|
|
294
295
|
do \
|
|
295
296
|
{ \
|
|
296
297
|
native_class* p = \
|
|
@@ -299,7 +300,7 @@
|
|
|
299
300
|
} \
|
|
300
301
|
while(0)
|
|
301
302
|
|
|
302
|
-
#define
|
|
303
|
+
#define RUCY_CHECK_OBJ(native_class, obj) \
|
|
303
304
|
do \
|
|
304
305
|
{ \
|
|
305
306
|
native_class* p = \
|
|
@@ -338,7 +339,7 @@ namespace Rucy
|
|
|
338
339
|
|
|
339
340
|
public:
|
|
340
341
|
|
|
341
|
-
GlobalValue value;
|
|
342
|
+
mutable GlobalValue value;
|
|
342
343
|
|
|
343
344
|
ClassWrapper ()
|
|
344
345
|
: value(nil(), true), overridable(true)
|
|
@@ -353,7 +354,10 @@ namespace Rucy
|
|
|
353
354
|
|
|
354
355
|
void release (intptr_t by_ruby) const override
|
|
355
356
|
{
|
|
356
|
-
if (
|
|
357
|
+
if (by_ruby)
|
|
358
|
+
value = nil();
|
|
359
|
+
else
|
|
360
|
+
value.enable_gc();
|
|
357
361
|
RucyWrapped::release();
|
|
358
362
|
}
|
|
359
363
|
|
|
@@ -496,7 +500,7 @@ namespace Rucy
|
|
|
496
500
|
static
|
|
497
501
|
RUCY_DEF1(wrapper_equal, other)
|
|
498
502
|
{
|
|
499
|
-
|
|
503
|
+
RUCY_CHECK_PTR(T, self);
|
|
500
504
|
if (!other.is_a(get_ruby_class<T>()))
|
|
501
505
|
return value(false);
|
|
502
506
|
return value(get_type_ptr<T>(self) == get_type_ptr<T>(other));
|
|
@@ -507,7 +511,7 @@ namespace Rucy
|
|
|
507
511
|
static
|
|
508
512
|
RUCY_DEF0(wrapper_hash)
|
|
509
513
|
{
|
|
510
|
-
|
|
514
|
+
RUCY_CHECK_PTR(T, self);
|
|
511
515
|
return value((unsigned long long) get_type_ptr<T>(self));
|
|
512
516
|
}
|
|
513
517
|
RUCY_DEF_END
|
data/include/rucy/value.h.erb
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
#define __RUCY_VALUE_H__
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
#include <
|
|
7
|
+
#include <iterator>
|
|
8
|
+
#include <type_traits>
|
|
8
9
|
#include <rucy/ruby.h>
|
|
9
10
|
#include <rucy/symbol.h>
|
|
10
11
|
|
|
@@ -111,6 +112,12 @@ namespace Rucy
|
|
|
111
112
|
|
|
112
113
|
bool respond_to (Symbol name) const;
|
|
113
114
|
|
|
115
|
+
Value freeze ();
|
|
116
|
+
|
|
117
|
+
bool is_frozen () const;
|
|
118
|
+
|
|
119
|
+
void check_frozen () const;
|
|
120
|
+
|
|
114
121
|
Value inspect () const;
|
|
115
122
|
|
|
116
123
|
// String
|
|
@@ -199,6 +206,8 @@ namespace Rucy
|
|
|
199
206
|
|
|
200
207
|
GlobalValue (const This& obj, bool gc = false);
|
|
201
208
|
|
|
209
|
+
GlobalValue& operator = (const RubyValue& v);
|
|
210
|
+
|
|
202
211
|
GlobalValue& operator = (const Value& v);
|
|
203
212
|
|
|
204
213
|
GlobalValue& operator = (const This& obj);
|
|
@@ -224,6 +233,8 @@ namespace Rucy
|
|
|
224
233
|
|
|
225
234
|
Value value ( char n);
|
|
226
235
|
|
|
236
|
+
Value value ( signed char n);
|
|
237
|
+
|
|
227
238
|
Value value (unsigned char n);
|
|
228
239
|
|
|
229
240
|
Value value ( short n);
|
|
@@ -264,8 +275,13 @@ namespace Rucy
|
|
|
264
275
|
std::input_iterator_tag
|
|
265
276
|
>::value>::type* = nullptr)
|
|
266
277
|
{
|
|
267
|
-
|
|
268
|
-
|
|
278
|
+
size_t size = 0;
|
|
279
|
+
if constexpr (std::sized_sentinel_for<T, T>)
|
|
280
|
+
size = end - begin;
|
|
281
|
+
|
|
282
|
+
Value ary = array(NULL, size);
|
|
283
|
+
for (T it = begin; it != end; ++it) ary.push(*it);
|
|
284
|
+
return ary;
|
|
269
285
|
}
|
|
270
286
|
|
|
271
287
|
|
|
@@ -293,6 +309,10 @@ namespace Rucy
|
|
|
293
309
|
}
|
|
294
310
|
|
|
295
311
|
|
|
312
|
+
// the range of char changes with the platform, so use signed or unsigned char
|
|
313
|
+
template <> char value_to<char> (Value obj, bool convert) = delete;
|
|
314
|
+
|
|
315
|
+
|
|
296
316
|
}// Rucy
|
|
297
317
|
|
|
298
318
|
|
data/rucy.gemspec
CHANGED
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
|
11
11
|
|
|
12
12
|
ext = Rucy::Extension
|
|
13
13
|
name = ext.name true
|
|
14
|
-
rdocs = glob.call
|
|
14
|
+
rdocs = glob.call(*%w[README .doc/ext/**/*.cpp])
|
|
15
15
|
|
|
16
16
|
s.name = name
|
|
17
17
|
s.version = ext.version
|
|
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
s.platform = Gem::Platform::RUBY
|
|
26
26
|
s.required_ruby_version = '>= 3.0.0'
|
|
27
27
|
|
|
28
|
-
s.add_dependency 'xot', '~> 0.
|
|
28
|
+
s.add_dependency 'xot', '~> 0.5.0'
|
|
29
29
|
|
|
30
30
|
s.files = `git ls-files`.split $/
|
|
31
31
|
s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
|
data/src/exception.cpp
CHANGED
|
@@ -144,4 +144,18 @@ namespace Rucy
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
|
|
147
|
+
Xot::String
|
|
148
|
+
get_unknown_exception_message (std::exception_ptr exception)
|
|
149
|
+
{
|
|
150
|
+
#if defined(OSX) || defined(IOS)
|
|
151
|
+
Xot::String get_native_unknown_exception_message (std::exception_ptr);
|
|
152
|
+
Xot::String message = get_native_unknown_exception_message(exception);
|
|
153
|
+
if (!message.empty())
|
|
154
|
+
return message;
|
|
155
|
+
#endif
|
|
156
|
+
|
|
157
|
+
return "Unknown C++ exception was thrown.";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
147
161
|
}// Rucy
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// -*- objc -*-
|
|
2
|
+
#include "rucy/exception.h"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#import <Foundation/Foundation.h>
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
namespace Rucy
|
|
9
|
+
{
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Xot::String
|
|
13
|
+
get_native_unknown_exception_message (std::exception_ptr exception)
|
|
14
|
+
{
|
|
15
|
+
try
|
|
16
|
+
{
|
|
17
|
+
std::rethrow_exception(exception);
|
|
18
|
+
}
|
|
19
|
+
catch (NSException* e)
|
|
20
|
+
{
|
|
21
|
+
return Xot::stringf(
|
|
22
|
+
"%s: %s", e.name.UTF8String, e.reason ? e.reason.UTF8String : "");
|
|
23
|
+
}
|
|
24
|
+
catch (...)
|
|
25
|
+
{
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
}// Rucy
|
data/src/rucy.cpp
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#include "rucy/rucy.h"
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
#include <xot/util.h>
|
|
6
5
|
#include "rucy/exception.h"
|
|
7
6
|
|
|
8
7
|
|
|
@@ -10,18 +9,6 @@ namespace Rucy
|
|
|
10
9
|
{
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
static void
|
|
14
|
-
hint_memory_usage (ssize_t size)
|
|
15
|
-
{
|
|
16
|
-
rb_gc_adjust_memory_usage(size);
|
|
17
|
-
|
|
18
|
-
// rb_gc_adjust_memory_usage() uses MEMOP_TYPE_REALLOC internally,
|
|
19
|
-
// which increases malloc_increase but does not check the GC trigger.
|
|
20
|
-
// A tiny ruby_xmalloc() goes through MEMOP_TYPE_MALLOC and triggers
|
|
21
|
-
// GC when malloc_increase exceeds malloc_limit.
|
|
22
|
-
if (size > 0) ruby_xfree(ruby_xmalloc(1));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
12
|
void
|
|
26
13
|
init ()
|
|
27
14
|
{
|
|
@@ -29,8 +16,6 @@ namespace Rucy
|
|
|
29
16
|
if (done) return;
|
|
30
17
|
done = true;
|
|
31
18
|
|
|
32
|
-
Xot::set_hint_memory_usage_fun(hint_memory_usage);
|
|
33
|
-
|
|
34
19
|
rucy_module();
|
|
35
20
|
native_error_class();
|
|
36
21
|
invalid_state_error_class();
|
data/src/value.cpp.erb
CHANGED
|
@@ -58,15 +58,13 @@ namespace Rucy
|
|
|
58
58
|
static VALUE
|
|
59
59
|
str_new (const char* s, rb_encoding* encoding)
|
|
60
60
|
{
|
|
61
|
-
|
|
62
|
-
return e ? rb_enc_str_new_cstr(s, e) : rb_str_new_cstr(s);
|
|
61
|
+
return rb_enc_str_new_cstr(s, encoding ? encoding : rb_utf8_encoding());
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
static VALUE
|
|
66
65
|
str_new (const char* s, size_t len, rb_encoding* encoding)
|
|
67
66
|
{
|
|
68
|
-
|
|
69
|
-
return e ? rb_enc_str_new(s, len, e) : rb_str_new(s, len);
|
|
67
|
+
return rb_enc_str_new(s, len, encoding ? encoding : rb_utf8_encoding());
|
|
70
68
|
}
|
|
71
69
|
|
|
72
70
|
Value::Value (const char* s, rb_encoding* encoding)
|
|
@@ -314,6 +312,24 @@ namespace Rucy
|
|
|
314
312
|
return rb_respond_to(val, name.symbol());
|
|
315
313
|
}
|
|
316
314
|
|
|
315
|
+
Value
|
|
316
|
+
Value::freeze ()
|
|
317
|
+
{
|
|
318
|
+
return rb_obj_freeze(val);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
bool
|
|
322
|
+
Value::is_frozen () const
|
|
323
|
+
{
|
|
324
|
+
return RB_OBJ_FROZEN(val);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
void
|
|
328
|
+
Value::check_frozen () const
|
|
329
|
+
{
|
|
330
|
+
rb_check_frozen(val);
|
|
331
|
+
}
|
|
332
|
+
|
|
317
333
|
Value
|
|
318
334
|
Value::inspect () const
|
|
319
335
|
{
|
|
@@ -492,6 +508,13 @@ namespace Rucy
|
|
|
492
508
|
init(gc_);
|
|
493
509
|
}
|
|
494
510
|
|
|
511
|
+
GlobalValue&
|
|
512
|
+
GlobalValue::operator = (const RubyValue& v)
|
|
513
|
+
{
|
|
514
|
+
Super::operator=(v);
|
|
515
|
+
return *this;
|
|
516
|
+
}
|
|
517
|
+
|
|
495
518
|
GlobalValue&
|
|
496
519
|
GlobalValue::operator = (const Value& v)
|
|
497
520
|
{
|
|
@@ -552,6 +575,12 @@ namespace Rucy
|
|
|
552
575
|
return (int) n;
|
|
553
576
|
}
|
|
554
577
|
|
|
578
|
+
Value
|
|
579
|
+
value (signed char n)
|
|
580
|
+
{
|
|
581
|
+
return (int) n;
|
|
582
|
+
}
|
|
583
|
+
|
|
555
584
|
Value
|
|
556
585
|
value (unsigned char n)
|
|
557
586
|
{
|
|
@@ -652,18 +681,18 @@ namespace Rucy
|
|
|
652
681
|
return (bool) obj;
|
|
653
682
|
}
|
|
654
683
|
|
|
655
|
-
template <> char
|
|
656
|
-
value_to<char> (Value obj, bool convert)
|
|
684
|
+
template <> signed char
|
|
685
|
+
value_to<signed char> (Value obj, bool convert)
|
|
657
686
|
{
|
|
658
687
|
if (convert) obj = obj.to_i();
|
|
659
688
|
int n = NUM2INT(obj.value());
|
|
660
689
|
if (
|
|
661
|
-
n < std::numeric_limits<char>::min() ||
|
|
662
|
-
n > std::numeric_limits<char>::max())
|
|
690
|
+
n < std::numeric_limits<signed char>::min() ||
|
|
691
|
+
n > std::numeric_limits<signed char>::max())
|
|
663
692
|
{
|
|
664
|
-
range_error(__FILE__, __LINE__, "cannot cast '%d' to char", n);
|
|
693
|
+
range_error(__FILE__, __LINE__, "cannot cast '%d' to signed char", n);
|
|
665
694
|
}
|
|
666
|
-
return (char) n;
|
|
695
|
+
return (signed char) n;
|
|
667
696
|
}
|
|
668
697
|
|
|
669
698
|
template <> unsigned char
|
data/test/test_class.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'weakref'
|
|
1
2
|
require_relative 'helper'
|
|
2
3
|
|
|
3
4
|
|
|
@@ -130,4 +131,16 @@ class TestClass < Test::Unit::TestCase
|
|
|
130
131
|
assert_equal '~SimpleObj(2)', last_log(/2/)
|
|
131
132
|
end
|
|
132
133
|
|
|
134
|
+
def test_freed_ruby_object_is_not_called()
|
|
135
|
+
# made on another thread, whose stack is gone with no stale value left
|
|
136
|
+
ref = Thread.new {WeakRef.new Base.set_raw_ref(Temp.new)}.value
|
|
137
|
+
3.times {GC.start; break unless ref.weakref_alive?}
|
|
138
|
+
# the gc scans the stack conservatively, so a stale value can keep it alive
|
|
139
|
+
omit 'the ruby object was not freed by the gc' if ref.weakref_alive?
|
|
140
|
+
|
|
141
|
+
assert_equal "Sub::name_overridable", Base.call_raw_ref_name_overridable
|
|
142
|
+
ensure
|
|
143
|
+
Base.clear_raw_ref
|
|
144
|
+
end
|
|
145
|
+
|
|
133
146
|
end# TestClass
|
data/test/test_exception.rb
CHANGED
|
@@ -33,4 +33,10 @@ class TestException < Test::Unit::TestCase
|
|
|
33
33
|
assert_raise(Rucy::NativeError) {throw_cstring}
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def test_throw_objc_exception()
|
|
37
|
+
return unless osx?
|
|
38
|
+
e = assert_raise(Rucy::NativeError) {throw_objc_exception}
|
|
39
|
+
assert_match(/TesterException: throw_objc_exception/, e.message)
|
|
40
|
+
end
|
|
41
|
+
|
|
36
42
|
end# TestException
|
data/test/test_value.rb
CHANGED
|
@@ -5,12 +5,12 @@ class TestFunction < Test::Unit::TestCase
|
|
|
5
5
|
|
|
6
6
|
include Rucy::Tester
|
|
7
7
|
|
|
8
|
-
def
|
|
9
|
-
assert_equal 0,
|
|
10
|
-
assert_equal 127,
|
|
11
|
-
assert_raise(RangeError) {
|
|
12
|
-
assert_equal(-128,
|
|
13
|
-
assert_raise(RangeError) {
|
|
8
|
+
def test_value_to_schar()
|
|
9
|
+
assert_equal 0, value_to_schar( 0)
|
|
10
|
+
assert_equal 127, value_to_schar( 127)
|
|
11
|
+
assert_raise(RangeError) {value_to_schar 128}
|
|
12
|
+
assert_equal(-128, value_to_schar(-128))
|
|
13
|
+
assert_raise(RangeError) {value_to_schar(-129)}
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def test_value_to_uchar()
|
|
@@ -61,4 +61,13 @@ class TestFunction < Test::Unit::TestCase
|
|
|
61
61
|
assert_raise(ArgumentError) {array_value 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
def test_frozen()
|
|
65
|
+
assert_false value_is_frozen(+'')
|
|
66
|
+
assert_true value_is_frozen( ''.freeze)
|
|
67
|
+
|
|
68
|
+
o = Object.new
|
|
69
|
+
assert_equal o, value_check_frozen(o)
|
|
70
|
+
assert_raise(FrozenError) {value_check_frozen o.freeze}
|
|
71
|
+
end
|
|
72
|
+
|
|
64
73
|
end# TestFunction
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rucy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- xordog
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: xot
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.5.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.5.0
|
|
27
27
|
description: This library helps you to develop Ruby Extension by C++.
|
|
28
28
|
email: xordog@gmail.com
|
|
29
29
|
executables:
|
|
@@ -48,7 +48,6 @@ files:
|
|
|
48
48
|
- ".github/workflows/release-gem.yml"
|
|
49
49
|
- ".github/workflows/tag.yml"
|
|
50
50
|
- ".github/workflows/test.yml"
|
|
51
|
-
- ".github/workflows/utils.rb"
|
|
52
51
|
- CLAUDE.md
|
|
53
52
|
- CONTRIBUTING.md
|
|
54
53
|
- ChangeLog.md
|
|
@@ -89,7 +88,9 @@ files:
|
|
|
89
88
|
- src/exception.cpp
|
|
90
89
|
- src/extension.cpp
|
|
91
90
|
- src/function.cpp.erb
|
|
91
|
+
- src/ios/exception.mm
|
|
92
92
|
- src/module.cpp.erb
|
|
93
|
+
- src/osx/exception.mm
|
|
93
94
|
- src/rucy.cpp
|
|
94
95
|
- src/symbol.cpp
|
|
95
96
|
- src/value.cpp.erb
|
|
@@ -119,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
119
120
|
- !ruby/object:Gem::Version
|
|
120
121
|
version: '0'
|
|
121
122
|
requirements: []
|
|
122
|
-
rubygems_version: 3.
|
|
123
|
+
rubygems_version: 3.5.22
|
|
123
124
|
signing_key:
|
|
124
125
|
specification_version: 4
|
|
125
126
|
summary: A Ruby C++ Extension Helper Library.
|
data/.github/workflows/utils.rb
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
require 'shellwords'
|
|
2
|
-
|
|
3
|
-
ALL_REPO = 'xord/all'
|
|
4
|
-
ALL_DIR = '../all'
|
|
5
|
-
ALL_FETCH_DEPTH = 100
|
|
6
|
-
|
|
7
|
-
RENAMES = {reflex: 'reflexion'}
|
|
8
|
-
|
|
9
|
-
def sh(cmd)
|
|
10
|
-
puts cmd
|
|
11
|
-
system cmd
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def setup_dependencies(only: nil)
|
|
15
|
-
gemspec_path = `git ls-files`.lines(chomp: true).find {|l| l =~ /\.gemspec$/}
|
|
16
|
-
return unless gemspec_path
|
|
17
|
-
|
|
18
|
-
gemspec = File.read gemspec_path
|
|
19
|
-
name = File.basename gemspec_path, '.gemspec'
|
|
20
|
-
|
|
21
|
-
exts = File.readlines('Rakefile')
|
|
22
|
-
.map {|l| l[%r|^\s*require\W+([\w\-\_]+)/extension\W+$|, 1]}
|
|
23
|
-
.compact
|
|
24
|
-
.reject {|ext| ext == name}
|
|
25
|
-
exts = exts & [only].flatten.map(&:to_s) if only
|
|
26
|
-
return if exts.empty?
|
|
27
|
-
|
|
28
|
-
unless setup_dependencies_via_monorepo(exts)
|
|
29
|
-
setup_dependencies_via_each_repo_by_version(gemspec, exts)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
exts.each {|ext| sh %( cd ../#{ext} && rake ext )}
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def setup_dependencies_via_monorepo(exts)
|
|
36
|
-
return false unless checkout_monorepo
|
|
37
|
-
exts.each {|ext| sh %( ln -snf all/#{ext} ../#{ext} )}
|
|
38
|
-
true
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def checkout_monorepo()
|
|
42
|
-
uuid = `git log -1 --format=%B`[/^\[\[([0-9a-fA-F-]+)\]\]$/, 1]
|
|
43
|
-
return false unless uuid
|
|
44
|
-
|
|
45
|
-
commit = setup_monorepo uuid
|
|
46
|
-
return false unless commit
|
|
47
|
-
|
|
48
|
-
Dir.chdir(ALL_DIR) {sh %( git checkout -q #{commit} )}
|
|
49
|
-
true
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def setup_monorepo(uuid)
|
|
53
|
-
unless File.directory? ALL_DIR
|
|
54
|
-
url = "https://github.com/#{ALL_REPO}.git"
|
|
55
|
-
sh %( git clone --no-tags --depth #{ALL_FETCH_DEPTH} #{url} #{ALL_DIR} )
|
|
56
|
-
end
|
|
57
|
-
loop do
|
|
58
|
-
commit = find_monorepo_commit uuid
|
|
59
|
-
return commit if commit
|
|
60
|
-
|
|
61
|
-
deepened = Dir.chdir ALL_DIR do
|
|
62
|
-
before = `git rev-list --count HEAD`.to_i
|
|
63
|
-
sh %( git fetch --deepen #{ALL_FETCH_DEPTH} )
|
|
64
|
-
`git rev-list --count HEAD`.to_i > before
|
|
65
|
-
end
|
|
66
|
-
return nil unless deepened
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def find_monorepo_commit(uuid)
|
|
71
|
-
Dir.chdir ALL_DIR do
|
|
72
|
-
out = `git log origin/HEAD -F --grep="[[#{uuid}]]" --format=%H -1`.strip
|
|
73
|
-
out.empty? ? nil : out
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def setup_dependencies_via_each_repo_by_version(gemspec, exts)
|
|
78
|
-
exts.each do |ext|
|
|
79
|
-
gem = RENAMES[ext.to_sym].then {|s| s || ext}
|
|
80
|
-
ver = gemspec[/add_dependency.*['"]#{gem}['"].*['"]\s*~>\s*([\d\.]+)\s*['"]/, 1]
|
|
81
|
-
opts = '-c advice.detachedHead=false --depth 1'
|
|
82
|
-
clone = "git clone #{opts} https://github.com/xord/#{ext}.git ../#{ext}"
|
|
83
|
-
|
|
84
|
-
# 'rake subtree:push' pushes all subrepos, so cloning by new tag
|
|
85
|
-
# often fails before tagging each new tag
|
|
86
|
-
sh %( #{clone} --branch v#{ver} || #{clone} )
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def tag_versions()
|
|
91
|
-
changes = changelogs
|
|
92
|
-
tags = `git tag`.lines chomp: true
|
|
93
|
-
vers = `git log --oneline ./VERSION`
|
|
94
|
-
.lines(chomp: true)
|
|
95
|
-
.map {|line| line.split.first[/^\w+$/]}
|
|
96
|
-
.map {|sha| [`git cat-file -p #{sha}:./VERSION 2>/dev/null`[/[\d\.]+/], sha]}
|
|
97
|
-
.select {|ver, sha| ver && sha}
|
|
98
|
-
.reverse
|
|
99
|
-
.to_h
|
|
100
|
-
|
|
101
|
-
vers.to_a.reverse.each do |ver, sha|
|
|
102
|
-
tag = "v#{ver}"
|
|
103
|
-
break if tags.include?(tag)
|
|
104
|
-
sh %( git tag -a -m \"#{changes[tag]&.gsub '"', '\\"'}\" #{tag} #{sha} )
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def release(*paths)
|
|
109
|
-
tag = ENV['GITHUB_REF']&.sub(%r|^refs/tags/|, '') || raise('GITHUB_REF tag not set')
|
|
110
|
-
notes = (changelogs[tag] || '').shellescape
|
|
111
|
-
paths = paths.flatten.join ' '
|
|
112
|
-
|
|
113
|
-
sh(%( gh release create #{tag} #{paths} --notes #{notes} )) ||
|
|
114
|
-
sh(%( gh release upload #{tag} #{paths} --clobber )) ||
|
|
115
|
-
raise('failed to upload to releases')
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def changelogs()
|
|
119
|
-
File.read('ChangeLog.md')
|
|
120
|
-
.split(/^\s*##\s*\[\s*(v[\d\.]+)\s*\].*$/)
|
|
121
|
-
.slice(1..)
|
|
122
|
-
.each_slice(2)
|
|
123
|
-
.to_h
|
|
124
|
-
.transform_values(&:strip!)
|
|
125
|
-
rescue Errno::ENOENT
|
|
126
|
-
raise 'failed to get changelogs'
|
|
127
|
-
end
|