json 2.4.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +27 -5
  3. data/README.md +3 -3
  4. data/VERSION +1 -1
  5. data/ext/json/ext/generator/generator.c +13 -17
  6. data/ext/json/ext/parser/extconf.rb +1 -0
  7. data/ext/json/ext/parser/parser.c +2971 -1797
  8. data/ext/json/ext/parser/parser.h +5 -1
  9. data/ext/json/ext/parser/parser.rl +106 -53
  10. data/json.gemspec +3 -76
  11. data/lib/json/common.rb +34 -13
  12. data/lib/json/pure/parser.rb +1 -1
  13. data/lib/json/version.rb +1 -1
  14. data/lib/json.rb +1 -1
  15. metadata +7 -110
  16. data/.gitignore +0 -18
  17. data/.travis.yml +0 -23
  18. data/Gemfile +0 -14
  19. data/README-json-jruby.md +0 -33
  20. data/Rakefile +0 -334
  21. data/diagrams/.keep +0 -0
  22. data/install.rb +0 -23
  23. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  24. data/java/src/json/ext/Generator.java +0 -447
  25. data/java/src/json/ext/GeneratorMethods.java +0 -231
  26. data/java/src/json/ext/GeneratorService.java +0 -42
  27. data/java/src/json/ext/GeneratorState.java +0 -520
  28. data/java/src/json/ext/OptionsReader.java +0 -113
  29. data/java/src/json/ext/Parser.java +0 -2374
  30. data/java/src/json/ext/Parser.rl +0 -905
  31. data/java/src/json/ext/ParserService.java +0 -34
  32. data/java/src/json/ext/RuntimeInfo.java +0 -116
  33. data/java/src/json/ext/StringDecoder.java +0 -166
  34. data/java/src/json/ext/StringEncoder.java +0 -117
  35. data/java/src/json/ext/Utils.java +0 -88
  36. data/json-java.gemspec +0 -38
  37. data/json_pure.gemspec +0 -33
  38. data/lib/json/ext/.keep +0 -0
  39. data/references/rfc7159.txt +0 -899
  40. data/tests/fixtures/fail10.json +0 -1
  41. data/tests/fixtures/fail11.json +0 -1
  42. data/tests/fixtures/fail12.json +0 -1
  43. data/tests/fixtures/fail13.json +0 -1
  44. data/tests/fixtures/fail14.json +0 -1
  45. data/tests/fixtures/fail18.json +0 -1
  46. data/tests/fixtures/fail19.json +0 -1
  47. data/tests/fixtures/fail2.json +0 -1
  48. data/tests/fixtures/fail20.json +0 -1
  49. data/tests/fixtures/fail21.json +0 -1
  50. data/tests/fixtures/fail22.json +0 -1
  51. data/tests/fixtures/fail23.json +0 -1
  52. data/tests/fixtures/fail24.json +0 -1
  53. data/tests/fixtures/fail25.json +0 -1
  54. data/tests/fixtures/fail27.json +0 -2
  55. data/tests/fixtures/fail28.json +0 -2
  56. data/tests/fixtures/fail3.json +0 -1
  57. data/tests/fixtures/fail4.json +0 -1
  58. data/tests/fixtures/fail5.json +0 -1
  59. data/tests/fixtures/fail6.json +0 -1
  60. data/tests/fixtures/fail7.json +0 -1
  61. data/tests/fixtures/fail8.json +0 -1
  62. data/tests/fixtures/fail9.json +0 -1
  63. data/tests/fixtures/obsolete_fail1.json +0 -1
  64. data/tests/fixtures/pass1.json +0 -56
  65. data/tests/fixtures/pass15.json +0 -1
  66. data/tests/fixtures/pass16.json +0 -1
  67. data/tests/fixtures/pass17.json +0 -1
  68. data/tests/fixtures/pass2.json +0 -1
  69. data/tests/fixtures/pass26.json +0 -1
  70. data/tests/fixtures/pass3.json +0 -6
  71. data/tests/json_addition_test.rb +0 -199
  72. data/tests/json_common_interface_test.rb +0 -169
  73. data/tests/json_encoding_test.rb +0 -107
  74. data/tests/json_ext_parser_test.rb +0 -15
  75. data/tests/json_fixtures_test.rb +0 -40
  76. data/tests/json_generator_test.rb +0 -432
  77. data/tests/json_generic_object_test.rb +0 -82
  78. data/tests/json_parser_test.rb +0 -497
  79. data/tests/json_string_matching_test.rb +0 -38
  80. data/tests/test_helper.rb +0 -17
  81. data/tools/diff.sh +0 -18
  82. data/tools/fuzz.rb +0 -131
  83. data/tools/server.rb +0 -62
