summaryrefslogtreecommitdiff
path: root/libre
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2017-07-04 21:31:51 -0400
committerLuke Shumaker <lukeshu@lukeshu.com>2017-07-04 21:32:15 -0400
commit213349485ac6296e3b423dec50c8dd2a748adac1 (patch)
tree19b17cfa8f1c1a4643bcfad0931ac16172df26ab /libre
parent6ecb10333877aa817912cd91f82473f096ec7b01 (diff)
downloadabslibre-213349485ac6296e3b423dec50c8dd2a748adac1.tar.gz
abslibre-213349485ac6296e3b423dec50c8dd2a748adac1.tar.bz2
abslibre-213349485ac6296e3b423dec50c8dd2a748adac1.zip
add libre/ruby2.3
Diffstat (limited to 'libre')
-rw-r--r--libre/ruby2.3/PKGBUILD118
-rw-r--r--libre/ruby2.3/json-1.8.3-libre.patch121
-rw-r--r--libre/ruby2.3/json-1.8.3-ruby-2.3.4-backports.patch3045
-rw-r--r--libre/ruby2.3/ruby-2.3.4-add-json_pure.patch22
-rw-r--r--libre/ruby2.3/ruby-2.3.4-remove-json-ext.patch80
5 files changed, 3386 insertions, 0 deletions
diff --git a/libre/ruby2.3/PKGBUILD b/libre/ruby2.3/PKGBUILD
new file mode 100644
index 000000000..fb0cf9725
--- /dev/null
+++ b/libre/ruby2.3/PKGBUILD
@@ -0,0 +1,118 @@
+# Maintainer (Arch): Sven-Hendrik Haase <sh@lutzhaase.com>
+# Contributor (Arch): Sergey Shatunov <me@prok.pw>
+# Contributor (Arch): Jonne Haß <me@jhass.eu>
+# Contributor (Arch): Thomas Dziedzic <gostrc@gmail.com>
+# Contributor (Arch): Allan McRae <allan@archlinux.org>
+# Contributor (Arch): John Proctor <jproctor@prium.net>
+# Contributor (Arch): Jeramy Rutley <jrutley@gmail.com>
+
+# Maintainer: Luke Shumaker <lukeshu@parabola.nu>
+
+# Rationale for inclusion in [libre]: Problematic license of
+# generator.c in bundled json extension.
+#
+# https://labs.parabola.nu/issues/674
+# https://bugs.ruby-lang.org/issues/11844
+# https://github.com/flori/json/issues/277
+
+_rubyver=2.3
+pkgname=ruby2.3
+pkgver=${_rubyver}.4
+_jsonver=1.8.3
+pkgdesc='An object-oriented language for quick and easy programming'
+pkgrel=3.parabola1
+_srcrel=1 # increment this to rebuild the sourceball without bumping pkgver
+arch=(i686 x86_64)
+url='http://www.ruby-lang.org/en/'
+license=(BSD custom)
+depends=(gdbm openssl-1.0 libffi libyaml gmp zlib)
+optdepends=('tk: for Ruby/TK')
+makedepends=(gdbm openssl-1.0 libffi doxygen graphviz libyaml ttf-dejavu tk)
+options=(!emptydirs)
+source=(https://repo.parabola.nu/other/ruby-libre/ruby-${pkgver}-libre${_srcrel}.tar.gz)
+sha512sums=('3cae39dfd8a2ad98f55d8e09346e8c26cb8d44229f6de9aaa0c179ba6ed2ae6959e24ec9121a6c8172796cba507514cda3b5d292128a93831f25133e22bb0c8e')
+
+mksource=(https://cache.ruby-lang.org/pub/ruby/${pkgver:0:3}/ruby-${pkgver}.tar.xz
+ ruby-${pkgver}-remove-json-ext.patch
+ ruby-${pkgver}-add-json_pure.patch
+ json-${_jsonver}.tar.gz::https://github.com/flori/json/archive/v${_jsonver}.tar.gz
+ json-${_jsonver}-ruby-${pkgver}-backports.patch
+ json-${_jsonver}-libre.patch)
+mksha512sums=('9e3adc2de6703e50e75db37db2981006d4c69759929d61db6a0d63627cfe5977d0ad66d2c69d7161cfc0c0d1c2cb38e5181a06ccd2790df2f72ec25c2ad01e02'
+ 'bd36519010a36d9368450de3bb6e46fd4b95682521877450f5875d0c0fc87119c52bd32cfdd7bcadf336d59e51665437a632d43d2f41934c808079ce6623a58c'
+ 'fcfde775beb157db7a9788c897b06c11191a5f1c34e94a1644ce9c9b32675dab9001b66f1b26fdb6082eb9e85ba38423ccc9917716c788bb9cd8fa54e723c757'
+ '147ce1834a1a0f02596386969c6e95c14237cc4d5303be974b9293d349d61a074cf9cc99d2f6bc434aa6da8aac9ddc35cfdeb7b9f77b14c112f8be70ff0846f7'
+ '05078d112741d80289acfe7221d98c244dad6c905b536c16886001ca78fef93523af0ba4d49f19cc8ebf0ac6a0e10278f53c07f055d8ae658a6bc57fcdc1c5ad'
+ 'aac35c74c16be38b4c7b2a5677189036bf90fbc00bcffdffe6a76ddaf6eb87d0ddb30ad239aefe4d7ff5c13ddd2b2fa18007e4d0a8f5e38b1153aed6e3d35c58')
+mksource() {
+ # Start with the vanilla version of json
+ cd "$srcdir/json-${_jsonver}"
+ # Apply changes made to it for the ruby distribution
+ patch -p1 -i ../json-${_jsonver}-ruby-${pkgver}-backports.patch
+ chmod 644 tests/test_json_*
+ # Modify it so that 'json' doesn't try to load (non-free!) 'json/ext'
+ rm -rf -- json.gemspec ext lib/json/ext*
+ patch -p1 -i ../json-${_jsonver}-libre.patch
+
+ # Now modify the ruby sources to include the json_pure lib instead
+ # of the json ext
+ cd "$srcdir/ruby-${pkgver}"
+ # remove the json ext
+ rm -rv ext/json test/json
+ patch -p1 -i ../ruby-${pkgver}-remove-json-ext.patch
+ # and insert the json_pure lib
+ cp -r ../json-${_jsonver}/lib/* -t lib/
+ cp ../json-${_jsonver}/json_pure.gemspec -t lib/json/
+ cp -rT ../json-${_jsonver}/tests test/json
+ patch -p1 -i ../ruby-${pkgver}-add-json_pure.patch
+
+ # Clean up the original json sources
+ cd "$srcdir"
+ rm -rf "json-${_jsonver}"
+}
+
+build() {
+ cd ruby-${pkgver}
+
+ CFLAGS+=' -O1' # GCC 7 produces a broken Ruby 2.3 with -O2
+ CPPFLAGS+=' -U_FORTIFY_SOURCE' # _FORTIFY_SOURCE requires at least -O2
+
+ export PKG_CONFIG_PATH=/usr/lib/openssl-1.0/pkgconfig
+ PKG_CONFIG=/usr/bin/pkg-config ./configure \
+ --prefix=/opt/ruby${_rubyver} \
+ --program-suffix=-${_rubyver} \
+ --sysconfdir=/etc \
+ --localstatedir=/var \
+ --sharedstatedir=/var/lib \
+ --libexecdir=/usr/lib/ruby \
+ --enable-shared \
+ --disable-rpath \
+ --with-dbm-type=gdbm_compat
+
+ make ruby
+}
+
+check() {
+ cd ruby-${pkgver}
+
+ make test
+}
+
+package() {
+ cd ruby-${pkgver}
+
+ make DESTDIR="${pkgdir}" install-nodoc
+
+ install -dm755 $pkgdir/usr/bin
+ install -dm755 $pkgdir/usr/lib
+
+ for i in erb irb rdoc ri ruby testrb rake gem; do
+ ln -s /opt/$pkgname/bin/$i-${_rubyver} $pkgdir/usr/bin/$i-${_rubyver}
+ ln -s /opt/$pkgname/bin/$i-${_rubyver} $pkgdir/opt/$pkgname/bin/$i
+ done
+
+ ln -s /opt/$pkgname/lib/libruby.so.${_rubyver} $pkgdir/usr/lib/libruby.so.${_rubyver}
+
+ install -D -m644 COPYING "${pkgdir}/usr/share/licenses/$pkgname/LICENSE"
+ install -D -m644 BSDL "${pkgdir}/usr/share/licenses/$pkgname/BSDL"
+}
diff --git a/libre/ruby2.3/json-1.8.3-libre.patch b/libre/ruby2.3/json-1.8.3-libre.patch
new file mode 100644
index 000000000..93ae03ee0
--- /dev/null
+++ b/libre/ruby2.3/json-1.8.3-libre.patch
@@ -0,0 +1,121 @@
+diff --git a/lib/json.rb b/lib/json.rb
+index 61bb8fae0e..8132cd571c 100644
+--- a/lib/json.rb
++++ b/lib/json.rb
+@@ -55,9 +55,5 @@ require 'json/common'
+ module JSON
+ require 'json/version'
+
+- begin
+- require 'json/ext'
+- rescue LoadError
+- require 'json/pure'
+- end
++ require 'json/pure'
+ end
+diff --git a/tests/setup_variant.rb b/tests/setup_variant.rb
+index f7fb2a1d56..5e9e050a26 100644
+--- a/tests/setup_variant.rb
++++ b/tests/setup_variant.rb
+@@ -1,12 +1,3 @@
+ # frozen_string_literal: false
+-case ENV['JSON']
+-when 'pure'
+- $:.unshift 'lib'
+- require 'json/pure'
+-when 'ext'
+- $:.unshift 'ext', 'lib'
+- require 'json/ext'
+-else
+- $:.unshift 'ext', 'lib'
+- require 'json'
+-end
++$:.unshift 'lib'
++require 'json'
+diff --git a/tests/test_json.rb b/tests/test_json.rb
+index 8fe9459978..b81ee506af 100755
+--- a/tests/test_json.rb
++++ b/tests/test_json.rb
+@@ -537,15 +537,6 @@ EOT
+ assert_equal orig, JSON[json5][0]
+ end
+
+- if defined?(JSON::Ext::Parser)
+- def test_allocate
+- parser = JSON::Ext::Parser.new("{}")
+- assert_raise(TypeError, '[ruby-core:35079]') {parser.__send__(:initialize, "{}")}
+- parser = JSON::Ext::Parser.allocate
+- assert_raise(TypeError, '[ruby-core:35079]') {parser.source}
+- end
+- end
+-
+ def test_argument_encoding
+ source = "{}".force_encoding("ascii-8bit")
+ JSON::Parser.new(source)
+@@ -565,13 +556,13 @@ EOT
+ if EnvUtil.gc_stress_to_class?
+ def assert_no_memory_leak(code, *rest, **opt)
+ code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}"
+- super(["-rjson/ext/parser"],
+- "GC.add_stress_to_class(JSON::Ext::Parser); "\
++ super(["-rjson/pure/parser"],
++ "GC.add_stress_to_class(JSON::Pure::Parser); "\
+ "#{code}", code, *rest, rss: true, limit: 1.1, **opt)
+ end
+
+ def test_no_memory_leak_allocate
+- assert_no_memory_leak("JSON::Ext::Parser.allocate")
++ assert_no_memory_leak("JSON::Pure::Parser.allocate")
+ end
+ end
+ end
+diff --git a/tests/test_json_generate.rb b/tests/test_json_generate.rb
+index 50895f6247..f85dd3a81c 100755
+--- a/tests/test_json_generate.rb
++++ b/tests/test_json_generate.rb
+@@ -283,28 +283,6 @@ EOT
+ assert_equal '2', state.indent
+ end
+
+- if defined?(JSON::Ext::Generator)
+- def test_broken_bignum # [ruby-core:38867]
+- pid = fork do
+- Bignum.class_eval do
+- def to_s
+- end
+- end
+- begin
+- JSON::Ext::Generator::State.new.generate(1<<64)
+- exit 1
+- rescue TypeError
+- exit 0
+- end
+- end
+- _, status = Process.waitpid2(pid)
+- assert status.success?
+- rescue NotImplementedError
+- # forking to avoid modifying core class of a parent process and
+- # introducing race conditions of tests are run in parallel
+- end
+- end
+-
+ def test_hash_likeness_set_symbol
+ state = JSON.state.new
+ assert_equal nil, state[:foo]
+@@ -349,13 +327,13 @@ EOT
+ if EnvUtil.gc_stress_to_class?
+ def assert_no_memory_leak(code, *rest, **opt)
+ code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}"
+- super(["-rjson/ext/generator"],
+- "GC.add_stress_to_class(JSON::Ext::Generator::State); "\
++ super(["-rjson/pure/generator"],
++ "GC.add_stress_to_class(JSON::Pure::Generator::State); "\
+ "#{code}", code, *rest, rss: true, limit: 1.1, **opt)
+ end
+
+ def test_no_memory_leak_allocate
+- assert_no_memory_leak("JSON::Ext::Generator::State.allocate")
++ assert_no_memory_leak("JSON::Pure::Generator::State.allocate")
+ end
+ end
+ end
diff --git a/libre/ruby2.3/json-1.8.3-ruby-2.3.4-backports.patch b/libre/ruby2.3/json-1.8.3-ruby-2.3.4-backports.patch
new file mode 100644
index 000000000..0696ca70b
--- /dev/null
+++ b/libre/ruby2.3/json-1.8.3-ruby-2.3.4-backports.patch
@@ -0,0 +1,3045 @@
+This is the complete set of patches applied to json-1.8.3 for the ruby
+2.3.4 distribution (excluding changes to integrate the two build
+systems together).
+
+Some of these might look a little funny (like trunk@50661) because the
+bulk of the patch made it upstream since it was originally applied,
+but part of it didn't (in the case of trunk@50661, the tests added to
+test for the fixed bug didn't make it in to 1.8.3).
+
+ -- Luke Shumaker
+ Parabola GNU/Linux-libre
+
+commit e62b06bb43baf7486b3b1793274cb7cc15eae135
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Tue Jan 6 05:32:41 2015 +0000
+
+ generic_object.rb: useless methods
+
+ * ext/json/lib/json/generic_object.rb (JSON::GenericObject):
+ remove useless overriding methods, [] and []=.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49161 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit c0ee6f2af98a8322e842bb2847492bfc56cb21b9)
+
+diff --git a/lib/json/generic_object.rb b/lib/json/generic_object.rb
+index 8b8fd53bef..3a14f0ea7d 100644
+--- a/lib/json/generic_object.rb
++++ b/lib/json/generic_object.rb
+@@ -47,14 +47,6 @@ module JSON
+ table
+ end
+
+- def [](name)
+- table[name.to_sym]
+- end
+-
+- def []=(name, value)
+- __send__ "#{name}=", value
+- end
+-
+ def |(other)
+ self.class[other.to_hash.merge(to_hash)]
+ end
+
+commit f1cd7efefbedd30bd78dc364873a9ea867e873f2
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Wed Feb 11 02:01:36 2015 +0000
+
+ generator.c: fix infinite recursion
+
+ * ext/json/generator/generator.c (generate_json): get rid of
+ unnecessary recursive calls which can cause infinite recursion.
+ T_STRING may not have rb_cString.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49562 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit e5c516c89a62839fd025ae112041ed9a5f06c9d0)
+
+diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
+index 6300c64f39..a135e28348 100644
+--- a/ext/json/ext/generator/generator.c
++++ b/ext/json/ext/generator/generator.c
+@@ -871,7 +871,7 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
+ } else {
+ tmp = rb_funcall(obj, i_to_s, 0);
+ Check_Type(tmp, T_STRING);
+- generate_json(buffer, Vstate, state, tmp);
++ generate_json_string(buffer, Vstate, state, tmp);
+ }
+ }
+
+diff --git a/tests/test_json_generate.rb b/tests/test_json_generate.rb
+index 8db0b7890b..1834290944 100755
+--- a/tests/test_json_generate.rb
++++ b/tests/test_json_generate.rb
+@@ -334,4 +334,14 @@ EOT
+ assert_equal true, JSON.generate(["\xea"])
+ end
+ end
++
++ def test_string_subclass
++ s = Class.new(String) do
++ def to_s; self; end
++ undef to_json
++ end
++ assert_nothing_raised(SystemStackError) do
++ assert_equal '[""]', JSON.generate([s.new])
++ end
++ end
+ end
+
+commit 8033ba67b1ccae1fcb059c6f9be432fef21a86cc
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Sat Apr 18 06:18:37 2015 +0000
+
+ parser.rl: use StringValue
+
+ * ext/json/parser/parser.rl (cParser_initialize): use StringValue
+ instead of direct rb_convert_type and remove duplicate
+ conversion.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50339 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit 6583e5dbfacf0bb6052c8d9b5cfccb2ab0df4e81)
+
+diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
+index 9c9d76ac3f..5927114250 100644
+--- a/ext/json/ext/parser/parser.c
++++ b/ext/json/ext/parser/parser.c
+@@ -1716,12 +1716,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ json->object_class = Qnil;
+ json->array_class = Qnil;
+ }
+- source = rb_convert_type(source, T_STRING, "String", "to_str");
++ StringValue(source);
+ if (!json->quirks_mode) {
+- source = convert_encoding(StringValue(source));
++ source = convert_encoding(source);
+ }
+ json->current_nesting = 0;
+- StringValue(source);
+ json->len = RSTRING_LEN(source);
+ json->source = RSTRING_PTR(source);;
+ json->Vsource = source;
+@@ -1729,7 +1728,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ }
+
+
+-#line 1733 "parser.c"
++#line 1732 "parser.c"
+ enum {JSON_start = 1};
+ enum {JSON_first_final = 10};
+ enum {JSON_error = 0};
+@@ -1737,7 +1736,7 @@ enum {JSON_error = 0};
+ enum {JSON_en_main = 1};
+
+
+-#line 740 "parser.rl"
++#line 739 "parser.rl"
+
+
+ static VALUE cParser_parse_strict(VALUE self)
+@@ -1748,16 +1747,16 @@ static VALUE cParser_parse_strict(VALUE self)
+ GET_PARSER;
+
+
+-#line 1752 "parser.c"
++#line 1751 "parser.c"
+ {
+ cs = JSON_start;
+ }
+
+-#line 750 "parser.rl"
++#line 749 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1761 "parser.c"
++#line 1760 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1813,7 +1812,7 @@ case 5:
+ goto st1;
+ goto st5;
+ tr3:
+-#line 729 "parser.rl"
++#line 728 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1822,7 +1821,7 @@ tr3:
+ }
+ goto st10;
+ tr4:
+-#line 722 "parser.rl"
++#line 721 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1834,7 +1833,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1838 "parser.c"
++#line 1837 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -1891,7 +1890,7 @@ case 9:
+ _out: {}
+ }
+
+-#line 753 "parser.rl"
++#line 752 "parser.rl"
+
+ if (cs >= JSON_first_final && p == pe) {
+ return result;
+@@ -1903,7 +1902,7 @@ case 9:
+
+
+
+-#line 1907 "parser.c"
++#line 1906 "parser.c"
+ enum {JSON_quirks_mode_start = 1};
+ enum {JSON_quirks_mode_first_final = 10};
+ enum {JSON_quirks_mode_error = 0};
+@@ -1911,7 +1910,7 @@ enum {JSON_quirks_mode_error = 0};
+ enum {JSON_quirks_mode_en_main = 1};
+
+
+-#line 778 "parser.rl"
++#line 777 "parser.rl"
+
+
+ static VALUE cParser_parse_quirks_mode(VALUE self)
+@@ -1922,16 +1921,16 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
+ GET_PARSER;
+
+
+-#line 1926 "parser.c"
++#line 1925 "parser.c"
+ {
+ cs = JSON_quirks_mode_start;
+ }
+
+-#line 788 "parser.rl"
++#line 787 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1935 "parser.c"
++#line 1934 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1965,7 +1964,7 @@ st0:
+ cs = 0;
+ goto _out;
+ tr2:
+-#line 770 "parser.rl"
++#line 769 "parser.rl"
+ {
+ char *np = JSON_parse_value(json, p, pe, &result);
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
+@@ -1975,7 +1974,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1979 "parser.c"
++#line 1978 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -2064,7 +2063,7 @@ case 9:
+ _out: {}
+ }
+
+-#line 791 "parser.rl"
++#line 790 "parser.rl"
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
+index 216ad26b20..de9c775001 100644
+--- a/ext/json/ext/parser/parser.rl
++++ b/ext/json/ext/parser/parser.rl
+@@ -700,12 +700,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ json->object_class = Qnil;
+ json->array_class = Qnil;
+ }
+- source = rb_convert_type(source, T_STRING, "String", "to_str");
++ StringValue(source);
+ if (!json->quirks_mode) {
+- source = convert_encoding(StringValue(source));
++ source = convert_encoding(source);
+ }
+ json->current_nesting = 0;
+- StringValue(source);
+ json->len = RSTRING_LEN(source);
+ json->source = RSTRING_PTR(source);;
+ json->Vsource = source;
+
+commit 2612a5b588d234535e9ed120d16b7afdd81756e4
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Sat Apr 18 06:18:50 2015 +0000
+
+ parser.rl: use rb_encoding
+
+ * ext/json/parser/parser.rl (convert_encoding): use rb_encoding
+ functions to compare and convert encodings.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50340 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit f47dc0738a2e1b875ecdaa875298cfda70d1eaef)
+
+diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
+index 5927114250..d334731e2a 100644
+--- a/ext/json/ext/parser/parser.c
++++ b/ext/json/ext/parser/parser.c
+@@ -3,6 +3,13 @@
+ #include "../fbuffer/fbuffer.h"
+ #include "parser.h"
+
++#ifdef HAVE_RB_ENC_RAISE
++# define EXC_ENCODING rb_utf8_encoding(),
++#else
++# define rb_enc_raise rb_raise
++# define EXC_ENCODING /* nothing */
++#endif
++
+ /* unicode */
+
+ static const char digit_values[256] = {
+@@ -68,9 +75,7 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
+ }
+
+ #ifdef HAVE_RUBY_ENCODING_H
+-static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
+- CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
+-static ID i_encoding, i_encode;
++static rb_encoding *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
+ #else
+ static ID i_iconv;
+ #endif
+@@ -84,11 +89,11 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
+ i_match_string, i_aset, i_aref, i_leftshift;
+
+
+-#line 110 "parser.rl"
++#line 115 "parser.rl"
+
+
+
+-#line 92 "parser.c"
++#line 97 "parser.c"
+ enum {JSON_object_start = 1};
+ enum {JSON_object_first_final = 27};
+ enum {JSON_object_error = 0};
+@@ -96,7 +101,7 @@ enum {JSON_object_error = 0};
+ enum {JSON_object_en_main = 1};
+
+
+-#line 151 "parser.rl"
++#line 156 "parser.rl"
+
+
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -112,14 +117,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
+ *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
+
+
+-#line 116 "parser.c"
++#line 121 "parser.c"
+ {
+ cs = JSON_object_start;
+ }
+
+-#line 166 "parser.rl"
++#line 171 "parser.rl"
+
+-#line 123 "parser.c"
++#line 128 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -147,7 +152,7 @@ case 2:
+ goto st2;
+ goto st0;
+ tr2:
+-#line 133 "parser.rl"
++#line 138 "parser.rl"
+ {
+ char *np;
+ json->parsing_name = 1;
+@@ -160,7 +165,7 @@ st3:
+ if ( ++p == pe )
+ goto _test_eof3;
+ case 3:
+-#line 164 "parser.c"
++#line 169 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st3;
+ case 32: goto st3;
+@@ -227,7 +232,7 @@ case 8:
+ goto st8;
+ goto st0;
+ tr11:
+-#line 118 "parser.rl"
++#line 123 "parser.rl"
+ {
+ VALUE v = Qnil;
+ char *np = JSON_parse_value(json, p, pe, &v);
+@@ -247,7 +252,7 @@ st9:
+ if ( ++p == pe )
+ goto _test_eof9;
+ case 9:
+-#line 251 "parser.c"
++#line 256 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st9;
+ case 32: goto st9;
+@@ -336,14 +341,14 @@ case 18:
+ goto st9;
+ goto st18;
+ tr4:
+-#line 141 "parser.rl"
++#line 146 "parser.rl"
+ { p--; {p++; cs = 27; goto _out;} }
+ goto st27;
+ st27:
+ if ( ++p == pe )
+ goto _test_eof27;
+ case 27:
+-#line 347 "parser.c"
++#line 352 "parser.c"
+ goto st0;
+ st19:
+ if ( ++p == pe )
+@@ -441,7 +446,7 @@ case 26:
+ _out: {}
+ }
+
+-#line 167 "parser.rl"
++#line 172 "parser.rl"
+
+ if (cs >= JSON_object_first_final) {
+ if (json->create_additions) {
+@@ -466,7 +471,7 @@ case 26:
+
+
+
+-#line 470 "parser.c"
++#line 475 "parser.c"
+ enum {JSON_value_start = 1};
+ enum {JSON_value_first_final = 21};
+ enum {JSON_value_error = 0};
+@@ -474,7 +479,7 @@ enum {JSON_value_error = 0};
+ enum {JSON_value_en_main = 1};
+
+
+-#line 271 "parser.rl"
++#line 276 "parser.rl"
+
+
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -482,14 +487,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
+ int cs = EVIL;
+
+
+-#line 486 "parser.c"
++#line 491 "parser.c"
+ {
+ cs = JSON_value_start;
+ }
+
+-#line 278 "parser.rl"
++#line 283 "parser.rl"
+
+-#line 493 "parser.c"
++#line 498 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -514,14 +519,14 @@ st0:
+ cs = 0;
+ goto _out;
+ tr0:
+-#line 219 "parser.rl"
++#line 224 "parser.rl"
+ {
+ char *np = JSON_parse_string(json, p, pe, result);
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
+ }
+ goto st21;
+ tr2:
+-#line 224 "parser.rl"
++#line 229 "parser.rl"
+ {
+ char *np;
+ if(pe > p + 9 - json->quirks_mode && !strncmp(MinusInfinity, p, 9)) {
+@@ -530,7 +535,7 @@ tr2:
+ {p = (( p + 10))-1;}
+ p--; {p++; cs = 21; goto _out;}
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ }
+ }
+ np = JSON_parse_float(json, p, pe, result);
+@@ -541,7 +546,7 @@ tr2:
+ }
+ goto st21;
+ tr5:
+-#line 242 "parser.rl"
++#line 247 "parser.rl"
+ {
+ char *np;
+ json->current_nesting++;
+@@ -551,7 +556,7 @@ tr5:
+ }
+ goto st21;
+ tr9:
+-#line 250 "parser.rl"
++#line 255 "parser.rl"
+ {
+ char *np;
+ json->current_nesting++;
+@@ -561,39 +566,39 @@ tr9:
+ }
+ goto st21;
+ tr16:
+-#line 212 "parser.rl"
++#line 217 "parser.rl"
+ {
+ if (json->allow_nan) {
+ *result = CInfinity;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
+ }
+ }
+ goto st21;
+ tr18:
+-#line 205 "parser.rl"
++#line 210 "parser.rl"
+ {
+ if (json->allow_nan) {
+ *result = CNaN;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
+ }
+ }
+ goto st21;
+ tr22:
+-#line 199 "parser.rl"
++#line 204 "parser.rl"
+ {
+ *result = Qfalse;
+ }
+ goto st21;
+ tr25:
+-#line 196 "parser.rl"
++#line 201 "parser.rl"
+ {
+ *result = Qnil;
+ }
+ goto st21;
+ tr28:
+-#line 202 "parser.rl"
++#line 207 "parser.rl"
+ {
+ *result = Qtrue;
+ }
+@@ -602,9 +607,9 @@ st21:
+ if ( ++p == pe )
+ goto _test_eof21;
+ case 21:
+-#line 258 "parser.rl"
++#line 263 "parser.rl"
+ { p--; {p++; cs = 21; goto _out;} }
+-#line 608 "parser.c"
++#line 613 "parser.c"
+ goto st0;
+ st2:
+ if ( ++p == pe )
+@@ -765,7 +770,7 @@ case 20:
+ _out: {}
+ }
+
+-#line 279 "parser.rl"
++#line 284 "parser.rl"
+
+ if (cs >= JSON_value_first_final) {
+ return p;
+@@ -775,7 +780,7 @@ case 20:
+ }
+
+
+-#line 779 "parser.c"
++#line 784 "parser.c"
+ enum {JSON_integer_start = 1};
+ enum {JSON_integer_first_final = 3};
+ enum {JSON_integer_error = 0};
+@@ -783,7 +788,7 @@ enum {JSON_integer_error = 0};
+ enum {JSON_integer_en_main = 1};
+
+
+-#line 295 "parser.rl"
++#line 300 "parser.rl"
+
+
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -791,15 +796,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
+ int cs = EVIL;
+
+
+-#line 795 "parser.c"
++#line 800 "parser.c"
+ {
+ cs = JSON_integer_start;
+ }
+
+-#line 302 "parser.rl"
++#line 307 "parser.rl"
+ json->memo = p;
+
+-#line 803 "parser.c"
++#line 808 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -833,14 +838,14 @@ case 3:
+ goto st0;
+ goto tr4;
+ tr4:
+-#line 292 "parser.rl"
++#line 297 "parser.rl"
+ { p--; {p++; cs = 4; goto _out;} }
+ goto st4;
+ st4:
+ if ( ++p == pe )
+ goto _test_eof4;
+ case 4:
+-#line 844 "parser.c"
++#line 849 "parser.c"
+ goto st0;
+ st5:
+ if ( ++p == pe )
+@@ -859,7 +864,7 @@ case 5:
+ _out: {}
+ }
+
+-#line 304 "parser.rl"
++#line 309 "parser.rl"
+
+ if (cs >= JSON_integer_first_final) {
+ long len = p - json->memo;
+@@ -874,7 +879,7 @@ case 5:
+ }
+
+
+-#line 878 "parser.c"
++#line 883 "parser.c"
+ enum {JSON_float_start = 1};
+ enum {JSON_float_first_final = 8};
+ enum {JSON_float_error = 0};
+@@ -882,7 +887,7 @@ enum {JSON_float_error = 0};
+ enum {JSON_float_en_main = 1};
+
+
+-#line 329 "parser.rl"
++#line 334 "parser.rl"
+
+
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -890,15 +895,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
+ int cs = EVIL;
+
+
+-#line 894 "parser.c"
++#line 899 "parser.c"
+ {
+ cs = JSON_float_start;
+ }
+
+-#line 336 "parser.rl"
++#line 341 "parser.rl"
+ json->memo = p;
+
+-#line 902 "parser.c"
++#line 907 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -956,14 +961,14 @@ case 8:
+ goto st0;
+ goto tr9;
+ tr9:
+-#line 323 "parser.rl"
++#line 328 "parser.rl"
+ { p--; {p++; cs = 9; goto _out;} }
+ goto st9;
+ st9:
+ if ( ++p == pe )
+ goto _test_eof9;
+ case 9:
+-#line 967 "parser.c"
++#line 972 "parser.c"
+ goto st0;
+ st5:
+ if ( ++p == pe )
+@@ -1024,7 +1029,7 @@ case 7:
+ _out: {}
+ }
+
+-#line 338 "parser.rl"
++#line 343 "parser.rl"
+
+ if (cs >= JSON_float_first_final) {
+ long len = p - json->memo;
+@@ -1040,7 +1045,7 @@ case 7:
+
+
+
+-#line 1044 "parser.c"
++#line 1049 "parser.c"
+ enum {JSON_array_start = 1};
+ enum {JSON_array_first_final = 17};
+ enum {JSON_array_error = 0};
+@@ -1048,7 +1053,7 @@ enum {JSON_array_error = 0};
+ enum {JSON_array_en_main = 1};
+
+
+-#line 381 "parser.rl"
++#line 386 "parser.rl"
+
+
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -1062,14 +1067,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
+ *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
+
+
+-#line 1066 "parser.c"
++#line 1071 "parser.c"
+ {
+ cs = JSON_array_start;
+ }
+
+-#line 394 "parser.rl"
++#line 399 "parser.rl"
+
+-#line 1073 "parser.c"
++#line 1078 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1108,7 +1113,7 @@ case 2:
+ goto st2;
+ goto st0;
+ tr2:
+-#line 358 "parser.rl"
++#line 363 "parser.rl"
+ {
+ VALUE v = Qnil;
+ char *np = JSON_parse_value(json, p, pe, &v);
+@@ -1128,7 +1133,7 @@ st3:
+ if ( ++p == pe )
+ goto _test_eof3;
+ case 3:
+-#line 1132 "parser.c"
++#line 1137 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st3;
+ case 32: goto st3;
+@@ -1228,14 +1233,14 @@ case 12:
+ goto st3;
+ goto st12;
+ tr4:
+-#line 373 "parser.rl"
++#line 378 "parser.rl"
+ { p--; {p++; cs = 17; goto _out;} }
+ goto st17;
+ st17:
+ if ( ++p == pe )
+ goto _test_eof17;
+ case 17:
+-#line 1239 "parser.c"
++#line 1244 "parser.c"
+ goto st0;
+ st13:
+ if ( ++p == pe )
+@@ -1291,12 +1296,12 @@ case 16:
+ _out: {}
+ }
+
+-#line 395 "parser.rl"
++#line 400 "parser.rl"
+
+ if(cs >= JSON_array_first_final) {
+ return p + 1;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return NULL;
+ }
+ }
+@@ -1372,7 +1377,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
+ }
+
+
+-#line 1376 "parser.c"
++#line 1381 "parser.c"
+ enum {JSON_string_start = 1};
+ enum {JSON_string_first_final = 8};
+ enum {JSON_string_error = 0};
+@@ -1380,7 +1385,7 @@ enum {JSON_string_error = 0};
+ enum {JSON_string_en_main = 1};
+
+
+-#line 494 "parser.rl"
++#line 499 "parser.rl"
+
+
+ static int
+@@ -1402,15 +1407,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
+
+ *result = rb_str_buf_new(0);
+
+-#line 1406 "parser.c"
++#line 1411 "parser.c"
+ {
+ cs = JSON_string_start;
+ }
+
+-#line 515 "parser.rl"
++#line 520 "parser.rl"
+ json->memo = p;
+
+-#line 1414 "parser.c"
++#line 1419 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1435,7 +1440,7 @@ case 2:
+ goto st0;
+ goto st2;
+ tr2:
+-#line 480 "parser.rl"
++#line 485 "parser.rl"
+ {
+ *result = json_string_unescape(*result, json->memo + 1, p);
+ if (NIL_P(*result)) {
+@@ -1446,14 +1451,14 @@ tr2:
+ {p = (( p + 1))-1;}
+ }
+ }
+-#line 491 "parser.rl"
++#line 496 "parser.rl"
+ { p--; {p++; cs = 8; goto _out;} }
+ goto st8;
+ st8:
+ if ( ++p == pe )
+ goto _test_eof8;
+ case 8:
+-#line 1457 "parser.c"
++#line 1462 "parser.c"
+ goto st0;
+ st3:
+ if ( ++p == pe )
+@@ -1529,7 +1534,7 @@ case 7:
+ _out: {}
+ }
+
+-#line 517 "parser.rl"
++#line 522 "parser.rl"
+
+ if (json->create_additions && RTEST(match_string = json->match_string)) {
+ VALUE klass;
+@@ -1573,22 +1578,22 @@ static VALUE convert_encoding(VALUE source)
+ }
+ #ifdef HAVE_RUBY_ENCODING_H
+ {
+- VALUE encoding = rb_funcall(source, i_encoding, 0);
+- if (encoding == CEncoding_ASCII_8BIT) {
++ rb_encoding *enc = rb_enc_get(source);
++ if (enc == rb_ascii8bit_encoding()) {
+ if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32BE);
++ source = rb_str_conv_enc(source, UTF_32BE, rb_utf8_encoding());
+ } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16BE);
++ source = rb_str_conv_enc(source, UTF_16BE, rb_utf8_encoding());
+ } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32LE);
++ source = rb_str_conv_enc(source, UTF_32LE, rb_utf8_encoding());
+ } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16LE);
++ source = rb_str_conv_enc(source, UTF_16LE, rb_utf8_encoding());
+ } else {
+ source = rb_str_dup(source);
+ FORCE_UTF8(source);
+ }
+ } else {
+- source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
++ source = rb_str_conv_enc(source, NULL, rb_utf8_encoding());
+ }
+ }
+ #else
+@@ -1728,7 +1733,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ }
+
+
+-#line 1732 "parser.c"
++#line 1737 "parser.c"
+ enum {JSON_start = 1};
+ enum {JSON_first_final = 10};
+ enum {JSON_error = 0};
+@@ -1736,7 +1741,7 @@ enum {JSON_error = 0};
+ enum {JSON_en_main = 1};
+
+
+-#line 739 "parser.rl"
++#line 744 "parser.rl"
+
+
+ static VALUE cParser_parse_strict(VALUE self)
+@@ -1747,16 +1752,16 @@ static VALUE cParser_parse_strict(VALUE self)
+ GET_PARSER;
+
+
+-#line 1751 "parser.c"
++#line 1756 "parser.c"
+ {
+ cs = JSON_start;
+ }
+
+-#line 749 "parser.rl"
++#line 754 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1760 "parser.c"
++#line 1765 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1812,7 +1817,7 @@ case 5:
+ goto st1;
+ goto st5;
+ tr3:
+-#line 728 "parser.rl"
++#line 733 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1821,7 +1826,7 @@ tr3:
+ }
+ goto st10;
+ tr4:
+-#line 721 "parser.rl"
++#line 726 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1833,7 +1838,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1837 "parser.c"
++#line 1842 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -1890,19 +1895,19 @@ case 9:
+ _out: {}
+ }
+
+-#line 752 "parser.rl"
++#line 757 "parser.rl"
+
+ if (cs >= JSON_first_final && p == pe) {
+ return result;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return Qnil;
+ }
+ }
+
+
+
+-#line 1906 "parser.c"
++#line 1911 "parser.c"
+ enum {JSON_quirks_mode_start = 1};
+ enum {JSON_quirks_mode_first_final = 10};
+ enum {JSON_quirks_mode_error = 0};
+@@ -1910,7 +1915,7 @@ enum {JSON_quirks_mode_error = 0};
+ enum {JSON_quirks_mode_en_main = 1};
+
+
+-#line 777 "parser.rl"
++#line 782 "parser.rl"
+
+
+ static VALUE cParser_parse_quirks_mode(VALUE self)
+@@ -1921,16 +1926,16 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
+ GET_PARSER;
+
+
+-#line 1925 "parser.c"
++#line 1930 "parser.c"
+ {
+ cs = JSON_quirks_mode_start;
+ }
+
+-#line 787 "parser.rl"
++#line 792 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1934 "parser.c"
++#line 1939 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1964,7 +1969,7 @@ st0:
+ cs = 0;
+ goto _out;
+ tr2:
+-#line 769 "parser.rl"
++#line 774 "parser.rl"
+ {
+ char *np = JSON_parse_value(json, p, pe, &result);
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
+@@ -1974,7 +1979,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1978 "parser.c"
++#line 1983 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -2063,12 +2068,12 @@ case 9:
+ _out: {}
+ }
+
+-#line 790 "parser.rl"
++#line 795 "parser.rl"
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return Qnil;
+ }
+ }
+@@ -2193,14 +2198,10 @@ void Init_parser(void)
+ i_aref = rb_intern("[]");
+ i_leftshift = rb_intern("<<");
+ #ifdef HAVE_RUBY_ENCODING_H
+- CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
+- CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
+- CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
+- CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
+- CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
+- CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
+- i_encoding = rb_intern("encoding");
+- i_encode = rb_intern("encode");
++ UTF_16BE = rb_enc_find("utf-16be");
++ UTF_16LE = rb_enc_find("utf-16le");
++ UTF_32BE = rb_enc_find("utf-32be");
++ UTF_32LE = rb_enc_find("utf-32le");
+ #else
+ i_iconv = rb_intern("iconv");
+ #endif
+diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
+index de9c775001..fd57a275bf 100644
+--- a/ext/json/ext/parser/parser.rl
++++ b/ext/json/ext/parser/parser.rl
+@@ -66,9 +66,7 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
+ }
+
+ #ifdef HAVE_RUBY_ENCODING_H
+-static VALUE CEncoding_ASCII_8BIT, CEncoding_UTF_8, CEncoding_UTF_16BE,
+- CEncoding_UTF_16LE, CEncoding_UTF_32BE, CEncoding_UTF_32LE;
+-static ID i_encoding, i_encode;
++static rb_encoding *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
+ #else
+ static ID i_iconv;
+ #endif
+@@ -557,22 +555,22 @@ static VALUE convert_encoding(VALUE source)
+ }
+ #ifdef HAVE_RUBY_ENCODING_H
+ {
+- VALUE encoding = rb_funcall(source, i_encoding, 0);
+- if (encoding == CEncoding_ASCII_8BIT) {
++ rb_encoding *enc = rb_enc_get(source);
++ if (enc == rb_ascii8bit_encoding()) {
+ if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32BE);
++ source = rb_str_conv_enc(source, UTF_32BE, rb_utf8_encoding());
+ } else if (len >= 4 && ptr[0] == 0 && ptr[2] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16BE);
++ source = rb_str_conv_enc(source, UTF_16BE, rb_utf8_encoding());
+ } else if (len >= 4 && ptr[1] == 0 && ptr[2] == 0 && ptr[3] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_32LE);
++ source = rb_str_conv_enc(source, UTF_32LE, rb_utf8_encoding());
+ } else if (len >= 4 && ptr[1] == 0 && ptr[3] == 0) {
+- source = rb_funcall(source, i_encode, 2, CEncoding_UTF_8, CEncoding_UTF_16LE);
++ source = rb_str_conv_enc(source, UTF_16LE, rb_utf8_encoding());
+ } else {
+ source = rb_str_dup(source);
+ FORCE_UTF8(source);
+ }
+ } else {
+- source = rb_funcall(source, i_encode, 1, CEncoding_UTF_8);
++ source = rb_str_conv_enc(source, NULL, rb_utf8_encoding());
+ }
+ }
+ #else
+@@ -916,14 +914,10 @@ void Init_parser(void)
+ i_aref = rb_intern("[]");
+ i_leftshift = rb_intern("<<");
+ #ifdef HAVE_RUBY_ENCODING_H
+- CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
+- CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
+- CEncoding_UTF_16LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16le"));
+- CEncoding_UTF_32BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32be"));
+- CEncoding_UTF_32LE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-32le"));
+- CEncoding_ASCII_8BIT = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("ascii-8bit"));
+- i_encoding = rb_intern("encoding");
+- i_encode = rb_intern("encode");
++ UTF_16BE = rb_enc_find("utf-16be");
++ UTF_16LE = rb_enc_find("utf-16le");
++ UTF_32BE = rb_enc_find("utf-32be");
++ UTF_32LE = rb_enc_find("utf-32le");
+ #else
+ i_iconv = rb_intern("iconv");
+ #endif
+
+commit c9d3b4b6f24aac4cf677256b10fb3c51ed283698
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Sat Apr 18 06:19:52 2015 +0000
+
+ parser.rl: rb_enc_raise
+
+ * ext/json/parser/parser.rl: raise with messages in UTF-8
+ encoding. [ruby-core:67386] [Bug #10705]
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50342 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit b38c0b7974854003a949a26f87bd7ff0e17113ef)
+
+diff --git a/ext/json/ext/parser/extconf.rb b/ext/json/ext/parser/extconf.rb
+index ae4f861c79..2addc53e7f 100644
+--- a/ext/json/ext/parser/extconf.rb
++++ b/ext/json/ext/parser/extconf.rb
+@@ -1,3 +1,5 @@
+ require 'mkmf'
+
++have_func("rb_enc_raise", "ruby.h")
++
+ create_makefile 'json/ext/parser'
+diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
+index d334731e2a..9d8cb54570 100644
+--- a/ext/json/ext/parser/parser.c
++++ b/ext/json/ext/parser/parser.c
+@@ -3,11 +3,26 @@
+ #include "../fbuffer/fbuffer.h"
+ #include "parser.h"
+
+-#ifdef HAVE_RB_ENC_RAISE
+-# define EXC_ENCODING rb_utf8_encoding(),
++#if defined HAVE_RUBY_ENCODING_H
++# define EXC_ENCODING UTF8,
++# ifndef HAVE_RB_ENC_RAISE
++static void
++enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
++{
++ va_list args;
++ VALUE mesg;
++
++ va_start(args, fmt);
++ mesg = rb_enc_vsprintf(enc, fmt, args);
++ va_end(args);
++
++ rb_exc_raise(rb_exc_new3(exc, mesg));
++}
++# endif
++# define rb_enc_raise enc_raise
+ #else
+-# define rb_enc_raise rb_raise
+ # define EXC_ENCODING /* nothing */
++# define rb_enc_raise rb_raise
+ #endif
+
+ /* unicode */
+@@ -75,7 +90,7 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
+ }
+
+ #ifdef HAVE_RUBY_ENCODING_H
+-static rb_encoding *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
++static rb_encoding *UTF_8, *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
+ #else
+ static ID i_iconv;
+ #endif
+@@ -89,11 +104,11 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
+ i_match_string, i_aset, i_aref, i_leftshift;
+
+
+-#line 115 "parser.rl"
++#line 130 "parser.rl"
+
+
+
+-#line 97 "parser.c"
++#line 112 "parser.c"
+ enum {JSON_object_start = 1};
+ enum {JSON_object_first_final = 27};
+ enum {JSON_object_error = 0};
+@@ -101,7 +116,7 @@ enum {JSON_object_error = 0};
+ enum {JSON_object_en_main = 1};
+
+
+-#line 156 "parser.rl"
++#line 171 "parser.rl"
+
+
+ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -117,14 +132,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
+ *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
+
+
+-#line 121 "parser.c"
++#line 136 "parser.c"
+ {
+ cs = JSON_object_start;
+ }
+
+-#line 171 "parser.rl"
++#line 186 "parser.rl"
+
+-#line 128 "parser.c"
++#line 143 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -152,7 +167,7 @@ case 2:
+ goto st2;
+ goto st0;
+ tr2:
+-#line 138 "parser.rl"
++#line 153 "parser.rl"
+ {
+ char *np;
+ json->parsing_name = 1;
+@@ -165,7 +180,7 @@ st3:
+ if ( ++p == pe )
+ goto _test_eof3;
+ case 3:
+-#line 169 "parser.c"
++#line 184 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st3;
+ case 32: goto st3;
+@@ -232,7 +247,7 @@ case 8:
+ goto st8;
+ goto st0;
+ tr11:
+-#line 123 "parser.rl"
++#line 138 "parser.rl"
+ {
+ VALUE v = Qnil;
+ char *np = JSON_parse_value(json, p, pe, &v);
+@@ -252,7 +267,7 @@ st9:
+ if ( ++p == pe )
+ goto _test_eof9;
+ case 9:
+-#line 256 "parser.c"
++#line 271 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st9;
+ case 32: goto st9;
+@@ -341,14 +356,14 @@ case 18:
+ goto st9;
+ goto st18;
+ tr4:
+-#line 146 "parser.rl"
++#line 161 "parser.rl"
+ { p--; {p++; cs = 27; goto _out;} }
+ goto st27;
+ st27:
+ if ( ++p == pe )
+ goto _test_eof27;
+ case 27:
+-#line 352 "parser.c"
++#line 367 "parser.c"
+ goto st0;
+ st19:
+ if ( ++p == pe )
+@@ -446,7 +461,7 @@ case 26:
+ _out: {}
+ }
+
+-#line 172 "parser.rl"
++#line 187 "parser.rl"
+
+ if (cs >= JSON_object_first_final) {
+ if (json->create_additions) {
+@@ -471,7 +486,7 @@ case 26:
+
+
+
+-#line 475 "parser.c"
++#line 490 "parser.c"
+ enum {JSON_value_start = 1};
+ enum {JSON_value_first_final = 21};
+ enum {JSON_value_error = 0};
+@@ -479,7 +494,7 @@ enum {JSON_value_error = 0};
+ enum {JSON_value_en_main = 1};
+
+
+-#line 276 "parser.rl"
++#line 291 "parser.rl"
+
+
+ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -487,14 +502,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
+ int cs = EVIL;
+
+
+-#line 491 "parser.c"
++#line 506 "parser.c"
+ {
+ cs = JSON_value_start;
+ }
+
+-#line 283 "parser.rl"
++#line 298 "parser.rl"
+
+-#line 498 "parser.c"
++#line 513 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -519,14 +534,14 @@ st0:
+ cs = 0;
+ goto _out;
+ tr0:
+-#line 224 "parser.rl"
++#line 239 "parser.rl"
+ {
+ char *np = JSON_parse_string(json, p, pe, result);
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
+ }
+ goto st21;
+ tr2:
+-#line 229 "parser.rl"
++#line 244 "parser.rl"
+ {
+ char *np;
+ if(pe > p + 9 - json->quirks_mode && !strncmp(MinusInfinity, p, 9)) {
+@@ -546,7 +561,7 @@ tr2:
+ }
+ goto st21;
+ tr5:
+-#line 247 "parser.rl"
++#line 262 "parser.rl"
+ {
+ char *np;
+ json->current_nesting++;
+@@ -556,7 +571,7 @@ tr5:
+ }
+ goto st21;
+ tr9:
+-#line 255 "parser.rl"
++#line 270 "parser.rl"
+ {
+ char *np;
+ json->current_nesting++;
+@@ -566,7 +581,7 @@ tr9:
+ }
+ goto st21;
+ tr16:
+-#line 217 "parser.rl"
++#line 232 "parser.rl"
+ {
+ if (json->allow_nan) {
+ *result = CInfinity;
+@@ -576,7 +591,7 @@ tr16:
+ }
+ goto st21;
+ tr18:
+-#line 210 "parser.rl"
++#line 225 "parser.rl"
+ {
+ if (json->allow_nan) {
+ *result = CNaN;
+@@ -586,19 +601,19 @@ tr18:
+ }
+ goto st21;
+ tr22:
+-#line 204 "parser.rl"
++#line 219 "parser.rl"
+ {
+ *result = Qfalse;
+ }
+ goto st21;
+ tr25:
+-#line 201 "parser.rl"
++#line 216 "parser.rl"
+ {
+ *result = Qnil;
+ }
+ goto st21;
+ tr28:
+-#line 207 "parser.rl"
++#line 222 "parser.rl"
+ {
+ *result = Qtrue;
+ }
+@@ -607,9 +622,9 @@ st21:
+ if ( ++p == pe )
+ goto _test_eof21;
+ case 21:
+-#line 263 "parser.rl"
++#line 278 "parser.rl"
+ { p--; {p++; cs = 21; goto _out;} }
+-#line 613 "parser.c"
++#line 628 "parser.c"
+ goto st0;
+ st2:
+ if ( ++p == pe )
+@@ -770,7 +785,7 @@ case 20:
+ _out: {}
+ }
+
+-#line 284 "parser.rl"
++#line 299 "parser.rl"
+
+ if (cs >= JSON_value_first_final) {
+ return p;
+@@ -780,7 +795,7 @@ case 20:
+ }
+
+
+-#line 784 "parser.c"
++#line 799 "parser.c"
+ enum {JSON_integer_start = 1};
+ enum {JSON_integer_first_final = 3};
+ enum {JSON_integer_error = 0};
+@@ -788,7 +803,7 @@ enum {JSON_integer_error = 0};
+ enum {JSON_integer_en_main = 1};
+
+
+-#line 300 "parser.rl"
++#line 315 "parser.rl"
+
+
+ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -796,15 +811,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
+ int cs = EVIL;
+
+
+-#line 800 "parser.c"
++#line 815 "parser.c"
+ {
+ cs = JSON_integer_start;
+ }
+
+-#line 307 "parser.rl"
++#line 322 "parser.rl"
+ json->memo = p;
+
+-#line 808 "parser.c"
++#line 823 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -838,14 +853,14 @@ case 3:
+ goto st0;
+ goto tr4;
+ tr4:
+-#line 297 "parser.rl"
++#line 312 "parser.rl"
+ { p--; {p++; cs = 4; goto _out;} }
+ goto st4;
+ st4:
+ if ( ++p == pe )
+ goto _test_eof4;
+ case 4:
+-#line 849 "parser.c"
++#line 864 "parser.c"
+ goto st0;
+ st5:
+ if ( ++p == pe )
+@@ -864,7 +879,7 @@ case 5:
+ _out: {}
+ }
+
+-#line 309 "parser.rl"
++#line 324 "parser.rl"
+
+ if (cs >= JSON_integer_first_final) {
+ long len = p - json->memo;
+@@ -879,7 +894,7 @@ case 5:
+ }
+
+
+-#line 883 "parser.c"
++#line 898 "parser.c"
+ enum {JSON_float_start = 1};
+ enum {JSON_float_first_final = 8};
+ enum {JSON_float_error = 0};
+@@ -887,7 +902,7 @@ enum {JSON_float_error = 0};
+ enum {JSON_float_en_main = 1};
+
+
+-#line 334 "parser.rl"
++#line 349 "parser.rl"
+
+
+ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -895,15 +910,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
+ int cs = EVIL;
+
+
+-#line 899 "parser.c"
++#line 914 "parser.c"
+ {
+ cs = JSON_float_start;
+ }
+
+-#line 341 "parser.rl"
++#line 356 "parser.rl"
+ json->memo = p;
+
+-#line 907 "parser.c"
++#line 922 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -961,14 +976,14 @@ case 8:
+ goto st0;
+ goto tr9;
+ tr9:
+-#line 328 "parser.rl"
++#line 343 "parser.rl"
+ { p--; {p++; cs = 9; goto _out;} }
+ goto st9;
+ st9:
+ if ( ++p == pe )
+ goto _test_eof9;
+ case 9:
+-#line 972 "parser.c"
++#line 987 "parser.c"
+ goto st0;
+ st5:
+ if ( ++p == pe )
+@@ -1029,7 +1044,7 @@ case 7:
+ _out: {}
+ }
+
+-#line 343 "parser.rl"
++#line 358 "parser.rl"
+
+ if (cs >= JSON_float_first_final) {
+ long len = p - json->memo;
+@@ -1045,7 +1060,7 @@ case 7:
+
+
+
+-#line 1049 "parser.c"
++#line 1064 "parser.c"
+ enum {JSON_array_start = 1};
+ enum {JSON_array_first_final = 17};
+ enum {JSON_array_error = 0};
+@@ -1053,7 +1068,7 @@ enum {JSON_array_error = 0};
+ enum {JSON_array_en_main = 1};
+
+
+-#line 386 "parser.rl"
++#line 401 "parser.rl"
+
+
+ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
+@@ -1067,14 +1082,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
+ *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
+
+
+-#line 1071 "parser.c"
++#line 1086 "parser.c"
+ {
+ cs = JSON_array_start;
+ }
+
+-#line 399 "parser.rl"
++#line 414 "parser.rl"
+
+-#line 1078 "parser.c"
++#line 1093 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1113,7 +1128,7 @@ case 2:
+ goto st2;
+ goto st0;
+ tr2:
+-#line 363 "parser.rl"
++#line 378 "parser.rl"
+ {
+ VALUE v = Qnil;
+ char *np = JSON_parse_value(json, p, pe, &v);
+@@ -1133,7 +1148,7 @@ st3:
+ if ( ++p == pe )
+ goto _test_eof3;
+ case 3:
+-#line 1137 "parser.c"
++#line 1152 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st3;
+ case 32: goto st3;
+@@ -1233,14 +1248,14 @@ case 12:
+ goto st3;
+ goto st12;
+ tr4:
+-#line 378 "parser.rl"
++#line 393 "parser.rl"
+ { p--; {p++; cs = 17; goto _out;} }
+ goto st17;
+ st17:
+ if ( ++p == pe )
+ goto _test_eof17;
+ case 17:
+-#line 1244 "parser.c"
++#line 1259 "parser.c"
+ goto st0;
+ st13:
+ if ( ++p == pe )
+@@ -1296,7 +1311,7 @@ case 16:
+ _out: {}
+ }
+
+-#line 400 "parser.rl"
++#line 415 "parser.rl"
+
+ if(cs >= JSON_array_first_final) {
+ return p + 1;
+@@ -1377,7 +1392,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
+ }
+
+
+-#line 1381 "parser.c"
++#line 1396 "parser.c"
+ enum {JSON_string_start = 1};
+ enum {JSON_string_first_final = 8};
+ enum {JSON_string_error = 0};
+@@ -1385,7 +1400,7 @@ enum {JSON_string_error = 0};
+ enum {JSON_string_en_main = 1};
+
+
+-#line 499 "parser.rl"
++#line 514 "parser.rl"
+
+
+ static int
+@@ -1407,15 +1422,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
+
+ *result = rb_str_buf_new(0);
+
+-#line 1411 "parser.c"
++#line 1426 "parser.c"
+ {
+ cs = JSON_string_start;
+ }
+
+-#line 520 "parser.rl"
++#line 535 "parser.rl"
+ json->memo = p;
+
+-#line 1419 "parser.c"
++#line 1434 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1440,7 +1455,7 @@ case 2:
+ goto st0;
+ goto st2;
+ tr2:
+-#line 485 "parser.rl"
++#line 500 "parser.rl"
+ {
+ *result = json_string_unescape(*result, json->memo + 1, p);
+ if (NIL_P(*result)) {
+@@ -1451,14 +1466,14 @@ tr2:
+ {p = (( p + 1))-1;}
+ }
+ }
+-#line 496 "parser.rl"
++#line 511 "parser.rl"
+ { p--; {p++; cs = 8; goto _out;} }
+ goto st8;
+ st8:
+ if ( ++p == pe )
+ goto _test_eof8;
+ case 8:
+-#line 1462 "parser.c"
++#line 1477 "parser.c"
+ goto st0;
+ st3:
+ if ( ++p == pe )
+@@ -1534,7 +1549,7 @@ case 7:
+ _out: {}
+ }
+
+-#line 522 "parser.rl"
++#line 537 "parser.rl"
+
+ if (json->create_additions && RTEST(match_string = json->match_string)) {
+ VALUE klass;
+@@ -1733,7 +1748,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ }
+
+
+-#line 1737 "parser.c"
++#line 1752 "parser.c"
+ enum {JSON_start = 1};
+ enum {JSON_first_final = 10};
+ enum {JSON_error = 0};
+@@ -1741,7 +1756,7 @@ enum {JSON_error = 0};
+ enum {JSON_en_main = 1};
+
+
+-#line 744 "parser.rl"
++#line 759 "parser.rl"
+
+
+ static VALUE cParser_parse_strict(VALUE self)
+@@ -1752,16 +1767,16 @@ static VALUE cParser_parse_strict(VALUE self)
+ GET_PARSER;
+
+
+-#line 1756 "parser.c"
++#line 1771 "parser.c"
+ {
+ cs = JSON_start;
+ }
+
+-#line 754 "parser.rl"
++#line 769 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1765 "parser.c"
++#line 1780 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1817,7 +1832,7 @@ case 5:
+ goto st1;
+ goto st5;
+ tr3:
+-#line 733 "parser.rl"
++#line 748 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1826,7 +1841,7 @@ tr3:
+ }
+ goto st10;
+ tr4:
+-#line 726 "parser.rl"
++#line 741 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1838,7 +1853,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1842 "parser.c"
++#line 1857 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -1895,7 +1910,7 @@ case 9:
+ _out: {}
+ }
+
+-#line 757 "parser.rl"
++#line 772 "parser.rl"
+
+ if (cs >= JSON_first_final && p == pe) {
+ return result;
+@@ -1907,7 +1922,7 @@ case 9:
+
+
+
+-#line 1911 "parser.c"
++#line 1926 "parser.c"
+ enum {JSON_quirks_mode_start = 1};
+ enum {JSON_quirks_mode_first_final = 10};
+ enum {JSON_quirks_mode_error = 0};
+@@ -1915,7 +1930,7 @@ enum {JSON_quirks_mode_error = 0};
+ enum {JSON_quirks_mode_en_main = 1};
+
+
+-#line 782 "parser.rl"
++#line 797 "parser.rl"
+
+
+ static VALUE cParser_parse_quirks_mode(VALUE self)
+@@ -1926,16 +1941,16 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
+ GET_PARSER;
+
+
+-#line 1930 "parser.c"
++#line 1945 "parser.c"
+ {
+ cs = JSON_quirks_mode_start;
+ }
+
+-#line 792 "parser.rl"
++#line 807 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1939 "parser.c"
++#line 1954 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1969,7 +1984,7 @@ st0:
+ cs = 0;
+ goto _out;
+ tr2:
+-#line 774 "parser.rl"
++#line 789 "parser.rl"
+ {
+ char *np = JSON_parse_value(json, p, pe, &result);
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
+@@ -1979,7 +1994,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1983 "parser.c"
++#line 1998 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -2068,7 +2083,7 @@ case 9:
+ _out: {}
+ }
+
+-#line 795 "parser.rl"
++#line 810 "parser.rl"
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+@@ -2198,6 +2213,7 @@ void Init_parser(void)
+ i_aref = rb_intern("[]");
+ i_leftshift = rb_intern("<<");
+ #ifdef HAVE_RUBY_ENCODING_H
++ UTF_8 = rb_utf8_encoding();
+ UTF_16BE = rb_enc_find("utf-16be");
+ UTF_16LE = rb_enc_find("utf-16le");
+ UTF_32BE = rb_enc_find("utf-32be");
+diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
+index fd57a275bf..735fa8f350 100644
+--- a/ext/json/ext/parser/parser.rl
++++ b/ext/json/ext/parser/parser.rl
+@@ -1,6 +1,28 @@
+ #include "../fbuffer/fbuffer.h"
+ #include "parser.h"
+
++#if defined HAVE_RUBY_ENCODING_H
++# define EXC_ENCODING UTF8,
++# ifndef HAVE_RB_ENC_RAISE
++static void
++enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
++{
++ va_list args;
++ VALUE mesg;
++
++ va_start(args, fmt);
++ mesg = rb_enc_vsprintf(enc, fmt, args);
++ va_end(args);
++
++ rb_exc_raise(rb_exc_new3(exc, mesg));
++}
++# endif
++# define rb_enc_raise enc_raise
++#else
++# define EXC_ENCODING /* nothing */
++# define rb_enc_raise rb_raise
++#endif
++
+ /* unicode */
+
+ static const char digit_values[256] = {
+@@ -66,7 +88,7 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
+ }
+
+ #ifdef HAVE_RUBY_ENCODING_H
+-static rb_encoding *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
++static rb_encoding *UTF_8, *UTF_16BE, *UTF_16LE, *UTF_32BE, *UTF_32LE;
+ #else
+ static ID i_iconv;
+ #endif
+@@ -204,14 +226,14 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
+ if (json->allow_nan) {
+ *result = CNaN;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
+ }
+ }
+ action parse_infinity {
+ if (json->allow_nan) {
+ *result = CInfinity;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
+ }
+ }
+ action parse_string {
+@@ -227,7 +249,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
+ fexec p + 10;
+ fhold; fbreak;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ }
+ }
+ np = JSON_parse_float(json, fpc, pe, result);
+@@ -394,7 +416,7 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
+ if(cs >= JSON_array_first_final) {
+ return p + 1;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return NULL;
+ }
+ }
+@@ -751,7 +773,7 @@ static VALUE cParser_parse_strict(VALUE self)
+ if (cs >= JSON_first_final && p == pe) {
+ return result;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return Qnil;
+ }
+ }
+@@ -789,7 +811,7 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+ } else {
+- rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
++ rb_enc_raise(EXC_ENCODING eParserError, "%u: unexpected token at '%s'", __LINE__, p);
+ return Qnil;
+ }
+ }
+@@ -914,6 +936,7 @@ void Init_parser(void)
+ i_aref = rb_intern("[]");
+ i_leftshift = rb_intern("<<");
+ #ifdef HAVE_RUBY_ENCODING_H
++ UTF_8 = rb_utf8_encoding();
+ UTF_16BE = rb_enc_find("utf-16be");
+ UTF_16LE = rb_enc_find("utf-16le");
+ UTF_32BE = rb_enc_find("utf-32be");
+diff --git a/tests/test_json.rb b/tests/test_json.rb
+index 7957773f23..46f000148f 100755
+--- a/tests/test_json.rb
++++ b/tests/test_json.rb
+@@ -550,4 +550,14 @@ EOT
+ JSON::Parser.new(source)
+ assert_equal Encoding::ASCII_8BIT, source.encoding
+ end if defined?(Encoding::ASCII_8BIT)
++
++ def test_error_message_encoding
++ bug10705 = '[ruby-core:67386] [Bug #10705]'
++ json = "\"\xE2\x88\x9A\"".force_encoding(Encoding::UTF_8)
++ e = assert_raise(JSON::ParserError) {
++ JSON.parse(json)
++ }
++ assert_equal(Encoding::UTF_8, e.message.encoding, bug10705)
++ assert_include(e.message, json, bug10705)
++ end if defined?(Encoding::UTF_8)
+ end
+
+commit 45b835fec8adaf0aa1ce47fc2acfa3f61f06ca53
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Sat Apr 18 06:24:38 2015 +0000
+
+ parser.rl: define enc_raise iff necessary
+
+ * ext/json/parser/parser.rl (enc_raise): no needs if rb_enc_raise
+ is available.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50343 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit 5c0df05b92de528a397d29fd9ca5dca534b4c930)
+
+diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
+index 9d8cb54570..ae9be78ec2 100644
+--- a/ext/json/ext/parser/parser.c
++++ b/ext/json/ext/parser/parser.c
+@@ -4,7 +4,7 @@
+ #include "parser.h"
+
+ #if defined HAVE_RUBY_ENCODING_H
+-# define EXC_ENCODING UTF8,
++# define EXC_ENCODING UTF_8,
+ # ifndef HAVE_RB_ENC_RAISE
+ static void
+ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
+@@ -18,8 +18,8 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
+
+ rb_exc_raise(rb_exc_new3(exc, mesg));
+ }
++# define rb_enc_raise enc_raise
+ # endif
+-# define rb_enc_raise enc_raise
+ #else
+ # define EXC_ENCODING /* nothing */
+ # define rb_enc_raise rb_raise
+diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
+index 735fa8f350..327e08cd81 100644
+--- a/ext/json/ext/parser/parser.rl
++++ b/ext/json/ext/parser/parser.rl
+@@ -2,7 +2,7 @@
+ #include "parser.h"
+
+ #if defined HAVE_RUBY_ENCODING_H
+-# define EXC_ENCODING UTF8,
++# define EXC_ENCODING UTF_8,
+ # ifndef HAVE_RB_ENC_RAISE
+ static void
+ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
+@@ -16,8 +16,8 @@ enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
+
+ rb_exc_raise(rb_exc_new3(exc, mesg));
+ }
++# define rb_enc_raise enc_raise
+ # endif
+-# define rb_enc_raise enc_raise
+ #else
+ # define EXC_ENCODING /* nothing */
+ # define rb_enc_raise rb_raise
+
+commit 39feffc4fbb9047e9dee99bab90761f5aba28060
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Thu May 28 07:17:42 2015 +0000
+
+ parser.rl: allocate structs with wrapper
+
+ * ext/json/parser/parser.rl (cJSON_parser_s_allocate): allocate
+ structs with making new wrapper objects and get rid of potential
+ memory leak.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50660 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit cbf902fc3308290383c8c5e926bf684a23778719)
+
+diff --git a/tests/test_json.rb b/tests/test_json.rb
+index 46f000148f..96ba744478 100755
+--- a/tests/test_json.rb
++++ b/tests/test_json.rb
+@@ -560,4 +560,17 @@ EOT
+ assert_equal(Encoding::UTF_8, e.message.encoding, bug10705)
+ assert_include(e.message, json, bug10705)
+ end if defined?(Encoding::UTF_8)
++
++ if EnvUtil.gc_stress_to_class?
++ def assert_no_memory_leak(code, *rest, **opt)
++ code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}"
++ super(["-rjson/ext/parser"],
++ "GC.add_stress_to_class(JSON::Ext::Parser); "\
++ "#{code}", code, *rest, rss: true, limit: 1.1, **opt)
++ end
++
++ def test_no_memory_leak_allocate
++ assert_no_memory_leak("JSON::Ext::Parser.allocate")
++ end
++ end
+ end
+
+commit a7b5c17a122a88e060676e74fc1925c5a703df03
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Thu May 28 07:17:55 2015 +0000
+
+ generator.c: allocate structs with wrapper
+
+ * ext/json/generator/generator.c (cState_s_allocate): allocate
+ structs with making new wrapper objects and get rid of potential
+ memory leak.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50661 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit 4d059bf9f5f10f3d3088de49fc87e5555db7770d)
+
+diff --git a/tests/test_json_generate.rb b/tests/test_json_generate.rb
+index 1834290944..ce470db3c2 100755
+--- a/tests/test_json_generate.rb
++++ b/tests/test_json_generate.rb
+@@ -344,4 +344,17 @@ EOT
+ assert_equal '[""]', JSON.generate([s.new])
+ end
+ end
++
++ if EnvUtil.gc_stress_to_class?
++ def assert_no_memory_leak(code, *rest, **opt)
++ code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}"
++ super(["-rjson/ext/generator"],
++ "GC.add_stress_to_class(JSON::Ext::Generator::State); "\
++ "#{code}", code, *rest, rss: true, limit: 1.1, **opt)
++ end
++
++ def test_no_memory_leak_allocate
++ assert_no_memory_leak("JSON::Ext::Generator::State.allocate")
++ end
++ end
+ end
+
+commit 73a2acda797178495ff3952c3b9293425b86f924
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Fri Sep 25 08:06:57 2015 +0000
+
+ parser.rl: rb_scan_args
+
+ * ext/json/parser/parser.rl (cParser_initialize): use ':' in
+ rb_scan_args.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51936 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit f12fccbec58ca57cef61380e0eebed591ba847d8)
+
+diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
+index 327e08cd81..2fa0caee7a 100644
+--- a/ext/json/ext/parser/parser.rl
++++ b/ext/json/ext/parser/parser.rl
+@@ -570,7 +570,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
+
+ static VALUE convert_encoding(VALUE source)
+ {
+- char *ptr = RSTRING_PTR(source);
++ const char *ptr = RSTRING_PTR(source);
+ long len = RSTRING_LEN(source);
+ if (len < 2) {
+ rb_raise(eParserError, "A JSON text must at least contain two octets!");
+@@ -643,12 +643,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ if (json->Vsource) {
+ rb_raise(rb_eTypeError, "already initialized instance");
+ }
++#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
++ rb_scan_args(argc, argv, "1:", &source, &opts);
++#else
+ rb_scan_args(argc, argv, "11", &source, &opts);
++#endif
+ if (!NIL_P(opts)) {
++#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
+ opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
+ if (NIL_P(opts)) {
+ rb_raise(rb_eArgError, "opts needs to be like a hash");
+ } else {
++#endif
+ VALUE tmp = ID2SYM(i_max_nesting);
+ if (option_given_p(opts, tmp)) {
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
+@@ -711,7 +717,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ } else {
+ json->match_string = Qnil;
+ }
++#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
+ }
++#endif
+ } else {
+ json->max_nesting = 100;
+ json->allow_nan = 0;
+
+commit 4b429e42608ecca027435a2cb6f9c10afd3b5c89
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Fri Sep 25 08:08:58 2015 +0000
+
+ parser.c: update
+
+ * ext/json/parser/parser.c: update to r51946.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51937 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit 460152ea73f7eb55449329e77b141d50f8cabe01)
+
+diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
+index ae9be78ec2..773605cf7c 100644
+--- a/ext/json/ext/parser/parser.c
++++ b/ext/json/ext/parser/parser.c
+@@ -1586,7 +1586,7 @@ case 7:
+
+ static VALUE convert_encoding(VALUE source)
+ {
+- char *ptr = RSTRING_PTR(source);
++ const char *ptr = RSTRING_PTR(source);
+ long len = RSTRING_LEN(source);
+ if (len < 2) {
+ rb_raise(eParserError, "A JSON text must at least contain two octets!");
+@@ -1659,12 +1659,18 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ if (json->Vsource) {
+ rb_raise(rb_eTypeError, "already initialized instance");
+ }
++#ifdef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
++ rb_scan_args(argc, argv, "1:", &source, &opts);
++#else
+ rb_scan_args(argc, argv, "11", &source, &opts);
++#endif
+ if (!NIL_P(opts)) {
++#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
+ opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
+ if (NIL_P(opts)) {
+ rb_raise(rb_eArgError, "opts needs to be like a hash");
+ } else {
++#endif
+ VALUE tmp = ID2SYM(i_max_nesting);
+ if (option_given_p(opts, tmp)) {
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
+@@ -1727,7 +1733,9 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ } else {
+ json->match_string = Qnil;
+ }
++#ifndef HAVE_RB_SCAN_ARGS_OPTIONAL_HASH
+ }
++#endif
+ } else {
+ json->max_nesting = 100;
+ json->allow_nan = 0;
+@@ -1748,7 +1756,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+ }
+
+
+-#line 1752 "parser.c"
++#line 1760 "parser.c"
+ enum {JSON_start = 1};
+ enum {JSON_first_final = 10};
+ enum {JSON_error = 0};
+@@ -1756,7 +1764,7 @@ enum {JSON_error = 0};
+ enum {JSON_en_main = 1};
+
+
+-#line 759 "parser.rl"
++#line 767 "parser.rl"
+
+
+ static VALUE cParser_parse_strict(VALUE self)
+@@ -1767,16 +1775,16 @@ static VALUE cParser_parse_strict(VALUE self)
+ GET_PARSER;
+
+
+-#line 1771 "parser.c"
++#line 1779 "parser.c"
+ {
+ cs = JSON_start;
+ }
+
+-#line 769 "parser.rl"
++#line 777 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1780 "parser.c"
++#line 1788 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1832,7 +1840,7 @@ case 5:
+ goto st1;
+ goto st5;
+ tr3:
+-#line 748 "parser.rl"
++#line 756 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1841,7 +1849,7 @@ tr3:
+ }
+ goto st10;
+ tr4:
+-#line 741 "parser.rl"
++#line 749 "parser.rl"
+ {
+ char *np;
+ json->current_nesting = 1;
+@@ -1853,7 +1861,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1857 "parser.c"
++#line 1865 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -1910,7 +1918,7 @@ case 9:
+ _out: {}
+ }
+
+-#line 772 "parser.rl"
++#line 780 "parser.rl"
+
+ if (cs >= JSON_first_final && p == pe) {
+ return result;
+@@ -1922,7 +1930,7 @@ case 9:
+
+
+
+-#line 1926 "parser.c"
++#line 1934 "parser.c"
+ enum {JSON_quirks_mode_start = 1};
+ enum {JSON_quirks_mode_first_final = 10};
+ enum {JSON_quirks_mode_error = 0};
+@@ -1930,7 +1938,7 @@ enum {JSON_quirks_mode_error = 0};
+ enum {JSON_quirks_mode_en_main = 1};
+
+
+-#line 797 "parser.rl"
++#line 805 "parser.rl"
+
+
+ static VALUE cParser_parse_quirks_mode(VALUE self)
+@@ -1941,16 +1949,16 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
+ GET_PARSER;
+
+
+-#line 1945 "parser.c"
++#line 1953 "parser.c"
+ {
+ cs = JSON_quirks_mode_start;
+ }
+
+-#line 807 "parser.rl"
++#line 815 "parser.rl"
+ p = json->source;
+ pe = p + json->len;
+
+-#line 1954 "parser.c"
++#line 1962 "parser.c"
+ {
+ if ( p == pe )
+ goto _test_eof;
+@@ -1984,7 +1992,7 @@ st0:
+ cs = 0;
+ goto _out;
+ tr2:
+-#line 789 "parser.rl"
++#line 797 "parser.rl"
+ {
+ char *np = JSON_parse_value(json, p, pe, &result);
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
+@@ -1994,7 +2002,7 @@ st10:
+ if ( ++p == pe )
+ goto _test_eof10;
+ case 10:
+-#line 1998 "parser.c"
++#line 2006 "parser.c"
+ switch( (*p) ) {
+ case 13: goto st10;
+ case 32: goto st10;
+@@ -2083,7 +2091,7 @@ case 9:
+ _out: {}
+ }
+
+-#line 810 "parser.rl"
++#line 818 "parser.rl"
+
+ if (cs >= JSON_quirks_mode_first_final && p == pe) {
+ return result;
+
+commit 466bd2712d728a26b04b0ea4796aa664f23e006f
+Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Fri Oct 30 04:37:13 2015 +0000
+
+ use assert_raise
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52384 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit 068f312a7c642a1b6c358c17ef83421756568545)
+
+diff --git a/tests/test_json.rb b/tests/test_json.rb
+index 96ba744478..07287eed81 100755
+--- a/tests/test_json.rb
++++ b/tests/test_json.rb
+@@ -65,10 +65,10 @@ class TestJSON < Test::Unit::TestCase
+ assert_equal([23], parse('[23]'))
+ assert_equal([0.23], parse('[0.23]'))
+ assert_equal([0.0], parse('[0e0]'))
+- assert_raises(JSON::ParserError) { parse('[+23.2]') }
+- assert_raises(JSON::ParserError) { parse('[+23]') }
+- assert_raises(JSON::ParserError) { parse('[.23]') }
+- assert_raises(JSON::ParserError) { parse('[023]') }
++ assert_raise(JSON::ParserError) { parse('[+23.2]') }
++ assert_raise(JSON::ParserError) { parse('[+23]') }
++ assert_raise(JSON::ParserError) { parse('[.23]') }
++ assert_raise(JSON::ParserError) { parse('[023]') }
+ assert_equal_float [3.141], parse('[3.141]')
+ assert_equal_float [-3.141], parse('[-3.141]')
+ assert_equal_float [3.141], parse('[3141e-3]')
+@@ -77,11 +77,11 @@ class TestJSON < Test::Unit::TestCase
+ assert_equal_float [3.141], parse('[3141.0E-3]')
+ assert_equal_float [-3.141], parse('[-3141.0e-3]')
+ assert_equal_float [-3.141], parse('[-3141e-3]')
+- assert_raises(ParserError) { parse('[NaN]') }
++ assert_raise(ParserError) { parse('[NaN]') }
+ assert parse('[NaN]', :allow_nan => true).first.nan?
+- assert_raises(ParserError) { parse('[Infinity]') }
++ assert_raise(ParserError) { parse('[Infinity]') }
+ assert_equal [1.0/0], parse('[Infinity]', :allow_nan => true)
+- assert_raises(ParserError) { parse('[-Infinity]') }
++ assert_raise(ParserError) { parse('[-Infinity]') }
+ assert_equal [-1.0/0], parse('[-Infinity]', :allow_nan => true)
+ assert_equal([""], parse('[""]'))
+ assert_equal(["foobar"], parse('["foobar"]'))
+@@ -95,7 +95,7 @@ class TestJSON < Test::Unit::TestCase
+ assert_equal({ "a" => nil }, parse('{"a":null}'))
+ assert_equal({ "a" => false }, parse('{ "a" : false } '))
+ assert_equal({ "a" => false }, parse('{"a":false}'))
+- assert_raises(JSON::ParserError) { parse('{false}') }
++ assert_raise(JSON::ParserError) { parse('{false}') }
+ assert_equal({ "a" => true }, parse('{"a":true}'))
+ assert_equal({ "a" => true }, parse(' { "a" : true } '))
+ assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
+@@ -380,7 +380,7 @@ EOT
+ * comment */
+ }
+ EOT
+- assert_raises(ParserError) { parse(json) }
++ assert_raise(ParserError) { parse(json) }
+ json = <<EOT
+ {
+ "key1":"value1" /* multi line
+@@ -389,7 +389,7 @@ EOT
+ and again, throw an Error */
+ }
+ EOT
+- assert_raises(ParserError) { parse(json) }
++ assert_raise(ParserError) { parse(json) }
+ json = <<EOT
+ {
+ "key1":"value1" /*/*/
+@@ -425,32 +425,32 @@ EOT
+ end
+
+ def test_wrong_inputs
+- assert_raises(ParserError) { JSON.parse('"foo"') }
+- assert_raises(ParserError) { JSON.parse('123') }
+- assert_raises(ParserError) { JSON.parse('[] bla') }
+- assert_raises(ParserError) { JSON.parse('[] 1') }
+- assert_raises(ParserError) { JSON.parse('[] []') }
+- assert_raises(ParserError) { JSON.parse('[] {}') }
+- assert_raises(ParserError) { JSON.parse('{} []') }
+- assert_raises(ParserError) { JSON.parse('{} {}') }
+- assert_raises(ParserError) { JSON.parse('[NULL]') }
+- assert_raises(ParserError) { JSON.parse('[FALSE]') }
+- assert_raises(ParserError) { JSON.parse('[TRUE]') }
+- assert_raises(ParserError) { JSON.parse('[07] ') }
+- assert_raises(ParserError) { JSON.parse('[0a]') }
+- assert_raises(ParserError) { JSON.parse('[1.]') }
+- assert_raises(ParserError) { JSON.parse(' ') }
++ assert_raise(ParserError) { JSON.parse('"foo"') }
++ assert_raise(ParserError) { JSON.parse('123') }
++ assert_raise(ParserError) { JSON.parse('[] bla') }
++ assert_raise(ParserError) { JSON.parse('[] 1') }
++ assert_raise(ParserError) { JSON.parse('[] []') }
++ assert_raise(ParserError) { JSON.parse('[] {}') }
++ assert_raise(ParserError) { JSON.parse('{} []') }
++ assert_raise(ParserError) { JSON.parse('{} {}') }
++ assert_raise(ParserError) { JSON.parse('[NULL]') }
++ assert_raise(ParserError) { JSON.parse('[FALSE]') }
++ assert_raise(ParserError) { JSON.parse('[TRUE]') }
++ assert_raise(ParserError) { JSON.parse('[07] ') }
++ assert_raise(ParserError) { JSON.parse('[0a]') }
++ assert_raise(ParserError) { JSON.parse('[1.]') }
++ assert_raise(ParserError) { JSON.parse(' ') }
+ end
+
+ def test_nesting
+- assert_raises(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 }
+- assert_raises(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse }
++ assert_raise(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 }
++ assert_raise(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse }
+ assert_equal [[]], JSON.parse('[[]]', :max_nesting => 2)
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
+ too_deep_ary = eval too_deep
+- assert_raises(JSON::NestingError) { JSON.parse too_deep }
+- assert_raises(JSON::NestingError) { JSON.parser.new(too_deep).parse }
+- assert_raises(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 100 }
++ assert_raise(JSON::NestingError) { JSON.parse too_deep }
++ assert_raise(JSON::NestingError) { JSON.parser.new(too_deep).parse }
++ assert_raise(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 100 }
+ ok = JSON.parse too_deep, :max_nesting => 101
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => nil
+@@ -459,10 +459,10 @@ EOT
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => 0
+ assert_equal too_deep_ary, ok
+- assert_raises(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 }
++ assert_raise(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 }
+ assert_equal '[[]]', JSON.generate([[]], :max_nesting => 2)
+- assert_raises(JSON::NestingError) { JSON.generate too_deep_ary }
+- assert_raises(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 100 }
++ assert_raise(JSON::NestingError) { JSON.generate too_deep_ary }
++ assert_raise(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 100 }
+ ok = JSON.generate too_deep_ary, :max_nesting => 101
+ assert_equal too_deep, ok
+ ok = JSON.generate too_deep_ary, :max_nesting => nil
+@@ -505,8 +505,8 @@ EOT
+ too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
+ assert_equal too_deep, JSON.dump(eval(too_deep))
+ assert_kind_of String, Marshal.dump(eval(too_deep))
+- assert_raises(ArgumentError) { JSON.dump(eval(too_deep), 100) }
+- assert_raises(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
++ assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 100) }
++ assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
+ assert_equal too_deep, JSON.dump(eval(too_deep), 101)
+ assert_kind_of String, Marshal.dump(eval(too_deep), 101)
+ output = StringIO.new
+diff --git a/tests/test_json_addition.rb b/tests/test_json_addition.rb
+index a30f06addd..6034a183bd 100755
+--- a/tests/test_json_addition.rb
++++ b/tests/test_json_addition.rb
+@@ -112,7 +112,7 @@ class TestJSONAddition < Test::Unit::TestCase
+ c = C.new
+ assert !C.json_creatable?
+ json = generate(c)
+- assert_raises(ArgumentError, NameError) { JSON.parse(json, :create_additions => true) }
++ assert_raise(ArgumentError, NameError) { JSON.parse(json, :create_additions => true) }
+ end
+
+ def test_raw_strings
+@@ -151,7 +151,7 @@ class TestJSONAddition < Test::Unit::TestCase
+ assert_equal s, JSON(JSON(s), :create_additions => true)
+ struct = Struct.new :foo, :bar
+ s = struct.new 4711, 'foot'
+- assert_raises(JSONError) { JSON(s) }
++ assert_raise(JSONError) { JSON(s) }
+ begin
+ raise TypeError, "test me"
+ rescue TypeError => e
+diff --git a/tests/test_json_encoding.rb b/tests/test_json_encoding.rb
+index fa7d878920..13903cd266 100644
+--- a/tests/test_json_encoding.rb
++++ b/tests/test_json_encoding.rb
+@@ -59,7 +59,7 @@ class TestJSONEncoding < Test::Unit::TestCase
+ assert_equal @generated, JSON.generate(@utf_16_data, :ascii_only => true)
+ else
+ # XXX checking of correct utf8 data is not as strict (yet?) without :ascii_only
+- assert_raises(JSON::GeneratorError) { JSON.generate(@utf_16_data, :ascii_only => true) }
++ assert_raise(JSON::GeneratorError) { JSON.generate(@utf_16_data, :ascii_only => true) }
+ end
+ end
+ end
+diff --git a/tests/test_json_fixtures.rb b/tests/test_json_fixtures.rb
+index 584dffdfdb..c861439573 100755
+--- a/tests/test_json_fixtures.rb
++++ b/tests/test_json_fixtures.rb
+@@ -26,7 +26,7 @@ class TestJSONFixtures < Test::Unit::TestCase
+
+ def test_failing
+ for name, source in @failed
+- assert_raises(JSON::ParserError, JSON::NestingError,
++ assert_raise(JSON::ParserError, JSON::NestingError,
+ "Did not fail for fixture '#{name}': #{source.inspect}") do
+ JSON.parse(source)
+ end
+diff --git a/tests/test_json_generate.rb b/tests/test_json_generate.rb
+index ce470db3c2..5da0d2f4f0 100755
+--- a/tests/test_json_generate.rb
++++ b/tests/test_json_generate.rb
+@@ -123,12 +123,12 @@ EOT
+ assert s[:check_circular?]
+ h = { 1=>2 }
+ h[3] = h
+- assert_raises(JSON::NestingError) { generate(h) }
+- assert_raises(JSON::NestingError) { generate(h, s) }
++ assert_raise(JSON::NestingError) { generate(h) }
++ assert_raise(JSON::NestingError) { generate(h, s) }
+ s = JSON.state.new
+ a = [ 1, 2 ]
+ a << a
+- assert_raises(JSON::NestingError) { generate(a, s) }
++ assert_raise(JSON::NestingError) { generate(a, s) }
+ assert s.check_circular?
+ assert s[:check_circular?]
+ end
+@@ -185,34 +185,34 @@ EOT
+ end
+
+ def test_allow_nan
+- assert_raises(GeneratorError) { generate([JSON::NaN]) }
++ assert_raise(GeneratorError) { generate([JSON::NaN]) }
+ assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
+- assert_raises(GeneratorError) { fast_generate([JSON::NaN]) }
+- assert_raises(GeneratorError) { pretty_generate([JSON::NaN]) }
++ assert_raise(GeneratorError) { fast_generate([JSON::NaN]) }
++ assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
+ assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
+- assert_raises(GeneratorError) { generate([JSON::Infinity]) }
++ assert_raise(GeneratorError) { generate([JSON::Infinity]) }
+ assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
+- assert_raises(GeneratorError) { fast_generate([JSON::Infinity]) }
+- assert_raises(GeneratorError) { pretty_generate([JSON::Infinity]) }
++ assert_raise(GeneratorError) { fast_generate([JSON::Infinity]) }
++ assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
+ assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
+- assert_raises(GeneratorError) { generate([JSON::MinusInfinity]) }
++ assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
+ assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
+- assert_raises(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
+- assert_raises(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
++ assert_raise(GeneratorError) { fast_generate([JSON::MinusInfinity]) }
++ assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
+ assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
+ end
+
+ def test_depth
+ ary = []; ary << ary
+ assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
+- assert_raises(JSON::NestingError) { JSON.generate(ary) }
++ assert_raise(JSON::NestingError) { JSON.generate(ary) }
+ assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
+ assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
+- assert_raises(JSON::NestingError) { JSON.pretty_generate(ary) }
++ assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
+ assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
+ s = JSON.state.new
+ assert_equal 0, s.depth
+- assert_raises(JSON::NestingError) { ary.to_json(s) }
++ assert_raise(JSON::NestingError) { ary.to_json(s) }
+ assert_equal 100, s.depth
+ end
+
+
+commit ab8e1eda2385d418939a239189688aeddb6b7bde
+Author: naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Wed Dec 16 05:07:31 2015 +0000
+
+ Add frozen_string_literal: false for all files
+
+ When you change this to true, you may need to add more tests.
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53141 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit 3e92b635fb5422207b7bbdc924e292e51e21f040)
+
+diff --git a/tests/setup_variant.rb b/tests/setup_variant.rb
+index 2dab184bc4..f7fb2a1d56 100644
+--- a/tests/setup_variant.rb
++++ b/tests/setup_variant.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ case ENV['JSON']
+ when 'pure'
+ $:.unshift 'lib'
+diff --git a/tests/test_json.rb b/tests/test_json.rb
+index 07287eed81..8fe9459978 100755
+--- a/tests/test_json.rb
++++ b/tests/test_json.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # encoding: utf-8
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+diff --git a/tests/test_json_addition.rb b/tests/test_json_addition.rb
+index 6034a183bd..f2059312de 100755
+--- a/tests/test_json_addition.rb
++++ b/tests/test_json_addition.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # -*- coding:utf-8 -*-
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+diff --git a/tests/test_json_encoding.rb b/tests/test_json_encoding.rb
+index 13903cd266..50fb4ea279 100644
+--- a/tests/test_json_encoding.rb
++++ b/tests/test_json_encoding.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # encoding: utf-8
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+diff --git a/tests/test_json_fixtures.rb b/tests/test_json_fixtures.rb
+index c861439573..e192706d6b 100755
+--- a/tests/test_json_fixtures.rb
++++ b/tests/test_json_fixtures.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # encoding: utf-8
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+diff --git a/tests/test_json_generate.rb b/tests/test_json_generate.rb
+index 5da0d2f4f0..50895f6247 100755
+--- a/tests/test_json_generate.rb
++++ b/tests/test_json_generate.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # encoding: utf-8
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+diff --git a/tests/test_json_generic_object.rb b/tests/test_json_generic_object.rb
+index c43c7762be..e04e1a1cb3 100644
+--- a/tests/test_json_generic_object.rb
++++ b/tests/test_json_generic_object.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # encoding: utf-8
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+diff --git a/tests/test_json_string_matching.rb b/tests/test_json_string_matching.rb
+index c233df8c2c..6158231103 100644
+--- a/tests/test_json_string_matching.rb
++++ b/tests/test_json_string_matching.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # encoding: utf-8
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+diff --git a/tests/test_json_unicode.rb b/tests/test_json_unicode.rb
+index 8352d5c6c6..16234f0491 100755
+--- a/tests/test_json_unicode.rb
++++ b/tests/test_json_unicode.rb
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env ruby
+ # encoding: utf-8
++# frozen_string_literal: false
+
+ require 'test/unit'
+ require File.join(File.dirname(__FILE__), 'setup_variant')
+
+commit ee1844bffb1750448defa4c982f3aff240ff536a
+Author: naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Wed Dec 16 05:31:54 2015 +0000
+
+ handle ext/ as r53141
+
+ g -L frozen_string_literal ext/**/*.rb|xargs ruby -Ka -e'ARGV.each{|fn|puts
+ fn;open(fn,"r+"){|f|s=f.read.sub(/\A(#!.*\n)?(#.*coding.*\n)?/,"\\&#
+ frozen_string_literal: false\n");f.rewind;f.write s}}'
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53143 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit c4fdfabcc8ea3f6186d1560f7756211fce125be3)
+
+diff --git a/ext/json/ext/generator/extconf.rb b/ext/json/ext/generator/extconf.rb
+index 8627c5f4bd..fd5c4a7f49 100644
+--- a/ext/json/ext/generator/extconf.rb
++++ b/ext/json/ext/generator/extconf.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ require 'mkmf'
+
+ $defs << "-DJSON_GENERATOR"
+diff --git a/ext/json/ext/parser/extconf.rb b/ext/json/ext/parser/extconf.rb
+index 2addc53e7f..f7360d46b2 100644
+--- a/ext/json/ext/parser/extconf.rb
++++ b/ext/json/ext/parser/extconf.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ require 'mkmf'
+
+ have_func("rb_enc_raise", "ruby.h")
+diff --git a/ext/json/extconf.rb b/ext/json/extconf.rb
+index 850798c643..ad1ef9ba82 100644
+--- a/ext/json/extconf.rb
++++ b/ext/json/extconf.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ require 'mkmf'
+ create_makefile('json')
+
+diff --git a/lib/json.rb b/lib/json.rb
+index 24aa385c91..61bb8fae0e 100644
+--- a/lib/json.rb
++++ b/lib/json.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ require 'json/common'
+
+ ##
+diff --git a/lib/json/add/bigdecimal.rb b/lib/json/add/bigdecimal.rb
+index 0ef69f12e0..a7646860a2 100644
+--- a/lib/json/add/bigdecimal.rb
++++ b/lib/json/add/bigdecimal.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/complex.rb b/lib/json/add/complex.rb
+index 2723f60103..cff40c1996 100644
+--- a/lib/json/add/complex.rb
++++ b/lib/json/add/complex.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/core.rb b/lib/json/add/core.rb
+index 77d9dc0b20..93b2bff424 100644
+--- a/lib/json/add/core.rb
++++ b/lib/json/add/core.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ # This file requires the implementations of ruby core's custom objects for
+ # serialisation/deserialisation.
+
+diff --git a/lib/json/add/date.rb b/lib/json/add/date.rb
+index 4288237db1..20f0e8dc77 100644
+--- a/lib/json/add/date.rb
++++ b/lib/json/add/date.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/date_time.rb b/lib/json/add/date_time.rb
+index 5ea42ea656..757d43c266 100644
+--- a/lib/json/add/date_time.rb
++++ b/lib/json/add/date_time.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/exception.rb b/lib/json/add/exception.rb
+index e6ad257abf..95379d97f5 100644
+--- a/lib/json/add/exception.rb
++++ b/lib/json/add/exception.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/ostruct.rb b/lib/json/add/ostruct.rb
+index da81e107a7..2fa1e88b93 100644
+--- a/lib/json/add/ostruct.rb
++++ b/lib/json/add/ostruct.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/range.rb b/lib/json/add/range.rb
+index e61e553cdb..4dd7ccf0eb 100644
+--- a/lib/json/add/range.rb
++++ b/lib/json/add/range.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/rational.rb b/lib/json/add/rational.rb
+index ee39c20e8d..e83a532775 100644
+--- a/lib/json/add/rational.rb
++++ b/lib/json/add/rational.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/regexp.rb b/lib/json/add/regexp.rb
+index 2fcbb6fb14..4bea64fb19 100644
+--- a/lib/json/add/regexp.rb
++++ b/lib/json/add/regexp.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/struct.rb b/lib/json/add/struct.rb
+index 6847cde99b..c9afe70770 100644
+--- a/lib/json/add/struct.rb
++++ b/lib/json/add/struct.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/symbol.rb b/lib/json/add/symbol.rb
+index 03dc9a56a5..831e5c6173 100644
+--- a/lib/json/add/symbol.rb
++++ b/lib/json/add/symbol.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/add/time.rb b/lib/json/add/time.rb
+index d9834677ac..18e57d7555 100644
+--- a/lib/json/add/time.rb
++++ b/lib/json/add/time.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+diff --git a/lib/json/common.rb b/lib/json/common.rb
+index f44184e138..020615fc1d 100644
+--- a/lib/json/common.rb
++++ b/lib/json/common.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ require 'json/version'
+ require 'json/generic_object'
+
+diff --git a/lib/json/ext.rb b/lib/json/ext.rb
+index c5f813181d..2486f084cd 100644
+--- a/lib/json/ext.rb
++++ b/lib/json/ext.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ if ENV['SIMPLECOV_COVERAGE'].to_i == 1
+ require 'simplecov'
+ SimpleCov.start do
+diff --git a/lib/json/generic_object.rb b/lib/json/generic_object.rb
+index 3a14f0ea7d..2241f6c7ce 100644
+--- a/lib/json/generic_object.rb
++++ b/lib/json/generic_object.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ require 'ostruct'
+
+ module JSON
+diff --git a/lib/json/version.rb b/lib/json/version.rb
+index 5a4013dbf6..b5748334b9 100644
+--- a/lib/json/version.rb
++++ b/lib/json/version.rb
+@@ -1,3 +1,4 @@
++# frozen_string_literal: false
+ module JSON
+ # JSON version
+ VERSION = '1.8.3'
+
+commit 5af0d7c8ca76269f90f987cfa7db700ff968bc10
+Author: nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
+Date: Wed Aug 10 16:30:43 2016 +0000
+
+ merge revision(s) 55380: [Backport #12255]
+
+ * ext/json/lib/*.rb: Removed some comments. Because these are unnecessary
+ class description. [ci skip][Bug #12255][ruby-core:74835]
+
+ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_3@55855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
+ (cherry picked from commit a3600fc3771818028f591969c2d3287fcecfa13c)
+
+diff --git a/lib/json/add/date.rb b/lib/json/add/date.rb
+index 20f0e8dc77..b58af76e10 100644
+--- a/lib/json/add/date.rb
++++ b/lib/json/add/date.rb
+@@ -4,7 +4,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ end
+ require 'date'
+
+-# Date serialization/deserialization
+ class Date
+
+ # Deserializes JSON string by converting Julian year <tt>y</tt>, month
+diff --git a/lib/json/add/date_time.rb b/lib/json/add/date_time.rb
+index 757d43c266..f794eb3d7d 100644
+--- a/lib/json/add/date_time.rb
++++ b/lib/json/add/date_time.rb
+@@ -4,7 +4,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ end
+ require 'date'
+
+-# DateTime serialization/deserialization
+ class DateTime
+
+ # Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
+diff --git a/lib/json/add/exception.rb b/lib/json/add/exception.rb
+index 95379d97f5..caac713c6a 100644
+--- a/lib/json/add/exception.rb
++++ b/lib/json/add/exception.rb
+@@ -3,7 +3,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+
+-# Exception serialization/deserialization
+ class Exception
+
+ # Deserializes JSON string by constructing new Exception object with message
+diff --git a/lib/json/add/ostruct.rb b/lib/json/add/ostruct.rb
+index 2fa1e88b93..1f9ce7b3b4 100644
+--- a/lib/json/add/ostruct.rb
++++ b/lib/json/add/ostruct.rb
+@@ -4,7 +4,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ end
+ require 'ostruct'
+
+-# OpenStruct serialization/deserialization
+ class OpenStruct
+
+ # Deserializes JSON string by constructing new Struct object with values
+diff --git a/lib/json/add/range.rb b/lib/json/add/range.rb
+index 4dd7ccf0eb..3ef20150bf 100644
+--- a/lib/json/add/range.rb
++++ b/lib/json/add/range.rb
+@@ -3,7 +3,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+
+-# Range serialization/deserialization
+ class Range
+
+ # Deserializes JSON string by constructing new Range object with arguments
+diff --git a/lib/json/add/regexp.rb b/lib/json/add/regexp.rb
+index 4bea64fb19..41b260f307 100644
+--- a/lib/json/add/regexp.rb
++++ b/lib/json/add/regexp.rb
+@@ -3,7 +3,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+
+-# Regexp serialization/deserialization
+ class Regexp
+
+ # Deserializes JSON string by constructing new Regexp object with source
+diff --git a/lib/json/add/struct.rb b/lib/json/add/struct.rb
+index c9afe70770..d08d88237a 100644
+--- a/lib/json/add/struct.rb
++++ b/lib/json/add/struct.rb
+@@ -3,7 +3,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+
+-# Struct serialization/deserialization
+ class Struct
+
+ # Deserializes JSON string by constructing new Struct object with values
+diff --git a/lib/json/add/symbol.rb b/lib/json/add/symbol.rb
+index 831e5c6173..31b56a294f 100644
+--- a/lib/json/add/symbol.rb
++++ b/lib/json/add/symbol.rb
+@@ -3,7 +3,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+
+-# Symbol serialization/deserialization
+ class Symbol
+ # Returns a hash, that will be turned into a JSON object and represent this
+ # object.
+diff --git a/lib/json/add/time.rb b/lib/json/add/time.rb
+index 18e57d7555..80b6434f17 100644
+--- a/lib/json/add/time.rb
++++ b/lib/json/add/time.rb
+@@ -3,7 +3,6 @@ unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+ end
+
+-# Time serialization/deserialization
+ class Time
+
+ # Deserializes JSON string by converting time since epoch to Time
diff --git a/libre/ruby2.3/ruby-2.3.4-add-json_pure.patch b/libre/ruby2.3/ruby-2.3.4-add-json_pure.patch
new file mode 100644
index 000000000..e543a58f1
--- /dev/null
+++ b/libre/ruby2.3/ruby-2.3.4-add-json_pure.patch
@@ -0,0 +1,22 @@
+diff --git a/doc/maintainers.rdoc b/doc/maintainers.rdoc
+index 74ee6aaee0..8536a3fe82 100644
+--- a/doc/maintainers.rdoc
++++ b/doc/maintainers.rdoc
+@@ -97,6 +97,8 @@ Zachary Scott (zzak)
+ [lib/jcode.rb]
+ * 1.8: _unmaintained_
+ * 1.9: _deprecated_
++[ext/json]
++ NARUSE, Yui (naruse)
+ [lib/logger.rb]
+ Naotoshi Seo (sonots)
+ [lib/mathn.rb]
+diff --git a/lib/json/.document b/lib/json/.document
+new file mode 100644
+index 0000000000..7ae6b614de
+--- /dev/null
++++ b/lib/json/.document
+@@ -0,0 +1,3 @@
++*.rb
++add/*.rb
++pure/*.rb
diff --git a/libre/ruby2.3/ruby-2.3.4-remove-json-ext.patch b/libre/ruby2.3/ruby-2.3.4-remove-json-ext.patch
new file mode 100644
index 000000000..99e3e825c
--- /dev/null
+++ b/libre/ruby2.3/ruby-2.3.4-remove-json-ext.patch
@@ -0,0 +1,80 @@
+diff --git a/common.mk b/common.mk
+index da4608bc61..71dcbf477c 100644
+--- a/common.mk
++++ b/common.mk
+@@ -781,8 +781,6 @@ EXT_SRCS = $(srcdir)/ext/ripper/ripper.c \
+
+ srcs-ext: $(EXT_SRCS)
+
+-srcs-extra: $(srcdir)/ext/json/parser/parser.c
+-
+ LIB_SRCS = $(srcdir)/lib/unicode_normalize/tables.rb
+
+ srcs-lib: $(LIB_SRCS)
+@@ -875,11 +873,6 @@ $(srcdir)/ext/ripper/ripper.c: parse.y id.h
+ Q=$(Q) ECHO=$(ECHO) RM="$(RM)" top_srcdir=../.. srcdir=. VPATH="$(PWD)" \
+ RUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)"
+
+-$(srcdir)/ext/json/parser/parser.c: $(srcdir)/ext/json/parser/parser.rl
+- $(ECHO) generating $@
+- $(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f prereq.mk $(MFLAGS) \
+- Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. BASERUBY="$(BASERUBY)"
+-
+ $(srcdir)/ext/rbconfig/sizeof/sizes.c: $(srcdir)/ext/rbconfig/sizeof/depend \
+ $(srcdir)/tool/generic_erb.rb $(srcdir)/template/sizes.c.tmpl $(srcdir)/configure.in
+ $(ECHO) generating $@
+diff --git a/doc/maintainers.rdoc b/doc/maintainers.rdoc
+index d657626e30..74ee6aaee0 100644
+--- a/doc/maintainers.rdoc
++++ b/doc/maintainers.rdoc
+@@ -269,8 +269,6 @@ Zachary Scott (zzak)
+ Nobuyuki Nakada (nobu)
+ [ext/io/wait]
+ Nobuyuki Nakada (nobu)
+-[ext/json]
+- NARUSE, Yui (naruse)
+ [ext/mathn/complex]
+ * 1.8: 1.9 feature
+ * 1.9: Keiju ISHITSUKA (keiju)
+diff --git a/ext/.document b/ext/.document
+index 2e6fc78879..f5da0912ed 100644
+--- a/ext/.document
++++ b/ext/.document
+@@ -35,9 +35,6 @@ io/console/console.c
+ io/nonblock/nonblock.c
+ io/wait/lib
+ io/wait/wait.c
+-json/ext/generator/generator.c
+-json/ext/parser/parser.c
+-json/lib
+ mathn/complex/complex.c
+ mathn/rational/rational.c
+ nkf/lib
+diff --git a/ext/Setup b/ext/Setup
+index 05998e3363..2ca8e9ce9e 100644
+--- a/ext/Setup
++++ b/ext/Setup
+@@ -20,9 +20,6 @@
+ #io/console
+ #io/nonblock
+ #io/wait
+-#json
+-#json/generator
+-#json/parser
+ #mathn/complex
+ #mathn/rational
+ #nkf
+diff --git a/ext/Setup.nacl b/ext/Setup.nacl
+index f205e367c6..4ef8d3972f 100644
+--- a/ext/Setup.nacl
++++ b/ext/Setup.nacl
+@@ -22,9 +22,6 @@
+ # io/console
+ # io/nonblock
+ # io/wait
+-# #json
+-# json/generator
+-# json/parser
+ # mathn/complex
+ # mathn/rational
+ # nkf