json 2.15.1 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- #include "ruby.h"
1
+ #include "../json.h"
2
2
  #include "../fbuffer/fbuffer.h"
3
3
  #include "../vendor/fpconv.c"
4
4
 
@@ -36,13 +36,9 @@ typedef struct JSON_Generator_StateStruct {
36
36
  bool strict;
37
37
  } JSON_Generator_State;
38
38
 
39
- #ifndef RB_UNLIKELY
40
- #define RB_UNLIKELY(cond) (cond)
41
- #endif
42
-
43
39
  static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8;
44
40
 
45
- static ID i_to_s, i_to_json, i_new, i_pack, i_unpack, i_create_id, i_extend, i_encode;
41
+ static ID i_to_s, i_to_json, i_new, i_encode;
46
42
  static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, sym_allow_duplicate_key,
47
43
  sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict, sym_as_json;
48
44
 
@@ -64,6 +60,7 @@ struct generate_json_data {
64
60
  JSON_Generator_State *state;
65
61
  VALUE obj;
66
62
  generator_func func;
63
+ long depth;
67
64
  };
68
65
 
69
66
  static VALUE cState_from_state_s(VALUE self, VALUE opts);
@@ -85,23 +82,18 @@ static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *d
85
82
 
86
83
  static int usascii_encindex, utf8_encindex, binary_encindex;
87
84
 
88
- #ifdef RBIMPL_ATTR_NORETURN
89
- RBIMPL_ATTR_NORETURN()
90
- #endif
91
- static void raise_generator_error_str(VALUE invalid_object, VALUE str)
85
+ NORETURN(static void) raise_generator_error_str(VALUE invalid_object, VALUE str)
92
86
  {
87
+ rb_enc_associate_index(str, utf8_encindex);
93
88
  VALUE exc = rb_exc_new_str(eGeneratorError, str);
94
89
  rb_ivar_set(exc, rb_intern("@invalid_object"), invalid_object);
95
90
  rb_exc_raise(exc);
96
91
  }
97
92
 
98
- #ifdef RBIMPL_ATTR_NORETURN
99
- RBIMPL_ATTR_NORETURN()
100
- #endif
101
93
  #ifdef RBIMPL_ATTR_FORMAT
102
94
  RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
103
95
  #endif
