opal 0.3.44 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -1
- data/CHANGELOG.md +52 -0
- data/README.md +3 -3
- data/Rakefile +32 -8
- data/bin/opal +69 -16
- data/config.ru +1 -1
- data/examples/native/app/app.rb +28 -9
- data/examples/rack/app/app.rb +1 -1
- data/lib/opal.rb +0 -1
- data/lib/opal/cli.rb +106 -0
- data/lib/opal/lexer.rb +4 -2
- data/lib/opal/parser.rb +603 -360
- data/lib/opal/processor.rb +20 -8
- data/lib/opal/server.rb +47 -0
- data/lib/opal/source_map.rb +63 -0
- data/lib/opal/sprockets_parser.rb +77 -0
- data/lib/opal/sprockets_source_map_header.rb +21 -0
- data/lib/opal/target_scope.rb +14 -7
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +2 -0
- data/opal/opal-browser/script_loader.rb +7 -7
- data/opal/opal-parser.js.erb +2 -2
- data/opal/opal-source-maps.js.erb +2 -0
- data/opal/opal.rb +3 -4
- data/opal/opal/array.rb +31 -28
- data/opal/opal/boolean.rb +4 -0
- data/opal/opal/class.rb +14 -5
- data/opal/opal/enumerable.rb +68 -8
- data/opal/opal/error.rb +1 -1
- data/opal/opal/hash.rb +15 -18
- data/opal/opal/kernel.rb +24 -10
- data/opal/opal/native.rb +31 -0
- data/opal/opal/nil_class.rb +7 -2
- data/opal/opal/numeric.rb +10 -1
- data/opal/opal/proc.rb +4 -0
- data/opal/opal/range.rb +1 -1
- data/opal/opal/regexp.rb +13 -3
- data/opal/opal/runtime.js +134 -51
- data/opal/opal/string.rb +45 -22
- data/opal/opal/time.rb +25 -7
- data/opal/source_map.rb +63 -0
- data/opal/source_map/generator.rb +251 -0
- data/opal/source_map/parser.rb +102 -0
- data/opal/source_map/vlq.rb +122 -0
- data/opal/strscan.rb +30 -12
- data/spec/opal/class/_inherited_spec.rb +1 -1
- data/spec/{rubyspec/core → opal}/class/bridge_class_spec.rb +5 -3
- data/spec/{rubyspec/core → opal}/class/extend_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/class/instance_methods_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/class/last_value_spec.rb +0 -1
- data/spec/{rubyspec/core → opal}/json/parse_spec.rb +0 -0
- data/spec/{rubyspec/core/kernel/block_given.rb → opal/kernel/block_given_spec.rb} +0 -0
- data/spec/{rubyspec/core → opal}/kernel/class_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/extend_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/format_spec.rb +0 -0
- data/spec/opal/kernel/freeze_spec.rb +15 -0
- data/spec/{rubyspec/core → opal}/kernel/match_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/method_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/methods_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/nil_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/p_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/printf_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/proc_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/rand_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/respond_to_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/sprintf_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/kernel/to_json_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/alias_method_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/ancestors_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/append_features_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/constants_spec.rb +0 -0
- data/spec/{rubyspec/core → opal}/module/module_function_spec.rb +0 -1
- data/spec/opal/native_spec.rb +85 -3
- data/spec/opal/numeric/equal_spec.rb +9 -0
- data/spec/opal/parser/irb_spec.rb +43 -0
- data/spec/{rubyspec/core → opal}/proc/proc_tricks_spec.rb +0 -0
- data/spec/opal/runtime/block_send_spec.rb +28 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/call_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/class_hierarchy_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/def_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/defined_spec.rb +0 -0
- data/spec/{rubyspec/core/runtime → opal/runtime2}/super_spec.rb +0 -0
- data/spec/opal/source_map_spec.rb +19 -0
- data/spec/opal/string/freeze_spec.rb +15 -0
- data/spec/{rubyspec/core → opal}/string/to_json_spec.rb +0 -0
- data/spec/ospec/runner.rb +3 -0
- data/spec/parser/str_spec.rb +4 -0
- data/spec/rubyspec/core/enumerable/fixtures/classes.rb +2 -2
- data/spec/rubyspec/core/enumerable/none_spec.rb +68 -0
- data/spec/rubyspec/core/enumerable/sort_by_spec.rb +31 -0
- data/spec/rubyspec/core/hash/size_spec.rb +1 -1
- data/spec/rubyspec/core/hash/to_native_spec.rb +3 -3
- data/spec/rubyspec/core/string/fixtures/classes.rb +49 -0
- data/spec/rubyspec/core/string/index_spec.rb +405 -0
- data/spec/rubyspec/filters/bugs/language/class.rb +0 -2
- data/spec/rubyspec/filters/bugs/language/module.rb +3 -0
- data/spec/rubyspec/language/array_spec.rb +1 -1
- data/spec/rubyspec/language/block_spec.rb +1 -1
- data/spec/rubyspec/language/module_spec.rb +5 -5
- data/spec/rubyspec/language/predefined_spec.rb +1 -2
- data/spec/rubyspec/library/stringscanner/element_reference_spec.rb +29 -0
- data/spec/rubyspec/spec_helper.rb +31 -0
- metadata +130 -76
- data/lib/opal/erb.rb +0 -41
- data/opal/erb.rb +0 -19
- data/spec/opal/erb/erb_spec.rb +0 -31
- data/spec/simple_erb_template.opalerb +0 -1
- data/spec/templates/foo/bar.opalerb +0 -1
- 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
|
data/opal/strscan.rb
CHANGED
@@ -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
|
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
|
63
|
+
return #{self}.matched = nil;
|
46
64
|
}
|
47
65
|
|
48
|
-
return
|
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
|
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
|
-
|
72
|
-
|
73
|
-
|
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 (
|
83
|
-
|
84
|
-
result =
|
85
|
-
|
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
|
-
|
106
|
+
#{self}.matched = nil;
|
89
107
|
}
|
90
108
|
|
91
109
|
return result;
|
@@ -9,7 +9,9 @@
|
|
9
9
|
};
|
10
10
|
}
|
11
11
|
|
12
|
-
|
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 "
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/opal/native_spec.rb
CHANGED
@@ -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
|
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.
|
77
|
-
def obj2.
|
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
|