jsi 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +11 -6
  5. data/jsi.gemspec +30 -0
  6. data/lib/jsi/base/node.rb +183 -0
  7. data/lib/jsi/base.rb +135 -161
  8. data/lib/jsi/jsi_coder.rb +3 -3
  9. data/lib/jsi/metaschema.rb +0 -1
  10. data/lib/jsi/metaschema_node/bootstrap_schema.rb +9 -8
  11. data/lib/jsi/metaschema_node.rb +48 -51
  12. data/lib/jsi/ptr.rb +28 -17
  13. data/lib/jsi/schema/application/child_application/contains.rb +11 -2
  14. data/lib/jsi/schema/application/child_application/items.rb +3 -3
  15. data/lib/jsi/schema/application/child_application/properties.rb +3 -3
  16. data/lib/jsi/schema/application/child_application.rb +1 -3
  17. data/lib/jsi/schema/application/inplace_application/dependencies.rb +1 -1
  18. data/lib/jsi/schema/application/inplace_application/ifthenelse.rb +3 -3
  19. data/lib/jsi/schema/application/inplace_application/ref.rb +1 -1
  20. data/lib/jsi/schema/application/inplace_application/someof.rb +26 -11
  21. data/lib/jsi/schema/application/inplace_application.rb +1 -6
  22. data/lib/jsi/schema/ref.rb +3 -2
  23. data/lib/jsi/schema/schema_ancestor_node.rb +11 -17
  24. data/lib/jsi/schema/validation/array.rb +3 -3
  25. data/lib/jsi/schema/validation/const.rb +1 -1
  26. data/lib/jsi/schema/validation/contains.rb +1 -1
  27. data/lib/jsi/schema/validation/dependencies.rb +1 -1
  28. data/lib/jsi/schema/validation/draft04/minmax.rb +6 -6
  29. data/lib/jsi/schema/validation/enum.rb +1 -1
  30. data/lib/jsi/schema/validation/ifthenelse.rb +5 -5
  31. data/lib/jsi/schema/validation/items.rb +4 -4
  32. data/lib/jsi/schema/validation/not.rb +1 -1
  33. data/lib/jsi/schema/validation/numeric.rb +5 -5
  34. data/lib/jsi/schema/validation/object.rb +2 -2
  35. data/lib/jsi/schema/validation/pattern.rb +1 -1
  36. data/lib/jsi/schema/validation/properties.rb +3 -3
  37. data/lib/jsi/schema/validation/property_names.rb +1 -1
  38. data/lib/jsi/schema/validation/ref.rb +1 -1
  39. data/lib/jsi/schema/validation/required.rb +1 -1
  40. data/lib/jsi/schema/validation/someof.rb +3 -3
  41. data/lib/jsi/schema/validation/string.rb +2 -2
  42. data/lib/jsi/schema/validation/type.rb +1 -1
  43. data/lib/jsi/schema/validation.rb +1 -1
  44. data/lib/jsi/schema.rb +91 -85
  45. data/lib/jsi/schema_classes.rb +70 -45
  46. data/lib/jsi/schema_registry.rb +15 -5
  47. data/lib/jsi/schema_set.rb +42 -2
  48. data/lib/jsi/simple_wrap.rb +23 -4
  49. data/lib/jsi/util/{attr_struct.rb → private/attr_struct.rb} +40 -19
  50. data/lib/jsi/util/private.rb +204 -0
  51. data/lib/jsi/{typelike_modules.rb → util/typelike.rb} +56 -82
  52. data/lib/jsi/util.rb +68 -148
  53. data/lib/jsi/version.rb +1 -1
  54. data/lib/jsi.rb +1 -17
  55. data/lib/schemas/json-schema.org/draft-04/schema.rb +3 -1
  56. data/lib/schemas/json-schema.org/draft-06/schema.rb +3 -1
  57. data/lib/schemas/json-schema.org/draft-07/schema.rb +3 -1
  58. metadata +11 -9
  59. data/lib/jsi/pathed_node.rb +0 -116
data/lib/jsi/util.rb CHANGED
@@ -1,11 +1,72 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSI
4
- # JSI::Util classes, modules, constants, and methods are internal, and will be added and removed without warning.
5
- #
6
- # @api private
4
+ # JSI::Util contains public utilities
7
5
  module Util
