opal 0.3.37 → 0.3.38

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 (51) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/Gemfile +0 -8
  3. data/README.md +7 -6
  4. data/bin/opal +18 -10
  5. data/config.ru +8 -21
  6. data/lib/assets/javascripts/opal-parser.js.erb +3 -60
  7. data/lib/assets/javascripts/opal/array.rb +87 -43
  8. data/lib/assets/javascripts/opal/basic_object.rb +4 -0
  9. data/lib/assets/javascripts/opal/boolean.rb +5 -3
  10. data/lib/assets/javascripts/opal/class.rb +19 -4
  11. data/lib/assets/javascripts/opal/comparable.rb +1 -1
  12. data/lib/assets/javascripts/opal/enumerable.rb +32 -0
  13. data/lib/assets/javascripts/opal/error.rb +1 -1
  14. data/lib/assets/javascripts/opal/hash.rb +166 -103
  15. data/lib/assets/javascripts/opal/json.rb +3 -2
  16. data/lib/assets/javascripts/opal/kernel.rb +9 -1
  17. data/lib/assets/javascripts/opal/native.rb +29 -0
  18. data/lib/assets/javascripts/opal/nil_class.rb +9 -1
  19. data/lib/assets/javascripts/opal/numeric.rb +6 -4
  20. data/lib/assets/javascripts/opal/parser.js +57 -0
  21. data/lib/assets/javascripts/opal/proc.rb +5 -5
  22. data/lib/assets/javascripts/opal/regexp.rb +1 -1
  23. data/lib/assets/javascripts/opal/runtime.js +13 -0
  24. data/lib/assets/javascripts/opal/string.rb +14 -3
  25. data/lib/assets/javascripts/opal/time.rb +1 -1
  26. data/lib/opal.rb +1 -1
  27. data/lib/opal/parser.rb +39 -13
  28. data/lib/opal/processor.rb +13 -2
  29. data/lib/opal/version.rb +1 -1
  30. data/opal.gemspec +3 -0
  31. data/spec/core/array/fill_spec.rb +26 -0
  32. data/spec/core/array/try_convert_spec.rb +15 -0
  33. data/spec/core/enumerable/each_slice_spec.rb +24 -0
  34. data/spec/core/enumerable/group_by_spec.rb +16 -0
  35. data/spec/core/module/const_get_spec.rb +34 -0
  36. data/spec/core/module/undef_method_spec.rb +67 -0
  37. data/spec/core/nil/to_h_spec.rb +10 -0
  38. data/spec/core/proc/element_reference_spec.rb +21 -0
  39. data/spec/{core → core_ext}/array/to_json_spec.rb +0 -0
  40. data/spec/core_ext/method_missing_spec.rb +43 -0
  41. data/spec/core_ext/native/fixtures/classes.rb +5 -0
  42. data/spec/core_ext/native/initialize_spec.rb +8 -0
  43. data/spec/core_ext/native/method_missing_spec.rb +7 -0
  44. data/spec/core_ext/native/to_native_spec.rb +7 -0
  45. data/spec/grammar/parser_spec.rb +1 -1
  46. data/spec/language/super_spec.rb +20 -0
  47. data/spec/language/variables_spec.rb +69 -0
  48. data/spec/spec_helper.rb +9 -5
  49. metadata +66 -8
  50. data/lib/assets/javascripts/opal/core.rb +0 -36
  51. data/spec/autorun.rb +0 -3
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ ## Edge ##
2
+
3
+ * Add Native module used for wrapping objects to forward calls as native
4
+ calls.
5
+
6
+ * Support method_missing for all objects. Feature can be enabled/disabled on
7
+ Opal::Processor.
8
+
9
+ * Hash can now use any ruby object as a key.
10
+
11
+ * Move to Sprockets based building via `Opal::Processor`.
data/Gemfile CHANGED
@@ -2,11 +2,3 @@ source :rubygems
2
2
  gemspec
3
3
 
4
4
  gem 'rake'
