opal 0.3.43 → 0.3.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/CHANGELOG.md +19 -0
  2. data/README.md +1 -0
  3. data/Rakefile +29 -19
  4. data/examples/native/Gemfile +3 -0
  5. data/examples/native/README.md +17 -0
  6. data/examples/native/app/app.rb +38 -0
  7. data/examples/native/config.ru +8 -0
  8. data/examples/native/index.html.erb +12 -0
  9. data/lib/opal/lexer.rb +5 -1
  10. data/lib/opal/parser.rb +36 -10
  11. data/lib/opal/processor.rb +10 -9
  12. data/lib/opal/server.rb +17 -7
  13. data/lib/opal/target_scope.rb +2 -2
  14. data/lib/opal/version.rb +1 -1
  15. data/opal/opal-browser/script_loader.rb +8 -13
  16. data/opal/opal.rb +23 -5
  17. data/opal/opal/array.rb +128 -14
  18. data/opal/opal/boolean.rb +1 -1
  19. data/opal/opal/class.rb +92 -18
  20. data/opal/opal/enumerable.rb +90 -0
  21. data/opal/opal/error.rb +1 -1
  22. data/opal/opal/hash.rb +2 -2
  23. data/opal/opal/kernel.rb +3 -3
  24. data/opal/opal/numeric.rb +1 -1
  25. data/opal/opal/proc.rb +1 -1
  26. data/opal/opal/regexp.rb +31 -31
  27. data/opal/opal/runtime.js +181 -69
  28. data/opal/opal/string.rb +561 -40
  29. data/opal/opal/time.rb +1 -1
  30. data/opal/rbconfig.rb +17 -3
  31. data/opal/strscan.rb +41 -5
  32. data/spec/opal/class/new_spec.rb +27 -0
  33. data/spec/opal/native_spec.rb +127 -0
  34. data/spec/ospec/runner.rb +0 -2
  35. data/spec/parser/strscan/get_byte_spec.rb +29 -0
  36. data/spec/parser/strscan/skip_spec.rb +40 -0
  37. data/spec/rubyspec/core/array/each_spec.rb +1 -1
  38. data/spec/rubyspec/core/array/intersection_spec.rb +5 -0
  39. data/spec/rubyspec/core/array/max_spec.rb +32 -0
  40. data/spec/rubyspec/core/array/min_spec.rb +32 -0
  41. data/spec/rubyspec/core/array/minus_spec.rb +7 -5
  42. data/spec/rubyspec/core/array/multiply_spec.rb +1 -1
  43. data/spec/rubyspec/core/array/plus_spec.rb +1 -1
  44. data/spec/rubyspec/core/array/pop_spec.rb +1 -1
  45. data/spec/rubyspec/core/array/push_spec.rb +1 -1
  46. data/spec/rubyspec/core/array/rassoc_spec.rb +1 -1
  47. data/spec/rubyspec/core/array/reject_spec.rb +2 -2
  48. data/spec/rubyspec/core/array/reverse_each_spec.rb +2 -2
  49. data/spec/rubyspec/core/array/rindex_spec.rb +2 -2
  50. data/spec/rubyspec/core/array/select_spec.rb +1 -1
  51. data/spec/rubyspec/core/array/shift_spec.rb +1 -1
  52. data/spec/rubyspec/core/array/slice_spec.rb +1 -1
  53. data/spec/rubyspec/core/array/sort_spec.rb +15 -15
  54. data/spec/rubyspec/core/array/to_a_spec.rb +1 -1
  55. data/spec/rubyspec/core/array/to_ary_spec.rb +1 -1
  56. data/spec/rubyspec/core/array/uniq_spec.rb +1 -1
  57. data/spec/rubyspec/core/array/unshift_spec.rb +1 -1
  58. data/spec/rubyspec/core/array/zip_spec.rb +1 -1
  59. data/spec/rubyspec/core/enumerable/select_spec.rb +4 -1
  60. data/spec/rubyspec/core/module/const_defined_spec.rb +86 -0
  61. data/spec/rubyspec/core/module/const_get_spec.rb +55 -3
  62. data/spec/rubyspec/core/module/const_set_spec.rb +2 -2
  63. data/spec/rubyspec/core/module/constants_spec.rb +49 -0
  64. data/spec/rubyspec/core/regexp/match_spec.rb +66 -1
  65. data/spec/rubyspec/core/string/center_spec.rb +71 -0
  66. data/spec/rubyspec/core/string/chomp_spec.rb +6 -1
  67. data/spec/rubyspec/core/string/clone_spec.rb +8 -0
  68. data/spec/rubyspec/core/string/dup_spec.rb +8 -0
  69. data/spec/rubyspec/core/string/end_with_spec.rb +5 -1
  70. data/spec/rubyspec/core/string/gsub_spec.rb +15 -1
  71. data/spec/rubyspec/core/string/lines_spec.rb +9 -0
  72. data/spec/rubyspec/core/string/ljust_spec.rb +17 -0
  73. data/spec/rubyspec/core/string/match_spec.rb +25 -3
  74. data/spec/rubyspec/core/string/rindex_spec.rb +50 -0
  75. data/spec/rubyspec/core/string/rjust_spec.rb +17 -0
  76. data/spec/rubyspec/core/string/scan_spec.rb +66 -0
  77. data/spec/rubyspec/core/string/sub_spec.rb +17 -1
  78. data/spec/rubyspec/core/string/tr_s_spec.rb +31 -0
  79. data/spec/rubyspec/core/string/tr_spec.rb +31 -0
  80. data/spec/rubyspec/fixtures/constants.rb +6 -0
  81. data/spec/rubyspec/language/class_spec.rb +4 -8
  82. data/spec/rubyspec/language/numbers_spec.rb +10 -4
  83. data/spec/rubyspec/language/predefined_spec.rb +69 -2
  84. data/spec/rubyspec/library/rbconfig/config_spec.rb +47 -0
  85. data/spec/rubyspec/spec_helper.rb +6 -0
  86. metadata +46 -25
  87. data/opal/opal-eventable.rb +0 -26
  88. data/opal/opal/native.rb +0 -115
  89. data/spec/opal/eventable_spec.rb +0 -75
  90. data/spec/opal/native/element_reference_spec.rb +0 -40
  91. data/spec/opal/native/equal_spec.rb +0 -17
  92. data/spec/opal/native/fixtures/classes.rb +0 -27
  93. data/spec/opal/native/global_spec.rb +0 -12
  94. data/spec/opal/native/initialize_spec.rb +0 -8
  95. data/spec/opal/native/method_missing_spec.rb +0 -53
  96. data/spec/opal/native/to_native_spec.rb +0 -8
  97. data/spec/rubyspec/core/string/demodulize_spec.rb +0 -10
  98. data/spec/rubyspec/core/string/underscore_spec.rb +0 -17