104
- static void raise_generator_error(VALUE invalid_object, const char *fmt, ...)
96
+ NORETURN(static void) raise_generator_error(VALUE invalid_object, const char *fmt, ...)
105
97
  {
106
98
  va_list args;
107
99
  va_start(args, fmt);
@@ -136,13 +128,7 @@ typedef struct _search_state {
136
128
  #endif /* HAVE_SIMD */
137
129
  } search_state;
138
130
 
139
- #if (defined(__GNUC__ ) || defined(__clang__))
140
- #define FORCE_INLINE __attribute__((always_inline))
141
- #else
142
- #define FORCE_INLINE
143
- #endif
144
-
145
- static inline FORCE_INLINE void search_flush(search_state *search)
131
+ ALWAYS_INLINE(static) void search_flush(search_state *search)
146
132
  {
147
133
  // Do not remove this conditional without profiling, specifically escape-heavy text.
148
134
  // escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush).
@@ -185,7 +171,7 @@ static inline unsigned char search_escape_basic(search_state *search)
185
171
  return 0;
186
172
  }
187
173
 
188
- static inline FORCE_INLINE void escape_UTF8_char_basic(search_state *search)
174
+ ALWAYS_INLINE(static) void escape_UTF8_char_basic(search_state *search)
189
175
  {
190
176
  const unsigned char ch = (unsigned char)*search->ptr;
191
177
  switch (ch) {
@@ -272,7 +258,7 @@ static inline void escape_UTF8_char(search_state *search, unsigned char ch_len)
272
258
 
273
259
  #ifdef HAVE_SIMD
274
260
 
275
- static inline FORCE_INLINE char *copy_remaining_bytes(search_state *search, unsigned long vec_len, unsigned long len)
261
+ ALWAYS_INLINE(static) char *copy_remaining_bytes(search_state *search, unsigned long vec_len, unsigned long len)
276
262
  {
277
263
  // Flush the buffer so everything up until the last 'len' characters are unflushed.
278
264
  search_flush(search);
@@ -295,7 +281,7 @@ static inline FORCE_INLINE char *copy_remaining_bytes(search_state *search, unsi
295
281
 
296
282
  #ifdef HAVE_SIMD_NEON
297
283
 
298
- static inline FORCE_INLINE unsigned char neon_next_match(search_state *search)
284
+ ALWAYS_INLINE(static) unsigned char neon_next_match(search_state *search)
299
285
  {
300
286
  uint64_t mask = search->matches_mask;
301
287
  uint32_t index = trailing_zeros64(mask) >> 2;
@@ -409,7 +395,7 @@ static inline unsigned char search_escape_basic_neon(search_state *search)
409
395
 
410
396
  #ifdef HAVE_SIMD_SSE2
411
397
 
412
- static inline FORCE_INLINE unsigned char sse2_next_match(search_state *search)
398
+ ALWAYS_INLINE(static) unsigned char sse2_next_match(search_state *search)
413
399
  {
414
400
  int mask = search->matches_mask;
415
401
  int index = trailing_zeros(mask);
@@ -433,7 +419,7 @@ static inline FORCE_INLINE unsigned char sse2_next_match(search_state *search)
433
419
  #define TARGET_SSE2
434
420
  #endif
435
421
 
436
- static inline TARGET_SSE2 FORCE_INLINE unsigned char search_escape_basic_sse2(search_state *search)
422
+ ALWAYS_INLINE(static) TARGET_SSE2 unsigned char search_escape_basic_sse2(search_state *search)
437
423
  {
438
424
  if (RB_UNLIKELY(search->has_matches)) {
439
425
  // There are more matches if search->matches_mask > 0.
@@ -941,11 +927,6 @@ static size_t State_memsize(const void *ptr)
941
927
  return sizeof(JSON_Generator_State);
942
928
  }
943
929
 
944
- #ifndef HAVE_RB_EXT_RACTOR_SAFE
945
- # undef RUBY_TYPED_FROZEN_SHAREABLE
946
- # define RUBY_TYPED_FROZEN_SHAREABLE 0
947
- #endif
948
-
949
930
  static const rb_data_type_t JSON_Generator_State_type = {
950
931
  "JSON/Generator/State",
951
932
  {
@@ -987,21 +968,24 @@ static void vstate_spill(struct generate_json_data *data)
987
968
  RB_OBJ_WRITTEN(vstate, Qundef, state->as_json);
988
969
  }
989
970
 
990
- static inline VALUE vstate_get(struct generate_json_data *data)
971
+ static inline VALUE json_call_to_json(struct generate_json_data *data, VALUE obj)
991
972
  {
992
973
  if (RB_UNLIKELY(!data->vstate)) {
993
974
  vstate_spill(data);
994
975
  }
995
- return data->vstate;
976
+ GET_STATE(data->vstate);
977
+ state->depth = data->depth;
978
+ VALUE tmp = rb_funcall(obj, i_to_json, 1, data->vstate);
979
+ // no need to restore state->depth, vstate is just a temporary State
980
+ return tmp;
996
981
  }
997
982
 
998
- struct hash_foreach_arg {
999
- VALUE hash;
1000
- struct generate_json_data *data;
1001
- int first_key_type;
1002
- bool first;
1003
- bool mixed_keys_encountered;
1004
- };
983
+ static VALUE
984
+ json_call_as_json(JSON_Generator_State *state, VALUE object, VALUE is_key)
985
+ {
986
+ VALUE proc_args[2] = {object, is_key};
987
+ return rb_proc_call_with_block(state->as_json, 2, proc_args, Qnil);
988
+ }
1005
989
 
1006
990
  static VALUE
1007
991
  convert_string_subclass(VALUE key)
@@ -1018,8 +1002,130 @@ convert_string_subclass(VALUE key)
1018
1002
  return key_to_s;
1019
1003
  }
1020
1004
 
1021
- NOINLINE()
1022
- static void
1005
+ static bool enc_utf8_compatible_p(int enc_idx)
1006
+ {
1007
+ if (enc_idx == usascii_encindex) return true;
1008
+ if (enc_idx == utf8_encindex) return true;
1009
+ return false;
1010
+ }
1011
+
1012
+ static VALUE encode_json_string_try(VALUE str)
1013
+ {
1014
+ return rb_funcall(str, i_encode, 1, Encoding_UTF_8);
1015
+ }
1016
+
1017
+ static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
1018
+ {
1019
+ raise_generator_error_str(str, rb_funcall(exception, rb_intern("message"), 0));
1020
+ return Qundef;
1021
+ }
1022
+
1023
+ static inline bool valid_json_string_p(VALUE str)
1024
+ {
1025
+ int coderange = rb_enc_str_coderange(str);
1026
+
1027
+ if (RB_LIKELY(coderange == ENC_CODERANGE_7BIT)) {
1028
+ return true;
1029
+ }
1030
+
1031
+ if (RB_LIKELY(coderange == ENC_CODERANGE_VALID)) {
1032
+ return enc_utf8_compatible_p(RB_ENCODING_GET_INLINED(str));
1033
+ }
1034
+
1035
+ return false;
1036
+ }
1037
+
1038
+ static inline VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
1039
+ {
1040
+ if (RB_LIKELY(valid_json_string_p(str))) {
1041
+ return str;
1042
+ }
1043
+
1044
+ if (!as_json_called && data->state->strict && RTEST(data->state->as_json)) {
1045
+ VALUE coerced_str = json_call_as_json(data->state, str, Qfalse);
1046
+ if (coerced_str != str) {
1047
+ if (RB_TYPE_P(coerced_str, T_STRING)) {
1048
+ if (!valid_json_string_p(coerced_str)) {
1049
+ raise_generator_error(str, "source sequence is illegal/malformed utf-8");
1050
+ }
1051
+ } else {
1052
+ // as_json could return another type than T_STRING
1053
+ if (is_key) {
1054
+ raise_generator_error(coerced_str, "%"PRIsVALUE" not allowed as object key in JSON", CLASS_OF(coerced_str));
1055
+ }
1056
+ }
1057
+
1058
+ return coerced_str;
1059
+ }
1060
+ }
1061
+
1062
+ if (RB_ENCODING_GET_INLINED(str) == binary_encindex) {
1063
+ VALUE utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
1064
+ switch (rb_enc_str_coderange(utf8_string)) {
1065
+ case ENC_CODERANGE_7BIT:
1066
+ return utf8_string;
1067
+ case ENC_CODERANGE_VALID:
1068
+ // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
1069
+ // TODO: Raise in 3.0.0
1070
+ rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
1071
+ return utf8_string;
1072
+ break;
1073
+ }
1074
+ }
1075
+
1076
+ return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
1077
+ }
1078
+
1079
+ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
1080
+ {
1081
+ fbuffer_append_char(buffer, '"');
1082
+
1083
+ long len;
1084
+ search_state search;
1085
+ search.buffer = buffer;
1086
+ RSTRING_GETMEM(obj, search.ptr, len);
1087
+ search.cursor = search.ptr;
1088
+ search.end = search.ptr + len;
1089
+
1090
+ #ifdef HAVE_SIMD
1091
+ search.matches_mask = 0;
1092
+ search.has_matches = false;
1093
+ search.chunk_base = NULL;
1094
+ #endif /* HAVE_SIMD */
1095
+
1096
+ switch (rb_enc_str_coderange(obj)) {
1097
+ case ENC_CODERANGE_7BIT:
1098
+ case ENC_CODERANGE_VALID:
1099
+ if (RB_UNLIKELY(data->state->ascii_only)) {
1100
+ convert_UTF8_to_ASCII_only_JSON(&search, data->state->script_safe ? script_safe_escape_table : ascii_only_escape_table);
1101
+ } else if (RB_UNLIKELY(data->state->script_safe)) {
1102
+ convert_UTF8_to_script_safe_JSON(&search);
1103
+ } else {
1104
+ convert_UTF8_to_JSON(&search);
1105
+ }
1106
+ break;
1107
+ default:
1108
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
1109
+ break;
1110
+ }
1111
+ fbuffer_append_char(buffer, '"');
1112
+ }
1113
+
1114
+ static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
1115
+ {
1116
+ obj = ensure_valid_encoding(data, obj, false, false);
1117
+ raw_generate_json_string(buffer, data, obj);
1118
+ }
1119
+
1120
+ struct hash_foreach_arg {
1121
+ VALUE hash;
1122
+ struct generate_json_data *data;
1123
+ int first_key_type;
1124
+ bool first;
1125
+ bool mixed_keys_encountered;
1126
+ };
1127
+
1128
+ NOINLINE(static) void
1023
1129
  json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
1024
1130
  {
1025
1131
  if (arg->mixed_keys_encountered) {
@@ -1034,13 +1140,6 @@ json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
1034
1140
  }
1035
1141
  }
1036
1142
 
1037
- static VALUE
1038
- json_call_as_json(JSON_Generator_State *state, VALUE object, VALUE is_key)
1039
- {
1040
- VALUE proc_args[2] = {object, is_key};
1041
- return rb_proc_call_with_block(state->as_json, 2, proc_args, Qnil);
1042
- }
1043
-
1044
1143
  static int
1045
1144
  json_object_i(VALUE key, VALUE val, VALUE _arg)
1046
1145
  {
@@ -1050,7 +1149,7 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
1050
1149
  FBuffer *buffer = data->buffer;
1051
1150
  JSON_Generator_State *state = data->state;
1052
1151
 
1053
- long depth = state->depth;
1152
+ long depth = data->depth;
1054
1153
  int key_type = rb_type(key);
1055
1154
 
1056
1155
  if (arg->first) {
@@ -1106,8 +1205,10 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
1106
1205
  break;
1107
1206
  }
1108
1207
 
1208
+ key_to_s = ensure_valid_encoding(data, key_to_s, as_json_called, true);
1209
+
1109
1210
  if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
1110
- generate_json_string(buffer, data, key_to_s);
1211
+ raw_generate_json_string(buffer, data, key_to_s);
1111
1212
  } else {
1112
1213
  generate_json(buffer, data, key_to_s);
1113
1214
  }
@@ -1122,9 +1223,9 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
1122
1223
  static inline long increase_depth(struct generate_json_data *data)
1123
1224
  {
1124
1225
  JSON_Generator_State *state = data->state;
1125
- long depth = ++state->depth;
1226
+ long depth = ++data->depth;
1126
1227
  if (RB_UNLIKELY(depth > state->max_nesting && state->max_nesting)) {
1127
- rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
1228
+ rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", --data->depth);
1128
1229
  }
1129
1230
  return depth;
1130
1231
  }
@@ -1135,7 +1236,7 @@ static void generate_json_object(FBuffer *buffer, struct generate_json_data *dat
1135
1236
 
1136
1237
  if (RHASH_SIZE(obj) == 0) {
1137
1238
  fbuffer_append(buffer, "{}", 2);
1138
- --data->state->depth;
1239
+ --data->depth;
1139
1240
  return;
1140
1241
  }
1141
1242
 
@@ -1148,7 +1249,7 @@ static void generate_json_object(FBuffer *buffer, struct generate_json_data *dat
1148
1249
  };
1149
1250
  rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
1150
1251
 
1151
- depth = --data->state->depth;
1252
+ depth = --data->depth;
1152
1253
  if (RB_UNLIKELY(data->state->object_nl)) {
1153
1254
  fbuffer_append_str(buffer, data->state->object_nl);
1154
1255
  if (RB_UNLIKELY(data->state->indent)) {
@@ -1164,7 +1265,7 @@ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data
1164
1265
 
1165
1266
  if (RARRAY_LEN(obj) == 0) {
1166
1267
  fbuffer_append(buffer, "[]", 2);
1167
- --data->state->depth;
1268
+ --data->depth;
1168
1269
  return;
1169
1270
  }
1170
1271
 
@@ -1180,7 +1281,7 @@ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data
1180
1281
  }
1181
1282
  generate_json(buffer, data, RARRAY_AREF(obj, i));
1182
1283
  }
1183
- data->state->depth = --depth;
1284
+ data->depth = --depth;
1184
1285
  if (RB_UNLIKELY(data->state->array_nl)) {
1185
1286
  fbuffer_append_str(buffer, data->state->array_nl);
1186
1287
  if (RB_UNLIKELY(data->state->indent)) {
@@ -1190,90 +1291,11 @@ static void generate_json_array(FBuffer *buffer, struct generate_json_data *data
1190
1291
  fbuffer_append_char(buffer, ']');
1191
1292
  }
1192
1293
 
1193
- static inline int enc_utf8_compatible_p(int enc_idx)
1194
- {
1195
- if (enc_idx == usascii_encindex) return 1;
1196
- if (enc_idx == utf8_encindex) return 1;
1197
- return 0;
1198
- }
1199
-
1200
- static VALUE encode_json_string_try(VALUE str)
1201
- {
1202
- return rb_funcall(str, i_encode, 1, Encoding_UTF_8);
1203
- }
1204
-
1205
- static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
1206
- {
1207
- raise_generator_error_str(str, rb_funcall(exception, rb_intern("message"), 0));
1208
- return Qundef;
1209
- }
1210
-
1211
- static inline VALUE ensure_valid_encoding(VALUE str)
1212
- {
1213
- int encindex = RB_ENCODING_GET(str);
1214
- VALUE utf8_string;
1215
- if (RB_UNLIKELY(!enc_utf8_compatible_p(encindex))) {
1216
- if (encindex == binary_encindex) {
1217
- utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
1218
- switch (rb_enc_str_coderange(utf8_string)) {
1219
- case ENC_CODERANGE_7BIT:
1220
- return utf8_string;
1221
- case ENC_CODERANGE_VALID:
1222
- // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
1223
- // TODO: Raise in 3.0.0
1224
- rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
1225
- return utf8_string;
1226
- break;
1227
- }
1228
- }
1229
-
1230
- str = rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
1231
- }
1232
- return str;
1233
- }
1234
-
1235
- static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
1236
- {
1237
- obj = ensure_valid_encoding(obj);
1238
-
1239
- fbuffer_append_char(buffer, '"');
1240
-
1241
- long len;
1242
- search_state search;
1243
- search.buffer = buffer;
1244
- RSTRING_GETMEM(obj, search.ptr, len);
1245
- search.cursor = search.ptr;
1246
- search.end = search.ptr + len;
1247
-
1248
- #ifdef HAVE_SIMD
1249
- search.matches_mask = 0;
1250
- search.has_matches = false;
1251
- search.chunk_base = NULL;
1252
- #endif /* HAVE_SIMD */
1253
-
1254
- switch (rb_enc_str_coderange(obj)) {
1255
- case ENC_CODERANGE_7BIT:
1256
- case ENC_CODERANGE_VALID:
1257
- if (RB_UNLIKELY(data->state->ascii_only)) {
1258
- convert_UTF8_to_ASCII_only_JSON(&search, data->state->script_safe ? script_safe_escape_table : ascii_only_escape_table);
1259
- } else if (RB_UNLIKELY(data->state->script_safe)) {
1260
- convert_UTF8_to_script_safe_JSON(&search);
1261
- } else {
1262
- convert_UTF8_to_JSON(&search);
1263
- }
1264
- break;
1265
- default:
1266
- raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
1267
- break;
1268
- }
1269
- fbuffer_append_char(buffer, '"');
1270
- }
1271
-
1272
1294
  static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
1273
1295
  {
1274
1296
  VALUE tmp;
1275
1297
  if (rb_respond_to(obj, i_to_json)) {
1276
- tmp = rb_funcall(obj, i_to_json, 1, vstate_get(data));
1298
+ tmp = json_call_to_json(data, obj);
1277
1299
  Check_Type(tmp, T_STRING);
1278
1300
  fbuffer_append_str(buffer, tmp);
1279
1301
  } else {
@@ -1340,7 +1362,7 @@ static void generate_json_float(FBuffer *buffer, struct generate_json_data *data
1340
1362
  if (casted_obj != obj) {
1341
1363
  increase_depth(data);
1342
1364
  generate_json(buffer, data, casted_obj);
1343
- data->state->depth--;
1365
+ data->depth--;
1344
1366
  return;
1345
1367
  }
1346
1368
  }
@@ -1407,7 +1429,16 @@ start:
1407
1429
  break;
1408
1430
  case T_STRING:
1409
1431
  if (klass != rb_cString) goto general;
1410
- generate_json_string(buffer, data, obj);
1432
+
1433
+ if (RB_LIKELY(valid_json_string_p(obj))) {
1434
+ raw_generate_json_string(buffer, data, obj);
1435
+ } else if (as_json_called) {
1436
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
1437
+ } else {
1438
+ obj = ensure_valid_encoding(data, obj, false, false);
1439
+ as_json_called = true;
1440
+ goto start;
1441
+ }
1411
1442
  break;
1412
1443
  case T_SYMBOL:
1413
1444
  generate_json_symbol(buffer, data, obj);
@@ -1443,16 +1474,14 @@ static VALUE generate_json_try(VALUE d)
1443
1474
 
1444
1475
  data->func(data->buffer, data, data->obj);
1445
1476
 
1446
- return Qnil;
1477
+ return fbuffer_finalize(data->buffer);
1447
1478
  }
1448
1479
 
1449
- static VALUE generate_json_rescue(VALUE d, VALUE exc)
1480
+ static VALUE generate_json_ensure(VALUE d)
1450
1481
  {
1451
1482
  struct generate_json_data *data = (struct generate_json_data *)d;
1452
1483
  fbuffer_free(data->buffer);
1453
1484
 
1454
- rb_exc_raise(exc);
1455
-
1456
1485
  return Qundef;
1457
1486
  }
1458
1487
 
@@ -1468,14 +1497,13 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func,
1468
1497
 
1469
1498
  struct generate_json_data data = {
1470
1499
  .buffer = &buffer,
1471
- .vstate = self,
1500
+ .vstate = Qfalse, // don't use self as it may be frozen and its depth is mutated when calling to_json
1472
1501
  .state = state,
1502
+ .depth = state->depth,
1473
1503
  .obj = obj,
1474
1504
  .func = func
1475
1505
  };
1476
- rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1477
-
1478
- return fbuffer_finalize(&buffer);
1506
+ return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
1479
1507
  }
1480
1508
 
1481
1509
  /* call-seq:
@@ -1491,10 +1519,7 @@ static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
1491
1519
  rb_check_arity(argc, 1, 2);
1492
1520
  VALUE obj = argv[0];
1493
1521
  VALUE io = argc > 1 ? argv[1] : Qnil;
1494
- VALUE result = cState_partial_generate(self, obj, generate_json, io);
1495
- GET_STATE(self);
1496
- (void)state;
1497
- return result;
1522
+ return cState_partial_generate(self, obj, generate_json, io);
1498
1523
  }
1499
1524
 
1500
1525
  static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
@@ -1575,6 +1600,7 @@ static VALUE string_config(VALUE config)
1575
1600
  */
1576
1601
  static VALUE cState_indent_set(VALUE self, VALUE indent)
1577
1602
  {
1603
+ rb_check_frozen(self);
1578
1604
  GET_STATE(self);
1579
1605
  RB_OBJ_WRITE(self, &state->indent, string_config(indent));
1580
1606
  return Qnil;
@@ -1600,6 +1626,7 @@ static VALUE cState_space(VALUE self)
1600
1626
  */
1601
1627
  static VALUE cState_space_set(VALUE self, VALUE space)
1602
1628
  {
1629
+ rb_check_frozen(self);
1603
1630
  GET_STATE(self);
1604
1631
  RB_OBJ_WRITE(self, &state->space, string_config(space));
1605
1632
  return Qnil;
@@ -1623,6 +1650,7 @@ static VALUE cState_space_before(VALUE self)
1623
1650
  */
1624
1651
  static VALUE cState_space_before_set(VALUE self, VALUE space_before)
1625
1652
  {
1653
+ rb_check_frozen(self);
1626
1654
  GET_STATE(self);
1627
1655
  RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
1628
1656
  return Qnil;
@@ -1648,6 +1676,7 @@ static VALUE cState_object_nl(VALUE self)
1648
1676
  */
1649
1677
  static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
1650
1678
  {
1679
+ rb_check_frozen(self);
1651
1680
  GET_STATE(self);
1652
1681
  RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
1653
1682
  return Qnil;
@@ -1671,6 +1700,7 @@ static VALUE cState_array_nl(VALUE self)
1671
1700
  */
1672
1701
  static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
1673
1702
  {
1703
+ rb_check_frozen(self);
1674
1704
  GET_STATE(self);
1675
1705
  RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
1676
1706
  return Qnil;
@@ -1694,6 +1724,7 @@ static VALUE cState_as_json(VALUE self)
1694
1724
  */
1695
1725
  static VALUE cState_as_json_set(VALUE self, VALUE as_json)
1696
1726
  {
1727
+ rb_check_frozen(self);
1697
1728
  GET_STATE(self);
1698
1729
  RB_OBJ_WRITE(self, &state->as_json, rb_convert_type(as_json, T_DATA, "Proc", "to_proc"));
1699
1730
  return Qnil;
@@ -1736,6 +1767,7 @@ static long long_config(VALUE num)
1736
1767
  */
1737
1768
  static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
1738
1769
  {
1770
+ rb_check_frozen(self);
1739
1771
  GET_STATE(self);
1740
1772
  state->max_nesting = long_config(depth);
1741
1773
  return Qnil;
@@ -1761,6 +1793,7 @@ static VALUE cState_script_safe(VALUE self)
1761
1793
  */
1762
1794
  static VALUE cState_script_safe_set(VALUE self, VALUE enable)
1763
1795
  {
1796
+ rb_check_frozen(self);
1764
1797
  GET_STATE(self);
1765
1798
  state->script_safe = RTEST(enable);
1766
1799
  return Qnil;
@@ -1792,6 +1825,7 @@ static VALUE cState_strict(VALUE self)
1792
1825
  */
1793
1826
  static VALUE cState_strict_set(VALUE self, VALUE enable)
1794
1827
  {
1828
+ rb_check_frozen(self);
1795
1829
  GET_STATE(self);
1796
1830
  state->strict = RTEST(enable);
1797
1831
  return Qnil;
@@ -1816,6 +1850,7 @@ static VALUE cState_allow_nan_p(VALUE self)
1816
1850
  */
1817
1851
  static VALUE cState_allow_nan_set(VALUE self, VALUE enable)
1818
1852
  {
1853
+ rb_check_frozen(self);
1819
1854
  GET_STATE(self);
1820
1855
  state->allow_nan = RTEST(enable);
1821
1856
  return Qnil;
@@ -1840,6 +1875,7 @@ static VALUE cState_ascii_only_p(VALUE self)
1840
1875
  */
1841
1876
  static VALUE cState_ascii_only_set(VALUE self, VALUE enable)
1842
1877
  {
1878
+ rb_check_frozen(self);
1843
1879
  GET_STATE(self);
1844
1880
  state->ascii_only = RTEST(enable);
1845
1881
  return Qnil;
@@ -1877,6 +1913,7 @@ static VALUE cState_depth(VALUE self)
1877
1913
  */
1878
1914
  static VALUE cState_depth_set(VALUE self, VALUE depth)
1879
1915
  {
1916
+ rb_check_frozen(self);
1880
1917
  GET_STATE(self);
1881
1918
  state->depth = long_config(depth);
1882
1919
  return Qnil;
@@ -1910,6 +1947,7 @@ static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_
1910
1947
  */
1911
1948
  static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
1912
1949
  {
1950
+ rb_check_frozen(self);
1913
1951
  GET_STATE(self);
1914
1952
  buffer_initial_length_set(state, buffer_initial_length);
1915
1953
  return Qnil;
@@ -1976,6 +2014,7 @@ static void configure_state(JSON_Generator_State *state, VALUE vstate, VALUE con
1976
2014
 
1977
2015
  static VALUE cState_configure(VALUE self, VALUE opts)
1978
2016
  {
2017
+ rb_check_frozen(self);
1979
2018
  GET_STATE(self);
1980
2019
  configure_state(state, self, opts);
1981
2020
  return self;
@@ -1997,12 +2036,11 @@ static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
1997
2036
  .buffer = &buffer,
1998
2037
  .vstate = Qfalse,
1999
2038
  .state = &state,
2039
+ .depth = state.depth,
2000
2040
  .obj = obj,
2001
2041
  .func = generate_json,
2002
2042
  };
2003
- rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
2004
-
2005
- return fbuffer_finalize(&buffer);
2043
+ return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
2006
2044
  }
2007
2045
 
2008
2046
  /*
@@ -2072,7 +2110,6 @@ void Init_generator(void)
2072
2110
  rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
2073
2111
  rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
2074
2112
  rb_define_method(cState, "generate", cState_generate, -1);
2075
- rb_define_alias(cState, "generate_new", "generate"); // :nodoc:
2076
2113
 
2077
2114
  rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
2078
2115
 
@@ -2120,10 +2157,6 @@ void Init_generator(void)
2120
2157
  i_to_s = rb_intern("to_s");
2121
2158
  i_to_json = rb_intern("to_json");
2122
2159
  i_new = rb_intern("new");
2123
- i_pack = rb_intern("pack");
2124
- i_unpack = rb_intern("unpack");
2125
- i_create_id = rb_intern("create_id");
2126
- i_extend = rb_intern("extend");
2127
2160
  i_encode = rb_intern("encode");
2128
2161
 
2129
2162
  sym_indent = ID2SYM(rb_intern("indent"));