opal 0.5.2 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|