@@ -136,7 +136,7 @@ module Opal
136
136
  # Generates code for this module to donate methods
137
137
  def to_donate_methods
138
138
  if should_donate? and !@methods.empty?
139
- "%s;#{@name}._donate([%s]);" % [@parser.parser_indent, @methods.map(&:inspect).join(', ')]
139
+ "%s;__opal.donate(#{@name}, [%s]);" % [@parser.parser_indent, @methods.map(&:inspect).join(', ')]
140
140
  else
141
141
  ""
142
142
  end
@@ -182,7 +182,7 @@ module Opal
182
182
  def new_temp
183
183
  return @queue.pop unless @queue.empty?
184
184
 
185
- tmp = "_#{@unique}"
185
+ tmp = "$#{@unique}"
186
186
  @unique = @unique.succ
187
187
  @temps << tmp
188
188
  tmp
data/lib/opal/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Opal
2
- VERSION = '0.3.43'
2
+ VERSION = '0.3.44'
3
3
  end
@@ -1,23 +1,18 @@
1
1
  class BrowserScriptLoader
2
- def initialize
3
- @doc = Native.global.document
4
- @win = Native.global
5
- end
6
-
7
2
  def run
8
3
  handler = proc { find_scripts }
9
4
 
10
- if @win.key? :addEventListener
11
- @win.addEventListener 'DOMContentLoaded', handler, false
5
+ if $window.respond_to? :addEventListener
6
+ $window.addEventListener 'DOMContentLoaded', handler, false
12
7
  else
