opal 0.3.39 → 0.3.40
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.
- 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
|