opal 0.3.39 → 0.3.40
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +14 -0
- data/Rakefile +7 -0
- data/lib/assets/javascripts/opal/array.rb +12 -10
- data/lib/assets/javascripts/opal/basic_object.rb +8 -1
- data/lib/assets/javascripts/opal/class.rb +15 -1
- data/lib/assets/javascripts/opal/date.rb +1 -1
- data/lib/assets/javascripts/opal/enumerator.rb +30 -0
- data/lib/assets/javascripts/opal/error.rb +12 -10
- data/lib/assets/javascripts/opal/hash.rb +1 -1
- data/lib/assets/javascripts/opal/kernel.rb +5 -1
- data/lib/assets/javascripts/opal/numeric.rb +2 -0
- data/lib/assets/javascripts/opal/regexp.rb +1 -1
- data/lib/assets/javascripts/opal/runtime.js +12 -0
- data/lib/assets/javascripts/opal/string.rb +4 -4
- data/lib/assets/javascripts/opal/time.rb +1 -1
- data/lib/opal.rb +1 -0
- data/lib/opal/parser.rb +35 -11
- data/lib/opal/processor.rb +5 -3
- data/lib/opal/server.rb +92 -0
- data/lib/opal/version.rb +1 -1
- data/spec/core/array/each_spec.rb +5 -1
- data/spec/core/enumerator/each_spec.rb +11 -0
- data/spec/core/enumerator/new_spec.rb +17 -0
- data/spec/core/enumerator/next_spec.rb +25 -0
- data/spec/core/enumerator/rewind_spec.rb +28 -0
- data/spec/core/module/const_set_spec.rb +65 -0
- data/spec/core_ext/basic_object/send_spec.rb +28 -0
- data/spec/core_ext/constants_spec.rb +13 -0
- data/spec/spec_helper.rb +5 -0
- metadata +18 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.3.40 2013-02-23
|
2
|
+
|
3
|
+
* Add Opal::Server as an easy to configure rack server for testing and
|
4
|
+
running Opal based apps.
|
5
|
+
|
6
|
+
* Added optional arity check mode for parser. When turned on, every method
|
7
|
+
will have code which checks the argument arity. Off by default.
|
8
|
+
|
9
|
+
* Exception subclasses now relfect their name in webkit/firefox debuggers
|
10
|
+
to show both their class name and message.
|
11
|
+
|
12
|
+
* Add Class#const_set. Trying to access undefined constants by a literal
|
13
|
+
constant will now also raise a NameError.
|
14
|
+
|
1
15
|
## 0.3.39 2013-02-20
|
2
16
|
|
3
17
|
* Fix bug where methods defined on a parent class after subclass was defined
|
data/Rakefile
CHANGED
@@ -4,6 +4,13 @@ Bundler.require
|
|
4
4
|
require 'opal/spec/rake_task'
|
5
5
|
Opal::Spec::RakeTask.new(:default)
|
6
6
|
|
7
|
+
desc "Run tests with method_missing turned off"
|
8
|
+
task :test_no_method_missing do
|
9
|
+
# some specs will fail (namely method_missing based specs)
|
10
|
+
Opal::Processor.method_missing_enabled = false
|
11
|
+
Rake::Task[:default].invoke
|
12
|
+
end
|
13
|
+
|
7
14
|
desc "Check file sizes for opal.js runtime"
|
8
15
|
task :sizes do
|
9
16
|
o = Opal::Environment.new['opal'].to_s
|
@@ -8,7 +8,7 @@ class Array < `Array`
|
|
8
8
|
objects
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.new(size, obj = nil, &block)
|
11
|
+
def self.new(size = undefined, obj = nil, &block)
|
12
12
|
%x{
|
13
13
|
var arr = [];
|
14
14
|
|
@@ -301,7 +301,7 @@ class Array < `Array`
|
|
301
301
|
self
|
302
302
|
end
|
303
303
|
|
304
|
-
def count(object)
|
304
|
+
def count(object = undefined)
|
305
305
|
%x{
|
306
306
|
if (object == null) {
|
307
307
|
return #{self}.length;
|
@@ -380,6 +380,8 @@ class Array < `Array`
|
|
380
380
|
alias dup clone
|
381
381
|
|
382
382
|
def each(&block)
|
383
|
+
return enum_for :each unless block_given?
|
384
|
+
|
383
385
|
`for (var i = 0, length = #{self}.length; i < length; i++) {`
|
384
386
|
yield `#{self}[i]`
|
385
387
|
`}`
|
@@ -399,7 +401,7 @@ class Array < `Array`
|
|
399
401
|
`!#{self}.length`
|
400
402
|
end
|
401
403
|
|
402
|
-
def fetch(index, defaults, &block)
|
404
|
+
def fetch(index, defaults = undefined, &block)
|
403
405
|
%x{
|
404
406
|
var original = index;
|
405
407
|
|
@@ -440,7 +442,7 @@ class Array < `Array`
|
|
440
442
|
self
|
441
443
|
end
|
442
444
|
|
443
|
-
def first(count)
|
445
|
+
def first(count = undefined)
|
444
446
|
%x{
|
445
447
|
if (count != null) {
|
446
448
|
return #{self}.slice(0, count);
|
@@ -450,7 +452,7 @@ class Array < `Array`
|
|
450
452
|
}
|
451
453
|
end
|
452
454
|
|
453
|
-
def flatten(level)
|
455
|
+
def flatten(level = undefined)
|
454
456
|
%x{
|
455
457
|
var result = [];
|
456
458
|
|
@@ -477,7 +479,7 @@ class Array < `Array`
|
|
477
479
|
}
|
478
480
|
end
|
479
481
|
|
480
|
-
def flatten!(level)
|
482
|
+
def flatten!(level = undefined)
|
481
483
|
%x{
|
482
484
|
var size = #{self}.length;
|
483
485
|
#{replace flatten level};
|
@@ -601,7 +603,7 @@ class Array < `Array`
|
|
601
603
|
self
|
602
604
|
end
|
603
605
|
|
604
|
-
def last(count)
|
606
|
+
def last(count = undefined)
|
605
607
|
%x{
|
606
608
|
var length = #{self}.length;
|
607
609
|
|
@@ -628,7 +630,7 @@ class Array < `Array`
|
|
628
630
|
|
629
631
|
alias map! collect!
|
630
632
|
|
631
|
-
def pop(count)
|
633
|
+
def pop(count = undefined)
|
632
634
|
%x{
|
633
635
|
var length = #{self}.length;
|
634
636
|
|
@@ -772,7 +774,7 @@ class Array < `Array`
|
|
772
774
|
}
|
773
775
|
end
|
774
776
|
|
775
|
-
def shift(count)
|
777
|
+
def shift(count = undefined)
|
776
778
|
%x{
|
777
779
|
if (#{self}.length === 0) {
|
778
780
|
return nil;
|
@@ -799,7 +801,7 @@ class Array < `Array`
|
|
799
801
|
|
800
802
|
alias slice :[]
|
801
803
|
|
802
|
-
def slice!(index, length)
|
804
|
+
def slice!(index, length = undefined)
|
803
805
|
%x{
|
804
806
|
if (index < 0) {
|
805
807
|
index += #{self}.length;
|
@@ -8,7 +8,14 @@ class BasicObject
|
|
8
8
|
|
9
9
|
def __send__(symbol, *args, &block)
|
10
10
|
%x{
|
11
|
-
|
11
|
+
var func = #{self}['$' + symbol]
|
12
|
+
|
13
|
+
if (func) {
|
14
|
+
if (block !== nil) { args.push(block); }
|
15
|
+
return func.apply(#{self}, args);
|
16
|
+
}
|
17
|
+
|
18
|
+
return #{self}.$method_missing.apply(#{self}, [symbol].concat(args));
|
12
19
|
}
|
13
20
|
end
|
14
21
|
|
@@ -141,6 +141,20 @@ class Class
|
|
141
141
|
}
|
142
142
|
end
|
143
143
|
|
144
|
+
def const_set(name, value)
|
145
|
+
raise NameError, "wrong constant name #{name}" unless name =~ /^[A-Z]/
|
146
|
+
raise NameError, "wrong constant name #{name}" unless name =~ /^[\w_]+$/
|
147
|
+
begin
|
148
|
+
name = name.to_str
|
149
|
+
rescue
|
150
|
+
raise TypeError, 'conversion with #to_str failed'
|
151
|
+
end
|
152
|
+
%x{
|
153
|
+
#{self}._scope[name] = #{value};
|
154
|
+
return #{value}
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
144
158
|
def define_method(name, &block)
|
145
159
|
%x{
|
146
160
|
if (block === nil) {
|
@@ -224,7 +238,7 @@ class Class
|
|
224
238
|
`#{self}._name`
|
225
239
|
end
|
226
240
|
|
227
|
-
def new()
|
241
|
+
def new(*)
|
228
242
|
%x{
|
229
243
|
var args = __slice.call(arguments);
|
230
244
|
var obj = new #{self};
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Enumerator
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
def initialize(obj, method = :each, *args)
|
5
|
+
@object = obj
|
6
|
+
@method = method
|
7
|
+
@args = args
|
8
|
+
end
|
9
|
+
|
10
|
+
def each(&block)
|
11
|
+
return enum_for :each unless block_given?
|
12
|
+
|
13
|
+
@object.__send__(@method, *@args) do |e|
|
14
|
+
block.call e
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def next
|
19
|
+
@cache ||= to_a
|
20
|
+
|
21
|
+
raise StopIteration, 'end of enumeration' if @cache.empty?
|
22
|
+
|
23
|
+
@cache.shift
|
24
|
+
end
|
25
|
+
|
26
|
+
def rewind
|
27
|
+
@cache = nil
|
28
|
+
self
|
29
|
+
end
|
30
|
+
end
|
@@ -5,6 +5,7 @@ class Exception < `Error`
|
|
5
5
|
%x{
|
6
6
|
var err = new Error(message);
|
7
7
|
err._klass = #{self};
|
8
|
+
err.name = #{self}._name;
|
8
9
|
return err;
|
9
10
|
}
|
10
11
|
end
|
@@ -31,13 +32,14 @@ class Exception < `Error`
|
|
31
32
|
alias to_s message
|
32
33
|
end
|
33
34
|
|
34
|
-
StandardError
|
35
|
-
RuntimeError
|
36
|
-
LocalJumpError
|
37
|
-
TypeError
|
38
|
-
NameError
|
39
|
-
NoMethodError
|
40
|
-
ArgumentError
|
41
|
-
IndexError
|
42
|
-
KeyError
|
43
|
-
RangeError
|
35
|
+
class StandardError < Exception; end
|
36
|
+
class RuntimeError < Exception; end
|
37
|
+
class LocalJumpError < Exception; end
|
38
|
+
class TypeError < Exception; end
|
39
|
+
class NameError < Exception; end
|
40
|
+
class NoMethodError < Exception; end
|
41
|
+
class ArgumentError < Exception; end
|
42
|
+
class IndexError < Exception; end
|
43
|
+
class KeyError < Exception; end
|
44
|
+
class RangeError < Exception; end
|
45
|
+
class StopIteration < Exception; end
|
@@ -92,6 +92,10 @@ module Kernel
|
|
92
92
|
}
|
93
93
|
end
|
94
94
|
|
95
|
+
def enum_for(method = :each, *args)
|
96
|
+
Enumerator.new self, method, *args
|
97
|
+
end
|
98
|
+
|
95
99
|
def equal?(other)
|
96
100
|
`#{self} === other`
|
97
101
|
end
|
@@ -364,7 +368,7 @@ module Kernel
|
|
364
368
|
}
|
365
369
|
end
|
366
370
|
|
367
|
-
def rand(max)
|
371
|
+
def rand(max = undefined)
|
368
372
|
`max == null ? Math.random() : Math.floor(Math.random() * max)`
|
369
373
|
end
|
370
374
|
|
@@ -240,6 +240,18 @@
|
|
240
240
|
}
|
241
241
|
};
|
242
242
|
|
243
|
+
// Const missing dispatcher
|
244
|
+
Opal.cm = function(name) {
|
245
|
+
throw Opal.NameError.$new('uninitialized constant ' + name);
|
246
|
+
};
|
247
|
+
|
248
|
+
// Arity count error dispatcher
|
249
|
+
Opal.ac = function(actual, expected, object, meth) {
|
250
|
+
var inspect = (object._isObject ? object._klass._name + '#' : object._name + '.') + meth;
|
251
|
+
var msg = '[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')'
|
252
|
+
throw Opal.ArgumentError.$new(msg);
|
253
|
+
}
|
254
|
+
|
243
255
|
// Initialization
|
244
256
|
// --------------
|
245
257
|
|
@@ -90,7 +90,7 @@ class String < `String`
|
|
90
90
|
}
|
91
91
|
end
|
92
92
|
|
93
|
-
def [](index, length)
|
93
|
+
def [](index, length = undefined)
|
94
94
|
%x{
|
95
95
|
var size = #{self}.length;
|
96
96
|
|
@@ -243,7 +243,7 @@ class String < `String`
|
|
243
243
|
|
244
244
|
alias_native :getbyte, :charCodeAt
|
245
245
|
|
246
|
-
def gsub(pattern, replace)
|
246
|
+
def gsub(pattern, replace = undefined)
|
247
247
|
if pattern.is_a?(String)
|
248
248
|
pattern = /#{Regexp.escape(pattern)}/
|
249
249
|
end
|
@@ -346,7 +346,7 @@ class String < `String`
|
|
346
346
|
`#{self}.replace(/^\\s*/, '')`
|
347
347
|
end
|
348
348
|
|
349
|
-
def match(pattern, pos, &block)
|
349
|
+
def match(pattern, pos = undefined, &block)
|
350
350
|
(pattern.is_a?(Regexp) ? pattern : /#{Regexp.escape(pattern)}/).match(self, pos, &block)
|
351
351
|
end
|
352
352
|
|
@@ -507,7 +507,7 @@ class String < `String`
|
|
507
507
|
%x{
|
508
508
|
var name = '$' + #{self};
|
509
509
|
|
510
|
-
return function(arg) { return arg[name](
|
510
|
+
return function(arg) { return arg[name](); };
|
511
511
|
}
|
512
512
|
end
|
513
513
|
|
@@ -5,7 +5,7 @@ class Time < `Date`
|
|
5
5
|
`new Date(seconds * 1000 + frac)`
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.new(year, month, day, hour, minute, second, millisecond)
|
8
|
+
def self.new(year = undefined, month = undefined, day = undefined, hour = undefined, minute = undefined, second = undefined, millisecond = undefined)
|
9
9
|
%x{
|
10
10
|
switch (arguments.length) {
|
11
11
|
case 1:
|
data/lib/opal.rb
CHANGED
data/lib/opal/parser.rb
CHANGED
@@ -99,6 +99,7 @@ module Opal
|
|
99
99
|
@file = options[:file] || '(file)'
|
100
100
|
@method_missing = (options[:method_missing] != false)
|
101
101
|
@optimized_operators = (options[:optimized_operators] != false)
|
102
|
+
@arity_check = options[:arity_check]
|
102
103
|
|
103
104
|
top @grammar.parse(source, @file)
|
104
105
|
end
|
@@ -875,7 +876,7 @@ module Opal
|
|
875
876
|
|
876
877
|
unless work.empty?
|
877
878
|
join = work.join ', '
|
878
|
-
code += (code.empty? ? join : ".concat([#{
|
879
|
+
code += (code.empty? ? join : ".concat([#{join}])")
|
879
880
|
end
|
880
881
|
|
881
882
|
code
|
@@ -1043,6 +1044,7 @@ module Opal
|
|
1043
1044
|
params = nil
|
1044
1045
|
scope_name = nil
|
1045
1046
|
uses_super = nil
|
1047
|
+
uses_splat = nil
|
1046
1048
|
|
1047
1049
|
# opt args if last arg is sexp
|
1048
1050
|
opt = args.pop if Array === args.last
|
@@ -1057,8 +1059,9 @@ module Opal
|
|
1057
1059
|
|
1058
1060
|
# splat args *splat
|
1059
1061
|
if args.last.to_s.start_with? '*'
|
1062
|
+
uses_splat = true
|
1060
1063
|
if args.last == :*
|
1061
|
-
args
|
1064
|
+
#args[-1] = splat
|
1062
1065
|
argc -= 1
|
1063
1066
|
else
|
1064
1067
|
splat = args[-1].to_s[1..-1].to_sym
|
@@ -1069,6 +1072,10 @@ module Opal
|
|
1069
1072
|
|
1070
1073
|
args << block_name if block_name # have to re-add incase there was a splat arg
|
1071
1074
|
|
1075
|
+
if @arity_check
|
1076
|
+
arity_code = arity_check(args, opt, uses_splat, block_name, mid) + "\n#{INDENT}"
|
1077
|
+
end
|
1078
|
+
|
1072
1079
|
indent do
|
1073
1080
|
in_scope(:def) do
|
1074
1081
|
@scope.mid = mid
|
@@ -1137,7 +1144,7 @@ module Opal
|
|
1137
1144
|
|
1138
1145
|
uses_super = @scope.uses_super
|
1139
1146
|
|
1140
|
-
code = "#@indent#{@scope.to_vars}" + code
|
1147
|
+
code = "#{arity_code}#@indent#{@scope.to_vars}" + code
|
1141
1148
|
end
|
1142
1149
|
end
|
1143
1150
|
|
@@ -1167,17 +1174,22 @@ module Opal
|
|
1167
1174
|
|
1168
1175
|
##
|
1169
1176
|
# Returns code used in debug mode to check arity of method call
|
1170
|
-
def arity_check(args, opt, splat)
|
1177
|
+
def arity_check(args, opt, splat, block_name, mid)
|
1178
|
+
meth = mid.to_s.inspect
|
1179
|
+
|
1171
1180
|
arity = args.size - 1
|
1172
1181
|
arity -= (opt.size - 1) if opt
|
1173
1182
|
arity -= 1 if splat
|
1183
|
+
arity -= 1 if block_name
|
1174
1184
|
arity = -arity - 1 if opt or splat
|
1175
1185
|
|
1176
|
-
|
1186
|
+
# $arity will point to our received arguments count
|
1187
|
+
aritycode = "var $arity = arguments.length;"
|
1188
|
+
|
1177
1189
|
if arity < 0 # splat or opt args
|
1178
|
-
aritycode + "if ($arity < #{-(arity + 1)}) {
|
1190
|
+
aritycode + "if ($arity < #{-(arity + 1)}) { __opal.ac($arity, #{arity}, this, #{meth}); }"
|
1179
1191
|
else
|
1180
|
-
aritycode + "if ($arity !== #{arity}) {
|
1192
|
+
aritycode + "if ($arity !== #{arity} && (typeof(arguments[$arity - 1]) !== 'function' || ($arity - 1) !== #{arity})) { __opal.ac($arity, #{arity}, this, #{meth}); }"
|
1181
1193
|
end
|
1182
1194
|
end
|
1183
1195
|
|
@@ -1186,6 +1198,7 @@ module Opal
|
|
1186
1198
|
|
1187
1199
|
until exp.empty?
|
1188
1200
|
a = exp.shift.to_sym
|
1201
|
+
next if a.to_s == '*'
|
1189
1202
|
a = "#{a}$".to_sym if RESERVED.include? a.to_s
|
1190
1203
|
@scope.add_arg a
|
1191
1204
|
args << a
|
@@ -1473,7 +1486,11 @@ module Opal
|
|
1473
1486
|
|
1474
1487
|
# s(:const, :const)
|
1475
1488
|
def process_const(sexp, level)
|
1476
|
-
|
1489
|
+
cname = sexp.shift.to_s
|
1490
|
+
|
1491
|
+
with_temp do |t|
|
1492
|
+
"((#{t} = __scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})"
|
1493
|
+
end
|
1477
1494
|
end
|
1478
1495
|
|
1479
1496
|
# s(:cdecl, :const, rhs)
|
@@ -1811,12 +1828,19 @@ module Opal
|
|
1811
1828
|
# s(:colon2, base, :NAME)
|
1812
1829
|
def process_colon2(sexp, level)
|
1813
1830
|
base = sexp[0]
|
1814
|
-
|
1815
|
-
|
1831
|
+
cname = sexp[1].to_s
|
1832
|
+
|
1833
|
+
with_temp do |t|
|
1834
|
+
base = process base, :expr
|
1835
|
+
"((#{t} = (#{base})._scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})"
|
1836
|
+
end
|
1816
1837
|
end
|
1817
1838
|
|
1818
1839
|
def process_colon3(exp, level)
|
1819
|
-
|
1840
|
+
with_temp do |t|
|
1841
|
+
cname = exp.shift.to_s
|
1842
|
+
"((#{t} = __opal.Object._scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})"
|
1843
|
+
end
|
1820
1844
|
end
|
1821
1845
|
|
1822
1846
|
# super a, b, c
|
data/lib/opal/processor.rb
CHANGED
@@ -12,22 +12,24 @@ module Opal
|
|
12
12
|
class << self
|
13
13
|
attr_accessor :method_missing_enabled
|
14
14
|
attr_accessor :optimized_operators_enabled
|
15
|
+
attr_accessor :arity_check_enabled
|
15
16
|
end
|
16
17
|
|
17
18
|
self.method_missing_enabled = true
|
18
19
|
self.optimized_operators_enabled = true
|
20
|
+
self.arity_check_enabled = false
|
19
21
|
|
20
22
|
def initialize_engine
|
21
23
|
require_template_library 'opal'
|
22
24
|
end
|
23
25
|
|
24
26
|
def prepare
|
25
|
-
# ...
|
26
27
|
end
|
27
28
|
|
28
29
|
def evaluate(context, locals, &block)
|
29
|
-
options = { :method_missing
|
30
|
-
:optimized_operators
|
30
|
+
options = { :method_missing => self.class.method_missing_enabled,
|
31
|
+
:optimized_operators => self.class.optimized_operators_enabled,
|
32
|
+
:arity_check => self.class.arity_check_enabled }
|
31
33
|
|
32
34
|
parser = Opal::Parser.new
|
33
35
|
result = parser.parse data, options
|
data/lib/opal/server.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'opal'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Opal
|
5
|
+
class Server
|
6
|
+
|
7
|
+
attr_accessor :debug, :index_path, :main, :public_dir, :sprockets
|
8
|
+
|
9
|
+
def initialize(debug = true)
|
10
|
+
@sprockets = Opal::Environment.new
|
11
|
+
@public_dir = '.'
|
12
|
+
@debug = debug
|
13
|
+
|
14
|
+
yield self if block_given?
|
15
|
+
create_app
|
16
|
+
end
|
17
|
+
|
18
|
+
def append_path(path)
|
19
|
+
@sprockets.append_path path
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_app
|
23
|
+
server, sprockets = self, @sprockets
|
24
|
+
|
25
|
+
@app = Rack::Builder.app do
|
26
|
+
map('/assets') { run sprockets }
|
27
|
+
use Index, server
|
28
|
+
run Rack::Directory.new(server.public_dir)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(env)
|
33
|
+
@app.call env
|
34
|
+
end
|
35
|
+
|
36
|
+
class Index
|
37
|
+
|
38
|
+
def initialize(app, server)
|
39
|
+
@app = app
|
40
|
+
@server = server
|
41
|
+
@index_path = server.index_path
|
42
|
+
end
|
43
|
+
|
44
|
+
def call(env)
|
45
|
+
if %w[/ /index.html].include? env['PATH_INFO']
|
46
|
+
[200, { 'Content-Type' => 'text/html' }, [html]]
|
47
|
+
else
|
48
|
+
@app.call env
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def html
|
53
|
+
source = if @index_path
|
54
|
+
raise "index does not exist: #{@index_path}" unless File.exist?(@index_path)
|
55
|
+
File.read @index_path
|
56
|
+
else
|
57
|
+
SOURCE
|
58
|
+
end
|
59
|
+
|
60
|
+
ERB.new(source).result binding
|
61
|
+
end
|
62
|
+
|
63
|
+
def javascript_include_tag(source)
|
64
|
+
if @server.debug
|
65
|
+
assets = @server.sprockets[source].to_a
|
66
|
+
|
67
|
+
raise "Cannot find asset: #{source}" if assets.empty?
|
68
|
+
|
69
|
+
scripts = assets.map do |a|
|
70
|
+
%Q{<script src="/assets/#{ a.logical_path }?body=1"></script>}
|
71
|
+
end
|
72
|
+
|
73
|
+
scripts.join "\n"
|
74
|
+
else
|
75
|
+
"<script src=\"/assets/#{source}.js\"></script>"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
SOURCE = <<-HTML
|
80
|
+
<!DOCTYPE html>
|
81
|
+
<html>
|
82
|
+
<head>
|
83
|
+
<title>Opal Server</title>
|
84
|
+
</head>
|
85
|
+
<body>
|
86
|
+
<%= javascript_include_tag @server.main %>
|
87
|
+
</body>
|
88
|
+
</html>
|
89
|
+
HTML
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/opal/version.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
describe "Enumerator#each" do
|
2
|
+
it "yield each element of self to the given block" do
|
3
|
+
acc = []
|
4
|
+
enumerator_class.new([1, 2, 3]).each {|e| acc << e }
|
5
|
+
acc.should == [1,2,3]
|
6
|
+
end
|
7
|
+
|
8
|
+
it "returns an enumerator if no block is given" do
|
9
|
+
enumerator_class.new([1]).each.should be_kind_of(enumerator_class)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Enumerator#new" do
|
4
|
+
it "creates a new custom enumerator with the given object, iterator and arguments" do
|
5
|
+
enum = enumerator_class.new(1, :upto, 3)
|
6
|
+
enum.should be_kind_of(Enumerator)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "creates a new custom enumerator that responds to #each" do
|
10
|
+
enum = enumerator_class.new(1, :upto, 3)
|
11
|
+
enum.respond_to?(:each).should == true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "creates a new custom enumerator that runs correctly" do
|
15
|
+
enumerator_class.new(1, :upto, 3).map{|x|x}.should == [1,2,3]
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
describe "Enumerator#next" do
|
2
|
+
before :each do
|
3
|
+
@enum = enumerator_class.new(1, :upto, 3)
|
4
|
+
end
|
5
|
+
|
6
|
+
it "returns the next element of the enumeration" do
|
7
|
+
@enum.next.should == 1
|
8
|
+
@enum.next.should == 2
|
9
|
+
@enum.next.should == 3
|
10
|
+
end
|
11
|
+
|
12
|
+
it "raises a StopIteration exception at the end of the stream" do
|
13
|
+
3.times { @enum.next }
|
14
|
+
lambda { @enum.next }.should raise_error(StopIteration)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "cannot be called again until the enumerator is rewound" do
|
18
|
+
3.times { @enum.next }
|
19
|
+
lambda { @enum.next }.should raise_error(StopIteration)
|
20
|
+
lambda { @enum.next }.should raise_error(StopIteration)
|
21
|
+
lambda { @enum.next }.should raise_error(StopIteration)
|
22
|
+
@enum.rewind
|
23
|
+
@enum.next.should == 1
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
describe "Enumerator#rewind" do
|
2
|
+
before(:each) do
|
3
|
+
@enum = enumerator_class.new(1, :upto, 3)
|
4
|
+
end
|
5
|
+
|
6
|
+
it "resets the enumerator to its initial state" do
|
7
|
+
@enum.next.should == 1
|
8
|
+
@enum.next.should == 2
|
9
|
+
@enum.rewind
|
10
|
+
@enum.next.should == 1
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns self" do
|
14
|
+
@enum.rewind.should == @enum
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has no effect on a new enumerator" do
|
18
|
+
@enum.rewind
|
19
|
+
@enum.next.should == 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it "has no effect if called multiple, consecutive times" do
|
23
|
+
@enum.next.should == 1
|
24
|
+
@enum.rewind
|
25
|
+
@enum.rewind
|
26
|
+
@enum.next.should == 1
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
+
require File.expand_path('../../../fixtures/constants', __FILE__)
|
3
|
+
|
4
|
+
|
5
|
+
module ConstantSpecs
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Module#const_set" do
|
9
|
+
it "sets the constant specified by a String or Symbol to the given value" do
|
10
|
+
ConstantSpecs.const_set :CS_CONST401, :const401
|
11
|
+
ConstantSpecs::CS_CONST401.should == :const401
|
12
|
+
|
13
|
+
ConstantSpecs.const_set "CS_CONST402", :const402
|
14
|
+
ConstantSpecs.const_get(:CS_CONST402).should == :const402
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns the value set" do
|
18
|
+
ConstantSpecs.const_set(:CS_CONST403, :const403).should == :const403
|
19
|
+
end
|
20
|
+
|
21
|
+
# PENDING: needs proper parser implementation
|
22
|
+
#
|
23
|
+
# it "sets the name of an anonymous module" do
|
24
|
+
# m = Module.new
|
25
|
+
# ConstantSpecs.const_set(:CS_CONST1000, m)
|
26
|
+
# m.name.should == "ConstantSpecs::CS_CONST1000"
|
27
|
+
# end
|
28
|
+
|
29
|
+
it "raises a NameError if the name does not start with a capital letter" do
|
30
|
+
lambda { ConstantSpecs.const_set "name", 1 }.should raise_error(NameError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "raises a NameError if the name starts with a non-alphabetic character" do
|
34
|
+
lambda { ConstantSpecs.const_set "__CONSTX__", 1 }.should raise_error(NameError)
|
35
|
+
lambda { ConstantSpecs.const_set "@Name", 1 }.should raise_error(NameError)
|
36
|
+
lambda { ConstantSpecs.const_set "!Name", 1 }.should raise_error(NameError)
|
37
|
+
lambda { ConstantSpecs.const_set "::Name", 1 }.should raise_error(NameError)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "raises a NameError if the name contains non-alphabetic characters except '_'" do
|
41
|
+
ConstantSpecs.const_set("CS_CONST404", :const404).should == :const404
|
42
|
+
lambda { ConstantSpecs.const_set "Name=", 1 }.should raise_error(NameError)
|
43
|
+
lambda { ConstantSpecs.const_set "Name?", 1 }.should raise_error(NameError)
|
44
|
+
end
|
45
|
+
|
46
|
+
# PENDING: should_receive isn't available on opal-spec
|
47
|
+
#
|
48
|
+
# it "calls #to_str to convert the given name to a String" do
|
49
|
+
#
|
50
|
+
# name = mock("CS_CONST405")
|
51
|
+
# name.should_receive(:to_str).and_return("CS_CONST405")
|
52
|
+
# ConstantSpecs.const_set(name, :const405).should == :const405
|
53
|
+
# ConstantSpecs::CS_CONST405.should == :const405
|
54
|
+
# end
|
55
|
+
|
56
|
+
# PENDING: should_receive isn't available on opal-spec
|
57
|
+
#
|
58
|
+
# it "raises a TypeError if conversion to a String by calling #to_str fails" do
|
59
|
+
# name = mock('123')
|
60
|
+
# lambda { ConstantSpecs.const_set name, 1 }.should raise_error(TypeError)
|
61
|
+
#
|
62
|
+
# name.should_receive(:to_str).and_return(123)
|
63
|
+
# lambda { ConstantSpecs.const_set name, 1 }.should raise_error(TypeError)
|
64
|
+
# end
|
65
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class BasicObjectSendSpec
|
4
|
+
def foo
|
5
|
+
:bar
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(symbol, *args, &block)
|
9
|
+
"called_#{symbol}"
|
10
|
+
end
|
11
|
+
|
12
|
+
class Subclass < BasicObjectSendSpec
|
13
|
+
def method_missing(symbol, *args, &block)
|
14
|
+
args
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "BasicObject#__send__" do
|
20
|
+
it "should call method_missing for undefined method" do
|
21
|
+
BasicObjectSendSpec.new.__send__(:foo).should eq(:bar)
|
22
|
+
BasicObjectSendSpec.new.__send__(:pow).should eq('called_pow')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should pass on arguments to method_missing" do
|
26
|
+
BasicObjectSendSpec::Subclass.new.__send__(:blah, 1, 2, 3).should eq([1, 2, 3])
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
describe "Missing constants" do
|
2
|
+
it "should raise a NameError when trying to access an undefined constant" do
|
3
|
+
lambda { ThisConstantDoesNotExist }.should raise_error(NameError)
|
4
|
+
end
|
5
|
+
|
6
|
+
it "raises an error for missing constants on base constant scope" do
|
7
|
+
lambda { Object::SomeRandomObjectName }.should raise_error(NameError)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "raises an error for missing constants on root constant scope" do
|
11
|
+
lambda { ::YetAnotherMissingConstant }.should raise_error(NameError)
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,6 +4,7 @@ require 'opal-spec'
|
|
4
4
|
|
5
5
|
# stdlib
|
6
6
|
require 'opal/date'
|
7
|
+
require 'opal/enumerator'
|
7
8
|
|
8
9
|
module Kernel
|
9
10
|
def opal_eval(str)
|
@@ -24,4 +25,8 @@ module Kernel
|
|
24
25
|
def ruby_version_is(version, &block)
|
25
26
|
block.call
|
26
27
|
end
|
28
|
+
|
29
|
+
def enumerator_class
|
30
|
+
Enumerator
|
31
|
+
end
|
27
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.40
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sprockets
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- lib/assets/javascripts/opal/comparable.rb
|
54
54
|
- lib/assets/javascripts/opal/date.rb
|
55
55
|
- lib/assets/javascripts/opal/enumerable.rb
|
56
|
+
- lib/assets/javascripts/opal/enumerator.rb
|
56
57
|
- lib/assets/javascripts/opal/error.rb
|
57
58
|
- lib/assets/javascripts/opal/hash.rb
|
58
59
|
- lib/assets/javascripts/opal/json.rb
|
@@ -78,6 +79,7 @@ files:
|
|
78
79
|
- lib/opal/parser.rb
|
79
80
|
- lib/opal/processor.rb
|
80
81
|
- lib/opal/scope.rb
|
82
|
+
- lib/opal/server.rb
|
81
83
|
- lib/opal/version.rb
|
82
84
|
- opal.gemspec
|
83
85
|
- spec/core/array/allocate_spec.rb
|
@@ -177,6 +179,10 @@ files:
|
|
177
179
|
- spec/core/enumerable/select_spec.rb
|
178
180
|
- spec/core/enumerable/take_spec.rb
|
179
181
|
- spec/core/enumerable/to_a_spec.rb
|
182
|
+
- spec/core/enumerator/each_spec.rb
|
183
|
+
- spec/core/enumerator/new_spec.rb
|
184
|
+
- spec/core/enumerator/next_spec.rb
|
185
|
+
- spec/core/enumerator/rewind_spec.rb
|
180
186
|
- spec/core/hash/allocate_spec.rb
|
181
187
|
- spec/core/hash/assoc_spec.rb
|
182
188
|
- spec/core/hash/clear_spec.rb
|
@@ -256,6 +262,7 @@ files:
|
|
256
262
|
- spec/core/module/ancestors_spec.rb
|
257
263
|
- spec/core/module/append_features_spec.rb
|
258
264
|
- spec/core/module/const_get_spec.rb
|
265
|
+
- spec/core/module/const_set_spec.rb
|
259
266
|
- spec/core/module/undef_method_spec.rb
|
260
267
|
- spec/core/nil/and_spec.rb
|
261
268
|
- spec/core/nil/inspect_spec.rb
|
@@ -372,8 +379,10 @@ files:
|
|
372
379
|
- spec/core/time/now_spec.rb
|
373
380
|
- spec/core/time/saturday_spec.rb
|
374
381
|
- spec/core_ext/array/to_json_spec.rb
|
382
|
+
- spec/core_ext/basic_object/send_spec.rb
|
375
383
|
- spec/core_ext/class/_inherited_spec.rb
|
376
384
|
- spec/core_ext/class/singleton_methods_spec.rb
|
385
|
+
- spec/core_ext/constants_spec.rb
|
377
386
|
- spec/core_ext/method_missing_spec.rb
|
378
387
|
- spec/core_ext/native/fixtures/classes.rb
|
379
388
|
- spec/core_ext/native/initialize_spec.rb
|
@@ -582,6 +591,10 @@ test_files:
|
|
582
591
|
- spec/core/enumerable/select_spec.rb
|
583
592
|
- spec/core/enumerable/take_spec.rb
|
584
593
|
- spec/core/enumerable/to_a_spec.rb
|
594
|
+
- spec/core/enumerator/each_spec.rb
|
595
|
+
- spec/core/enumerator/new_spec.rb
|
596
|
+
- spec/core/enumerator/next_spec.rb
|
597
|
+
- spec/core/enumerator/rewind_spec.rb
|
585
598
|
- spec/core/hash/allocate_spec.rb
|
586
599
|
- spec/core/hash/assoc_spec.rb
|
587
600
|
- spec/core/hash/clear_spec.rb
|
@@ -661,6 +674,7 @@ test_files:
|
|
661
674
|
- spec/core/module/ancestors_spec.rb
|
662
675
|
- spec/core/module/append_features_spec.rb
|
663
676
|
- spec/core/module/const_get_spec.rb
|
677
|
+
- spec/core/module/const_set_spec.rb
|
664
678
|
- spec/core/module/undef_method_spec.rb
|
665
679
|
- spec/core/nil/and_spec.rb
|
666
680
|
- spec/core/nil/inspect_spec.rb
|
@@ -777,8 +791,10 @@ test_files:
|
|
777
791
|
- spec/core/time/now_spec.rb
|
778
792
|
- spec/core/time/saturday_spec.rb
|
779
793
|
- spec/core_ext/array/to_json_spec.rb
|
794
|
+
- spec/core_ext/basic_object/send_spec.rb
|
780
795
|
- spec/core_ext/class/_inherited_spec.rb
|
781
796
|
- spec/core_ext/class/singleton_methods_spec.rb
|
797
|
+
- spec/core_ext/constants_spec.rb
|
782
798
|
- spec/core_ext/method_missing_spec.rb
|
783
799
|
- spec/core_ext/native/fixtures/classes.rb
|
784
800
|
- spec/core_ext/native/initialize_spec.rb
|