jsi 0.6.0 → 0.7.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 (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