13
- @win.attachEvent 'onload', handler
8
+ $window.attachEvent 'onload', handler
14
9
  end
15
10
  end
16
11
 
17
12
  def find_scripts
18
13
  ruby_scripts.each do |script|
19
14
  if src = script.src and src != ""
20
- puts "Cannot currently load script src: #{src}"
15
+ puts "Cannot currently load remote script: #{src}"
21
16
  else
22
17
  run_ruby script.innerHTML
23
18
  end
@@ -25,16 +20,16 @@ class BrowserScriptLoader
25
20
  end
26
21
 
27
22
  def ruby_scripts
28
- all = @doc.getElementsByTagName 'script'
29
- all.to_a.select { |s| s.type == "text/ruby" }
23
+ $document.getElementsByTagName('script').to_a.select { |s|
24
+ s.type == "text/ruby" }
30
25
  end
31
26
 
32
27
  def run_ruby str
33
- Native.global.Opal.eval str
28
+ $window.Opal.eval str
34
29
  end
35
30
  end
36
31
 
37
- if Native.global.key? :window and Native.global.key? :document
32
+ if $window and $document
38
33
  BrowserScriptLoader.new.run
39
34
  end
40
35
 
data/opal/opal.rb CHANGED
@@ -17,18 +17,36 @@ require 'opal/proc'
17
17
  require 'opal/range'
18
18
  require 'opal/time'
19
19
  require 'opal/json'
20
- require 'opal/native'
21
20
 
22
21
  # regexp matches
23
- $~ = nil
22
+ $& = $~ = $` = $' = nil
23
+
24
+ # stub library path
25
+ $: = []
24
26
 
25
27
  # split lines
26
- $/ = "\n"
28
+ $/ = "\n"
27
29
 
28
- $stderr = $stdout = Object.new
30
+ # native globals
31
+ $global = `Opal.global`
32
+ $window = $global
33
+ $document = $window.document
34
+
35
+ ARGV = []
36
+ ARGF = Object.new
37
+ ENV = {}
38
+ TRUE = true
39
+ FALSE = false
40
+ NIL = nil
41
+
42
+ STDERR = $stderr = Object.new
43
+ STDIN = $stdin = Object.new
44
+ STDOUT = $stdout = Object.new
29
45
 
30
- RUBY_ENGINE = 'opal'
31
46
  RUBY_PLATFORM = 'opal'
47
+ RUBY_ENGINE = 'opal'
48
+ RUBY_VERSION = '1.9.3'
49
+ RUBY_RELEASE_DATE = '2013-05-02'
32
50
 
33
51
  def to_s
34
52
  'main'
data/opal/opal/array.rb CHANGED
@@ -1,4 +1,4 @@
1
- class Array < `Array`
1
+ class Array
2
2
  include Enumerable
3
3
 
4
4
  # Mark all javascript arrays as being valid ruby arrays
@@ -51,12 +51,18 @@ class Array < `Array`
51
51
 
52
52
  for (var i = 0, length = #{self}.length; i < length; i++) {
53
53
  var item = #{self}[i];
54
+ if (item._isString) {
55
+ item = item.toString();
56
+ }
54
57
 
55
58
  if (!seen[item]) {
56
59
  for (var j = 0, length2 = other.length; j < length2; j++) {
57
60
  var item2 = other[j];
61
+ if (item2._isString) {
62
+ item2 = item2.toString();
63
+ }
58
64
 
59
- if ((item === item2) && !seen[item]) {
65
+ if (item === item2 && !seen[item]) {
60
66
  seen[item] = true;
61
67
 
62
68
  result.push(item);
@@ -90,7 +96,38 @@ class Array < `Array`
90
96
  end
91
97
 
92
98
  def -(other)
93
- reject { |i| other.include? i }
99
+ %x{
100
+ var a = #{self},
101
+ b = #{other},
102
+ tmp = [],
103
+ result = [];
104
+
105
+ if (typeof(b) == "object" && !(b instanceof Array)) {
106
+ if (b['$to_ary'] && typeof(b['$to_ary']) == "function") {
107
+ b = b['$to_ary']();
108
+ } else {
109
+ #{raise TypeError.new("can't convert to Array. Array#-") };
110
+ }
111
+ }else if ((typeof(b) != "object")) {
112
+ #{raise TypeError.new("can't convert to Array. Array#-") };
113
+ }
114
+
115
+ if (a.length == 0)
116
+ return [];
117
+ if (b.length == 0)
118
+ return a;
119
+
120
+ for(var i = 0, length = b.length; i < length; i++) {
121
+ tmp[b[i]] = true;
122
+ }
123
+ for(var i = 0, length = a.length; i < length; i++) {
124
+ if (!tmp[a[i]]) {
125
+ result.push(a[i]);
126
+ }
127
+ }
128
+
129
+ return result;
130
+ }
94
131
  end
95
132
 
96
133
  def <<(object)
@@ -125,11 +162,25 @@ class Array < `Array`
125
162
  return false;
126
163
  }
127
164
 
128
- for (var i = 0, length = #{self}.length; i < length; i++) {
165
+ for (var i = 0, length = #{self}.length, tmp1, tmp2; i < length; i++) {
166
+ tmp1 = #{self}[i];
167
+ tmp2 = #{other}[i];
168
+
169
+ //recursive
170
+ if ((typeof(tmp1.indexOf) == "function") &&
171
+ (typeof(tmp2.indexOf) == "function") &&
172
+ (tmp1.indexOf(tmp2) == tmp2.indexOf(tmp1))) {
173
+ if (tmp1.indexOf(tmp1) == tmp2.indexOf(tmp2)) {
174
+ continue;
175
+ }
176
+ }
177
+
129
178
  if (!#{`#{self}[i]` == `other[i]`}) {
