opal 0.3.44 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. data/.travis.yml +0 -1
  2. data/CHANGELOG.md +52 -0
  3. data/README.md +3 -3
  4. data/Rakefile +32 -8
  5. data/bin/opal +69 -16
  6. data/config.ru +1 -1
  7. data/examples/native/app/app.rb +28 -9
  8. data/examples/rack/app/app.rb +1 -1
  9. data/lib/opal.rb +0 -1
  10. data/lib/opal/cli.rb +106 -0
  11. data/lib/opal/lexer.rb +4 -2
  12. data/lib/opal/parser.rb +603 -360
  13. data/lib/opal/processor.rb +20 -8
  14. data/lib/opal/server.rb +47 -0
  15. data/lib/opal/source_map.rb +63 -0
  16. data/lib/opal/sprockets_parser.rb +77 -0
  17. data/lib/opal/sprockets_source_map_header.rb +21 -0
  18. data/lib/opal/target_scope.rb +14 -7
  19. data/lib/opal/version.rb +1 -1
  20. data/opal.gemspec +2 -0
  21. data/opal/opal-browser/script_loader.rb +7 -7
  22. data/opal/opal-parser.js.erb +2 -2
  23. data/opal/opal-source-maps.js.erb +2 -0
  24. data/opal/opal.rb +3 -4
  25. data/opal/opal/array.rb +31 -28
  26. data/opal/opal/boolean.rb +4 -0
  27. data/opal/opal/class.rb +14 -5
  28. data/opal/opal/enumerable.rb +68 -8
  29. data/opal/opal/error.rb +1 -1
  30. data/opal/opal/hash.rb +15 -18
  31. data/opal/opal/kernel.rb +24 -10
  32. data/opal/opal/native.rb +31 -0
  33. data/opal/opal/nil_class.rb +7 -2
  34. data/opal/opal/numeric.rb +10 -1
  35. data/opal/opal/proc.rb +4 -0
  36. data/opal/opal/range.rb +1 -1
  37. data/opal/opal/regexp.rb +13 -3
  38. data/opal/opal/runtime.js +134 -51
  39. data/opal/opal/string.rb +45 -22
  40. data/opal/opal/time.rb +25 -7
  41. data/opal/source_map.rb +63 -0
  42. data/opal/source_map/generator.rb +251 -0
  43. data/opal/source_map/parser.rb +102 -0
  44. data/opal/source_map/vlq.rb +122 -0
  45. data/opal/strscan.rb +30 -12
  46. data/spec/opal/class/_inherited_spec.rb +1 -1
  47. data/spec/{rubyspec/core → opal}/class/bridge_class_spec.rb +5 -3
  48. data/spec/{rubyspec/core → opal}/class/extend_spec.rb +0 -0
  49. data/spec/{rubyspec/core → opal}/class/instance_methods_spec.rb +0 -0
  50. data/spec/{rubyspec/core → opal}/class/last_value_spec.rb +0 -1
  51. data/spec/{rubyspec/core → opal}/json/parse_spec.rb +0 -0
  52. data/spec/{rubyspec/core/kernel/block_given.rb → opal/kernel/block_given_spec.rb} +0 -0
  53. data/spec/{rubyspec/core → opal}/kernel/class_spec.rb +0 -0
  54. data/spec/{rubyspec/core → opal}/kernel/extend_spec.rb +0 -0
  55. data/spec/{rubyspec/core → opal}/kernel/format_spec.rb +0 -0
  56. data/spec/opal/kernel/freeze_spec.rb +15 -0
  57. data/spec/{rubyspec/core → opal}/kernel/match_spec.rb +0 -0
  58. data/spec/{rubyspec/core → opal}/kernel/method_spec.rb +0 -0
  59. data/spec/{rubyspec/core → opal}/kernel/methods_spec.rb +0 -0
  60. data/spec/{rubyspec/core → opal}/kernel/nil_spec.rb +0 -0
  61. data/spec/{rubyspec/core → opal}/kernel/p_spec.rb +0 -0
  62. data/spec/{rubyspec/core → opal}/kernel/printf_spec.rb +0 -0
  63. data/spec/{rubyspec/core → opal}/kernel/proc_spec.rb +0 -0
  64. data/spec/{rubyspec/core → opal}/kernel/rand_spec.rb +0 -0
  65. data/spec/{rubyspec/core → opal}/kernel/respond_to_spec.rb +0 -0
  66. data/spec/{rubyspec/core → opal}/kernel/sprintf_spec.rb +0 -0
  67. data/spec/{rubyspec/core → opal}/kernel/to_json_spec.rb +0 -0
  68. data/spec/{rubyspec/core → opal}/module/alias_method_spec.rb +0 -0
  69. data/spec/{rubyspec/core → opal}/module/ancestors_spec.rb +0 -0
  70. data/spec/{rubyspec/core → opal}/module/append_features_spec.rb +0 -0
  71. data/spec/{rubyspec/core → opal}/module/constants_spec.rb +0 -0
  72. data/spec/{rubyspec/core → opal}/module/module_function_spec.rb +0 -1
  73. data/spec/opal/native_spec.rb +85 -3
  74. data/spec/opal/numeric/equal_spec.rb +9 -0
  75. data/spec/opal/parser/irb_spec.rb +43 -0
  76. data/spec/{rubyspec/core → opal}/proc/proc_tricks_spec.rb +0 -0
  77. data/spec/opal/runtime/block_send_spec.rb +28 -0
  78. data/spec/{rubyspec/core/runtime → opal/runtime2}/call_spec.rb +0 -0
  79. data/spec/{rubyspec/core/runtime → opal/runtime2}/class_hierarchy_spec.rb +0 -0
  80. data/spec/{rubyspec/core/runtime → opal/runtime2}/def_spec.rb +0 -0
  81. data/spec/{rubyspec/core/runtime → opal/runtime2}/defined_spec.rb +0 -0
  82. data/spec/{rubyspec/core/runtime → opal/runtime2}/super_spec.rb +0 -0
  83. data/spec/opal/source_map_spec.rb +19 -0
  84. data/spec/opal/string/freeze_spec.rb +15 -0
  85. data/spec/{rubyspec/core → opal}/string/to_json_spec.rb +0 -0
  86. data/spec/ospec/runner.rb +3 -0
  87. data/spec/parser/str_spec.rb +4 -0
  88. data/spec/rubyspec/core/enumerable/fixtures/classes.rb +2 -2
  89. data/spec/rubyspec/core/enumerable/none_spec.rb +68 -0
  90. data/spec/rubyspec/core/enumerable/sort_by_spec.rb +31 -0
  91. data/spec/rubyspec/core/hash/size_spec.rb +1 -1
  92. data/spec/rubyspec/core/hash/to_native_spec.rb +3 -3
  93. data/spec/rubyspec/core/string/fixtures/classes.rb +49 -0
  94. data/spec/rubyspec/core/string/index_spec.rb +405 -0
  95. data/spec/rubyspec/filters/bugs/language/class.rb +0 -2
  96. data/spec/rubyspec/filters/bugs/language/module.rb +3 -0
  97. data/spec/rubyspec/language/array_spec.rb +1 -1
  98. data/spec/rubyspec/language/block_spec.rb +1 -1
  99. data/spec/rubyspec/language/module_spec.rb +5 -5
  100. data/spec/rubyspec/language/predefined_spec.rb +1 -2
  101. data/spec/rubyspec/library/stringscanner/element_reference_spec.rb +29 -0
  102. data/spec/rubyspec/spec_helper.rb +31 -0
  103. metadata +130 -76
  104. data/lib/opal/erb.rb +0 -41
  105. data/opal/erb.rb +0 -19
  106. data/spec/opal/erb/erb_spec.rb +0 -31
  107. data/spec/simple_erb_template.opalerb +0 -1
  108. data/spec/templates/foo/bar.opalerb +0 -1
  109. data/spec/templates/prefixed.opalerb +0 -1
