opal 0.5.2 → 0.5.4
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/README.md +2 -0
- data/lib/opal.rb +0 -5
- data/lib/opal/compiler.rb +24 -44
- data/lib/opal/nodes/base.rb +5 -8
- data/lib/opal/nodes/call.rb +4 -0
- data/lib/opal/nodes/class.rb +6 -7
- data/lib/opal/nodes/def.rb +4 -4
- data/lib/opal/nodes/definitions.rb +0 -14
- data/lib/opal/nodes/iter.rb +51 -38
- data/lib/opal/nodes/literal.rb +21 -24
- data/lib/opal/nodes/module.rb +4 -4
- data/lib/opal/nodes/runtime_helpers.rb +45 -0
- data/lib/opal/nodes/scope.rb +280 -0
- data/lib/opal/nodes/singleton_class.rb +4 -5
- data/lib/opal/nodes/super.rb +1 -1
- data/lib/opal/nodes/top.rb +9 -7
- data/lib/opal/nodes/yield.rb +14 -3
- data/lib/opal/parser.rb +4 -18
- data/lib/opal/parser/grammar.rb +3745 -3667
- data/lib/opal/parser/grammar.y +1692 -1778
- data/lib/opal/parser/keywords.rb +35 -35
- data/lib/opal/parser/lexer.rb +356 -325
- data/lib/opal/parser/sexp.rb +1 -1
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +1 -0
- data/opal/core/array.rb +320 -81
- data/opal/core/enumerable.rb +46 -5
- data/opal/core/hash.rb +6 -64
- data/opal/core/helpers.rb +67 -0
- data/opal/core/method.rb +1 -1
- data/opal/core/module.rb +4 -4
- data/opal/core/range.rb +1 -12
- data/opal/core/regexp.rb +2 -8
- data/opal/core/runtime.js +74 -3
- data/opal/core/string.rb +99 -74
- data/opal/opal.rb +3 -72
- data/spec/filters/bugs/array.rb +2 -30
- data/spec/filters/bugs/basic_object.rb +0 -1
- data/spec/filters/bugs/string.rb +26 -21
- data/spec/filters/unsupported/enumerator.rb +3 -0
- data/spec/filters/unsupported/float.rb +1 -0
- data/spec/filters/unsupported/immutable_strings.rb +15 -0
- data/spec/filters/unsupported/tainted.rb +58 -30
- data/spec/filters/unsupported/trusted.rb +35 -15
- data/spec/opal/parser/class_spec.rb +4 -4
- data/spec/opal/parser/def_spec.rb +4 -4
- data/spec/opal/parser/lvar_spec.rb +6 -6
- data/spec/opal/parser/module_spec.rb +4 -4
- data/spec/opal/parser/sclass_spec.rb +2 -2
- data/spec/stdlib/native/exposure_spec.rb +33 -0
- data/stdlib/buffer.rb +1 -1
- data/stdlib/buffer/view.rb +1 -1
- data/stdlib/native.rb +193 -174
- data/stdlib/opal-parser.rb +0 -6
- data/stdlib/pp.rb +9 -0
- data/tasks/mspec.rake +3 -1
- metadata +9 -9
- data/lib/opal/nodes/base_scope.rb +0 -11
- data/lib/opal/target_scope.rb +0 -281
- data/spec/filters/20.rb +0 -4
- data/spec/filters/unsupported/array_subclasses.rb +0 -37
data/opal/core/string.rb
CHANGED
@@ -2,7 +2,6 @@ class String
|
|
2
2
|
include Comparable
|
3
3
|
|
4
4
|
`def._isString = true`
|
5
|
-
`var native_string = "".constructor;`
|
6
5
|
|
7
6
|
def self.try_convert(what)
|
8
7
|
what.to_str
|
@@ -11,7 +10,7 @@ class String
|
|
11
10
|
end
|
12
11
|
|
13
12
|
def self.new(str = '')
|
14
|
-
`new
|
13
|
+
`new String(str)`
|
15
14
|
end
|
16
15
|
|
17
16
|
def %(data)
|
@@ -45,30 +44,27 @@ class String
|
|
45
44
|
end
|
46
45
|
|
47
46
|
def +(other)
|
48
|
-
|
49
|
-
if (other._isString) {
|
50
|
-
return self + other;
|
51
|
-
}
|
52
|
-
}
|
47
|
+
other = Opal.coerce_to other, String, :to_str
|
53
48
|
|
54
|
-
|
55
|
-
raise TypeError, "no implicit conversion of #{other.class.name} into String"
|
56
|
-
end
|
57
|
-
|
58
|
-
`self + #{other.to_str}`
|
49
|
+
`self + #{other.to_s}`
|
59
50
|
end
|
60
51
|
|
61
52
|
def <=>(other)
|
62
|
-
%x{
|
63
|
-
if (other._isString) {
|
64
|
-
return self > other ? 1 : (self < other ? -1 : 0);
|
65
|
-
}
|
66
|
-
}
|
67
|
-
|
68
53
|
if other.respond_to? :to_str
|
69
|
-
other = other.to_str
|
54
|
+
other = other.to_str.to_s
|
70
55
|
|
71
56
|
`self > other ? 1 : (self < other ? -1 : 0)`
|
57
|
+
else
|
58
|
+
%x{
|
59
|
+
var cmp = #{other <=> self};
|
60
|
+
|
61
|
+
if (cmp === nil) {
|
62
|
+
return nil;
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
return cmp > 0 ? -1 : (cmp < 0 ? 1 : 0);
|
66
|
+
}
|
67
|
+
}
|
72
68
|
end
|
73
69
|
end
|
74
70
|
|
@@ -147,27 +143,26 @@ class String
|
|
147
143
|
end
|
148
144
|
|
149
145
|
def casecmp(other)
|
150
|
-
|
151
|
-
if (other._isString) {
|
152
|
-
return #{`self.toLowerCase()` <=> `other.toLowerCase()`};
|
153
|
-
}
|
154
|
-
}
|
155
|
-
|
156
|
-
unless other.respond_to? :to_str
|
157
|
-
raise TypeError, "no implicit conversion of #{other.class.name} into String"
|
158
|
-
end
|
146
|
+
other = Opal.coerce_to(other, String, :to_str).to_s
|
159
147
|
|
160
|
-
`self.toLowerCase()` <=>
|
148
|
+
`self.toLowerCase()` <=> `other.toLowerCase()`
|
161
149
|
end
|
162
150
|
|
163
151
|
def center(width, padstr = ' ')
|
164
|
-
|
152
|
+
width = Opal.coerce_to(width, Integer, :to_int)
|
153
|
+
padstr = Opal.coerce_to(padstr, String, :to_str).to_s
|
154
|
+
|
155
|
+
if padstr.empty?
|
156
|
+
raise ArgumentError, 'zero width padding'
|
157
|
+
end
|
158
|
+
|
159
|
+
return self if `width <= self.length`
|
165
160
|
|
166
161
|
%x{
|
167
|
-
var ljustified = #{ljust ((width + @length) / 2).
|
168
|
-
rjustified = #{rjust ((width + @length) / 2).
|
162
|
+
var ljustified = #{ljust ((width + @length) / 2).ceil, padstr},
|
163
|
+
rjustified = #{rjust ((width + @length) / 2).floor, padstr};
|
169
164
|
|
170
|
-
return
|
165
|
+
return rjustified + ljustified.slice(self.length);
|
171
166
|
}
|
172
167
|
end
|
173
168
|
|
@@ -178,13 +173,7 @@ class String
|
|
178
173
|
def chomp(separator = $/)
|
179
174
|
return self if `separator === nil || self.length === 0`
|
180
175
|
|
181
|
-
|
182
|
-
unless separator.respond_to? :to_str
|
183
|
-
raise TypeError, "no implicit conversion of #{separator.class.name} into String"
|
184
|
-
end
|
185
|
-
|
186
|
-
separator = separator.to_str
|
187
|
-
end
|
176
|
+
separator = Opal.coerce_to!(separator, String, :to_str).to_s
|
188
177
|
|
189
178
|
%x{
|
190
179
|
if (separator === "\\n") {
|
@@ -206,7 +195,20 @@ class String
|
|
206
195
|
end
|
207
196
|
|
208
197
|
def chop
|
209
|
-
|
198
|
+
%x{
|
199
|
+
var length = self.length;
|
200
|
+
|
201
|
+
if (length <= 1) {
|
202
|
+
return "";
|
203
|
+
}
|
204
|
+
|
205
|
+
if (self.charAt(length - 1) === "\\n" && self.charAt(length - 2) === "\\r") {
|
206
|
+
return self.substr(0, length - 2);
|
207
|
+
}
|
208
|
+
else {
|
209
|
+
return self.substr(0, length - 1);
|
210
|
+
}
|
211
|
+
}
|
210
212
|
end
|
211
213
|
|
212
214
|
def chr
|
@@ -323,44 +325,53 @@ class String
|
|
323
325
|
end
|
324
326
|
|
325
327
|
def index(what, offset = nil)
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
328
|
+
if String === what
|
329
|
+
what = what.to_s
|
330
|
+
elsif what.respond_to? :to_str
|
331
|
+
what = what.to_str.to_s
|
332
|
+
elsif not Regexp === what
|
333
|
+
raise TypeError, "type mismatch: #{what.class} given"
|
334
|
+
end
|
330
335
|
|
331
|
-
|
336
|
+
result = -1
|
337
|
+
|
338
|
+
if offset
|
339
|
+
offset = Opal.coerce_to offset, Integer, :to_int
|
340
|
+
|
341
|
+
%x{
|
342
|
+
var size = self.length;
|
332
343
|
|
333
|
-
if (offset !== nil) {
|
334
344
|
if (offset < 0) {
|
335
|
-
offset = offset +
|
345
|
+
offset = offset + size;
|
336
346
|
}
|
337
347
|
|
338
|
-
if (offset >
|
348
|
+
if (offset > size) {
|
339
349
|
return nil;
|
340
350
|
}
|
351
|
+
}
|
341
352
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
}
|
353
|
+
if Regexp === what
|
354
|
+
result = (what =~ `self.substr(offset)`) || -1
|
355
|
+
else
|
356
|
+
result = `self.substr(offset).indexOf(what)`
|
357
|
+
end
|
348
358
|
|
359
|
+
%x{
|
349
360
|
if (result !== -1) {
|
350
361
|
result += offset;
|
351
362
|
}
|
352
363
|
}
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
}
|
364
|
+
else
|
365
|
+
if Regexp === what
|
366
|
+
result = (what =~ self) || -1
|
367
|
+
else
|
368
|
+
result = `self.indexOf(what)`
|
369
|
+
end
|
370
|
+
end
|
361
371
|
|
362
|
-
|
363
|
-
|
372
|
+
unless `result === -1`
|
373
|
+
result
|
374
|
+
end
|
364
375
|
end
|
365
376
|
|
366
377
|
def inspect
|
@@ -400,6 +411,13 @@ class String
|
|
400
411
|
end
|
401
412
|
|
402
413
|
def ljust(width, padstr = ' ')
|
414
|
+
width = Opal.coerce_to(width, Integer, :to_int)
|
415
|
+
padstr = Opal.coerce_to(padstr, String, :to_str).to_s
|
416
|
+
|
417
|
+
if padstr.empty?
|
418
|
+
raise ArgumentError, 'zero width padding'
|
419
|
+
end
|
420
|
+
|
403
421
|
return self if `width <= self.length`
|
404
422
|
|
405
423
|
%x{
|
@@ -439,7 +457,7 @@ class String
|
|
439
457
|
}
|
440
458
|
|
441
459
|
var initial = #{self}.substr(0, #{self}.length - 1);
|
442
|
-
var last =
|
460
|
+
var last = String.fromCharCode(#{self}.charCodeAt(#{self}.length - 1) + 1);
|
443
461
|
|
444
462
|
return initial + last;
|
445
463
|
}
|
@@ -466,7 +484,7 @@ class String
|
|
466
484
|
def rindex(search, offset = undefined)
|
467
485
|
%x{
|
468
486
|
var search_type = (search == null ? Opal.NilClass : search.constructor);
|
469
|
-
if (search_type !=
|
487
|
+
if (search_type != String && search_type != RegExp) {
|
470
488
|
var msg = "type mismatch: " + search_type + " given";
|
471
489
|
#{raise TypeError.new(`msg`)};
|
472
490
|
}
|
@@ -481,7 +499,7 @@ class String
|
|
481
499
|
offset = #{self}.length + offset;
|
482
500
|
}
|
483
501
|
|
484
|
-
if (search_type ==
|
502
|
+
if (search_type == String) {
|
485
503
|
result = #{self}.lastIndexOf(search, offset);
|
486
504
|
}
|
487
505
|
else {
|
@@ -492,7 +510,7 @@ class String
|
|
492
510
|
}
|
493
511
|
}
|
494
512
|
else {
|
495
|
-
if (search_type ==
|
513
|
+
if (search_type == String) {
|
496
514
|
result = #{self}.lastIndexOf(search);
|
497
515
|
}
|
498
516
|
else {
|
@@ -508,6 +526,13 @@ class String
|
|
508
526
|
end
|
509
527
|
|
510
528
|
def rjust(width, padstr = ' ')
|
529
|
+
width = Opal.coerce_to(width, Integer, :to_int)
|
530
|
+
padstr = Opal.coerce_to(padstr, String, :to_str).to_s
|
531
|
+
|
532
|
+
if padstr.empty?
|
533
|
+
raise ArgumentError, 'zero width padding'
|
534
|
+
end
|
535
|
+
|
511
536
|
return self if `width <= self.length`
|
512
537
|
|
513
538
|
%x{
|
@@ -658,7 +683,7 @@ class String
|
|
658
683
|
return $1 ? $0.toUpperCase() : $0.toLowerCase();
|
659
684
|
});
|
660
685
|
|
661
|
-
if (#{self}.constructor ===
|
686
|
+
if (#{self}.constructor === String) {
|
662
687
|
return str;
|
663
688
|
}
|
664
689
|
|
@@ -761,7 +786,7 @@ class String
|
|
761
786
|
var start = last_from.charCodeAt(0) + 1;
|
762
787
|
var end = char.charCodeAt(0);
|
763
788
|
for (var c = start; c < end; c++) {
|
764
|
-
from_chars_expanded.push(
|
789
|
+
from_chars_expanded.push(String.fromCharCode(c));
|
765
790
|
}
|
766
791
|
from_chars_expanded.push(char);
|
767
792
|
in_range = null;
|
@@ -807,7 +832,7 @@ class String
|
|
807
832
|
var start = last_from.charCodeAt(0) + 1;
|
808
833
|
var end = char.charCodeAt(0);
|
809
834
|
for (var c = start; c < end; c++) {
|
810
|
-
to_chars_expanded.push(
|
835
|
+
to_chars_expanded.push(String.fromCharCode(c));
|
811
836
|
}
|
812
837
|
to_chars_expanded.push(char);
|
813
838
|
in_range = null;
|
@@ -896,7 +921,7 @@ class String
|
|
896
921
|
var start = last_from.charCodeAt(0) + 1;
|
897
922
|
var end = char.charCodeAt(0);
|
898
923
|
for (var c = start; c < end; c++) {
|
899
|
-
from_chars_expanded.push(
|
924
|
+
from_chars_expanded.push(String.fromCharCode(c));
|
900
925
|
}
|
901
926
|
from_chars_expanded.push(char);
|
902
927
|
in_range = null;
|
@@ -942,7 +967,7 @@ class String
|
|
942
967
|
var start = last_from.charCodeAt(0) + 1;
|
943
968
|
var end = char.charCodeAt(0);
|
944
969
|
for (var c = start; c < end; c++) {
|
945
|
-
to_chars_expanded.push(
|
970
|
+
to_chars_expanded.push(String.fromCharCode(c));
|
946
971
|
}
|
947
972
|
to_chars_expanded.push(char);
|
948
973
|
in_range = null;
|
data/opal/opal.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'core/runtime'
|
2
|
+
require 'core/helpers'
|
2
3
|
require 'core/module'
|
3
4
|
require 'core/class'
|
4
5
|
require 'core/basic_object'
|
@@ -47,75 +48,5 @@ $SAFE = 0
|
|
47
48
|
RUBY_PLATFORM = 'opal'
|
48
49
|
RUBY_ENGINE = 'opal'
|
49
50
|
RUBY_VERSION = '1.9.3'
|
50
|
-
RUBY_ENGINE_VERSION = '0.5.
|
51
|
-
RUBY_RELEASE_DATE = '2013-11-
|
52
|
-
|
53
|
-
module Opal
|
54
|
-
def self.coerce_to(object, type, method)
|
55
|
-
return object if type === object
|
56
|
-
|
57
|
-
unless object.respond_to? method
|
58
|
-
raise TypeError, "no implicit conversion of #{object.class} into #{type}"
|
59
|
-
end
|
60
|
-
|
61
|
-
object.__send__ method
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.coerce_to!(object, type, method)
|
65
|
-
coerced = coerce_to(object, type, method)
|
66
|
-
|
67
|
-
unless type === coerced
|
68
|
-
raise TypeError, "can't convert #{object.class} into #{type} (#{object.class}##{method} gives #{coerced.class}"
|
69
|
-
end
|
70
|
-
|
71
|
-
coerced
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.try_convert(object, type, method)
|
75
|
-
return object if type === object
|
76
|
-
|
77
|
-
if object.respond_to? method
|
78
|
-
object.__send__ method
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def self.compare(a, b)
|
83
|
-
compare = a <=> b
|
84
|
-
|
85
|
-
if `compare === nil`
|
86
|
-
raise ArgumentError, "comparison of #{a.class.name} with #{b.class.name} failed"
|
87
|
-
end
|
88
|
-
|
89
|
-
compare
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.truthy?(value)
|
93
|
-
if value
|
94
|
-
true
|
95
|
-
else
|
96
|
-
false
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def self.falsy?(value)
|
101
|
-
if value
|
102
|
-
false
|
103
|
-
else
|
104
|
-
true
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def self.destructure(args)
|
109
|
-
%x{
|
110
|
-
if (args.length == 1) {
|
111
|
-
return args[0];
|
112
|
-
}
|
113
|
-
else if (args._isArray) {
|
114
|
-
return args;
|
115
|
-
}
|
116
|
-
else {
|
117
|
-
return $slice.call(args);
|
118
|
-
}
|
119
|
-
}
|
120
|
-
end
|
121
|
-
end
|
51
|
+
RUBY_ENGINE_VERSION = '0.5.4'
|
52
|
+
RUBY_RELEASE_DATE = '2013-11-20'
|
data/spec/filters/bugs/array.rb
CHANGED
@@ -31,35 +31,11 @@ opal_filter "Array" do
|
|
31
31
|
fails "Array#delete may be given a block that is executed if no element matches object"
|
32
32
|
fails "Array#delete returns the last element in the array for which object is equal under #=="
|
33
33
|
|
34
|
-
fails "Array#drop_while removes elements from the start of the array until the block returns false"
|
35
|
-
fails "Array#drop_while removes elements from the start of the array until the block returns nil"
|
36
|
-
fails "Array#drop_while removes elements from the start of the array while the block evaluates to true"
|
37
|
-
|
38
34
|
fails "Array#dup creates a new array containing all elements or the original"
|
39
35
|
|
40
|
-
fails "Array#[] tries to convert the passed argument to an Integer using #to_int"
|
41
|
-
fails "Array#[] accepts Range instances having a negative m and both signs for n with [m..n] and [m...n]"
|
42
|
-
fails "Array#[] tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]"
|
43
|
-
fails "Array#[] returns nil if range start is not in the array with [m..n]"
|
44
|
-
fails "Array#[] raises a RangeError when the start index is out of range of Fixnum"
|
45
|
-
fails "Array#[] raises a RangeError when the start index is out of range of Fixnum"
|
46
|
-
fails "Array#[] raises a RangeError when the length is out of range of Fixnum"
|
47
|
-
fails "Array#[] raises a RangeError when the length is out of range of Fixnum"
|
48
36
|
fails "Array.[] can unpack 2 or more nested referenced array"
|
49
37
|
|
50
|
-
fails "Array#[]= calls to_ary on its rhs argument for multi-element sets"
|
51
|
-
fails "Array#[]= raises an IndexError when passed indexes out of bounds"
|
52
|
-
fails "Array#[]= tries to convert Range elements to Integers using #to_int with [m..n] and [m...n]"
|
53
|
-
|
54
|
-
fails "Array#[]= with [m..n] accepts Range subclasses"
|
55
|
-
fails "Array#[]= with [m..n] inserts the other section at m if m > n"
|
56
|
-
fails "Array#[]= with [m..n] replaces the section if m < 0 and n > 0"
|
57
|
-
fails "Array#[]= with [m..n] replaces the section if m and n < 0"
|
58
|
-
fails "Array#[]= with [m..n] just sets the section defined by range to nil if m and n < 0 and the rhs is nil"
|
59
|
-
|
60
38
|
fails "Array#[]= sets elements in the range arguments when passed ranges"
|
61
|
-
fails "Array#[]= calls to_int on its start and length arguments"
|
62
|
-
fails "Array#[]= does nothing if the section defined by range has negative width and the rhs is an empty array"
|
63
39
|
|
64
40
|
fails "Array#eql? ignores array class differences"
|
65
41
|
fails "Array#eql? handles well recursive arrays"
|
@@ -213,6 +189,7 @@ opal_filter "Array" do
|
|
213
189
|
fails "Array#values_at returns an array of elements in the ranges when passes ranges"
|
214
190
|
fails "Array#values_at properly handles recursive arrays"
|
215
191
|
fails "Array#values_at calls to_int on arguments of ranges when passes ranges"
|
192
|
+
fails "Array#values_at does not return subclass instance on Array subclasses"
|
216
193
|
|
217
194
|
fails "Array#zip calls #to_ary to convert the argument to an Array"
|
218
195
|
fails "Array#zip uses #each to extract arguments' elements when #to_ary fails"
|
@@ -225,13 +202,8 @@ opal_filter "Array" do
|
|
225
202
|
fails "Array#hash returns the same hash for equal recursive arrays"
|
226
203
|
fails "Array#hash returns the same fixnum for arrays with the same content"
|
227
204
|
|
228
|
-
fails "Array#initialize_copy tries to convert the passed argument to an Array using #to_ary"
|
229
|
-
fails "Array#initialize_copy does not make self dependent to the original array"
|
230
|
-
fails "Array#initialize_copy returns self"
|
231
|
-
fails "Array#initialize_copy properly handles recursive arrays"
|
232
|
-
fails "Array#initialize_copy replaces the elements with elements from other array"
|
233
|
-
|
234
205
|
fails "Array#partition properly handles recursive arrays"
|
235
206
|
fails "Array#partition returns in the left array values for which the block evaluates to true"
|
236
207
|
fails "Array#partition returns two arrays"
|
208
|
+
fails "Array#partition does not return subclass instances on Array subclasses"
|
237
209
|
end
|