8
- autoload :AttrStruct, 'jsi/util/attr_struct'
6
+ autoload :Private, 'jsi/util/private'
7
+
8
+ include Private
9
+
10
+ autoload :Arraylike, 'jsi/util/typelike'
11
+ autoload :Hashlike, 'jsi/util/typelike'
12
+
13
+ # yields the content of the given param `object`. for objects which have a #jsi_modified_copy
14
+ # method of their own (JSI::Base, JSI::MetaschemaNode) that method is invoked with the given
15
+ # block. otherwise the given object itself is yielded.
16
+ #
17
+ # the given block must result in a modified copy of its block parameter
18
+ # (not destructively modifying the yielded content).
19
+ #
20
+ # @yield [Object] the content of the given object. the block should result
21
+ # in a (nondestructively) modified copy of this.
22
+ # @return [object.class] modified copy of the given object
23
+ def modified_copy(object, &block)
24
+ if object.respond_to?(:jsi_modified_copy)
25
+ object.jsi_modified_copy(&block)
26
+ else
27
+ return yield(object)
28
+ end
29
+ end
30
+
31
+ # recursive method to express the given argument object in json-compatible
32
+ # types of Hash, Array, and basic types of String/boolean/numeric/nil. this
33
+ # will raise TypeError if an object is given that is not a type that seems
34
+ # to be expressable as json.
35
+ #
36
+ # similar effect could be achieved by requiring 'json/add/core' and using #as_json,
37
+ # but I don't much care for how it represents classes that are
38
+ # not naturally expressable in JSON, and prefer not to load its
39
+ # monkey-patching.
40
+ #
41
+ # @param object [Object] the object to be converted to jsonifiability
42
+ # @return [Array, Hash, String, Boolean, NilClass, Numeric] jsonifiable
43
+ # expression of param object
44
+ # @raise [TypeError] when the object (or an object nested with a hash or
45
+ # array of object) cannot be expressed as json
46
+ def as_json(object, *opt)
47
+ if object.is_a?(JSI::Base)
48
+ as_json(object.jsi_node_content, *opt)
49
+ elsif object.respond_to?(:to_hash)
50
+ (object.respond_to?(:map) ? object : object.to_hash).map do |k, v|
51
+ unless k.is_a?(Symbol) || k.respond_to?(:to_str)
52
+ raise(TypeError, "json object (hash) cannot be keyed with: #{k.pretty_inspect.chomp}")
53
+ end
54
+ {k.to_s => as_json(v, *opt)}
55
+ end.inject({}, &:update)
56
+ elsif object.respond_to?(:to_ary)
57
+ (object.respond_to?(:map) ? object : object.to_ary).map { |e| as_json(e, *opt) }
58
+ elsif [String, TrueClass, FalseClass, NilClass, Numeric].any? { |c| object.is_a?(c) }
59
+ object
60
+ elsif object.is_a?(Symbol)
61
+ object.to_s
62
+ elsif object.is_a?(Set)
63
+ as_json(object.to_a, *opt)
64
+ elsif object.respond_to?(:as_json)
65
+ as_json(object.as_json(*opt), *opt)
66
+ else
67
+ raise(TypeError, "cannot express object as json: #{object.pretty_inspect.chomp}")
68
+ end
69
+ end
9
70
 
10
71
  # a hash copied from the given hashlike, in which any symbol keys are
11
72
  # converted to strings. behavior on collisions is undefined (but in the
@@ -25,7 +86,7 @@ module JSI
25
86
  unless hashlike.respond_to?(:to_hash)
26
87
  raise(ArgumentError, "expected argument to be a hash; got #{hashlike.class.inspect}: #{hashlike.pretty_inspect.chomp}")
27
88
  end
28
- JSI::Typelike.modified_copy(hashlike) do |hash|
89
+ JSI::Util.modified_copy(hashlike) do |hash|
29
90
  out = {}
30
91
  hash.each do |k, v|
31
92
  out[k.is_a?(Symbol) ? k.to_s : k] = v
@@ -36,7 +97,7 @@ module JSI
36
97
 
37
98
  def deep_stringify_symbol_keys(object)
38
99
  if object.respond_to?(:to_hash)