@@ -0,0 +1,122 @@
1
+ class SourceMap
2
+ # Support for encoding/decoding the variable length quantity format
3
+ # described in the spec at:
4
+ #
5
+ # https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
6
+ #
7
+ # This implementation is heavily based on https://github.com/mozilla/source-map
8
+ # Copyright 2009-2011, Mozilla Foundation and contributors, BSD
9
+ #
10
+ module VLQ
11
+
12
+ # A single base 64 digit can contain 6 bits of data. For the base 64 variable
13
+ # length quantities we use in the source map spec, the first bit is the sign,
14
+ # the next four bits are the actual value, and the 6th bit is the
15
+ # continuation bit. The continuation bit tells us whether there are more
16
+ # digits in this value following this digit.
17
+ #
18
+ # Continuation
19
+ # | Sign
20
+ # | |
21
+ # V V
22
+ # 101011
23
+
24
+ VLQ_BASE_SHIFT = 5;
25
+
26
+ # binary: 100000
27
+ VLQ_BASE = 1 << VLQ_BASE_SHIFT;
28
+
29
+ # binary: 011111
30
+ VLQ_BASE_MASK = VLQ_BASE - 1;
31
+
32
+ # binary: 100000
33
+ VLQ_CONTINUATION_BIT = VLQ_BASE;
34
+
35
+ BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('')
36
+ BASE64_VALUES = (0..64).inject({}){ |h, i| h.update BASE64_DIGITS[i] => i }
37
+
38
+ # Returns the base 64 VLQ encoded value.
39
+ def self.encode(int)
40
+
41
+ vlq = to_vlq_signed(int)
42
+ encoded = []
43
+
44
+ begin
45
+ digit = vlq & VLQ_BASE_MASK
46
+ vlq >>= VLQ_BASE_SHIFT
47
+ digit |= VLQ_CONTINUATION_BIT if vlq > 0
48
+ encoded << base64_encode(digit)
49
+ end while vlq > 0
50
+
51
+ encoded.join
52
+ end
53
+
54
+ # Decodes the next base 64 VLQ value from the given string and returns the
55
+ # value and the rest of the string.
56
+ def self.decode(str)
57
+
58
+ vlq = 0
59
+ shift = 0
60
+ continue = true
61
+ chars = str.split('')
62
+
63
+ while continue
64
+ char = chars.shift or raise "Expected more digits in base 64 VLQ value."
65
+ digit = base64_decode(char)
66
+ continue = false if (digit & VLQ_CONTINUATION_BIT) == 0
67
+ digit &= VLQ_BASE_MASK
68
+ vlq += digit << shift
69
+ shift += VLQ_BASE_SHIFT
70
+ end
71
+
72
+ [from_vlq_signed(vlq), chars.join('')]
73
+ end
74
+
75
+ # Decode an array of variable length quantities from the given string and
76
+ # return them.
77
+ def self.decode_array(str)
78
+ output = []
79
+ while str != ''
80
+ int, str = decode(str)
81
+ output << int
82
+ end
83
+ output
84
+ end
85
+
86
+ protected
87
+
88
+ def self.base64_encode(int)
89
+ BASE64_DIGITS[int] or raise ArgumentError, "#{int} is not a valid base64 digit"
90
+ end
91
+
92
+ def self.base64_decode(char)
93
+ BASE64_VALUES[char] or raise ArgumentError, "#{char} is not a valid base64 digit"
94
+ end
95
+
96
+ # Converts from a two's-complement integer to an integer where the
97
+ # sign bit is placed in the least significant bit. For example, as decimals:
98
+ # 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
99
+ # 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
100
+ def self.to_vlq_signed(int)
101
+ if int < 0
102
+ ((-int) << 1) + 1
103
+ else
104
+ int << 1
105
+ end
106
+ end
107
+
108
+ # Converts to a two's-complement value from a value where the sign bit is
109
+ # placed in the least significant bit. For example, as decimals:
110
+ #
111
+ # 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
112
+ # 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
113
+ def self.from_vlq_signed(vlq)
114
+ if vlq & 1 == 1
115
+ -(vlq >> 1)
116
+ else
117
+ vlq >> 1
118
+ end
119
+ end
120
+
121
+ end
122
+ end
@@ -7,6 +7,7 @@ class StringScanner
7
7
  @pos = 0