@@ -13,6 +13,10 @@
13
13
  #include "st.h"
14
14
  #endif
15
15
 
16
+ #ifndef MAYBE_UNUSED
17
+ # define MAYBE_UNUSED(x) x
18
+ #endif
19
+
16
20
  #define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
17
21
 
18
22
  /* unicode */
@@ -63,7 +67,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
63
67
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
64
68
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
65
69
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
66
- static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd);
70
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize);
67
71
  static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
68
72
  static VALUE convert_encoding(VALUE source);
69
73
  static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
@@ -89,13 +89,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
89
89
 
90
90
  static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
91
91
  static VALUE CNaN, CInfinity, CMinusInfinity;
92
- static VALUE cBigDecimal = Qundef;
93
92
 
94
93
  static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
95
94
  i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
96
95
  i_object_class, i_array_class, i_decimal_class, i_key_p,
97
96
  i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
98
- i_leftshift, i_new, i_BigDecimal, i_freeze, i_uminus;
97
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
99
98
 
100
99
  %%{
101
100
  machine JSON_common;
@@ -345,19 +344,6 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
345
344
  ) (^[0-9Ee.\-]? @exit );
346
345
  }%%
347
346
 
348
- static int is_bigdecimal_class(VALUE obj)
349
- {
350
- if (cBigDecimal == Qundef) {
351
- if (rb_const_defined(rb_cObject, i_BigDecimal)) {
352
- cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
353
- }
354
- else {
355
- return 0;
356
- }
357
- }
358
- return obj == cBigDecimal;
359
- }
360
-
361
347
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
362
348
  {
363
349
  int cs = EVIL;
@@ -367,21 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
367
353
  %% write exec;
368
354
 
369
355
  if (cs >= JSON_float_first_final) {
356
+ VALUE mod = Qnil;
357
+ ID method_id = 0;
358
+ if (rb_respond_to(json->decimal_class, i_try_convert)) {
359
+ mod = json->decimal_class;
360
+ method_id = i_try_convert;
361
+ } else if (rb_respond_to(json->decimal_class, i_new)) {
362
+ mod = json->decimal_class;
363
+ method_id = i_new;
364
+ } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
365
+ VALUE name = rb_class_name(json->decimal_class);
366
+ const char *name_cstr = RSTRING_PTR(name);
367
+ const char *last_colon = strrchr(name_cstr, ':');
368
+ if (last_colon) {
369
+ const char *mod_path_end = last_colon - 1;
370
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
371
+ mod = rb_path_to_class(mod_path);
372
+
373
+ const char *method_name_beg = last_colon + 1;
374
+ long before_len = method_name_beg - name_cstr;
375
+ long len = RSTRING_LEN(name) - before_len;
376
+ VALUE method_name = rb_str_substr(name, before_len, len);
377
+ method_id = SYM2ID(rb_str_intern(method_name));
378
+ } else {
379
+ mod = rb_mKernel;
380
+ method_id = SYM2ID(rb_str_intern(name));
381
+ }
382
+ }
383
+
370
384
  long len = p - json->memo;
371
385
  fbuffer_clear(json->fbuffer);
372
386
  fbuffer_append(json->fbuffer, json->memo, len);
373
387
  fbuffer_append_char(json->fbuffer, '\0');
374
- if (NIL_P(json->decimal_class)) {
375
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
388
+
389
+ if (method_id) {
390
+ VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
391
+ *result = rb_funcallv(mod, method_id, 1, &text);
376
392
  } else {
377
- VALUE text;
378
- text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
379
- if (is_bigdecimal_class(json->decimal_class)) {
380
- *result = rb_funcall(Qnil, i_BigDecimal, 1, text);
381
- } else {
382
- *result = rb_funcall(json->decimal_class, i_new, 1, text);
383
- }
393
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
384
394
  }
395
+
385
396
  return p + 1;
386
397
  } else {
387
398
  return NULL;
@@ -441,17 +452,29 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
441
452
  }
442
453
  }