130
179
  return false;
131
180
  }
181
+
132
182
  }
183
+
133
184
 
134
185
  return true;
135
186
  }
@@ -139,7 +190,7 @@ class Array < `Array`
139
190
  %x{
140
191
  var size = #{self}.length;
141
192
 
142
- if (typeof index !== 'number') {
193
+ if (typeof index !== 'number' && !index._isNumber) {
143
194
  if (index._isRange) {
144
195
  var exclude = index.exclude;
145
196
  length = index.end;
@@ -382,9 +433,19 @@ class Array < `Array`
382
433
  def each(&block)
383
434
  return enum_for :each unless block_given?
384
435
 
385
- `for (var i = 0, length = #{self}.length; i < length; i++) {`
386
- yield `#{self}[i]`
387
- `}`
436
+ if block.arity > 0
437
+ %x{
438
+ for (var i = 0, length = #{self}.length; i < length; i++) {
439
+ if (block.apply(null, #{self}[i]._isArray ? #{self}[i] : [#{self}[i]]) === __breaker) return __breaker.$v;
440
+ }
441
+ }
442
+ else
443
+ %x{
444
+ for (var i = 0, length = #{self}.length; i < length; i++) {
445
+ #{yield `#{self}[i]`};
446
+ }
447
+ }
448
+ end
388
449
 
389
450
  self
390
451
  end
@@ -831,22 +892,75 @@ class Array < `Array`
831
892
  def sort(&block)
832
893
  %x{
833
894
  var copy = #{self}.slice();
834
-
895
+ var t_arg_error = false;
896
+ var t_break = [];
897
+
835
898
  if (block !== nil) {
836
- return copy.sort(block);
899
+ var result = copy.sort(function(x, y) {
900
+ var result = block(x, y);
901
+ if (result === __breaker) {
902
+ t_break.push(__breaker.$v);
903
+ }
904
+ if (result === nil) {
905
+ t_arg_error = true;
906
+ }
907
+ if (result['$<=>'] && typeof(result['$<=>']) == "function") {
908
+ result = result['$<=>'](0);
909
+ }
910
+ if ([-1, 0, 1].indexOf(result) == -1) {
911
+ t_arg_error = true;
912
+ }
913
+ return result;
914
+ });
915
+
916
+ if (t_break.length > 0)
917
+ return t_break[0];
918
+ if (t_arg_error)
919
+ #{raise ArgumentError, "Array#sort"};
920
+
921
+ return result;
837
922
  }
923
+
924
+ var result = copy.sort(function(a, b){
925
+ if (typeof(a) !== typeof(b)) {
926
+ t_arg_error = true;
927
+ }
928
+
929
+ if (a['$<=>'] && typeof(a['$<=>']) == "function") {
930
+ var result = a['$<=>'](b);
931
+ if (result === nil) {
932
+ t_arg_error = true;
933
+ }
934
+ return result;
935
+ }
936
+ if (a > b)
937
+ return 1;
938
+ if (a < b)
939
+ return -1;
940
+ return 0;
941
+ });
942
+
943
+ if (t_arg_error)
944
+ #{raise ArgumentError, "Array#sort"};
838
945
 
839
- return copy.sort();
946
+ return result;
840
947
  }
841
948
  end
842
949
 
843
950
  def sort!(&block)
844
951
  %x{
952
+ var result;
845
953
  if (block !== nil) {
846
- return #{self}.sort(block);
954
+ //strangely
955
+ result = #{self}.slice().sort(block);
956
+ } else {
957
+ result = #{self}.slice()['$sort']();
847
958
  }
848
-
849
- return #{self}.sort();
959
+ #{self}.length = 0;
960
+ for(var i = 0; i < result.length; i++) {
961
+ #{self}.push(result[i]);
962
+ }
963
+ return #{self};
850
964
  }
851
965
  end
852
966
 
data/opal/opal/boolean.rb CHANGED
@@ -1,4 +1,4 @@
1
- class Boolean < `Boolean`
1
+ class Boolean
2
2
  `def._isBoolean = true`
3
3
 
4
4
  def &(other)
data/opal/opal/class.rb CHANGED
@@ -82,7 +82,7 @@ class Class
82
82
  }
83
83
 
84
84
  if (klass.$included_in) {
85
- klass._donate(methods.slice(), true);
85
+ __opal.donate(klass, methods.slice(), true);
86
86
  }
87
87
  }
88
88
 
@@ -103,7 +103,7 @@ class Class
103
103
  var func = function() { return this[name] };
104
104
 
105
105
  if (cls._isSingleton) {
106
- proto._defs('$' + name, func);
106
+ __opal.defs(proto, '$' + name, func);
107
107
  }
108
108
  else {
109
109
  proto['$' + name] = func;
@@ -124,7 +124,7 @@ class Class
124
124
  var func = function(value) { return this[name] = value; };
125
125
 
126
126
  if (cls._isSingleton) {
127
- proto._defs('$' + name + '=', func);
127
+ __opal.defs(proto, '$' + name + '=', func);
128
128
  }
129
129
  else {
130
130
  proto['$' + name + '='] = func;
@@ -137,19 +137,85 @@ class Class
137
137
 
138
138
  alias attr attr_accessor
139
139
 
140
- def const_defined?(name)
141
- `!!(#{self}._scope[#{name}])`
140
+ # when self is Module (or Class), implement 1st form:
141
+ # - global constants, classes and modules in global scope
142
+ # when self is not Module (or Class), implement 2nd form:
143
+ # - constants, classes and modules scoped to instance
144
+ def constants
145
+ %x{
146
+ var result = [];
147
+ var name_re = /^[A-Z][A-Za-z0-9_]+$/;
148
+ var scopes = [#{self}._scope];
149
+ var own_only;
150
+ if (#{self} === Opal.Class) {
151
+ own_only = false;
152
+ }
153
+ else {
154
+ own_only = true;
155
+ var parent = #{self}._super;
156
+ while (parent !== Opal.Object) {
157
+ scopes.push(parent._scope);
158
+ parent = parent._super;
159
+ }
160
+ }
161
+ for (var i = 0, len = scopes.length; i < len; i++) {
162
+ var scope = scopes[i];
163
+ for (name in scope) {
164
+ if ((!own_only || scope.hasOwnProperty(name)) && name_re.test(name)) {
165
+ result.push(name);
166
+ }
167
+ }
168
+ }
169
+
170
+ return result;
171
+ }
142
172
  end
143
173
 
144
- def const_get(name)
174
+ # check for constant within current scope
175
+ # if inherit is true or self is Object, will also check ancestors
176
+ def const_defined?(name, inherit = true)
177
+ raise NameError, "wrong constant name #{name}" unless name =~ /^[A-Z]\w+$/
145
178
  %x{
146
- var result = #{self}._scope[name];
179
+ scopes = [#{self}._scope];
180
+ if (inherit || #{self} === Opal.Object) {
181
+ var parent = #{self}._super;
182
+ while (parent !== Opal.BasicObject) {
183
+ scopes.push(parent._scope);
184
+ parent = parent._super;
185
+ }
186
+ }
147
187
 
148
- if (result == null) {
149
- return #{ const_missing name };
188
+ for (var i = 0, len = scopes.length; i < len; i++) {
189
+ if (scopes[i].hasOwnProperty(name)) {
190
+ return true;
191
+ }
150
192
  }
151
193
 
152
- return result;
194
+ return false;
195
+ }
196
+ end
197
+
198
+ # check for constant within current scope
199
+ # if inherit is true or self is Object, will also check ancestors
200
+ def const_get(name, inherit = true)
201
+ raise NameError, "wrong constant name #{name}" unless name =~ /^[A-Z]\w+$/
202
+ %x{
203
+ var scopes = [#{self}._scope];
204
+ if (inherit || #{self} == Opal.Object) {
205
+ var parent = #{self}._super;
206
+ while (parent !== Opal.BasicObject) {
207
+ scopes.push(parent._scope);
208
+ parent = parent._super;
209
+ }
210
+ }
211
+
212
+ for (var i = 0, len = scopes.length; i < len; i++) {
213
+ if (scopes[i].hasOwnProperty(name)) {
214
+ return scopes[i][name];
215
+ }
216
+ }
217
+
218
+ return #{const_missing name};
153
219
  }
154
220
  end
155
221
 
@@ -159,8 +225,7 @@ class Class
159
225
  end
160
226
 
161
227
  def const_set(name, value)
162
- raise NameError, "wrong constant name #{name}" unless name =~ /^[A-Z]/
163
- raise NameError, "wrong constant name #{name}" unless name =~ /^[\w_]+$/
228
+ raise NameError, "wrong constant name #{name}" unless name =~ /^[A-Z]\w+$/
164
229
  begin
165
230
  name = name.to_str
166
231
  rescue
@@ -188,7 +253,7 @@ class Class
188
253
  block._s = null;
189
254
 
190
255
  #{self}.prototype[jsid] = block;
191
- #{self}._donate([jsid]);
256
+ __opal.donate(#{self}, [jsid]);
192
257
 
193
258
  return nil;
194
259
  }
@@ -283,12 +348,21 @@ class Class
283
348
 
284
349
  def new(*args, &block)
285
350
  %x{
286
- var obj = new #{self};
287
- obj._id = Opal.uid();
351
+ if (#{self}.prototype.$initialize) {
352
+ var obj = new #{self};
353
+ obj._id = Opal.uid();
288
354
 
289
- obj.$initialize._p = block;
290
- obj.$initialize.apply(obj, args);
291
- return obj;
355
+ obj.$initialize._p = block;
356
+ obj.$initialize.apply(obj, args);
357
+ return obj;
358
+ }
359
+ else {
360
+ var cons = function() {};
361
+ cons.prototype = #{self}.prototype;
362
+ var obj = new cons;
363
+ #{self}.apply(obj, args);
364
+ return obj;
365
+ }
292
366
  }
293
367
  end
294
368