8
8
  @matched = nil
9
9
  @working = string
10
+ @match = []
10
11
  end
11
12
 
12
13
  def scan(regex)
@@ -15,12 +16,13 @@ class StringScanner
15
16
  result = regex.exec(#@working);
16
17
 
17
18
  if (result == null) {
18
- return this.matched = nil;
19
+ return #{self}.matched = nil;
19
20
  }
20
21
  else if (typeof(result) === 'object') {
21
22
  #@pos += result[0].length;
22
23
  #@working = #@working.substring(result[0].length);
23
24
  #@matched = result[0];
25
+ #@match = result;
24
26
 
25
27
  return result[0];
26
28
  }
@@ -36,16 +38,32 @@ class StringScanner
36
38
  }
37
39
  end
38
40
 
41
+ def [](idx)
42
+ %x{
43
+ var match = #@match;
44
+
45
+ if (idx < 0) {
46
+ idx += match.length;
47
+ }
48
+
49
+ if (idx < 0 || idx >= match.length) {
50
+ return nil;
51
+ }
52
+
53
+ return match[idx];
54
+ }
55
+ end
56
+
39
57
  def check(regex)
40
58
  %x{
41
59
  var regexp = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1)),
42
60
  result = regexp.exec(#@working);
43
61
 
44
62
  if (result == null) {
45
- return this.matched = nil;
63
+ return #{self}.matched = nil;
46
64
  }
47
65
 
48
- return this.matched = result[0];
66
+ return #{self}.matched = result[0];
49
67
  }