443
454
 
444
- static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
455
+ static const size_t MAX_STACK_BUFFER_SIZE = 128;
456
+ static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
445
457
  {
446
- char *p = string, *pe = string, *unescape;
458
+ VALUE result = Qnil;
459
+ size_t bufferSize = stringEnd - string;
460
+ char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
447
461
  int unescape_len;
448
462
  char buf[4];
449
463
 
464
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
465
+ bufferStart = buffer = ALLOC_N(char, bufferSize);
466
+ } else {
467
+ bufferStart = buffer = ALLOCA_N(char, bufferSize);
468
+ }
469
+
450
470
  while (pe < stringEnd) {
451
471
  if (*pe == '\\') {
452
472
  unescape = (char *) "?";
453
473
  unescape_len = 1;
454
- if (pe > p) rb_str_buf_cat(result, p, pe - p);
474
+ if (pe > p) {
475
+ MEMCPY(buffer, p, char, pe - p);
476
+ buffer += pe - p;
477
+ }
455
478
  switch (*++pe) {
456
479
  case 'n':
457
480
  unescape = (char *) "\n";
@@ -476,6 +499,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
476
499
  break;
477
500
  case 'u':
478
501
  if (pe > stringEnd - 4) {
502
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
503
+ free(bufferStart);
504
+ }
479
505
  rb_enc_raise(
480
506
  EXC_ENCODING eParserError,
481
507
  "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
@@ -486,6 +512,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
486
512
  if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
487
513
  pe++;
488
514
  if (pe > stringEnd - 6) {
515
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
516
+ free(bufferStart);
517
+ }
489
518
  rb_enc_raise(
490
519
  EXC_ENCODING eParserError,
491
520
  "%u: incomplete surrogate pair at '%s'", __LINE__, p
@@ -509,13 +538,55 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
509
538
  p = pe;
510
539
  continue;
511
540
  }
512
- rb_str_buf_cat(result, unescape, unescape_len);
541
+ MEMCPY(buffer, unescape, char, unescape_len);
542
+ buffer += unescape_len;
513
543
  p = ++pe;
514
544
  } else {
515
545
  pe++;
516
546
  }
517
547
  }
518
- rb_str_buf_cat(result, p, pe - p);
548
+
549
+ if (pe > p) {
550
+ MEMCPY(buffer, p, char, pe - p);
551
+ buffer += pe - p;
552
+ }
553
+
554
+ # ifdef HAVE_RB_ENC_INTERNED_STR
555
+ if (intern) {
556
+ result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
557
+ } else {
558
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
559
+ }
560
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
561
+ free(bufferStart);
562
+ }
563
+ # else
564
+ result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
565
+
566
+ if (bufferSize > MAX_STACK_BUFFER_SIZE) {
567
+ free(bufferStart);
568
+ }
569
+
570
+ if (intern) {
571
+ # if STR_UMINUS_DEDUPE_FROZEN
572
+ // Starting from MRI 2.8 it is preferable to freeze the string
573
+ // before deduplication so that it can be interned directly
574
+ // otherwise it would be duplicated first which is wasteful.
575
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
576
+ # elif STR_UMINUS_DEDUPE
577
+ // MRI 2.5 and older do not deduplicate strings that are already
578
+ // frozen.
579
+ result = rb_funcall(result, i_uminus, 0);
580
+ # else
581
+ result = rb_str_freeze(result);
582
+ # endif
583
+ }
584
+ # endif
585
+
586
+ if (symbolize) {
587
+ result = rb_str_intern(result);
588
+ }
589
+
519
590
  return result;
520
591
  }
521
592
 
@@ -526,12 +597,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
526
597
  write data;
527
598
 
528
599
  action parse_string {
529
- *result = json_string_unescape(*result, json->memo + 1, p);
600
+ *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
530
601
  if (NIL_P(*result)) {
531
602
  fhold;
532
603
  fbreak;
533
604
  } else {
534
- FORCE_UTF8(*result);
535
605
  fexec p + 1;
536
606
  }
537
607
  }
@@ -558,7 +628,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
558
628
  int cs = EVIL;