5
-
6
- gem 'sprockets'
7
- gem 'opal-spec', '~> 0.2.8'
8
-
9
- # for rebuilding grammar.rb from grammar.y
10
- group :grammar do
11
- gem 'racc'
12
- end
data/README.md CHANGED
@@ -14,11 +14,13 @@ See the website, [http://opalrb.org](http://opalrb.org).
14
14
 
15
15
  ## Running tests
16
16
 
17
+ First, install dependencies:
18
+
19
+ $ bundle install
20
+
17
21
  Tests can be run with phantomjs using:
18
22
 
19
- ```
20
- $ rake
21
- ```
23
+ $ rake
22
24
 
23
25
  Alternatively, you can just load up a rack instance using `rackup`, and
24
26
  visit `http://localhost:9292/` in any web browser.
@@ -34,14 +36,13 @@ to allow compilation in any javascript environment.
34
36
  ### lib/assets/javascripts
35
37
 
36
38
  This directory holds the opal runtime and corelib implemented in ruby and
37
- javascript. These are built using `rake opal`, as above.
39
+ javascript. These are built using `rake`, as above.
38
40
 
39
41
  ### spec
40
42
 
41
43
  * **core** contains rubyspecs that apply to opal.
42
44
  * **language** applicable specs from rubyspec for testing language semantics
43
- * **opal** tests for extra methods/features in opal not found in standard ruby
44
- * **lib** specs for opal lib (parser, lexer, grammar etc)
45
+ * **grammar** specs for opal lib (parser, lexer, grammar etc)
45
46
 
46
47
  ## License
47
48
 
data/bin/opal CHANGED
@@ -1,16 +1,24 @@
1
- #! /usr/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
+ require 'optparse'
3
4
  require 'opal'
4
5
 
5
- first = ARGV.first
6
+ options = {}
7
+ parser = OptionParser.new do |opts|
8
+ opts.banner = "Usage: opal [options] file.rb"
6
9
 
7
- if first.nil?
8
- puts "Usage: opal path/to/file.rb"
9
- puts 'Usage: opal "code to compile"'
10
- elsif first == '-v' or first == '--version'
11
- puts Opal::VERSION
12
- elsif File.exist? first
13
- puts Opal.parse File.read(first)
10
+ opts.on("-v", "--version", "Opal Version") do |v|
11
+ puts Opal::VERSION
12
+ exit
13
+ end
14
+ end
15
+
16
+ parser.parse!
17
+
18
+ if ARGV.empty?
19
+ puts parser.banner
14
20
  else
15
- puts Opal.parse(first)
21
+ src = ARGV.first
22
+ src = File.read src if File.exist? src
23
+ puts Opal.parse(src)
16
24
  end
data/config.ru CHANGED
@@ -1,26 +1,13 @@
1
1
  require 'bundler'
2
2
  Bundler.require
3
3
 
4
- html = <<HTML
5
- <!DOCTYPE html>
6
- <html>
7
- <head>
8
- <title>Opal corelib and runtime specs</title>
9
- </head>
10
- <body>
11
- <script type="text/javascript" src="/assets/autorun.js"></script>
12
- </body>
13
- </html>
14
- HTML
4
+ require 'opal/spec/server'
15
5
 
16
- map '/assets' do
17
- env = Opal::Environment.new
18
- env.append_path 'spec'
19
- run env
20
- end
6
+ # method_missing can be turned off if required (on by default)
7
+ # Opal::Processor.method_missing_enabled = false
21
8
 
22
- map '/' do
23
- run lambda { |env|
24
- [200, {'Content-Type' => 'text/html'}, [html]]
25
- }
26
- end
9
+ # Run in non-debug mode (faster, all files concatenated into 1 file)
10
+ run Opal::Spec::Server.new(false)
11
+
12
+ # Run in debug mode - all files loaded seperately, but slower
13
+ # run Opal::Spec::Server.new
@@ -1,65 +1,8 @@
1
- //= require opal/racc
2
- //= require opal/strscan
1
+ <% require_asset 'opal/racc' %>
2
+ <% require_asset 'opal/strscan' %>
3
+ <% require_asset 'opal/parser' %>
3
4
 
4
5
  // We need (some) of the libs from our real ruby parser (not in sprockets load path)
5
6
  <% ['/grammar', '/lexer', '/parser', '/scope', ''].each do |f| %>
6
7
  <%= Opal.parse File.read(File.join Opal.core_dir, '..', '..', "opal#{f}.rb") %>
7
8
  <% end %>
8
-
9
- (function() {
10
- // quick exit if not insde browser
11
- if (typeof(window) === 'undefined' || typeof(document) === 'undefined') {
12
- return;
13
- }
14
-
15
- function findRubyScripts() {
16
- var all = document.getElementsByTagName('script');
17
- for (var i = 0, script; i < all.length; i++) {
18
- script = all[i];
19
- if (script.type === 'text/ruby') {
20
- if (script.src) {
21
- request(script.src, function(result) {
22
- runRuby(result);
23
- });
24
- }
25
- else {
26
- runRuby(script.innerHTML);
27
- }
28
- }
29
- else if (script.type === 'text/erb') {
30
- runERB(script.innerHTML);
31
- }
32
- }
33
- }
34
-
35
- function runRuby(source) {
36
- var js = Opal.Opal.Parser.$new().$parse(source);
37
- eval('(' + js + ')()');
38
- }
39
-
40
- function request(url, callback) {
41
- var xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
42
- xhr.open('GET', url, true);
43
- if ('overrideMimeType' in xhr) {
44
- xhr.overrideMimeType('text/plain');
45
- }
46
- xhr.onreadystatechange = function() {
47
- if (xhr.readyState === 4) {
48
- if (xhr.status === 0 || xhr.status === 200) {
49
- callback(xhr.responseText);
50
- }
51
- else {
52
- throw new Error('Could not load ruby at: ' + url);
53
- }
54
- }
55
- };
56
- xhr.send(null);
57
- }
58
-
59
- if (window.addEventListener) {
60
- window.addEventListener('DOMContentLoaded', findRubyScripts, false);
61
- }
62
- else {
63
- window.attachEvent('onload', findRubyScripts);
64
- }
65
- })();
@@ -1,14 +1,11 @@
1
1
  class Array < `Array`
2
- %x{
3
- Array.prototype._isArray = true;
4
- }
5
-
6
2
  include Enumerable
7
3
 
4
+ # Mark all javascript arrays as being valid ruby arrays
5
+ `def._isArray = true`
6
+
8
7
  def self.[](*objects)
9
- %x{
10
- return objects;
11
- }
8
+ objects
12
9
  end
13
10
 
14
11
  def self.new(size, obj = nil, &block)
@@ -37,6 +34,16 @@ class Array < `Array`
37
34
  }
