opal 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +40 -9
  3. data/CHANGELOG.md +349 -0
  4. data/Gemfile +7 -8
  5. data/README.md +25 -3
  6. data/Rakefile +4 -2
  7. data/bin/opal +1 -1
  8. data/examples/rack/Gemfile +3 -0
  9. data/examples/rack/app/application.rb +13 -0
  10. data/examples/rack/app/user.rb +21 -0
  11. data/examples/rack/config.ru +7 -0
  12. data/examples/rack/index.html.erb +10 -0
  13. data/examples/sinatra/Gemfile +4 -0
  14. data/examples/sinatra/app/application.rb +7 -0
  15. data/examples/sinatra/config.ru +21 -0
  16. data/lib/mspec/opal/rake_task.rb +29 -8
  17. data/lib/mspec/opal/runner.rb +5 -4
  18. data/lib/opal.rb +1 -0
  19. data/lib/opal/builder.rb +0 -28
  20. data/lib/opal/cli.rb +0 -14
  21. data/lib/opal/compiler.rb +12 -11
  22. data/lib/opal/fragment.rb +8 -1
  23. data/lib/opal/nodes/array.rb +1 -1
  24. data/lib/opal/nodes/base.rb +4 -0
  25. data/lib/opal/nodes/call.rb +6 -2
  26. data/lib/opal/nodes/call_special.rb +1 -1
  27. data/lib/opal/nodes/class.rb +2 -2
  28. data/lib/opal/nodes/constants.rb +3 -1
  29. data/lib/opal/nodes/helpers.rb +23 -14
  30. data/lib/opal/nodes/if.rb +16 -9
  31. data/lib/opal/nodes/literal.rb +37 -5
  32. data/lib/opal/nodes/logic.rb +7 -1
  33. data/lib/opal/nodes/module.rb +2 -2
  34. data/lib/opal/nodes/scope.rb +13 -2
  35. data/lib/opal/nodes/top.rb +9 -0
  36. data/lib/opal/nodes/variables.rb +5 -2
  37. data/lib/opal/parser.rb +306 -71
  38. data/lib/opal/parser/grammar.rb +2667 -2775
  39. data/lib/opal/parser/grammar.y +177 -233
  40. data/lib/opal/parser/lexer.rb +511 -427
  41. data/lib/opal/parser/sexp.rb +15 -3
  42. data/lib/opal/source_map.rb +8 -4
  43. data/lib/opal/sprockets.rb +4 -0
  44. data/lib/opal/sprockets/cache_key_fix.rb +17 -0
  45. data/lib/opal/sprockets/environment.rb +21 -0
  46. data/lib/opal/sprockets/erb.rb +30 -0
  47. data/lib/opal/sprockets/processor.rb +127 -0
  48. data/lib/opal/sprockets/server.rb +166 -0
  49. data/lib/opal/util.rb +29 -0
  50. data/lib/opal/version.rb +1 -1
  51. data/opal.gemspec +1 -1
  52. data/opal/corelib/array.rb +106 -187
  53. data/opal/corelib/array/inheritance.rb +113 -0
  54. data/opal/corelib/basic_object.rb +6 -2
  55. data/opal/corelib/boolean.rb +4 -0
  56. data/opal/corelib/class.rb +2 -0
  57. data/opal/corelib/complex.rb +3 -0
  58. data/opal/corelib/enumerable.rb +75 -8
  59. data/opal/corelib/enumerator.rb +2 -0
  60. data/opal/corelib/error.rb +23 -23
  61. data/opal/corelib/hash.rb +5 -5
  62. data/opal/corelib/helpers.rb +51 -16
  63. data/opal/corelib/io.rb +7 -24
  64. data/opal/corelib/kernel.rb +23 -11
  65. data/opal/corelib/module.rb +44 -47
  66. data/opal/corelib/nil_class.rb +4 -0
  67. data/opal/corelib/numeric.rb +101 -15
  68. data/opal/corelib/range.rb +2 -0
  69. data/opal/corelib/rational.rb +3 -0
  70. data/opal/corelib/regexp.rb +36 -17
  71. data/opal/corelib/runtime.js +22 -7
  72. data/opal/corelib/string.rb +213 -110
  73. data/opal/corelib/string/inheritance.rb +78 -0
  74. data/opal/corelib/struct.rb +8 -0
  75. data/opal/corelib/time.rb +54 -42
  76. data/opal/corelib/variables.rb +24 -0
  77. data/opal/opal.rb +5 -27
  78. data/spec/cli/compiler_spec.rb +136 -0
  79. data/spec/cli/dependency_resolver_spec.rb +40 -0
  80. data/spec/cli/lexer_spec.rb +110 -0
  81. data/spec/cli/parser/alias_spec.rb +26 -0
  82. data/spec/cli/parser/and_spec.rb +13 -0
  83. data/spec/cli/parser/attrasgn_spec.rb +28 -0
  84. data/spec/cli/parser/begin_spec.rb +42 -0
  85. data/spec/cli/parser/block_spec.rb +12 -0
  86. data/spec/cli/parser/break_spec.rb +17 -0
  87. data/spec/cli/parser/call_spec.rb +139 -0
  88. data/spec/cli/parser/class_spec.rb +35 -0
  89. data/spec/cli/parser/comments_spec.rb +11 -0
  90. data/spec/cli/parser/def_spec.rb +61 -0
  91. data/spec/cli/parser/if_spec.rb +26 -0
  92. data/spec/cli/parser/iter_spec.rb +59 -0
  93. data/spec/cli/parser/lambda_spec.rb +64 -0
  94. data/spec/cli/parser/literal_spec.rb +113 -0
  95. data/spec/cli/parser/masgn_spec.rb +37 -0
  96. data/spec/cli/parser/module_spec.rb +27 -0
  97. data/spec/cli/parser/not_spec.rb +27 -0
  98. data/spec/cli/parser/op_asgn1_spec.rb +23 -0
  99. data/spec/cli/parser/op_asgn2_spec.rb +23 -0
  100. data/spec/cli/parser/or_spec.rb +13 -0
  101. data/spec/cli/parser/return_spec.rb +17 -0
  102. data/spec/cli/parser/sclass_spec.rb +21 -0
  103. data/spec/cli/parser/string_spec.rb +269 -0
  104. data/spec/cli/parser/super_spec.rb +20 -0
  105. data/spec/cli/parser/undef_spec.rb +15 -0
  106. data/spec/cli/parser/unless_spec.rb +13 -0
  107. data/spec/cli/parser/variables_spec.rb +92 -0
  108. data/spec/cli/parser/while_spec.rb +15 -0
  109. data/spec/cli/parser/yield_spec.rb +20 -0
  110. data/spec/cli/spec_helper.rb +31 -11
  111. data/spec/opal/core/array/set_range_to_array_spec.rb +7 -0
  112. data/spec/opal/core/date_spec.rb +122 -0
  113. data/spec/opal/core/language/predefined_spec.rb +1 -1
  114. data/spec/opal/core/runtime/operator_call_spec.rb +13 -0
  115. data/spec/opal/core/runtime/truthy_spec.rb +23 -0
  116. data/spec/opal/filters/bugs/array.rb +96 -87
  117. data/spec/opal/filters/bugs/basic_object.rb +9 -0
  118. data/spec/opal/filters/bugs/class.rb +16 -0
  119. data/spec/opal/filters/bugs/enumerable.rb +54 -0
  120. data/spec/opal/filters/bugs/language.rb +37 -3
  121. data/spec/opal/filters/bugs/math.rb +93 -0
  122. data/spec/opal/filters/bugs/nil.rb +7 -0
  123. data/spec/opal/filters/bugs/numeric.rb +19 -0
  124. data/spec/opal/filters/bugs/opal.rb +12 -0
  125. data/spec/opal/filters/bugs/regexp.rb +0 -2
  126. data/spec/opal/filters/bugs/string.rb +317 -19
  127. data/spec/opal/filters/bugs/struct.rb +29 -0
  128. data/spec/opal/filters/bugs/time.rb +130 -9
  129. data/spec/opal/filters/unsupported/encoding.rb +52 -4
  130. data/spec/opal/filters/unsupported/enumerator.rb +0 -3
  131. data/spec/opal/filters/unsupported/integer_size.rb +7 -0
  132. data/spec/opal/filters/unsupported/method_added.rb +10 -0
  133. data/spec/opal/filters/unsupported/mutable_strings.rb +299 -1
  134. data/spec/opal/filters/unsupported/private_constants.rb +30 -0
  135. data/spec/opal/filters/unsupported/private_methods.rb +16 -0
  136. data/spec/opal/filters/unsupported/random.rb +4 -0
  137. data/spec/opal/filters/unsupported/tainted.rb +53 -0
  138. data/spec/opal/filters/unsupported/trusted.rb +5 -0
  139. data/spec/opal/rubyspecs +167 -234
  140. data/spec/opal/spec_helper.rb +3 -0
  141. data/spec/opal/stdlib/promise/error_spec.rb +15 -0
  142. data/spec/opal/stdlib/promise/rescue_spec.rb +35 -0
  143. data/spec/opal/stdlib/promise/then_spec.rb +54 -0
  144. data/spec/opal/stdlib/promise/trace_spec.rb +35 -0
  145. data/spec/opal/stdlib/promise/value_spec.rb +15 -0
  146. data/spec/opal/stdlib/promise/when_spec.rb +34 -0
  147. data/stdlib/base64.rb +152 -0
  148. data/stdlib/date.rb +82 -49
  149. data/{opal/corelib → stdlib}/encoding.rb +3 -1
  150. data/stdlib/erb.rb +0 -1
  151. data/stdlib/json.rb +10 -26
  152. data/stdlib/math.rb +370 -0
  153. data/stdlib/native.rb +40 -33
  154. data/stdlib/opal-parser.rb +7 -4
  155. data/stdlib/promise.rb +292 -0
  156. data/stdlib/strscan.rb +1 -1
  157. data/stdlib/template.rb +1 -3
  158. data/stdlib/time.rb +9 -0
  159. metadata +143 -204
  160. data/doc/compiler.md +0 -42
  161. data/doc/compiler_options.md +0 -5
  162. data/doc/examples/node_http_server.rb +0 -49
  163. data/doc/external_libraries.md +0 -9
  164. data/doc/generated_javascript.md +0 -272
  165. data/doc/home.md +0 -17
  166. data/doc/method_missing.md +0 -58
  167. data/doc/static_applications.md +0 -60
  168. data/doc/using_ruby_from_javascript.md +0 -18
  169. data/doc/using_sprockets.md +0 -65
  170. data/spec/opal/core/numeric/abs_spec.rb +0 -12
  171. data/spec/opal/core/numeric/downto_spec.rb +0 -19
  172. data/spec/opal/core/numeric/equal_value_spec.rb +0 -9
  173. data/spec/opal/core/numeric/even_spec.rb +0 -21
  174. data/spec/opal/core/numeric/magnitude_spec.rb +0 -12
  175. data/spec/opal/core/numeric/odd_spec.rb +0 -21
  176. data/spec/opal/core/string/chop_spec.rb +0 -10
  177. data/spec/opal/core/string/chr_spec.rb +0 -13
  178. data/spec/opal/core/string/clone_spec.rb +0 -8
  179. data/spec/opal/core/string/comparison_spec.rb +0 -13
  180. data/spec/opal/core/string/dup_spec.rb +0 -8
  181. data/spec/opal/core/string/element_reference_spec.rb +0 -96
  182. data/spec/opal/core/string/fixtures/classes.rb +0 -49
  183. data/spec/opal/core/string/format_spec.rb +0 -9
  184. data/spec/opal/core/string/freeze_spec.rb +0 -15
  185. data/spec/opal/core/string/gsub_spec.rb +0 -31
  186. data/spec/opal/core/string/lines_spec.rb +0 -9
  187. data/spec/opal/core/string/ljust_spec.rb +0 -32
  188. data/spec/opal/core/string/lstrip_spec.rb +0 -7
  189. data/spec/opal/core/string/match_spec.rb +0 -49
  190. data/spec/opal/core/string/next_spec.rb +0 -10
  191. data/spec/opal/core/string/ord_spec.rb +0 -9
  192. data/spec/opal/core/string/partition_spec.rb +0 -10
  193. data/spec/opal/core/string/rindex_spec.rb +0 -50
  194. data/spec/opal/core/string/rjust_spec.rb +0 -32
  195. data/spec/opal/core/string/rstrip_spec.rb +0 -7
  196. data/spec/opal/core/string/scan_spec.rb +0 -66
  197. data/spec/opal/core/string/slice_spec.rb +0 -74
  198. data/spec/opal/core/string/split_spec.rb +0 -5
  199. data/spec/opal/core/string/strip_spec.rb +0 -6
  200. data/spec/opal/core/string/sub_spec.rb +0 -38
  201. data/spec/opal/core/string/succ_spec.rb +0 -10
  202. data/spec/opal/core/string/sum_spec.rb +0 -5
  203. data/spec/opal/core/string/to_f_spec.rb +0 -14
  204. data/spec/opal/core/string/to_i_spec.rb +0 -25
  205. data/spec/opal/core/string/tr_s_spec.rb +0 -31
  206. data/spec/opal/core/string/tr_spec.rb +0 -31
  207. data/spec/opal/filters/bugs/parser.rb +0 -10
  208. data/spec/opal/filters/unsupported/immutable_strings.rb +0 -24
  209. data/spec/opal/filters/unsupported/string_subclasses.rb +0 -8
  210. data/spec/opal/parser/alias_spec.rb +0 -26
  211. data/spec/opal/parser/and_spec.rb +0 -13
  212. data/spec/opal/parser/array_spec.rb +0 -22
  213. data/spec/opal/parser/attrasgn_spec.rb +0 -28
  214. data/spec/opal/parser/begin_spec.rb +0 -42
  215. data/spec/opal/parser/block_spec.rb +0 -12
  216. data/spec/opal/parser/break_spec.rb +0 -17
  217. data/spec/opal/parser/call_spec.rb +0 -131
  218. data/spec/opal/parser/class_spec.rb +0 -35
  219. data/spec/opal/parser/const_spec.rb +0 -13
  220. data/spec/opal/parser/cvar_spec.rb +0 -11
  221. data/spec/opal/parser/def_spec.rb +0 -61
  222. data/spec/opal/parser/false_spec.rb +0 -17
  223. data/spec/opal/parser/file_spec.rb +0 -7
  224. data/spec/opal/parser/gvar_spec.rb +0 -13
  225. data/spec/opal/parser/hash_spec.rb +0 -17
  226. data/spec/opal/parser/heredoc_spec.rb +0 -30
  227. data/spec/opal/parser/iasgn_spec.rb +0 -9
  228. data/spec/opal/parser/if_spec.rb +0 -26
  229. data/spec/opal/parser/int_spec.rb +0 -13
  230. data/spec/opal/parser/iter_spec.rb +0 -59
  231. data/spec/opal/parser/ivar_spec.rb +0 -9
  232. data/spec/opal/parser/lambda_spec.rb +0 -64
  233. data/spec/opal/parser/lasgn_spec.rb +0 -8
  234. data/spec/opal/parser/line_spec.rb +0 -8
  235. data/spec/opal/parser/lvar_spec.rb +0 -38
  236. data/spec/opal/parser/masgn_spec.rb +0 -37
  237. data/spec/opal/parser/module_spec.rb +0 -27
  238. data/spec/opal/parser/nil_spec.rb +0 -17
  239. data/spec/opal/parser/not_spec.rb +0 -27
  240. data/spec/opal/parser/nth_ref_spec.rb +0 -13
  241. data/spec/opal/parser/op_asgn1_spec.rb +0 -23
  242. data/spec/opal/parser/op_asgn2_spec.rb +0 -23
  243. data/spec/opal/parser/or_spec.rb +0 -13
  244. data/spec/opal/parser/parse_spec.rb +0 -66
  245. data/spec/opal/parser/regexp_spec.rb +0 -16
  246. data/spec/opal/parser/return_spec.rb +0 -17
  247. data/spec/opal/parser/sclass_spec.rb +0 -21
  248. data/spec/opal/parser/self_spec.rb +0 -17
  249. data/spec/opal/parser/str_spec.rb +0 -107
  250. data/spec/opal/parser/string_spec.rb +0 -8
  251. data/spec/opal/parser/super_spec.rb +0 -20
  252. data/spec/opal/parser/true_spec.rb +0 -17
  253. data/spec/opal/parser/undef_spec.rb +0 -15
  254. data/spec/opal/parser/unless_spec.rb +0 -13
  255. data/spec/opal/parser/while_spec.rb +0 -15
  256. data/spec/opal/parser/xstr_spec.rb +0 -116
  257. data/spec/opal/parser/yield_spec.rb +0 -20