39
- JSI::Typelike.modified_copy(object) do |hash|
100
+ JSI::Util.modified_copy(object) do |hash|
40
101
  out = {}
41
102
  (hash.respond_to?(:each) ? hash : hash.to_hash).each do |k, v|
42
103
  out[k.is_a?(Symbol) ? k.to_s : deep_stringify_symbol_keys(k)] = deep_stringify_symbol_keys(v)
@@ -44,7 +105,7 @@ module JSI
44
105
  out
45
106
  end
46
107
  elsif object.respond_to?(:to_ary)
47
- JSI::Typelike.modified_copy(object) do |ary|
108
+ JSI::Util.modified_copy(object) do |ary|
48
109
  (ary.respond_to?(:each) ? ary : ary.to_ary).map do |e|
49
110
  deep_stringify_symbol_keys(e)
50
111
  end
@@ -78,147 +139,6 @@ module JSI
78
139
  set
79
140
  end
80
141
 
81
- # is the given name ok to use as a ruby method name?
82
- def ok_ruby_method_name?(name)
83
- # must be a string
84
- return false unless name.respond_to?(:to_str)
85
- # must not begin with a digit
86
- return false if name =~ /\A[0-9]/
87
- # must not contain characters special to ruby syntax
88
- return false if name =~ /[\\\s\#;\.,\(\)\[\]\{\}'"`%\+\-\/\*\^\|&=<>\?:!@\$~]/
89
-
90
- return true
91
- end
92
-
93
- # this is the Y-combinator, which allows anonymous recursive functions. for a simple example,
94
- # to define a recursive function to return the length of an array:
95
- #
96
- # length = ycomb do |len|
97
- # proc { |list| list == [] ? 0 : 1 + len.call(list[1..-1]) }
98
- # end
99
- #
100
- # length.call([0])
101
- # # => 1
102
- #
103
- # see https://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator
104
- # and chapter 9 of the little schemer, available as the sample chapter at
105
- # https://felleisen.org/matthias/BTLS-index.html
106
- def ycomb
107
- proc { |f| f.call(f) }.call(proc { |f| yield proc { |*x| f.call(f).call(*x) } })
108
- end
109
-
110
- module FingerprintHash
111
- # overrides BasicObject#==
112
- def ==(other)
113
- __id__ == other.__id__ || (other.respond_to?(:jsi_fingerprint) && other.jsi_fingerprint == self.jsi_fingerprint)
114
- end
115
-
116
- alias_method :eql?, :==
117
-
118
- # overrides Kernel#hash
119
- def hash
120
- jsi_fingerprint.hash
121
- end
122
- end
123
-
124
- class MemoMap
125
- Result = Util::AttrStruct[*%w(
126
- value
127
- inputs
128
- inputs_hash
129
- )]
130
-
131
- class Result
132
- end
133
-
134
- def initialize(key_by: nil, &block)
135
- @key_by = key_by
136
- @block = block
137
-
138
- # each result has its own mutex to update its memoized value thread-safely
139
- @result_mutexes = {}
140
- # another mutex to thread-safely initialize each result mutex
141
- @result_mutexes_mutex = Mutex.new
142
-
143
- @results = {}
144
- end
145
-
146
- def [](*inputs)
147
- if @key_by
148
- key = @key_by.call(*inputs)
149
- else
150
- key = inputs
151
- end
152
- result_mutex = @result_mutexes_mutex.synchronize do
153
- @result_mutexes[key] ||= Mutex.new
154
- end
155
-
156
- result_mutex.synchronize do
157
- inputs_hash = inputs.hash
158
- if @results.key?(key) && inputs_hash == @results[key].inputs_hash && inputs == @results[key].inputs
159
- @results[key].value
160
- else
161
- value = @block.call(*inputs)
162
- @results[key] = Result.new(value: value, inputs: inputs, inputs_hash: inputs_hash)
163
- value
164
- end
165
- end
166
- end
167
- end
168
-
169
- module Memoize
170
- def self.extended(object)
171
- object.send(:jsi_initialize_memos)
172
- end
173
-
174
- private
175
-
176
- def jsi_initialize_memos
177
- @jsi_memomaps_mutex = Mutex.new
178
- @jsi_memomaps = {}
179
- end
180
-
181
- # @return [Util::MemoMap]
182
- def jsi_memomap(name, **options, &block)
183
- raise(Bug, 'must jsi_initialize_memos') unless @jsi_memomaps
184
- unless @jsi_memomaps.key?(name)
185
- @jsi_memomaps_mutex.synchronize do
186
- # note: this ||= appears redundant with `unless @jsi_memomaps.key?(name)`,
187
- # but that check is not thread safe. this check is.
188
- @jsi_memomaps[name] ||= Util::MemoMap.new(**options, &block)
189
- end
190
- end
191
- @jsi_memomaps[name]
192
- end
193
-
194
- def jsi_memoize(name, *inputs, &block)
195
- jsi_memomap(name, &block)[*inputs]
196
- end
197
- end
198
-
199
- module Virtual
200
- class InstantiationError < StandardError
201
- end
202
-
203
- # this virtual class is not intended to be instantiated except by its subclasses, which override #initialize
204
- def initialize
205
- # :nocov:
206
- raise(InstantiationError, "cannot instantiate virtual class #{self.class}")
207
- # :nocov:
208
- end
209
-
210
- # virtual_method is used to indicate that the method calling it must be implemented on the (non-virtual) subclass
211
- def virtual_method
212
- # :nocov:
213
- raise(Bug, "class #{self.class} must implement #{caller_locations.first.label}")
214
- # :nocov:
215
- end
216
- end
217
-
218
- public
219
-
220
142
  extend self
221
143
  end
222
- public
223
- extend Util
224
144
  end
data/lib/jsi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSI
4
- VERSION = "0.6.0".freeze
4
+ VERSION = "0.7.0".freeze
5
5
  end
data/lib/jsi.rb CHANGED
@@ -9,7 +9,6 @@ require "bigdecimal"
9
9
  require "addressable/uri"
10
10
 
11
11
  require "jsi/util"
12
- require "jsi/typelike_modules"
13
12
 
14
13
  module JSI
15
14
  # generally put in code paths that are not expected to be valid control flow paths.
@@ -30,17 +29,7 @@ module JSI
30
29
  SCHEMAS_PATH = RESOURCES_PATH.join('schemas')
31
30
 
32
31
  autoload :Ptr, 'jsi/ptr'
33
-
34
- # @private
35
- # @deprecated
36
- module JSON
37
- Pointer = Ptr
38
- end
39
-
40
- autoload :PathedNode, 'jsi/pathed_node'
41
- autoload :Typelike, 'jsi/typelike_modules'
42
- autoload :Hashlike, 'jsi/typelike_modules'
43
- autoload :Arraylike, 'jsi/typelike_modules'
32
+ autoload :Typelike, 'jsi/util/typelike'
44
33
  autoload :Schema, 'jsi/schema'
45
34
  autoload :SchemaSet, 'jsi/schema_set'
46
35
  autoload :Base, 'jsi/base'
@@ -77,11 +66,6 @@ module JSI
77
66
  JSI::Schema.new_schema(schema_object, **kw).jsi_schema_module
78
67
  end
79
68
 
80
- # @private @deprecated
81
- def self.class_for_schemas(schemas)
82
- SchemaClasses.class_for_schemas(schemas.map { |schema| JSI.new_schema(schema) })
83
- end
84
-
85
69
  # `JSI.schema_registry` is the {JSI::SchemaRegistry} in which schemas are registered.
86
70
  #
87
71
  # @return [JSI::SchemaRegistry]
@@ -3,10 +3,12 @@
3
3
  module JSI
4
4
  metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-04/schema.json').read)
5
5
  JSONSchemaOrgDraft04 = MetaschemaNode.new(metaschema_document,
6
- metaschema_instance_modules: [JSI::Schema::Draft04],
6
+ schema_implementation_modules: [JSI::Schema::Draft04],
7
7
  ).jsi_schema_module
8
8
 
9
9
  # the JSI schema module for `http://json-schema.org/draft-04/schema`
10
10
  module JSONSchemaOrgDraft04
11
+ # @!parse extend JSI::DescribesSchemaModule
12
+ # @!parse include JSI::Schema::Draft04
11
13
  end
12
14
  end
@@ -3,10 +3,12 @@
3
3
  module JSI
4
4
  metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-06/schema.json').read)
5
5
  JSONSchemaOrgDraft06 = MetaschemaNode.new(metaschema_document,
6
- metaschema_instance_modules: [JSI::Schema::Draft06],
6
+ schema_implementation_modules: [JSI::Schema::Draft06],
7
7
  ).jsi_schema_module
8
8
 
9
9
  # the JSI schema module for `http://json-schema.org/draft-06/schema`
10
10
  module JSONSchemaOrgDraft06
11
+ # @!parse extend JSI::DescribesSchemaModule
12
+ # @!parse include JSI::Schema::Draft06
11
13
  end
12
14
  end
@@ -3,10 +3,12 @@
3
3
  module JSI
4
4
  metaschema_document = ::JSON.parse(SCHEMAS_PATH.join('json-schema.org/draft-07/schema.json').read)
5
5
  JSONSchemaOrgDraft07 = MetaschemaNode.new(metaschema_document,
6
- metaschema_instance_modules: [JSI::Schema::Draft07],
6
+ schema_implementation_modules: [JSI::Schema::Draft07],
7
7
  ).jsi_schema_module
8
8
 
9
9
  # the JSI schema module for `http://json-schema.org/draft-07/schema`
10
10
  module JSONSchemaOrgDraft07
11
+ # @!parse extend JSI::DescribesSchemaModule
12
+ # @!parse include JSI::Schema::Draft07
11
13
  end
12
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-25 00:00:00.000000000 Z
11
+ date: 2023-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -36,13 +36,14 @@ files:
36
36
  - CHANGELOG.md
37
37
  - LICENSE.md
38
38
  - README.md
39
+ - jsi.gemspec
39
40
  - lib/jsi.rb
40
41
  - lib/jsi/base.rb
42
+ - lib/jsi/base/node.rb
41
43
  - lib/jsi/jsi_coder.rb
42
44
  - lib/jsi/metaschema.rb
43
45
  - lib/jsi/metaschema_node.rb
44
46
  - lib/jsi/metaschema_node/bootstrap_schema.rb
45
- - lib/jsi/pathed_node.rb
46
47
  - lib/jsi/ptr.rb
47
48
  - lib/jsi/schema.rb
48
49
  - lib/jsi/schema/application.rb
@@ -98,9 +99,10 @@ files:
98
99
  - lib/jsi/schema_registry.rb
99
100
  - lib/jsi/schema_set.rb
100
101
  - lib/jsi/simple_wrap.rb
101
- - lib/jsi/typelike_modules.rb
102
102
  - lib/jsi/util.rb
103
- - lib/jsi/util/attr_struct.rb
103
+ - lib/jsi/util/private.rb
104
+ - lib/jsi/util/private/attr_struct.rb
105
+ - lib/jsi/util/typelike.rb
104
106
  - lib/jsi/validation.rb
105
107
  - lib/jsi/validation/error.rb
106
108
  - lib/jsi/validation/result.rb
@@ -116,7 +118,7 @@ homepage: https://github.com/notEthan/jsi
116
118
  licenses:
117
119
  - AGPL-3.0
118
120
  metadata: {}
119
- post_install_message:
121
+ post_install_message:
120
122
  rdoc_options: []
121
123
  require_paths:
122
124
  - lib
@@ -131,8 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
133
  - !ruby/object:Gem::Version
132
134
  version: '0'
133
135
  requirements: []
134
- rubygems_version: 3.1.2
135
- signing_key:
136
+ rubygems_version: 3.1.6
137
+ signing_key:
136
138
  specification_version: 4
137
139
  summary: 'JSI: JSON Schema Instantiation'
138
140
  test_files: []
@@ -1,116 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module JSI
4
- # this module represents a node in a document.
5
- #
6
- # including class MUST define
7
- #
8
- # - `#jsi_document` [Object] the document
9
- # - `#jsi_ptr` [JSI::Ptr] a pointer to the node in the document
10
- module PathedNode
11
- # the content of this node
12
- def jsi_node_content
13
- content = jsi_ptr.evaluate(jsi_document)
14
- content
15
- end
16
- end
17
-
18
- # module extending a {JSI::PathedNode} object when its jsi_node_content is Hash-like (responds to #to_hash)
19
- module PathedHashNode
20
- # yields each hash key and value of this node.
21
- #
22
- # each yielded key is the same as a key of the node content hash,
23
- # and each yielded value is the result of self[key] (see #[]).
24
- #
25
- # returns an Enumerator if no block is given.
26
- #
27
- # @param a arguments are passed to `#[]`
28
- # @yield [Object, Object] each key and value of this hash node
29
- # @return [self, Enumerator] an Enumerator if invoked without a block; otherwise self
30
- def each(*a, &block)
31
- return to_enum(__method__) { jsi_node_content_hash_pubsend(:size) } unless block
32
- if block.arity > 1
33
- jsi_node_content_hash_pubsend(:each_key) { |k| yield k, self[k, *a] }
34
- else
35
- jsi_node_content_hash_pubsend(:each_key) { |k| yield [k, self[k, *a]] }
36
- end
37
- self
38
- end
39
-
40
- # a hash in which each key is a key of the jsi_node_content hash and each value is the
41
- # result of `self[key]`
42
- # @param a arguments are passed to `#[]`
43
- # @return [Hash]
44
- def to_hash(*a)
45
- {}.tap { |h| jsi_node_content_hash_pubsend(:each_key) { |k| h[k] = self[k, *a] } }
46
- end
47
-
48
- include Hashlike
49
-
50
- # invokes the method with the given name on the jsi_node_content (if defined) or its #to_hash
51
- # @param method_name [String, Symbol]
52
- # @param a arguments and block are passed to the invocation of method_name
53
- # @return [Object] the result of calling method method_name on the jsi_node_content or its #to_hash
54
- def jsi_node_content_hash_pubsend(method_name, *a, &b)
55
- if jsi_node_content.respond_to?(method_name)
56
- jsi_node_content.public_send(method_name, *a, &b)
57
- else
58
- jsi_node_content.to_hash.public_send(method_name, *a, &b)
59
- end
60
- end
61
-
62
- # methods that don't look at the value; can skip the overhead of #[] (invoked by #to_hash)
63
- SAFE_KEY_ONLY_METHODS.each do |method_name|
64
- define_method(method_name) do |*a, &b|
65
- jsi_node_content_hash_pubsend(method_name, *a, &b)
66
- end
67
- end
68
- end
69
-
70
- module PathedArrayNode
71
- # yields each array element of this node.
72
- #
73
- # each yielded element is the result of self[index] for each index of our array (see #[]).
74
- #
75
- # returns an Enumerator if no block is given.
76
- #
77
- # @param a arguments are passed to `#[]`
78
- # @yield [Object] each element of this array node
79
- # @return [self, Enumerator] an Enumerator if invoked without a block; otherwise self
80
- def each(*a, &block)
81
- return to_enum(__method__) { jsi_node_content_ary_pubsend(:size) } unless block
82
- jsi_node_content_ary_pubsend(:each_index) { |i| yield(self[i, *a]) }
83
- self
84
- end
85
-
86
- # an array, the same size as the jsi_node_content, in which the element at each index is the
87
- # result of `self[index]`
88
- # @param a arguments are passed to `#[]`
89
- # @return [Array]
90
- def to_ary(*a)
91
- to_a(*a)
92
- end
93
-
94
- include Arraylike
95
-
96
- # invokes the method with the given name on the jsi_node_content (if defined) or its #to_ary
97
- # @param method_name [String, Symbol]
98
- # @param a arguments and block are passed to the invocation of method_name
99
- # @return [Object] the result of calling method method_name on the jsi_node_content or its #to_ary
100
- def jsi_node_content_ary_pubsend(method_name, *a, &b)
101
- if jsi_node_content.respond_to?(method_name)
102
- jsi_node_content.public_send(method_name, *a, &b)
103
- else
104
- jsi_node_content.to_ary.public_send(method_name, *a, &b)
105
- end
106
- end
107
-
108
- # methods that don't look at the value; can skip the overhead of #[] (invoked by #to_a).
109
- # we override these methods from Arraylike
110
- SAFE_INDEX_ONLY_METHODS.each do |method_name|
111
- define_method(method_name) do |*a, &b|
112
- jsi_node_content_ary_pubsend(method_name, *a, &b)
113
- end
114
- end
115
- end
116
- end