50
68
  end
51
69
 
@@ -63,14 +81,14 @@ class StringScanner
63
81
  var result = re.exec(#@working);
64
82
 
65
83
  if (result == null) {
66
- return this.matched = nil;
84
+ return #{self}.matched = nil;
67
85
  }
68
86
  else {
69
87
  var match_str = result[0];
70
88
  var match_len = match_str.length;
71
- this.matched = match_str;
72
- this.pos += match_len;
73
- this.working = this.working.substring(match_len);
89
+ #{self}.matched = match_str;
90
+ #{self}.pos += match_len;
91
+ #{self}.working = #{self}.working.substring(match_len);
74
92
  return match_len;
75
93
  }
76
94
  }
@@ -79,13 +97,13 @@ class StringScanner
79
97
  def get_byte()
80
98
  %x{
81
99
  var result = nil;
82
- if (this.pos < this.string.length) {
83
- this.pos += 1;
84
- result = this.matched = this.working.substring(0, 1);
85
- this.working = this.working.substring(1);
100
+ if (#{self}.pos < #{self}.string.length) {
101
+ #{self}.pos += 1;
102
+ result = #{self}.matched = #{self}.working.substring(0, 1);
103
+ #{self}.working = #{self}.working.substring(1);
86
104
  }
87
105
  else {
88
- this.matched = nil;
106
+ #{self}.matched = nil;
89
107
  }
90
108
 
91
109
  return result;
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  class Class
4
4
  def get_inherited_classes
5
- `#{self}._inherited`
5
+ `#{self}._inherited || []`
6
6
  end
7
7
  end
8
8
 
@@ -9,7 +9,9 @@
9
9
  };
10
10
  }
11
11
 
12
- class BridgeClassSpec < `BridgeClassProto`
12
+ Class.bridge_class :BridgeClassSpec, `BridgeClassProto`
13
+
14
+ class BridgeClassSpec
13
15
  def get_foo
14
16
  `#{self}.foo`
15
17
  end
@@ -19,7 +21,7 @@ class BridgeClassSpec < `BridgeClassProto`
19
21
  end
20
22
  end
21
23
 
22
- describe "Bridging native prototypes to a class" do
24
+ describe "Class#bridge_class" do
23
25
  it "should have a superclass of Object" do
24
26
  BridgeClassSpec.superclass.should == Object
25
27
  end
@@ -34,4 +36,4 @@ describe "Bridging native prototypes to a class" do
34
36
  obj.get_foo.should == 200
35
37
  obj.say_it.should == "hello world"
36
38
  end
37
- end
39
+ end
@@ -1,5 +1,4 @@
1
1
  require File.expand_path('../../../spec_helper', __FILE__)
2
- require File.expand_path('../fixtures/classes', __FILE__)
3
2
 
4
3
  describe 'Class definition returning its last value' do
5
4
  it 'with a number' do
@@ -0,0 +1,15 @@
1
+ # No real support, just mocking
2
+
3
+ describe "Kernel#freeze" do
4
+ it 'responds to #freeze and #frozen?' do
5
+ o = mock('o')
6
+ o.frozen?.should be_false
7
+ o.freeze
8
+ o.frozen?.should be_true
9
+ end
10
+
11
+ it "returns self" do
12
+ o = Object.new
13
+ o.freeze.should equal(o)
14
+ end
15
+ end
@@ -1,5 +1,4 @@
1
1
  require File.expand_path('../../../spec_helper', __FILE__)