@@ -6,6 +6,9 @@ require 'mspec'
6
6
  require 'mspec/opal/mspec_fixes'
7
7
  require 'mspec/opal/runner'
8
8
 
9
+ require 'math'
10
+ require 'encoding'
11
+
9
12
  ENV['MSPEC_RUNNER'] = true
10
13
 
11
14
  module Kernel
@@ -0,0 +1,15 @@
1
+ require 'promise'
2
+
3
+ describe 'Promise.error' do
4
+ it 'rejects the promise with the given error' do
5
+ Promise.error(23).error.should == 23
6
+ end
7
+
8
+ it 'marks the promise as realized' do
9
+ Promise.error(23).realized?.should be_true
10
+ end
11
+
12
+ it 'marks the promise as rejected' do
13
+ Promise.error(23).rejected?.should be_true
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ require 'promise'
2
+
3
+ describe 'Promise#rescue' do
4
+ it 'calls the block when the promise has already been rejected' do
5
+ x = 42
6
+ Promise.error(23).rescue { |v| x = v }
7
+ x.should == 23
8
+ end
9
+
10
+ it 'calls the block when the promise is rejected' do
11
+ a = Promise.new
12
+ x = 42
13
+
14
+ a.rescue { |v| x = v }
15
+ a.reject(23)
16
+
17
+ x.should == 23
18
+ end
19
+
20
+ it 'does not call then blocks when the promise is rejected' do
21
+ x = 42
22
+ y = 23
23
+
24
+ Promise.error(23).then { y = 42 }.rescue { |v| x = v }
25
+
26
+ x.should == 23
27
+ y.should == 23
28
+ end
29
+
30
+ it 'does not call subsequent rescue blocks' do
31
+ x = 42
32
+ Promise.error(23).rescue { |v| x = v }.rescue { x = 42 }
33
+ x.should == 23
34
+ end
35
+ end
@@ -0,0 +1,54 @@
1
+ require 'promise'
2
+
3
+ describe 'Promise#then' do
4
+ it 'calls the block when the promise has already been resolved' do
5
+ x = 42
6
+ Promise.value(23).then { |v| x = v }
7
+ x.should == 23
8
+ end
9
+
10
+ it 'calls the block when the promise is resolved' do
11
+ a = Promise.new
12
+ x = 42
13
+
14
+ a.then { |v| x = v }
15
+ a.resolve(23)
16
+
17
+ x.should == 23
18
+ end
19
+
20
+ it 'works with multiple chains' do
21
+ x = 42
22
+ Promise.value(2).then { |v| v * 2 }.then { |v| v * 4 }.then { |v| x = v }
23
+ x.should == 16
24
+ end
25
+
26
+ it 'works when a block returns a promise' do
27
+ a = Promise.new
28
+ b = Promise.new
29
+
30
+ x = 42
31
+ a.then { b }.then { |v| x = v }
32
+
33
+ a.resolve(42)
34
+ b.resolve(23)
35
+
36
+ x.should == 23
37
+ end
38
+
39
+ it 'sends raised exceptions as rejections' do
40
+ x = nil
41
+
42
+ Promise.value(2).then { raise "hue" }.rescue { |v| x = v }
43
+
44
+ x.should be_kind_of(RuntimeError)
45
+ end
46
+
47
+ it 'sends raised exceptions inside rescue blocks as next errors' do
48
+ x = nil
49
+
50
+ Promise.value(2).then { raise "hue" }.rescue { raise "omg" }.rescue { |v| x = v }
51
+
52
+ x.should be_kind_of(RuntimeError)
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ require 'promise'
2
+
3
+ describe 'Promise#trace' do
4
+ it 'calls the block with all the previous results' do
5
+ x = 42
6
+
7
+ Promise.value(1).then { 2 }.then { 3 }.trace {|a, b, c|
8
+ x = a + b + c
9
+ }
10
+
11
+ x.should == 6
12
+ end
13
+
14
+ it 'calls the then after the trace' do
15
+ x = 42
16
+
17
+ Promise.value(1).then { 2 }.then { 3 }.trace {|a, b, c|
18
+ a + b + c
19
+ }.then { |v| x = v }
20
+
21
+ x.should == 6
22
+ end
23
+
24
+ it 'works after a when' do
25
+ x = 42
26
+
27
+ Promise.value(1).then {
28
+ Promise.when Promise.value(2), Promise.value(3)
29
+ }.trace {|a, b|
30
+ x = a + b[0] + b[1]
31
+ }
32
+
33
+ x.should == 6
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ require 'promise'
2
+
3
+ describe 'Promise.value' do
4
+ it 'resolves the promise with the given value' do
5
+ Promise.value(23).value.should == 23
6
+ end
7
+
8
+ it 'marks the promise as realized' do
9
+ Promise.value(23).realized?.should be_true
10
+ end
11
+
12
+ it 'marks the promise as resolved' do
13
+ Promise.value(23).resolved?.should be_true
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ require 'promise'
2
+
3
+ describe 'Promise.when' do
4
+ it 'calls the block with all promises results' do
5
+ a = Promise.new
6
+ b = Promise.new
7
+
8
+ x = 42
9
+
10
+ Promise.when(a, b).then {|y, z|
11
+ x = y + z
12
+ }
13
+
14
+ a.resolve(1)
15
+ b.resolve(2)
16
+
17
+ x.should == 3
18
+ end
19
+
20
+ it 'can be built lazily' do
21
+ a = Promise.new
22
+ b = Promise.value(3)
23
+
24
+ x = 42
25
+
26
+ Promise.when(a).and(b).then {|c, d|
27
+ x = c + d
28
+ }
29
+
30
+ a.resolve(2)
31
+
32
+ x.should == 5
33
+ end
34
+ end
@@ -0,0 +1,152 @@
1
+ module Base64
2
+ %x{
3
+ var charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
4
+ lookup = {};
5
+
6
+ for (var i = 0, length = charset.length; i < length; i++) {
7
+ lookup[charset.charAt(i)] = i;
8
+ }
9
+
10
+ function from(string) {
11
+ var buffer = [];
12
+
13
+ for (var i = 0, length = string.length; i < length; i++) {
14
+ var a, b, c, d;
15
+
16
+ a = lookup[string.charAt(i)];
17
+ b = lookup[string.charAt(++i)];
18
+
19
+ buffer.push((a << 2) | (b >> 4));
20
+
21
+ c = lookup[string.charAt(++i)];
22
+
23
+ if (c == 64) {
24
+ break;
25
+ }
26
+
27
+ buffer.push(((b & 15) << 4) | (c >> 2));
28
+
29
+ d = lookup[string.charAt(++i)];
30
+
31
+ if (d == 64) {
32
+ break;
33
+ }
34
+
35
+ buffer.push(((c & 3) << 6) | d);
36
+ }
37
+
38
+ return buffer;
39
+ }
40
+
41
+ function decode(string) {
42
+ var buffer = from(string),
43
+ result = [];
44
+
45
+ for (var i = 0, length = buffer.length; i < length; i++) {
46
+ if (buffer[i] < 128) {
47
+ result.push(String.fromCharCode(buffer[i]));
48
+ }
49
+ else if (buffer[i] > 191 && buffer[i] < 224) {
50
+ var a = (buffer[i] & 31) << 6,
51
+ b = buffer[++i] & 63;
52
+
53
+ result.push(String.fromCharCode(a | b));
54
+ }
55
+ else {
56
+ var a = (buffer[i] & 15) << 12,
57
+ b = (buffer[++i] & 63) << 6,
58
+ c = buffer[++i] & 63;
59
+
60
+ result.push(String.fromCharCode(a | b | c));
61
+ }
62
+ }
63
+
64
+ return result.join('');
65
+ }
66
+
67
+ function to(string) {
68
+ var buffer = [];
69
+
70
+ if (/^[\x00-\x7f]*$/.test(string)) {
71
+ for (var i = 0, length = string.length; i < length; i++) {
72
+ buffer.push(string.charCodeAt(i));
73
+ }
74
+ }
75
+ else {
76
+ for (var i = 0, length = string.length; i < length; i++) {
77
+ var ch = string.charCodeAt(i);
78
+
79
+ if (ch < 128) {
80
+ buffer.push(ch);
81
+ }
82
+ else if (ch < 2048) {
83
+ buffer.push((ch >> 6) | 192);
84
+ buffer.push((ch & 63) | 128);
85
+ }
86
+ else {
87
+ buffer.push((ch >> 12) | 224);
88
+ buffer.push(((ch >> 6) & 63) | 128);
89
+ buffer.push((ch & 63) | 128);
90
+ }
91
+ }
92
+ }
93
+
94
+ return buffer;
95
+ }
96
+
97
+ function encode(string) {
98
+ var buffer = to(string),
99
+ result = [];
100
+
101
+ for (var i = 0, length = buffer.length; i < length; i++) {
102
+ var a = buffer[i],
103
+ b = buffer[++i],
104
+ c = 0,
105
+ d = a >> 2,
106
+ e = ((a & 3) << 4) | (b >> 4),
107
+ f = 0,
108
+ g = 0;
109
+
110
+ if (isNaN(a)) {
111
+ f = g = 64;
112
+ }
113
+ else {
114
+ c = buffer[++i];
115
+ f = ((b & 15) << 2) | (c >> 6);
116
+ g = isNaN(c) ? 64 : c & 63;
117
+ }
118
+
119
+ result.push(charset.charAt(d));
120
+ result.push(charset.charAt(e));
121
+ result.push(charset.charAt(f));
122
+ result.push(charset.charAt(g));
123
+ }
124
+
125
+ return result.join('');
126
+ }
127
+ }
128
+
129
+ def self.decode64(string)
130
+ `decode(string.replace(/\r?\n/g, ''))`
131
+ end
132
+
133
+ def self.encode64(string)
134
+ `encode(string).replace(/(.{60})/g, "$1\n")`
135
+ end
136
+
137
+ def self.strict_decode64(string)
138
+ `decode(string)`
139
+ end
140
+
141
+ def self.strict_encode64(string)
142
+ `encode(string)`
143
+ end
144
+
145
+ def self.urlsafe_decode64(string)
146
+ `decode(string.replace(/\-/g, '+').replace(/_/g, '/'))`
147
+ end
148
+
149
+ def self.urlsafe_encode64(string)
150
+ `encode(string).replace(/\+/g, '-').replace(/\//g, '_')`
151
+ end
152
+ end
@@ -1,35 +1,59 @@
1
- native_date = `Date`
2
-
3
1
  class Date