559
629
  VALUE match_string;
560
630
 
561
- *result = rb_str_buf_new(0);
562
631
  %% write init;
563
632
  json->memo = p;
564
633
  %% write exec;
@@ -574,26 +643,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
574
643
  }
575
644
  }
576
645
 
577
- if (json->symbolize_names && json->parsing_name) {
578
- *result = rb_str_intern(*result);
579
- } else if (RB_TYPE_P(*result, T_STRING)) {
580
- # if STR_UMINUS_DEDUPE_FROZEN
581
- if (json->freeze) {
582
- // Starting from MRI 2.8 it is preferable to freeze the string
583
- // before deduplication so that it can be interned directly
584
- // otherwise it would be duplicated first which is wasteful.
585
- *result = rb_funcall(rb_str_freeze(*result), i_uminus, 0);
586
- }
587
- # elif STR_UMINUS_DEDUPE
588
- if (json->freeze) {
589
- // MRI 2.5 and older do not deduplicate strings that are already
590
- // frozen.
591
- *result = rb_funcall(*result, i_uminus, 0);
592
- }
593
- # else
594
- rb_str_resize(*result, RSTRING_LEN(*result));
595
- # endif
596
- }
597
646
  if (cs >= JSON_string_first_final) {
598
647
  return p + 1;
599
648
  } else {
@@ -868,6 +917,10 @@ static VALUE cParser_source(VALUE self)
868
917
 
869
918
  void Init_parser(void)
870
919
  {
920
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
921
+ rb_ext_ractor_safe(true);
922
+ #endif
923
+
871
924
  #undef rb_intern
872
925
  rb_require("json/common");
873
926
  mJSON = rb_define_module("JSON");
@@ -910,7 +963,7 @@ void Init_parser(void)
910
963
  i_aref = rb_intern("[]");
911
964
  i_leftshift = rb_intern("<<");
912
965
  i_new = rb_intern("new");
913
- i_BigDecimal = rb_intern("BigDecimal");
966
+ i_try_convert = rb_intern("try_convert");
914
967
  i_freeze = rb_intern("freeze");
915
968
  i_uminus = rb_intern("-@");
916
969
  }
data/json.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "json"
5
- s.version = File.read('VERSION').chomp
5
+ s.version = File.read(File.expand_path('../VERSION', __FILE__)).chomp
6
6
 
7
7
  s.summary = "JSON Implementation for Ruby"
8
8
  s.description = "This is a JSON implementation as a Ruby extension in C."
@@ -12,18 +12,12 @@ Gem::Specification.new do |s|
12
12
 
13
13
  s.extensions = ["ext/json/ext/generator/extconf.rb", "ext/json/ext/parser/extconf.rb", "ext/json/extconf.rb"]
14
14
  s.extra_rdoc_files = ["README.md"]
15
- s.rdoc_options = ["--title", "JSON implemention for Ruby", "--main", "README.md"]
15
+ s.rdoc_options = ["--title", "JSON implementation for Ruby", "--main", "README.md"]
16
16
  s.files = [
17
- ".gitignore",
18
- ".travis.yml",
19
17
  "CHANGES.md",
20
- "Gemfile",
21
18
  "LICENSE",
22
- "README-json-jruby.md",
23
19
  "README.md",
24
- "Rakefile",
25
20
  "VERSION",
26
- "diagrams/.keep",
27
21
  "ext/json/ext/fbuffer/fbuffer.h",
28
22
  "ext/json/ext/generator/depend",
29
23
  "ext/json/ext/generator/extconf.rb",
@@ -35,23 +29,7 @@ Gem::Specification.new do |s|
35
29
  "ext/json/ext/parser/parser.h",
36
30
  "ext/json/ext/parser/parser.rl",
37
31
  "ext/json/extconf.rb",
38
- "install.rb",
39
- "java/src/json/ext/ByteListTranscoder.java",
40
- "java/src/json/ext/Generator.java",
41
- "java/src/json/ext/GeneratorMethods.java",
42
- "java/src/json/ext/GeneratorService.java",
43
- "java/src/json/ext/GeneratorState.java",
44
- "java/src/json/ext/OptionsReader.java",
45
- "java/src/json/ext/Parser.java",
46
- "java/src/json/ext/Parser.rl",
47
- "java/src/json/ext/ParserService.java",
48
- "java/src/json/ext/RuntimeInfo.java",
49
- "java/src/json/ext/StringDecoder.java",
50
- "java/src/json/ext/StringEncoder.java",
51
- "java/src/json/ext/Utils.java",
52
- "json-java.gemspec",
53
32
  "json.gemspec",
54
- "json_pure.gemspec",
55
33
  "lib/json.rb",
56
34
  "lib/json/add/bigdecimal.rb",
57
35
  "lib/json/add/complex.rb",
@@ -69,58 +47,11 @@ Gem::Specification.new do |s|
69
47
  "lib/json/add/time.rb",
70
48
  "lib/json/common.rb",
71
49
  "lib/json/ext.rb",
72
- "lib/json/ext/.keep",
73
50
  "lib/json/generic_object.rb",
74
51
  "lib/json/pure.rb",
75
52
  "lib/json/pure/generator.rb",
76
53
  "lib/json/pure/parser.rb",
77
54
  "lib/json/version.rb",
78
- "references/rfc7159.txt",
79
- "tests/fixtures/fail10.json",
80
- "tests/fixtures/fail11.json",
81
- "tests/fixtures/fail12.json",
82
- "tests/fixtures/fail13.json",
83
- "tests/fixtures/fail14.json",
84
- "tests/fixtures/fail18.json",
85
- "tests/fixtures/fail19.json",
86
- "tests/fixtures/fail2.json",
87
- "tests/fixtures/fail20.json",
88
- "tests/fixtures/fail21.json",
89
- "tests/fixtures/fail22.json",
90
- "tests/fixtures/fail23.json",
91
- "tests/fixtures/fail24.json",
92
- "tests/fixtures/fail25.json",
93
- "tests/fixtures/fail27.json",
94
- "tests/fixtures/fail28.json",
95
- "tests/fixtures/fail3.json",
96
- "tests/fixtures/fail4.json",
97
- "tests/fixtures/fail5.json",
98
- "tests/fixtures/fail6.json",
99
- "tests/fixtures/fail7.json",
100
- "tests/fixtures/fail8.json",
101
- "tests/fixtures/fail9.json",
102
- "tests/fixtures/obsolete_fail1.json",
103
- "tests/fixtures/pass1.json",
104
- "tests/fixtures/pass15.json",
105
- "tests/fixtures/pass16.json",
106
- "tests/fixtures/pass17.json",
107
- "tests/fixtures/pass2.json",
108
- "tests/fixtures/pass26.json",
109
- "tests/fixtures/pass3.json",
110
- "tests/json_addition_test.rb",
111
- "tests/json_common_interface_test.rb",
112
- "tests/json_encoding_test.rb",
113
- "tests/json_ext_parser_test.rb",
114
- "tests/json_fixtures_test.rb",
115
- "tests/json_generator_test.rb",
116
- "tests/json_generic_object_test.rb",
117
- "tests/json_parser_test.rb",
118
- "tests/json_string_matching_test.rb",
119
- "tests/test_helper.rb",
120
- "tests/test_helper.rb",
121
- "tools/diff.sh",
122
- "tools/fuzz.rb",
123
- "tools/server.rb",
124
55
  ]
125
56
  s.homepage = "http://flori.github.com/json"
126
57
  s.metadata = {
@@ -132,9 +63,5 @@ Gem::Specification.new do |s|
132
63
  'wiki_uri' => 'https://github.com/flori/json/wiki'
133
64
  }
134
65
 
135
- s.required_ruby_version = Gem::Requirement.new(">= 2.0")
136
- s.test_files = ["tests/test_helper.rb"]
137
-
138
- s.add_development_dependency("rake", [">= 0"])
139
- s.add_development_dependency("test-unit", [">= 2.0", "< 4.0"])
66
+ s.required_ruby_version = Gem::Requirement.new(">= 2.3")
140
67
  end
data/lib/json/common.rb CHANGED
@@ -71,22 +71,30 @@ module JSON
71
71
  end
72
72
  self.state = generator::State
73
73
  const_set :State, self.state
74
- const_set :SAFE_STATE_PROTOTYPE, State.new
75
- const_set :FAST_STATE_PROTOTYPE, State.new(
74
+ const_set :SAFE_STATE_PROTOTYPE, State.new # for JRuby
75
+ const_set :FAST_STATE_PROTOTYPE, create_fast_state
76
+ const_set :PRETTY_STATE_PROTOTYPE, create_pretty_state
77
+ ensure
78
+ $VERBOSE = old
79
+ end
80
+
81
+ def create_fast_state
82
+ State.new(
76
83
  :indent => '',
77
84
  :space => '',
78
85
  :object_nl => "",
79
86
  :array_nl => "",
80
87
  :max_nesting => false
81
88
  )
82
- const_set :PRETTY_STATE_PROTOTYPE, State.new(
89
+ end
90
+
91
+ def create_pretty_state
92
+ State.new(
83
93
  :indent => ' ',
84
94
  :space => ' ',
85
95
  :object_nl => "\n",
86
96
  :array_nl => "\n"
87
97
  )
88
- ensure
89
- $VERBOSE = old
90
98
  end
91
99
 
92
100
  # Returns the JSON generator module that is used by JSON. This is
@@ -98,13 +106,26 @@ module JSON
98
106
  # either JSON::Ext::Generator::State or JSON::Pure::Generator::State:
99
107
  # JSON.state # => JSON::Ext::Generator::State
100
108
  attr_accessor :state
109
+ end
110
+
111
+ DEFAULT_CREATE_ID = 'json_class'.freeze
112
+ private_constant :DEFAULT_CREATE_ID
113
+
114
+ CREATE_ID_TLS_KEY = "JSON.create_id".freeze
115
+ private_constant :CREATE_ID_TLS_KEY
116
+
117
+ # Sets create identifier, which is used to decide if the _json_create_
118
+ # hook of a class should be called; initial value is +json_class+:
119
+ # JSON.create_id # => 'json_class'
120
+ def self.create_id=(new_value)
121
+ Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze
122
+ end
101
123
 
102
- # Sets or returns create identifier, which is used to decide if the _json_create_
103
- # hook of a class should be called; initial value is +json_class+:
104
- # JSON.create_id # => 'json_class'
105
- attr_accessor :create_id
124
+ # Returns the current create identifier.
125
+ # See also JSON.create_id=.
126
+ def self.create_id
127
+ Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID
106
128
  end
107
- self.create_id = 'json_class'
108
129
 
109
130
  NaN = 0.0/0
110
131
 
@@ -276,7 +297,7 @@ module JSON
276
297
  if State === opts
277
298
  state, opts = opts, nil
278
299
  else
279
- state = SAFE_STATE_PROTOTYPE.dup
300
+ state = State.new
280
301
  end
281
302
  if opts
282
303
  if opts.respond_to? :to_hash
@@ -315,7 +336,7 @@ module JSON
315
336
  if State === opts
316
337
  state, opts = opts, nil
317
338
  else
318
- state = FAST_STATE_PROTOTYPE.dup
339
+ state = JSON.create_fast_state
319
340
  end
320
341
  if opts
321
342
  if opts.respond_to? :to_hash
@@ -370,7 +391,7 @@ module JSON
370
391
  if State === opts
371
392
  state, opts = opts, nil
372
393
  else
373
- state = PRETTY_STATE_PROTOTYPE.dup
394
+ state = JSON.create_pretty_state
374
395
  end
375
396
  if opts
376
397
  if opts.respond_to? :to_hash
@@ -45,7 +45,7 @@ module JSON
45
45
  /(?=\*/) # single slash before this comment's end
46
46
  )*
47
47
  \*/ # the End of this comment
48
- |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
48
+ |[ \t\r\n]+ # whitespaces: space, horizontal tab, lf, cr
49
49
  )+
50
50
  )mx
51
51
 
data/lib/json/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
  module JSON
3
3
  # JSON version
4
- VERSION = '2.3.1'
4
+ VERSION = '2.6.0'
5
5
  VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
6
6
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
7
7
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/lib/json.rb CHANGED
@@ -493,7 +493,7 @@ require 'json/common'
493
493
  # json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]}
494
494
  # ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main">
495
495
  # ruby1.class # Customer
496
- #
496
+ #
497
497
  # \Symbol:
498
498
  # require 'json/add/symbol'
499
499
  # ruby0 = :foo # foo