opal 0.3.43 → 0.3.44

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.
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