4
- def self.wrap(native)
5
- instance = allocate
6
- `#{instance}._date = #{native}`
7
- instance
8
- end
2
+ class << self
3
+ alias civil new
9
4
 
10
- def self.parse(string)
11
- wrap `native_date.parse(string)`
12
- end
5
+ def wrap(native)
6
+ instance = allocate
7
+ `#{instance}.date = #{native}`
8
+ instance
9
+ end
13
10
 
14
- def self.today
15
- %x{
16
- var date = #{new};
17
- date._date = new native_date();
18
- return date;
19
- }
11
+ def parse(string)
12
+ match = `/^(\d*)-(\d*)-(\d*)/.exec(string)`
13
+ wrap `new Date(parseInt(match[1]), parseInt(match[2]) - 1, parseInt(match[3]))`
14
+ end
15
+
16
+ def today
17
+ wrap `new Date()`
18
+ end
20
19
  end
21
20
 
22
21
  def initialize(year = undefined, month = undefined, day = undefined)
23
- `#{self}._date = new native_date(year, month - 1, day)`
22
+ @date = `new Date(year, month - 1, day)`
24
23
  end
25
24
 
26
25
  def -(date)
27
- `Math.round((#{self}._date - #{date}._date) / (1000 * 60 * 60 * 24))`
26
+ %x{
27
+ if (date._isNumber) {
28
+ var result = #{clone};
29
+ result.date.setDate(#@date.getDate() - date);
30
+ return result;
31
+ }
32
+ else if (date.date) {
33
+ return Math.round((#@date - #{date}.date) / (1000 * 60 * 60 * 24));
34
+ }
35
+ else {
36
+ #{raise TypeError};
37
+ }
38
+ }
39
+ end
40
+
41
+ def +(date)
42
+ %x{
43
+ if (date._isNumber) {
44
+ var result = #{clone};
45
+ result.date.setDate(#@date.getDate() + date);
46
+ return result;
47
+ }
48
+ else {
49
+ #{raise TypeError};
50
+ }
51
+ }
28
52
  end
29
53
 
30
54
  def <(other)
31
55
  %x{
32
- var a = #{self}._date, b = #{other}._date;
56
+ var a = #@date, b = #{other}.date;
33
57
  a.setHours(0, 0, 0, 0);
34
58
  b.setHours(0, 0, 0, 0);
35
59
  return a < b;
@@ -38,7 +62,7 @@ class Date
38
62
 
39
63
  def <=(other)
40
64
  %x{
41
- var a = #{self}._date, b = #{other}._date;
65
+ var a = #@date, b = #{other}.date;
42
66
  a.setHours(0, 0, 0, 0);
43
67
  b.setHours(0, 0, 0, 0);
44
68
  return a <= b;
@@ -47,7 +71,7 @@ class Date
47
71
 
48
72
  def >(other)
49
73
  %x{
50
- var a = #{self}._date, b = #{other}._date;
74
+ var a = #@date, b = #{other}.date;
51
75
  a.setHours(0, 0, 0, 0);
52
76
  b.setHours(0, 0, 0, 0);
53
77
  return a > b;
@@ -56,7 +80,7 @@ class Date
56
80
 
57
81
  def >=(other)
58
82
  %x{
59
- var a = #{self}._date, b = #{other}._date;
83
+ var a = #@date, b = #{other}.date;
60
84
  a.setHours(0, 0, 0, 0);
61
85
  b.setHours(0, 0, 0, 0);
62
86
  return a >= b;
@@ -65,73 +89,82 @@ class Date
65
89
 
66
90
  def ==(other)
67
91
  %x{
68
- var a = #{self}._date, b = #{other}._date;
69
- a.setHours(0, 0, 0, 0);
70
- b.setHours(0, 0, 0, 0);
92
+ var a = #@date, b = other.date;
71
93
  return (a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate());
72
94
  }
73
95
  end
74
96
 
97
+ alias eql? ==
98
+
75
99
  def clone
76
- Date.wrap(`new native_date(#{self}._date.getTime())`)
100
+ Date.wrap(`new Date(#@date.getTime())`)
77
101
  end
78
102
 
79
103
  def day
80
- `#{self}._date.getDate()`
104
+ `#@date.getDate()`
81
105
  end
82
106
 
83
107
  def month
84
- `#{self}._date.getMonth() + 1`
108
+ `#@date.getMonth() + 1`
85
109
  end
86
110
 
87
111
  def next
88
112
  res = self.clone
89
- `res._date.setDate(#{self}._date.getDate() + 1)`
113
+ `res.date.setDate(#@date.getDate() + 1)`
90
114
  res
91
115
  end
92
116
 
93
117
  def next_month
94
- res = self.clone
95
- `res._date.add({months: 1})`
96
- res
118
+ %x{
119
+ var result = #{clone}, date = result.date, cur = date.getDate();
120
+ date.setDate(1);
121
+ date.setMonth(date.getMonth() + 1);
122
+ date.setDate(Math.min(cur, days_in_month(date.getFullYear(), date.getMonth())));
123
+ return result;
124
+ }
97
125
  end
98
126
 
99
127
  def prev
100
128
  res = self.clone
101
- `res._date.setDate(#{self}._date.getDate() - 1)`
129
+ `res.date.setDate(#@date.getDate() - 1)`
102
130
  res
103
131
  end
104
132
 
105
133
  def prev_month
106
- res = self.clone
107
- `res._date.add({months: -1})`
108
- res
134
+ %x{
135
+ var result = #{clone}, date = result.date, cur = date.getDate();
136
+ date.setDate(1);
137
+ date.setMonth(date.getMonth() - 1);
138
+ date.setDate(Math.min(cur, days_in_month(date.getFullYear(), date.getMonth())));
139
+ return result;
140
+ }
109
141
  end
110
142
 
111
143
  def strftime(format = '')
112
- `#{self}._date.$strftime(#{format})`
144
+ `#@date.$strftime(#{format})`
113
145
  end
114
146
 
115
147
  def to_s
116
148
  %x{
117
- var date = #{self}._date;
118
- return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
149
+ var d = #@date, year = d.getFullYear(), month = d.getMonth() + 1, day = d.getDate();
150
+ if (month < 10) { month = '0' + month; }
151
+ if (day < 10) { day = '0' + day; }
152
+ return year + '-' + month + '-' + day;
119
153
  }
120
154
  end
121
155
 
122
- def to_json
123
- to_s.to_json
124
- end
125
-
126
- def as_json
127
- to_s
128
- end
129
-
130
156
  def wday
131
- `#{self}._date.getDay()`
157
+ `#@date.getDay()`
132
158
  end
133
159
 
134
160
  def year
135
- `#{self}._date.getFullYear()`
161
+ `#@date.getFullYear()`
136
162
  end
163
+
164
+ %x{
165
+ function days_in_month(year, month) {
166
+ var leap = ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
167
+ return [31, (leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
168
+ }
169
+ }
137
170
  end