38
35
  end
39
36
 
37
+ def self.try_convert(obj)
38
+ %x{
39
+ if (obj._isArray) {
40
+ return obj;
41
+ }
42
+
43
+ return nil;
44
+ }
45
+ end
46
+
40
47
  def &(other)
41
48
  %x{
42
49
  var result = [],
@@ -416,6 +423,23 @@ class Array < `Array`
416
423
  }
417
424
  end
418
425
 
426
+ def fill(obj = undefined, &block)
427
+ %x{
428
+ if (block !== nil) {
429
+ for (var i = 0, length = #{self}.length; i < length; i++) {
430
+ #{self}[i] = block(i);
431
+ }
432
+ }
433
+ else {
434
+ for (var i = 0, length = #{self}.length; i < length; i++) {
435
+ #{self}[i] = obj;
436
+ }
437
+ }
438
+ }
439
+
440
+ self
441
+ end
442
+
419
443
  def first(count)
420
444
  %x{
421
445
  if (count != null) {
@@ -760,6 +784,19 @@ class Array < `Array`
760
784
 
761
785
  alias size length
762
786
 
787
+ def shuffle()
788
+ %x{
789
+ for (var i = #{self}.length - 1; i > 0; i--) {
790
+ var j = Math.floor(Math.random() * (i + 1));
791
+ var tmp = #{self}[i];
792
+ #{self}[i] = #{self}[j];
793
+ #{self}[j] = tmp;
794
+ }
795
+
796
+ return #{self};
797
+ }
798
+ end
799
+
763
800
  alias slice :[]
764
801
 
765
802
  def slice!(index, length)
@@ -780,6 +817,28 @@ class Array < `Array`
780
817
  }
781
818
  end
782
819
 
820
+ def sort(&block)
821
+ %x{
822
+ var copy = #{self}.slice();
823
+
824
+ if (block !== nil) {
825
+ return copy.sort(block);
826
+ }
827
+
828
+ return copy.sort();
829
+ }
830
+ end
831
+
832
+ def sort!(&block)
833
+ %x{
834
+ if (block !== nil) {
835
+ return #{self}.sort(block);
836
+ }
837
+
838
+ return #{self}.sort();
839
+ }
840
+ end
841
+
783
842
  def take(count)
784
843
  `#{self}.slice(0, count)`
785
844
  end
@@ -824,6 +883,26 @@ class Array < `Array`
824
883
  }