2
- require File.expand_path('../fixtures/classes', __FILE__)
3
2
 
4
3
  describe "Module#module_function with specific method names" do
5
4
  it "creates duplicates of the given instance methods on the Module object" do
@@ -20,6 +20,14 @@ require 'spec_helper'
20
20
 
21
21
  child_object: {
22
22
  grand_child: 100
23
+ },
24
+
25
+ func_returning_null: function() {
26
+ return null;
27
+ },
28
+
29
+ func_returning_undefined: function() {
30
+ return undefined;
23
31
  }
24
32
  };
25
33
  }
@@ -71,13 +79,18 @@ describe "Native objects" do
71
79
  @obj.check_args(1, 2, 3).should == [1, 2, 3]
72
80
  end
73
81
 
74
- it "tries to convert each argument with to_native if defined" do
82
+ it "tries to convert each argument with to_n if defined" do
75
83
  obj, obj2, obj3 = Object.new, Object.new, Object.new
76
- def obj.to_native; "foo"; end
77
- def obj2.to_native; 42; end
84
+ def obj.to_n; "foo"; end
85
+ def obj2.to_n; 42; end
78
86
 
79
87
  @obj.check_args(obj, obj2, obj3).should == ["foo", 42, obj3]
80
88
  end
89
+
90
+ it "converts null/undefined values to nil from function" do
91
+ @obj.func_returning_null.should be_nil
92
+ @obj.func_returning_undefined.should be_nil
93
+ end
81
94
  end
82
95
 
83
96
  describe "#[]" do
@@ -110,6 +123,22 @@ describe "Native objects" do
110
123
  end
111
124
  end
112
125
 
126
+ describe "#[]=" do
127
+ it "sets values on the receiver object" do
128
+ object = `{}`
129
+
130
+ object["foo"] = 42
131
+ object["foo"].should == 42
132
+ end
133
+
134
+ it "sets null on the object when nil given as value" do
135
+ object = `{}`
136
+
137
+ object["foo"] = nil
138
+ `(object.foo === null)`.should be_true
139
+ end
140
+ end
141
+
113
142
  describe "==" do
114
143
  it "returns true if the wrapped objects are `===` to each other" do
115
144
  %x{
@@ -124,4 +153,57 @@ describe "Native objects" do
124
153
  (a == c).should be_false
125
154
  end
126
155
  end
156
+
157
+ describe "each" do
158
+ describe "with an array-like object" do
159
+ it "yields each element to block" do
160
+ object = `{ "0": 3.142, "1": 42, "length": 2 }`
161
+ result = []
162
+
163
+ object.each { |obj| result << obj }
164
+ result.should == [3.142, 42]
165
+ end
166
+
167
+ it "yields null and undefined values as nil" do
168
+ object = `{length: 3, 0: null, 1: undefined}`
169
+ result = []
170
+
171
+ object.each { |obj| result << obj }
172
+ result.should == [nil, nil, nil]
173
+ end
174
+ end
175
+
176
+ describe "with a normal js object" do
177
+ it "yields each key-value pair to the block" do
178
+ object = `{"foo": 3.142, "bar": 42}`
179
+ result = []
180
+
181
+ object.each { |k, v| result << [k, v] }
182
+ result.should == [["foo", 3.142], ["bar", 42]]
183
+ end
184
+
185
+ it "yields null and undefined values as nil" do
186
+ object = `{"foo": null, "bar": undefined}`
187
+ result = []
188
+
189
+ object.each { |k, v| result << v }
190
+ result.should == [nil, nil]
191
+ end
192
+ end
193
+ end
194
+
195
+ describe "#to_h" do
196
+ it "converts a simple js object into a ruby hash" do
197
+ object = `{"foo": true, "bar": 42}`
198
+ hash = object.to_h
199
+
200
+ hash.should be_kind_of(Hash)
201
+ hash.should == {"foo" => true, "bar" => 42}
202
+ end
203
+
204
+ it "converts all null and undefined values to nil" do
205
+ object = `{"a": null, "b": undefined}`
206
+ object.to_h.should == {"a" => nil, "b" => nil}
207
+ end
208
+ end
127
209
  end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Numeric#==" do
4
+ it "should be true when two js Number objects are compared" do
5
+ first = `new Number(42)`
6
+ second = `new Number(42)`
7
+ first.should == second
8
+ end
9
+ end