polyfill 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +30 -7
- data/Rakefile +3 -1
- data/lib/polyfill.rb +104 -14
- data/lib/polyfill/v2_2/enumerable.rb +20 -9
- data/lib/polyfill/v2_3/enumerable.rb +8 -24
- data/lib/polyfill/v2_4/array.rb +7 -7
- data/lib/polyfill/v2_4/enumerable.rb +5 -6
- data/lib/polyfill/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce45400dde62a6c4481017080a3770fe3557619e
|
4
|
+
data.tar.gz: 29d853335b679ed69d51df345786021e8919b121
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f9a80ce2cc37783a1060d403317eb5e142c6c1a97a81057fc4123c9c7d8e7fcf6fcbec1f40d130d43ef8ad737df0db2f55c09b62f2a10de674d815d88b01f2d
|
7
|
+
data.tar.gz: e465ec4b46c0ba099cfd5121402e6366eeca20991f6c00d03656127b0cfb6fe36159f5fd87d955655282e0bc076025d69a1622e10357f81996c7e3bd2ec6525b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
# [0.8.0][] (2017-04-27)
|
2
|
+
|
3
|
+
## Changed
|
4
|
+
|
5
|
+
- `Polyfill()` is no longer used with `include` or `extend`. Instead `Polyfill.get` should
|
6
|
+
be used.
|
7
|
+
|
8
|
+
## Added
|
9
|
+
|
10
|
+
- Polyfill.get for getting modules to include or extend
|
11
|
+
- v2.2 Enumerable#slice_when
|
12
|
+
|
13
|
+
## Fixed
|
14
|
+
|
15
|
+
- v2.3 Enumerable#chunk_while and v2.2 Enumerable#slice_after should not require `count`
|
16
|
+
- v2.4 Array#sum should not use `each` (the Enumerable version does)
|
17
|
+
- load modules before classes so they don't override the local method
|
18
|
+
|
1
19
|
# [0.7.0][] (2017-04-22)
|
2
20
|
|
3
21
|
## Changed
|
@@ -123,6 +141,7 @@
|
|
123
141
|
- v2.4 String#concat?
|
124
142
|
- v2.4 String#prepend?
|
125
143
|
|
144
|
+
[0.8.0]: https://github.com/AaronLasseigne/polyfill/compare/v0.7.0...v0.8.0
|
126
145
|
[0.7.0]: https://github.com/AaronLasseigne/polyfill/compare/v0.6.0...v0.7.0
|
127
146
|
[0.6.0]: https://github.com/AaronLasseigne/polyfill/compare/v0.5.0...v0.6.0
|
128
147
|
[0.5.0]: https://github.com/AaronLasseigne/polyfill/compare/v0.4.0...v0.5.0
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ See the [implementation table](#implementation-table) for specifics about what h
|
|
33
33
|
Add it to your Gemfile:
|
34
34
|
|
35
35
|
```ruby
|
36
|
-
gem 'polyfill', '0.
|
36
|
+
gem 'polyfill', '0.8.0'
|
37
37
|
```
|
38
38
|
|
39
39
|
Or install it manually:
|
@@ -52,6 +52,8 @@ This project uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
52
52
|
|
53
53
|
## Usage
|
54
54
|
|
55
|
+
### Polyfill
|
56
|
+
|
55
57
|
With the `Polyfill` method, you can polyfill methods for one or more Ruby
|
56
58
|
objects. Each object is passed as a key. The value is an array of strings
|
57
59
|
containing the methods you would like to polyfill. Instance methods need to
|
@@ -88,15 +90,37 @@ This currently adds support for `respond_to?`, `__send__`, and `send`.
|
|
88
90
|
using Polyfill(native: true, Numeric: :all)
|
89
91
|
```
|
90
92
|
|
93
|
+
### Polyfill.get
|
94
|
+
|
91
95
|
Prior to Ruby 2.4, refinements do not work on Modules. When using a polyfill
|
92
96
|
on a module it will instead refine the core classes that use the module. If
|
93
97
|
you're building your own class, it will not receive the polyfill. Instead,
|
94
|
-
you can
|
98
|
+
you can `include` (or `extend`) in a polyfill with `Polyfill.get`.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
class Foo
|
102
|
+
include Comparable
|
103
|
+
include Polyfill.get(:Comparable, :all)
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
To use specific methods you can pass an array of symbols in place of `:all`.
|
95
108
|
|
96
109
|
```ruby
|
97
110
|
class Foo
|
98
111
|
include Comparable
|
99
|
-
include Polyfill(Comparable
|
112
|
+
include Polyfill.get(:Comparable, %i[clamp])
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
Like before, the polyfills can be halted at a maximum version with the
|
117
|
+
`:version` option. The version must be a string with the major and minor
|
118
|
+
version only.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class Foo
|
122
|
+
include Comparable
|
123
|
+
include Polyfill.get(:Comparable, :all, version: '2.3')
|
100
124
|
end
|
101
125
|
```
|
102
126
|
|
@@ -111,7 +135,7 @@ end
|
|
111
135
|
| | #min | No | This method already existed but was inherited from `Enumerable`. It was optimized on `Array` so redefining `Enumerable#min` no longer affects this.
|
112
136
|
| | #pack | No |
|
113
137
|
| | #sum | Yes |
|
114
|
-
| BasicObject |
|
138
|
+
| BasicObject | #\_\_send\_\_ | No |
|
115
139
|
| Binding | #irb | No |
|
116
140
|
| Comparable | #clamp | Yes |
|
117
141
|
| CSV | #new | No |
|
@@ -297,7 +321,7 @@ end
|
|
297
321
|
| | #min | No |
|
298
322
|
| | #min_by | No |
|
299
323
|
| | #slice_after | Yes |
|
300
|
-
| | #slice_when |
|
324
|
+
| | #slice_when | Yes |
|
301
325
|
| Etc | .confstr | No |
|
302
326
|
| | .sysconf | No |
|
303
327
|
| | .nprocessors | No |
|
@@ -306,9 +330,8 @@ end
|
|
306
330
|
| | #prev_float | No |
|
307
331
|
| File | .birthtime | No |
|
308
332
|
| | #birthtime | No |
|
309
|
-
| | .find | No |
|
310
|
-
| | #find | No |
|
311
333
|
| File::Stat | #birthtime | No |
|
334
|
+
| Find | .find | No |
|
312
335
|
| GC | .latest_gc_info | No |
|
313
336
|
| | .stat | No |
|
314
337
|
| IO | #each_codepoint | No |
|
data/Rakefile
CHANGED
data/lib/polyfill.rb
CHANGED
@@ -5,6 +5,99 @@ require 'polyfill/utils'
|
|
5
5
|
|
6
6
|
module Polyfill
|
7
7
|
module Parcel; end
|
8
|
+
|
9
|
+
def get(module_name, methods, options = {})
|
10
|
+
if Object.const_get(module_name.to_s).is_a?(Class)
|
11
|
+
raise ArgumentError, "#{module_name} is a class not a module"
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# parse options
|
16
|
+
#
|
17
|
+
versions = {
|
18
|
+
'2.2' => Polyfill::V2_2,
|
19
|
+
'2.3' => Polyfill::V2_3,
|
20
|
+
'2.4' => Polyfill::V2_4
|
21
|
+
}
|
22
|
+
desired_version = options.delete(:version) || versions.keys.max
|
23
|
+
unless versions.keys.include?(desired_version)
|
24
|
+
raise ArgumentError, "invalid value for keyword version: #{desired_version}"
|
25
|
+
end
|
26
|
+
versions.reject! do |version_number, _|
|
27
|
+
version_number > desired_version
|
28
|
+
end
|
29
|
+
|
30
|
+
unless options.empty?
|
31
|
+
raise ArgumentError, "unknown keyword: #{options.first[0]}"
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# find all polyfills for the module across all versions
|
36
|
+
#
|
37
|
+
module_names = module_name.to_s.split('::')
|
38
|
+
current_ruby_version = RUBY_VERSION[/\A(\d+\.\d+)/, 1]
|
39
|
+
|
40
|
+
modules_with_updates = []
|
41
|
+
modules = []
|
42
|
+
versions.each do |version_number, version_module|
|
43
|
+
begin
|
44
|
+
final_module = module_names
|
45
|
+
.reduce(version_module) do |current_mod, name|
|
46
|
+
current_mod.const_get(name, false)
|
47
|
+
end
|
48
|
+
|
49
|
+
modules_with_updates << final_module
|
50
|
+
|
51
|
+
next if version_number <= current_ruby_version
|
52
|
+
|
53
|
+
modules << final_module.clone
|
54
|
+
rescue NameError
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if modules_with_updates.empty?
|
60
|
+
raise ArgumentError, %Q("#{module_name}" has no updates)
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# remove methods that were not requested
|
65
|
+
#
|
66
|
+
methods_with_updates = modules_with_updates.flat_map(&:instance_methods).uniq
|
67
|
+
requested_methods = methods == :all ? methods_with_updates : methods
|
68
|
+
|
69
|
+
unless (leftovers = (requested_methods - methods_with_updates)).empty?
|
70
|
+
raise ArgumentError, %Q("##{leftovers.first}" is not a valid method on #{module_name} or has no updates)
|
71
|
+
end
|
72
|
+
|
73
|
+
modules.each do |instance_module|
|
74
|
+
instance_module.instance_methods.each do |name|
|
75
|
+
instance_module.send(:remove_method, name) unless requested_methods.include?(name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# build the module to return
|
81
|
+
#
|
82
|
+
mod = Module.new
|
83
|
+
|
84
|
+
# make sure the methods get added if this module is included
|
85
|
+
mod.singleton_class.send(:define_method, :included) do |base|
|
86
|
+
modules.each do |module_to_add|
|
87
|
+
base.include module_to_add unless module_to_add.instance_methods.empty?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# make sure the methods get added if this module is extended
|
92
|
+
mod.singleton_class.send(:define_method, :extended) do |base|
|
93
|
+
modules.each do |module_to_add|
|
94
|
+
base.extend module_to_add unless module_to_add.instance_methods.empty?
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
Polyfill::Parcel.const_set("O#{mod.object_id}", mod)
|
99
|
+
end
|
100
|
+
module_function :get
|
8
101
|
end
|
9
102
|
|
10
103
|
def Polyfill(options = {}) # rubocop:disable Style/MethodName
|
@@ -14,6 +107,15 @@ def Polyfill(options = {}) # rubocop:disable Style/MethodName
|
|
14
107
|
# parse options
|
15
108
|
#
|
16
109
|
objects, others = options.partition { |key,| key[/\A[A-Z]/] }
|
110
|
+
objects.sort! do |a, b|
|
111
|
+
if !a.is_a?(Class) && b.is_a?(Class)
|
112
|
+
-1
|
113
|
+
elsif a.is_a?(Class) && !b.is_a?(Class)
|
114
|
+
1
|
115
|
+
else
|
116
|
+
0
|
117
|
+
end
|
118
|
+
end
|
17
119
|
others = others.to_h
|
18
120
|
|
19
121
|
versions = {
|
@@ -36,10 +138,9 @@ def Polyfill(options = {}) # rubocop:disable Style/MethodName
|
|
36
138
|
end
|
37
139
|
|
38
140
|
#
|
39
|
-
# useful
|
141
|
+
# useful var
|
40
142
|
#
|
41
143
|
current_ruby_version = RUBY_VERSION[/\A(\d+\.\d+)/, 1]
|
42
|
-
all_instance_modules = []
|
43
144
|
|
44
145
|
objects.each do |full_name, methods|
|
45
146
|
#
|
@@ -63,7 +164,7 @@ def Polyfill(options = {}) # rubocop:disable Style/MethodName
|
|
63
164
|
.compact
|
64
165
|
|
65
166
|
if object_modules.empty?
|
66
|
-
raise ArgumentError, %Q("#{full_name}" is not a valid
|
167
|
+
raise ArgumentError, %Q("#{full_name}" is not a valid object or has no updates)
|
67
168
|
end
|
68
169
|
|
69
170
|
#
|
@@ -172,8 +273,6 @@ def Polyfill(options = {}) # rubocop:disable Style/MethodName
|
|
172
273
|
|
173
274
|
next if instance_module.instance_methods.empty?
|
174
275
|
|
175
|
-
all_instance_modules << instance_module
|
176
|
-
|
177
276
|
mod.module_exec(requested_instance_methods) do |methods_added|
|
178
277
|
base_classes.each do |klass|
|
179
278
|
refine Object.const_get(klass) do
|
@@ -201,15 +300,6 @@ def Polyfill(options = {}) # rubocop:disable Style/MethodName
|
|
201
300
|
end
|
202
301
|
end
|
203
302
|
|
204
|
-
#
|
205
|
-
# make sure the includes get added if this module is included
|
206
|
-
#
|
207
|
-
mod.singleton_class.send(:define_method, :included) do |base|
|
208
|
-
all_instance_modules.each do |instance_module|
|
209
|
-
base.include instance_module
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
303
|
Polyfill::Parcel.const_set("O#{mod.object_id}", mod)
|
214
304
|
end
|
215
305
|
|
@@ -6,27 +6,38 @@ module Polyfill
|
|
6
6
|
raise ArgumentError, 'wrong number of arguments (given 0, expected 1)' if !pattern && !block_given?
|
7
7
|
|
8
8
|
matcher = pattern || ::Proc.new
|
9
|
-
enum_count =
|
10
|
-
begin
|
11
|
-
size
|
12
|
-
rescue NameError
|
13
|
-
count
|
14
|
-
end
|
15
9
|
|
16
10
|
::Enumerator.new do |yielder|
|
17
11
|
output = []
|
18
|
-
run = 1
|
19
12
|
each do |element, *rest|
|
20
13
|
elements = rest.any? ? [element, *rest] : element
|
21
14
|
|
22
15
|
output.push(elements)
|
23
|
-
if matcher ===
|
16
|
+
if matcher === output.last # rubocop:disable Style/CaseEquality
|
24
17
|
yielder << output
|
25
18
|
output = []
|
26
19
|
end
|
20
|
+
end
|
21
|
+
yielder << output unless output.empty?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def slice_when
|
26
|
+
block = ::Proc.new
|
27
|
+
|
28
|
+
::Enumerator.new do |yielder|
|
29
|
+
output = []
|
30
|
+
each do |element, *rest|
|
31
|
+
elements = rest.any? ? [element, *rest] : element
|
27
32
|
|
28
|
-
|
33
|
+
if output.empty? || !block.call(output.last, elements)
|
34
|
+
output.push(elements)
|
35
|
+
else
|
36
|
+
yielder << output
|
37
|
+
output = [elements]
|
38
|
+
end
|
29
39
|
end
|
40
|
+
yielder << output unless output.empty?
|
30
41
|
end
|
31
42
|
end
|
32
43
|
end
|
@@ -4,35 +4,19 @@ module Polyfill
|
|
4
4
|
def chunk_while
|
5
5
|
block = ::Proc.new
|
6
6
|
|
7
|
-
enum_count =
|
8
|
-
begin
|
9
|
-
size
|
10
|
-
rescue NameError
|
11
|
-
count
|
12
|
-
end
|
13
|
-
|
14
|
-
return [self] if enum_count == 1
|
15
|
-
|
16
7
|
::Enumerator.new do |yielder|
|
17
8
|
output = []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
else
|
24
|
-
output.push(a)
|
25
|
-
yielder << output
|
26
|
-
yielder << [b]
|
27
|
-
end
|
9
|
+
each do |element, *rest|
|
10
|
+
elements = rest.any? ? [element, *rest] : element
|
11
|
+
|
12
|
+
if output.empty? || block.call(output.last, elements)
|
13
|
+
output.push(elements)
|
28
14
|
else
|
29
|
-
output
|
30
|
-
|
31
|
-
yielder << output
|
32
|
-
output = []
|
33
|
-
end
|
15
|
+
yielder << output
|
16
|
+
output = [elements]
|
34
17
|
end
|
35
18
|
end
|
19
|
+
yielder << output unless output.empty?
|
36
20
|
end
|
37
21
|
end
|
38
22
|
|
data/lib/polyfill/v2_4/array.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
require_relative 'numeric'
|
2
|
+
|
1
3
|
module Polyfill
|
2
4
|
module V2_4
|
3
5
|
module Array
|
6
|
+
using Polyfill(Numeric: %w[#dup])
|
7
|
+
|
4
8
|
def concat(*others)
|
5
9
|
return super if others.length == 1
|
6
10
|
|
@@ -13,14 +17,10 @@ module Polyfill
|
|
13
17
|
end
|
14
18
|
|
15
19
|
def sum(init = 0)
|
16
|
-
acc =
|
17
|
-
begin
|
18
|
-
init.dup
|
19
|
-
rescue TypeError
|
20
|
-
init
|
21
|
-
end
|
20
|
+
acc = init.dup
|
22
21
|
|
23
|
-
|
22
|
+
for i in 0..(size - 1) # rubocop:disable Style/For
|
23
|
+
elem = self[i]
|
24
24
|
acc += block_given? ? yield(elem) : elem
|
25
25
|
end
|
26
26
|
|
@@ -1,6 +1,10 @@
|
|
1
|
+
require_relative 'numeric'
|
2
|
+
|
1
3
|
module Polyfill
|
2
4
|
module V2_4
|
3
5
|
module Enumerable
|
6
|
+
using Polyfill(Numeric: %w[#dup])
|
7
|
+
|
4
8
|
def chunk(*)
|
5
9
|
return enum_for(:chunk) unless block_given?
|
6
10
|
|
@@ -8,12 +12,7 @@ module Polyfill
|
|
8
12
|
end
|
9
13
|
|
10
14
|
def sum(init = 0)
|
11
|
-
acc =
|
12
|
-
begin
|
13
|
-
init.dup
|
14
|
-
rescue TypeError
|
15
|
-
init
|
16
|
-
end
|
15
|
+
acc = init.dup
|
17
16
|
|
18
17
|
each do |elem|
|
19
18
|
acc += block_given? ? yield(elem) : elem
|
data/lib/polyfill/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polyfill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Lasseigne
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|