opal 0.9.0.rc1 → 0.9.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 +6 -0
- data/lib/opal/parser/lexer.rb +1 -1
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +34 -34
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/module.rb +44 -6
- data/opal/corelib/range.rb +30 -0
- data/opal/corelib/regexp.rb +15 -15
- data/opal/corelib/runtime.js +31 -15
- data/opal/corelib/string.rb +13 -4
- data/spec/filters/bugs/language.rb +90 -15
- data/spec/filters/bugs/module.rb +47 -17
- data/spec/filters/bugs/proc.rb +36 -2
- data/spec/filters/bugs/range.rb +6 -6
- data/spec/filters/bugs/unboundmethod.rb +14 -0
- data/spec/lib/parser/string_spec.rb +5 -0
- data/spec/opal/core/language/class_spec.rb +4 -4
- data/spec/opal/stdlib/native/array_spec.rb +11 -0
- data/spec/opal/stdlib/native/hash_spec.rb +8 -0
- data/spec/opal/stdlib/native/struct_spec.rb +12 -0
- data/spec/rubyspecs +4 -15
- data/stdlib/native.rb +3 -13
- data/tasks/testing.rake +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6fe130e39483fb75ec092a749d65571a4bc6ed72
|
4
|
+
data.tar.gz: dd168e47177f8de9d738ada116a3fef82caea16d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a69c71365c06a89859f96ea7447e94d1ace48757680fa6022526c14c58e3700f072d3c123650476630ffc2d6f2725dc56e19869f0067bd0b791d57ca88e9682
|
7
|
+
data.tar.gz: f7d8b51da3dfcb0cd4c1870a5380b311ed0b0a9e1cbbc0666c7295b4951b2895a3d184877fd2119e176ce5141dc2f7966950cd2676cd0357aeb08114c86ddcd9
|
data/CHANGELOG.md
CHANGED
@@ -38,6 +38,8 @@
|
|
38
38
|
* `Enumerable#chunk`
|
39
39
|
* `Enumerable#each_cons`
|
40
40
|
* `Enumerable#minmax`
|
41
|
+
* `Range#to_a`
|
42
|
+
* `Module` comparison methods: `#<` `#<=` `#<=>` `#>` `#>=`
|
41
43
|
|
42
44
|
* Operator methods (e.g. `+`, `<`, etc.) can be handled by `method_missing`
|
43
45
|
|
@@ -77,6 +79,10 @@
|
|
77
79
|
|
78
80
|
* Fixed a number of syntax errors (e.g. #1224 #1225 #1227 #1231 #1233 #1226)
|
79
81
|
|
82
|
+
* Fix `Array#to_n`, `Hash#to_n`, `Struct#to_n` when the object contains native objects (#1249).
|
83
|
+
|
84
|
+
* Internal cleanup and lots of bugs!
|
85
|
+
|
80
86
|
## 0.8.1 2015-10-12
|
81
87
|
|
82
88
|
* Use official Sprockets processor cache keys API:
|
data/lib/opal/parser/lexer.rb
CHANGED
@@ -900,7 +900,7 @@ module Opal
|
|
900
900
|
(@lex_state == :expr_arg && @space_seen) or
|
901
901
|
@lex_state == :expr_mid
|
902
902
|
start_word = scan(/./)
|
903
|
-
end_word = { '(' => ')', '[' => ']', '{' => '}' }[start_word] || start_word
|
903
|
+
end_word = { '(' => ')', '[' => ']', '{' => '}', '<' => '>' }[start_word] || start_word
|
904
904
|
self.strterm = new_strterm2(STR_DQUOTE, end_word, start_word)
|
905
905
|
return :tSTRING_BEG
|
906
906
|
end
|
data/lib/opal/version.rb
CHANGED
data/opal/corelib/array.rb
CHANGED
@@ -1328,20 +1328,20 @@ class Array < `Array`
|
|
1328
1328
|
alias map collect
|
1329
1329
|
|
1330
1330
|
alias map! collect!
|
1331
|
-
|
1331
|
+
|
1332
1332
|
def permutation(num = undefined, &block)
|
1333
1333
|
return enum_for(:permutation, num){self.size} unless block_given?
|
1334
1334
|
|
1335
1335
|
%x{
|
1336
1336
|
var permute, offensive, output;
|
1337
|
-
|
1337
|
+
|
1338
1338
|
if (num === undefined) {
|
1339
1339
|
num = self.length;
|
1340
1340
|
}
|
1341
1341
|
else {
|
1342
1342
|
num = #{ Opal.coerce_to num, Integer, :to_int }
|
1343
1343
|
}
|
1344
|
-
|
1344
|
+
|
1345
1345
|
if (num < 0 || self.length < num) {
|
1346
1346
|
// no permutations, yield nothing
|
1347
1347
|
}
|
@@ -1359,17 +1359,17 @@ class Array < `Array`
|
|
1359
1359
|
// this is the general case
|
1360
1360
|
#{ perm = Array.new(num) }
|
1361
1361
|
#{ used = Array.new(`self.length`, false) }
|
1362
|
-
|
1362
|
+
|
1363
1363
|
permute = function(num, perm, index, used, blk) {
|
1364
1364
|
self = this;
|
1365
1365
|
for(var i = 0; i < self.length; i++){
|
1366
|
-
if(#{ !used[`i`] }) {
|
1366
|
+
if(#{ !used[`i`] }) {
|
1367
1367
|
perm[index] = i;
|
1368
1368
|
if(index < num - 1) {
|
1369
1369
|
used[i] = true;
|
1370
1370
|
permute.call(self, num, perm, index + 1, used, blk);
|
1371
1371
|
used[i] = false;
|
1372
|
-
}
|
1372
|
+
}
|
1373
1373
|
else {
|
1374
1374
|
output = [];
|
1375
1375
|
for (var j = 0; j < perm.length; j++) {
|
@@ -1380,7 +1380,7 @@ class Array < `Array`
|
|
1380
1380
|
}
|
1381
1381
|
}
|
1382
1382
|
}
|
1383
|
-
|
1383
|
+
|
1384
1384
|
if (#{block_given?}) {
|
1385
1385
|
// offensive (both definitions) copy.
|
1386
1386
|
offensive = self.slice();
|
@@ -1394,7 +1394,7 @@ class Array < `Array`
|
|
1394
1394
|
|
1395
1395
|
self
|
1396
1396
|
end
|
1397
|
-
|
1397
|
+
|
1398
1398
|
def pop(count = undefined)
|
1399
1399
|
if `count === undefined`
|
1400
1400
|
return if `self.length === 0`
|
@@ -1586,28 +1586,28 @@ class Array < `Array`
|
|
1586
1586
|
return nil;
|
1587
1587
|
}
|
1588
1588
|
end
|
1589
|
-
|
1589
|
+
|
1590
1590
|
def rotate(n=1)
|
1591
1591
|
n = Opal.coerce_to n, Integer, :to_int
|
1592
1592
|
%x{
|
1593
1593
|
var ary, idx, firstPart, lastPart;
|
1594
|
-
|
1594
|
+
|
1595
1595
|
if (self.length === 1) {
|
1596
1596
|
return self.slice();
|
1597
1597
|
}
|
1598
1598
|
if (self.length === 0) {
|
1599
1599
|
return [];
|
1600
1600
|
}
|
1601
|
-
|
1601
|
+
|
1602
1602
|
ary = self.slice();
|
1603
1603
|
idx = n % ary.length;
|
1604
|
-
|
1604
|
+
|
1605
1605
|
firstPart = ary.slice(idx);
|
1606
1606
|
lastPart = ary.slice(0, idx);
|
1607
1607
|
return firstPart.concat(lastPart);
|
1608
|
-
}
|
1608
|
+
}
|
1609
1609
|
end
|
1610
|
-
|
1610
|
+
|
1611
1611
|
def rotate!(cnt=1)
|
1612
1612
|
%x{
|
1613
1613
|
if (self.length === 0 || self.length === 1) {
|
@@ -1618,7 +1618,7 @@ class Array < `Array`
|
|
1618
1618
|
ary = rotate(cnt)
|
1619
1619
|
replace ary
|
1620
1620
|
end
|
1621
|
-
|
1621
|
+
|
1622
1622
|
class SampleRandom
|
1623
1623
|
def initialize(rng)
|
1624
1624
|
@rng = rng
|
@@ -1635,7 +1635,7 @@ class Array < `Array`
|
|
1635
1635
|
|
1636
1636
|
def sample(count = undefined, options = undefined)
|
1637
1637
|
return at Kernel.rand(`self.length`) if `count === undefined`
|
1638
|
-
|
1638
|
+
|
1639
1639
|
if `options === undefined`
|
1640
1640
|
if (o = Opal.coerce_to? count, Hash, :to_hash)
|
1641
1641
|
options = o
|
@@ -1663,13 +1663,13 @@ class Array < `Array`
|
|
1663
1663
|
return `self[#{rng.rand(`self.length`)}]` unless count
|
1664
1664
|
|
1665
1665
|
%x{
|
1666
|
-
|
1666
|
+
|
1667
1667
|
var abandon, spin, result, i, j, k, targetIndex, oldValue;
|
1668
|
-
|
1669
|
-
if (count > self.length) {
|
1668
|
+
|
1669
|
+
if (count > self.length) {
|
1670
1670
|
count = self.length;
|
1671
1671
|
}
|
1672
|
-
|
1672
|
+
|
1673
1673
|
switch (count) {
|
1674
1674
|
case 0:
|
1675
1675
|
return [];
|
@@ -1689,15 +1689,15 @@ class Array < `Array`
|
|
1689
1689
|
if (self.length / count > 3) {
|
1690
1690
|
abandon = false;
|
1691
1691
|
spin = 0;
|
1692
|
-
|
1692
|
+
|
1693
1693
|
result = #{ Array.new(count) };
|
1694
1694
|
i = 1;
|
1695
|
-
|
1695
|
+
|
1696
1696
|
result[0] = #{rng.rand(`self.length`)};
|
1697
1697
|
while (i < count) {
|
1698
1698
|
k = #{rng.rand(`self.length`)};
|
1699
1699
|
j = 0;
|
1700
|
-
|
1700
|
+
|
1701
1701
|
while (j < i) {
|
1702
1702
|
while (k === result[j]) {
|
1703
1703
|
spin++;
|
@@ -1708,42 +1708,42 @@ class Array < `Array`
|
|
1708
1708
|
k = #{rng.rand(`self.length`)};
|
1709
1709
|
}
|
1710
1710
|
if (abandon) { break; }
|
1711
|
-
|
1711
|
+
|
1712
1712
|
j++;
|
1713
1713
|
}
|
1714
|
-
|
1714
|
+
|
1715
1715
|
if (abandon) { break; }
|
1716
|
-
|
1716
|
+
|
1717
1717
|
result[i] = k;
|
1718
|
-
|
1718
|
+
|
1719
1719
|
i++;
|
1720
1720
|
}
|
1721
|
-
|
1721
|
+
|
1722
1722
|
if (!abandon) {
|
1723
1723
|
i = 0;
|
1724
1724
|
while (i < count) {
|
1725
1725
|
result[i] = self[result[i]];
|
1726
1726
|
i++;
|
1727
1727
|
}
|
1728
|
-
|
1728
|
+
|
1729
1729
|
return result;
|
1730
1730
|
}
|
1731
1731
|
}
|
1732
|
-
|
1732
|
+
|
1733
1733
|
result = self.slice();
|
1734
|
-
|
1734
|
+
|
1735
1735
|
for (var c = 0; c < count; c++) {
|
1736
1736
|
targetIndex = #{rng.rand(`self.length`)};
|
1737
1737
|
oldValue = result[c];
|
1738
1738
|
result[c] = result[targetIndex];
|
1739
1739
|
result[targetIndex] = oldValue;
|
1740
1740
|
}
|
1741
|
-
|
1741
|
+
|
1742
1742
|
return count === self.length ? result : #{`result`[0, count]};
|
1743
1743
|
}
|
1744
1744
|
}
|
1745
1745
|
end
|
1746
|
-
|
1746
|
+
|
1747
1747
|
def select(&block)
|
1748
1748
|
return enum_for(:select){self.size} unless block_given?
|
1749
1749
|
|
@@ -2069,7 +2069,7 @@ class Array < `Array`
|
|
2069
2069
|
if elem.kind_of? Range
|
2070
2070
|
finish = Opal.coerce_to elem.last, Integer, :to_int
|
2071
2071
|
start = Opal.coerce_to elem.first, Integer, :to_int
|
2072
|
-
|
2072
|
+
|
2073
2073
|
%x{
|
2074
2074
|
if (start < 0) {
|
2075
2075
|
start = start + self.length;
|
data/opal/corelib/constants.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
RUBY_PLATFORM = 'opal'
|
2
2
|
RUBY_ENGINE = 'opal'
|
3
3
|
RUBY_VERSION = '2.2.3'
|
4
|
-
RUBY_ENGINE_VERSION = '0.9.0
|
5
|
-
RUBY_RELEASE_DATE = '2015-
|
4
|
+
RUBY_ENGINE_VERSION = '0.9.0'
|
5
|
+
RUBY_RELEASE_DATE = '2015-12-20'
|
6
6
|
RUBY_PATCHLEVEL = 0
|
7
7
|
RUBY_REVISION = 0
|
8
8
|
RUBY_COPYRIGHT = 'opal - Copyright (C) 2013-2015 Adam Beynon'
|
data/opal/corelib/module.rb
CHANGED
@@ -29,28 +29,66 @@ class Module
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def <(other)
|
32
|
+
unless Module === other
|
33
|
+
raise TypeError, "compared with non class/module"
|
34
|
+
end
|
35
|
+
|
32
36
|
# class cannot be a descendant of itself
|
33
37
|
%x{
|
34
|
-
var working = self
|
38
|
+
var working = self,
|
39
|
+
ancestors,
|
40
|
+
i, length;
|
35
41
|
|
36
42
|
if (working === other) {
|
37
43
|
return false;
|
38
44
|
}
|
39
45
|
|
40
|
-
|
41
|
-
if (
|
46
|
+
for (i = 0, ancestors = Opal.ancestors(self), length = ancestors.length; i < length; i++) {
|
47
|
+
if (ancestors[i] === other) {
|
42
48
|
return true;
|
43
49
|
}
|
50
|
+
}
|
44
51
|
|
45
|
-
|
52
|
+
for (i = 0, ancestors = Opal.ancestors(other), length = ancestors.length; i < length; i++) {
|
53
|
+
if (ancestors[i] === self) {
|
54
|
+
return false;
|
55
|
+
}
|
46
56
|
}
|
47
57
|
|
48
|
-
return
|
58
|
+
return nil;
|
49
59
|
}
|
50
60
|
end
|
51
61
|
|
52
62
|
def <=(other)
|
53
|
-
equal?(other)
|
63
|
+
equal?(other) || self < other
|
64
|
+
end
|
65
|
+
|
66
|
+
def >(other)
|
67
|
+
unless Module === other
|
68
|
+
raise TypeError, "compared with non class/module"
|
69
|
+
end
|
70
|
+
|
71
|
+
other < self
|
72
|
+
end
|
73
|
+
|
74
|
+
def >=(other)
|
75
|
+
equal?(other) || self > other
|
76
|
+
end
|
77
|
+
|
78
|
+
def <=>(other)
|
79
|
+
%x{
|
80
|
+
if (self === other) {
|
81
|
+
return 0;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
unless Module === other
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
|
89
|
+
lt = self < other
|
90
|
+
return nil if lt.nil?
|
91
|
+
lt ? -1 : 1
|
54
92
|
end
|
55
93
|
|
56
94
|
def alias_method(newname, oldname)
|
data/opal/corelib/range.rb
CHANGED
@@ -38,6 +38,36 @@ class Range
|
|
38
38
|
def each(&block)
|
39
39
|
return enum_for :each unless block_given?
|
40
40
|
|
41
|
+
%x{
|
42
|
+
var i, limit, value;
|
43
|
+
|
44
|
+
if (#@begin.$$is_number && #@end.$$is_number) {
|
45
|
+
if (#@begin % 1 !== 0 || #@end % 1 !== 0) {
|
46
|
+
#{raise TypeError, "can't iterate from Float"}
|
47
|
+
}
|
48
|
+
|
49
|
+
for (i = #@begin, limit = #@end + #{@exclude ? 0 : 1}; i < limit; i++) {
|
50
|
+
value = block(i);
|
51
|
+
if (value === $breaker) { return $breaker.$v; }
|
52
|
+
}
|
53
|
+
|
54
|
+
return self;
|
55
|
+
}
|
56
|
+
|
57
|
+
if (#@begin.$$is_string && #@end.$$is_string) {
|
58
|
+
value = #{@begin.upto(@end, @exclude, &block)};
|
59
|
+
|
60
|
+
// The following is a bit hackish: we know that
|
61
|
+
// String#upto normally returns self, but may
|
62
|
+
// return a different value if there's a `break`
|
63
|
+
// statement in the supplied block. We need to
|
64
|
+
// propagate this `break` value here, so we
|
65
|
+
// test for equality with `@begin` string to
|
66
|
+
// determine the return value:
|
67
|
+
return value === #@begin ? self : value;
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
41
71
|
current = @begin
|
42
72
|
last = @end
|
43
73
|
|
data/opal/corelib/regexp.rb
CHANGED
@@ -3,16 +3,16 @@ class RegexpError < StandardError; end
|
|
3
3
|
class Regexp < `RegExp`
|
4
4
|
IGNORECASE = 1
|
5
5
|
MULTILINE = 4
|
6
|
-
|
7
|
-
`def.$$is_regexp = true`
|
6
|
+
|
7
|
+
`def.$$is_regexp = true`
|
8
8
|
|
9
9
|
class << self
|
10
10
|
def allocate
|
11
11
|
allocated = super
|
12
12
|
`#{allocated}.uninitialized = true`
|
13
|
-
allocated
|
13
|
+
allocated
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def escape(string)
|
17
17
|
%x{
|
18
18
|
return string.replace(/([-[\]\/{}()*+?.^$\\| ])/g, '\\$1')
|
@@ -55,8 +55,8 @@ class Regexp < `RegExp`
|
|
55
55
|
if (part.$$is_string) {
|
56
56
|
quoted_validated.push(#{escape(`part`)});
|
57
57
|
}
|
58
|
-
else if (part.$$is_regexp) {
|
59
|
-
each_part_options = #{`part`.options};
|
58
|
+
else if (part.$$is_regexp) {
|
59
|
+
each_part_options = #{`part`.options};
|
60
60
|
if (options != undefined && options != each_part_options) {
|
61
61
|
#{raise TypeError, 'All expressions must use the same options'}
|
62
62
|
}
|
@@ -69,10 +69,10 @@ class Regexp < `RegExp`
|
|
69
69
|
}
|
70
70
|
}
|
71
71
|
# Take advantage of logic that can parse options from JS Regex
|
72
|
-
new(`quoted_validated`.join('|'), `options`)
|
72
|
+
new(`quoted_validated`.join('|'), `options`)
|
73
73
|
end
|
74
74
|
|
75
|
-
def new(regexp, options = undefined)
|
75
|
+
def new(regexp, options = undefined)
|
76
76
|
%x{
|
77
77
|
if (regexp.$$is_regexp) {
|
78
78
|
return new RegExp(regexp);
|
@@ -126,7 +126,7 @@ class Regexp < `RegExp`
|
|
126
126
|
if (self.uninitialized) {
|
127
127
|
#{raise TypeError, 'uninitialized Regexp'}
|
128
128
|
}
|
129
|
-
|
129
|
+
|
130
130
|
if (pos === undefined) {
|
131
131
|
pos = 0;
|
132
132
|
} else {
|
@@ -154,7 +154,7 @@ class Regexp < `RegExp`
|
|
154
154
|
flags += 'm';
|
155
155
|
}
|
156
156
|
|
157
|
-
// global RegExp maintains state, so not using self/this
|
157
|
+
// global RegExp maintains state, so not using self/this
|
158
158
|
var md, re = new RegExp(source, flags + (self.ignoreCase ? 'i' : ''));
|
159
159
|
|
160
160
|
while (true) {
|
@@ -178,13 +178,13 @@ class Regexp < `RegExp`
|
|
178
178
|
def source
|
179
179
|
`self.source`
|
180
180
|
end
|
181
|
-
|
181
|
+
|
182
182
|
def options
|
183
183
|
# Flags would be nice to use with this, but still experimental - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags
|
184
184
|
%x{
|
185
185
|
if (self.uninitialized) {
|
186
186
|
#{raise TypeError, 'uninitialized Regexp'}
|
187
|
-
}
|
187
|
+
}
|
188
188
|
var result = 0;
|
189
189
|
// should be supported in IE6 according to https://msdn.microsoft.com/en-us/library/7f5z26w4(v=vs.94).aspx
|
190
190
|
if (self.multiline) {
|
@@ -192,11 +192,11 @@ class Regexp < `RegExp`
|
|
192
192
|
}
|
193
193
|
if (self.ignoreCase) {
|
194
194
|
result |= #{IGNORECASE};
|
195
|
-
}
|
195
|
+
}
|
196
196
|
return result;
|
197
|
-
}
|
197
|
+
}
|
198
198
|
end
|
199
|
-
|
199
|
+
|
200
200
|
def casefold?
|
201
201
|
`self.ignoreCase`
|
202
202
|
end
|