825
884
  end
826
885
 
886
+ def to_native
887
+ %x{
888
+ var result = [], obj
889
+
890
+ for (var i = 0, len = #{self}.length; i < len; i++) {
891
+ obj = #{self}[i];
892
+
893
+ if (obj.$to_native) {
894
+ result.push(#{ `obj`.to_native });
895
+ }
896
+ else {
897
+ result.push(obj);
898
+ }
899
+ }
900
+
901
+ return result;
902
+ }
903
+ end
904
+
905
+
827
906
  alias to_s inspect
828
907
 
829
908
  def uniq
@@ -911,39 +990,4 @@ class Array < `Array`
911
990
  return result;
912
991
  }
913
992
  end
914
-
915
- def sort(&block)
916
- %x{
917
- var copy = #{self}.slice();
918
-
919
- if (block !== nil) {
920
- return copy.sort(block);
921
- }
922
-
923
- return copy.sort();
924
- }
925
- end
926
-
927
- def sort!(&block)
928
- %x{
929
- if (block !== nil) {
930
- return #{self}.sort(block);
931
- }
932
-
933
- return #{self}.sort();
934
- }
935
- end
936
-
937
- def shuffle()
938
- %x{
939
- for (var i = #{self}.length - 1; i > 0; i--) {
940
- var j = Math.floor(Math.random() * (i + 1));
941
- var tmp = #{self}[i];
942
- #{self}[i] = #{self}[j];
943
- #{self}[j] = tmp;
944
- }
945
-
946
- return #{self};
947
- }
948
- end
949
- end
993
+ end
@@ -46,4 +46,8 @@ class BasicObject
46
46
  return result;
47
47
  }
48
48
  end
49
+
50
+ def method_missing(symbol, *args, &block)
51
+ Kernel.raise NoMethodError, "undefined method `#{symbol}' for BasicObject instance"
52
+ end
49
53
  end
@@ -1,7 +1,5 @@
1
1
  class Boolean < `Boolean`
2
- %x{
3
- Boolean.prototype._isBoolean = true;
4
- }
2
+ `def._isBoolean = true`
5
3
 
6
4
  def &(other)
7
5
  `(#{self} == true) ? (other !== false && other !== nil) : false`
@@ -19,6 +17,10 @@ class Boolean < `Boolean`
19
17
  `(#{self} == true) === other.valueOf()`
20
18
  end
21
19
 
20
+ def as_json
21
+ self
22
+ end
23
+
22
24
  alias singleton_class class
23
25
 
24
26
  def to_json
@@ -128,6 +128,18 @@ class Class
128
128
 
129
129
  alias attr attr_accessor
130
130
 
131
+ def const_get(name)
132
+ %x{
133
+ var result = #{self}._scope[name];
134
+
135
+ if (result == null) {
136
+ #{ raise NameError, "uninitialized constant #{name}" }
137
+ }
138
+
139
+ return result;
140
+ }
141
+ end
142
+
131
143
  def define_method(name, &block)
132
144
  %x{
133
145
  if (block === nil) {
@@ -229,8 +241,11 @@ class Class
229
241
  alias protected public
230
242
 
231
243
  def superclass
232
- %x{
233
- return #{self}._super || nil;
234
- }
244
+ `#{self}._super || nil`
245
+ end
246
+
247
+ def undef_method(symbol)
248
+ `#{self}.prototype['$' + symbol] = undefined`
249
+ self
235
250
  end
236
- end
251
+ end
@@ -22,4 +22,4 @@ module Comparable
22
22
  def between?(min, max)
23
23
  self > min && self < max
24
24
  end
25
- end
25
+ end