opal 0.3.21 → 0.3.22
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/.travis.yml +1 -4
- data/Gemfile +9 -4
- data/README.md +10 -589
- data/Rakefile +51 -19
- data/config.ru +17 -0
- data/core/array.rb +42 -34
- data/core/basic_object.rb +4 -4
- data/core/browser.js +31 -0
- data/core/class.rb +7 -7
- data/core/enumerable.rb +65 -69
- data/core/erb.rb +30 -0
- data/core/error.rb +2 -3
- data/core/hash.rb +47 -18
- data/core/kernel.rb +15 -16
- data/core/load_order +2 -1
- data/core/module.rb +19 -37
- data/core/numeric.rb +4 -2
- data/core/object.rb +4 -0
- data/core/proc.rb +6 -3
- data/core/racc.rb +215 -0
- data/core/regexp.rb +16 -21
- data/core/runtime.js +141 -153
- data/core/string.rb +41 -19
- data/core/strscan.rb +61 -0
- data/core/time.rb +1 -5
- data/docs/index.md +616 -0
- data/docs/post.html +2 -8
- data/docs/pre.html +29 -26
- data/docs/try.html +52 -0
- data/lib/opal.rb +33 -3
- data/lib/opal/builder.rb +14 -34
- data/lib/opal/erb_parser.rb +19 -0
- data/lib/opal/grammar.rb +7 -3
- data/lib/opal/grammar.y +3 -0
- data/lib/opal/lexer.rb +16 -8
- data/lib/opal/parser.rb +156 -119
- data/lib/opal/rake_task.rb +2 -2
- data/lib/opal/scope.rb +9 -10
- data/lib/opal/version.rb +1 -1
- data/{test → spec}/core/array/allocate_spec.rb +0 -0
- data/{test → spec}/core/array/append_spec.rb +0 -0
- data/{test → spec}/core/array/assoc_spec.rb +0 -0
- data/{test → spec}/core/array/at_spec.rb +0 -0
- data/{test → spec}/core/array/clear_spec.rb +0 -0
- data/{test → spec}/core/array/clone_spec.rb +0 -0
- data/{test → spec}/core/array/collect_spec.rb +0 -0
- data/{test → spec}/core/array/compact_spec.rb +0 -0
- data/{test → spec}/core/array/concat_spec.rb +0 -0
- data/{test → spec}/core/array/constructor_spec.rb +0 -0
- data/{test → spec}/core/array/count_spec.rb +0 -0
- data/{test → spec}/core/array/delete_at_spec.rb +0 -0
- data/{test → spec}/core/array/delete_if_spec.rb +0 -0
- data/{test → spec}/core/array/delete_spec.rb +0 -0
- data/{test → spec}/core/array/each_index_spec.rb +0 -0
- data/{test → spec}/core/array/each_spec.rb +0 -0
- data/{test → spec}/core/array/element_reference_spec.rb +0 -0
- data/{test → spec}/core/array/empty_spec.rb +0 -0
- data/{test → spec}/core/array/eql_spec.rb +0 -0
- data/{test → spec}/core/array/fetch_spec.rb +0 -0
- data/{test → spec}/core/array/first_spec.rb +0 -0
- data/{test → spec}/core/array/flatten_spec.rb +0 -0
- data/{test → spec}/core/array/include_spec.rb +0 -0
- data/{test → spec}/core/array/insert_spec.rb +0 -0
- data/{test → spec}/core/array/last_spec.rb +0 -0
- data/{test → spec}/core/array/length_spec.rb +0 -0
- data/{test → spec}/core/array/map_spec.rb +0 -0
- data/{test → spec}/core/array/minus_spec.rb +0 -0
- data/{test → spec}/core/array/plus_spec.rb +0 -0
- data/{test → spec}/core/array/pop_spec.rb +0 -0
- data/{test → spec}/core/array/push_spec.rb +0 -0
- data/{test → spec}/core/array/rassoc_spec.rb +0 -0
- data/{test → spec}/core/array/reject_spec.rb +0 -0
- data/{test → spec}/core/array/replace_spec.rb +0 -0
- data/{test → spec}/core/array/reverse_each_spec.rb +0 -0
- data/{test → spec}/core/array/reverse_spec.rb +0 -0
- data/{test → spec}/core/array/size_spec.rb +0 -0
- data/{test → spec}/core/array/to_ary_spec.rb +0 -0
- data/{test → spec}/core/array/uniq_spec.rb +0 -0
- data/{test → spec}/core/array/zip_spec.rb +0 -0
- data/{test → spec}/core/class/fixtures/classes.rb +0 -0
- data/{test → spec}/core/class/new_spec.rb +3 -0
- data/{test → spec}/core/enumerable/all_spec.rb +3 -0
- data/{test → spec}/core/enumerable/any_spec.rb +0 -0
- data/{test → spec}/core/enumerable/collect_spec.rb +0 -0
- data/{test → spec}/core/enumerable/count_spec.rb +0 -0
- data/{test → spec}/core/enumerable/detect_spec.rb +0 -0
- data/{test → spec}/core/enumerable/drop_spec.rb +0 -0
- data/{test → spec}/core/enumerable/drop_while_spec.rb +0 -0
- data/{test → spec}/core/enumerable/each_with_index_spec.rb +0 -0
- data/{test → spec}/core/enumerable/each_with_object_spec.rb +0 -0
- data/{test → spec}/core/enumerable/entries_spec.rb +0 -0
- data/{test → spec}/core/enumerable/find_all_spec.rb +0 -0
- data/{test → spec}/core/enumerable/find_index_spec.rb +0 -0
- data/{test → spec}/core/enumerable/find_spec.rb +0 -0
- data/{test → spec}/core/enumerable/first_spec.rb +0 -0
- data/{test → spec}/core/enumerable/fixtures/classes.rb +0 -0
- data/{test → spec}/core/enumerable/grep_spec.rb +0 -0
- data/{test → spec}/core/enumerable/take_spec.rb +0 -0
- data/{test → spec}/core/enumerable/to_a_spec.rb +0 -0
- data/{test → spec}/core/false/and_spec.rb +0 -0
- data/{test → spec}/core/false/inspect_spec.rb +0 -0
- data/{test → spec}/core/false/or_spec.rb +0 -0
- data/{test → spec}/core/false/to_s_spec.rb +0 -0
- data/{test → spec}/core/false/xor_spec.rb +0 -0
- data/{test → spec}/core/hash/allocate_spec.rb +0 -0
- data/{test → spec}/core/hash/assoc_spec.rb +0 -0
- data/{test → spec}/core/hash/clear_spec.rb +0 -0
- data/{test → spec}/core/hash/clone_spec.rb +0 -0
- data/{test → spec}/core/hash/default_spec.rb +0 -0
- data/{test → spec}/core/hash/delete_if_spec.rb +0 -0
- data/{test → spec}/core/hash/each_key_spec.rb +0 -0
- data/{test → spec}/core/hash/each_pair_spec.rb +0 -0
- data/{test → spec}/core/hash/each_spec.rb +0 -0
- data/{test → spec}/core/hash/each_value_spec.rb +0 -0
- data/{test → spec}/core/hash/element_reference_spec.rb +14 -1
- data/{test → spec}/core/hash/element_set_spec.rb +0 -0
- data/{test → spec}/core/hash/empty_spec.rb +0 -0
- data/{test → spec}/core/hash/fetch_spec.rb +0 -0
- data/{test → spec}/core/hash/flatten_spec.rb +0 -0
- data/{test → spec}/core/hash/has_key_spec.rb +0 -0
- data/{test → spec}/core/hash/has_value_spec.rb +0 -0
- data/{test → spec}/core/hash/include_spec.rb +0 -0
- data/{test → spec}/core/hash/index_spec.rb +0 -0
- data/{test → spec}/core/hash/indexes_spec.rb +0 -0
- data/{test → spec}/core/hash/indices_spec.rb +0 -0
- data/{test → spec}/core/hash/invert_spec.rb +0 -0
- data/{test → spec}/core/hash/keep_if_spec.rb +0 -0
- data/{test → spec}/core/hash/key_spec.rb +0 -0
- data/{test → spec}/core/hash/keys_spec.rb +0 -0
- data/{test → spec}/core/hash/length_spec.rb +0 -0
- data/{test → spec}/core/hash/member_spec.rb +0 -0
- data/{test → spec}/core/hash/merge_spec.rb +0 -0
- data/{test → spec}/core/hash/new_spec.rb +8 -0
- data/{test → spec}/core/hash/rassoc_spec.rb +0 -0
- data/{test → spec}/core/hash/replace_spec.rb +0 -0
- data/{test → spec}/core/hash/select_spec.rb +0 -0
- data/{test → spec}/core/hash/shift_spec.rb +0 -0
- data/{test → spec}/core/hash/size_spec.rb +0 -0
- data/{test → spec}/core/hash/update_spec.rb +0 -0
- data/{test → spec}/core/hash/value_spec.rb +0 -0
- data/{test → spec}/core/hash/values_at_spec.rb +0 -0
- data/{test → spec}/core/hash/values_spec.rb +0 -0
- data/{test → spec}/core/kernel/define_singleton_method_spec.rb +0 -0
- data/{test → spec}/core/kernel/eql_spec.rb +0 -0
- data/{test → spec}/core/kernel/equal_value_spec.rb +0 -0
- data/{test → spec}/core/kernel/loop_spec.rb +0 -0
- data/{test → spec}/core/kernel/nil_spec.rb +0 -0
- data/{test → spec}/core/kernel/proc_spec.rb +4 -0
- data/{test → spec}/core/kernel/rand_spec.rb +0 -0
- data/{test → spec}/core/kernel/respond_to_spec.rb +0 -0
- data/{test → spec}/core/kernel/send_spec.rb +0 -0
- data/{test → spec}/core/kernel/tap_spec.rb +0 -0
- data/{test → spec}/core/kernel/to_s_spec.rb +0 -0
- data/{test → spec}/core/matchdata/to_a_spec.rb +0 -0
- data/{test → spec}/core/nil/and_spec.rb +0 -0
- data/{test → spec}/core/nil/inspect_spec.rb +0 -0
- data/{test → spec}/core/nil/nil_spec.rb +0 -0
- data/{test → spec}/core/nil/or_spec.rb +0 -0
- data/{test → spec}/core/nil/to_a_spec.rb +0 -0
- data/{test → spec}/core/nil/to_f_spec.rb +0 -0
- data/{test → spec}/core/nil/to_i_spec.rb +0 -0
- data/{test → spec}/core/nil/to_s_spec.rb +0 -0
- data/{test → spec}/core/nil/xor_spec.rb +0 -0
- data/{test → spec}/core/numeric/equal_value_spec.rb +0 -0
- data/spec/core/proc/proc_tricks_spec.rb +7 -0
- data/{test → spec}/core/range/begin_spec.rb +0 -0
- data/{test → spec}/core/range/case_compare_spec.rb +0 -0
- data/{test → spec}/core/range/end_spec.rb +0 -0
- data/{test → spec}/core/regexp/match_spec.rb +0 -0
- data/{test → spec}/core/string/capitalize_spec.rb +0 -0
- data/{test → spec}/core/string/casecmp_spec.rb +0 -0
- data/{test → spec}/core/string/chomp_spec.rb +0 -0
- data/{test → spec}/core/string/chop_spec.rb +0 -0
- data/{test → spec}/core/string/chr_spec.rb +0 -0
- data/{test → spec}/core/string/comparison_spec.rb +0 -0
- data/{test → spec}/core/string/downcase_spec.rb +0 -0
- data/{test → spec}/core/string/element_reference_spec.rb +14 -2
- data/{test → spec}/core/string/empty_spec.rb +0 -0
- data/{test → spec}/core/string/end_with_spec.rb +0 -0
- data/{test → spec}/core/string/fixtures/classes.rb +0 -0
- data/{test → spec}/core/string/gsub_spec.rb +0 -0
- data/{test → spec}/core/string/include_spec.rb +0 -0
- data/{test → spec}/core/string/intern_spec.rb +0 -0
- data/{test → spec}/core/string/length_spec.rb +0 -0
- data/{test → spec}/core/string/lstrip_spec.rb +0 -0
- data/{test → spec}/core/string/match_spec.rb +0 -0
- data/{test → spec}/core/string/next_spec.rb +0 -0
- data/{test → spec}/core/string/ord_spec.rb +0 -0
- data/{test → spec}/core/string/partition_spec.rb +0 -0
- data/{test → spec}/core/string/reverse_spec.rb +0 -0
- data/{test → spec}/core/string/rstrip_spec.rb +0 -0
- data/{test → spec}/core/string/size_spec.rb +0 -0
- data/{test → spec}/core/string/slice_spec.rb +4 -1
- data/{test → spec}/core/string/split_spec.rb +0 -0
- data/{test → spec}/core/string/start_with_spec.rb +0 -0
- data/{test → spec}/core/string/strip_spec.rb +0 -0
- data/{test → spec}/core/string/sub_spec.rb +0 -0
- data/{test → spec}/core/string/succ_spec.rb +0 -0
- data/{test → spec}/core/string/sum_spec.rb +0 -0
- data/{test → spec}/core/string/swapcase_spec.rb +0 -0
- data/{test → spec}/core/string/to_a_spec.rb +0 -0
- data/{test → spec}/core/string/to_f_spec.rb +0 -0
- data/{test → spec}/core/string/to_i_spec.rb +0 -0
- data/{test → spec}/core/string/to_s_spec.rb +0 -0
- data/{test → spec}/core/string/to_str_spec.rb +0 -0
- data/{test → spec}/core/string/to_sym_spec.rb +0 -0
- data/{test → spec}/core/string/upcase_spec.rb +0 -0
- data/{test → spec}/core/symbol/to_proc_spec.rb +0 -0
- data/{test → spec}/core/time/at_spec.rb +0 -0
- data/{test → spec}/core/time/day_spec.rb +0 -0
- data/{test → spec}/core/time/friday_spec.rb +0 -0
- data/{test → spec}/core/time/hour_spec.rb +0 -0
- data/{test → spec}/core/time/min_spec.rb +0 -0
- data/{test → spec}/core/time/monday_spec.rb +0 -0
- data/{test → spec}/core/time/month_spec.rb +0 -0
- data/{test → spec}/core/time/now_spec.rb +0 -0
- data/{test → spec}/core/time/saturday_spec.rb +0 -0
- data/{test → spec}/core/true/and_spec.rb +0 -0
- data/{test → spec}/core/true/inspect_spec.rb +0 -0
- data/{test → spec}/core/true/or_spec.rb +0 -0
- data/{test → spec}/core/true/to_s_spec.rb +0 -0
- data/{test → spec}/core/true/xor_spec.rb +0 -0
- data/spec/grammar/lvar_spec.rb +2 -1
- data/spec/grammar/str_spec.rb +1 -1
- data/spec/grammar/xstr_spec.rb +1 -1
- data/{test → spec}/index.html +3 -3
- data/{test → spec}/language/alias_spec.rb +0 -0
- data/{test → spec}/language/and_spec.rb +0 -0
- data/{test → spec}/language/array_spec.rb +0 -0
- data/{test → spec}/language/block_spec.rb +0 -0
- data/{test → spec}/language/break_spec.rb +0 -0
- data/{test → spec}/language/case_spec.rb +0 -0
- data/{test → spec}/language/defined_spec.rb +0 -0
- data/{test → spec}/language/ensure_spec.rb +2 -2
- data/{test → spec}/language/fixtures/next.rb +0 -0
- data/{test → spec}/language/fixtures/yield.rb +0 -0
- data/{test → spec}/language/hash_spec.rb +0 -0
- data/{test → spec}/language/if_spec.rb +0 -0
- data/{test → spec}/language/literal_lambda_spec.rb +0 -0
- data/{test → spec}/language/loop_spec.rb +0 -0
- data/{test → spec}/language/metaclass_spec.rb +0 -0
- data/{test → spec}/language/next_spec.rb +2 -0
- data/{test → spec}/language/or_spec.rb +0 -0
- data/{test → spec}/language/predefined_spec.rb +0 -0
- data/{test → spec}/language/regexp_spec.rb +0 -0
- data/{test → spec}/language/send_spec.rb +0 -0
- data/{test → spec}/language/singleton_class_spec.rb +0 -0
- data/{test → spec}/language/super_spec.rb +0 -0
- data/{test → spec}/language/symbol_spec.rb +0 -0
- data/{test → spec}/language/undef_spec.rb +0 -0
- data/{test → spec}/language/unless_spec.rb +0 -0
- data/{test → spec}/language/until_spec.rb +0 -0
- data/{test → spec}/language/variables_spec.rb +0 -0
- data/{test → spec}/language/while_spec.rb +0 -0
- data/{test → spec}/language/yield_spec.rb +2 -0
- data/{test → spec}/opal/array/subclassing_spec.rb +0 -0
- data/{test → spec}/opal/array/to_json_spec.rb +0 -0
- data/{test → spec}/opal/boolean/singleton_class_spec.rb +0 -0
- data/{test → spec}/opal/boolean/to_json_spec.rb +0 -0
- data/{test → spec}/opal/class/bridge_class_spec.rb +0 -0
- data/spec/opal/erb/erb_spec.rb +15 -0
- data/{test → spec}/opal/exception/subclassing_spec.rb +0 -0
- data/{test → spec}/opal/hash/to_json_spec.rb +0 -0
- data/spec/opal/hash/to_native_spec.rb +5 -0
- data/{test → spec}/opal/json/parse_spec.rb +0 -0
- data/{test → spec}/opal/kernel/to_json_spec.rb +0 -0
- data/{test → spec}/opal/nil/to_json_spec.rb +0 -0
- data/{test → spec}/opal/numeric/to_json_spec.rb +0 -0
- data/{test → spec}/opal/runtime/call_spec.rb +0 -0
- data/{test → spec}/opal/runtime/class_hierarchy_spec.rb +0 -0
- data/{test → spec}/opal/runtime/def_spec.rb +0 -0
- data/{test → spec}/opal/runtime/defined_spec.rb +0 -0
- data/{test → spec}/opal/runtime/method_missing_spec.rb +3 -3
- data/{test → spec}/opal/runtime/super_spec.rb +0 -0
- data/{test → spec}/opal/string/subclassing_spec.rb +0 -0
- data/{test → spec}/opal/string/to_json_spec.rb +0 -0
- data/spec/opal/strscan/check_spec.rb +13 -0
- data/spec/opal/strscan/scan_spec.rb +33 -0
- data/spec/parser/simple_spec.rb +44 -0
- data/spec/spec_helper.rb +7 -7
- metadata +487 -497
- data/core/dir.rb +0 -89
- data/core/file.rb +0 -85
- data/spec/browser_spec.rb +0 -28
- data/spec/builder/fixtures/build_source/adam.rb +0 -0
- data/spec/builder/fixtures/build_source/bar/a.rb +0 -0
- data/spec/builder/fixtures/build_source/bar/wow/b.rb +0 -0
- data/spec/builder/fixtures/build_source/bar/wow/cow/c.rb +0 -0
- data/spec/builder/fixtures/build_source/beynon.rb +0 -0
- data/spec/builder/fixtures/build_source/charles.js +0 -0
- data/spec/builder/fixtures/build_source/foo/a.rb +0 -0
- data/spec/builder/fixtures/build_source/foo/b.rb +0 -0
- data/spec/builder/fixtures/build_source/foo/x.js +0 -0
- data/spec/builder/fixtures/build_source/foo/y.js +0 -0
- data/spec/builder/lib_name_for_spec.rb +0 -19
- data/test/index.min.html +0 -12
- data/test/spec_helper.rb +0 -4
data/core/string.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class String < `String`
|
2
|
-
`
|
2
|
+
`String_prototype._isString = true`
|
3
3
|
|
4
4
|
include Comparable
|
5
5
|
|
@@ -11,15 +11,17 @@ class String < `String`
|
|
11
11
|
|
12
12
|
def self.new(str = '')
|
13
13
|
%x{
|
14
|
-
|
15
|
-
s.$m = #{self}.$m_tbl;
|
16
|
-
s.$k = #{self};
|
17
|
-
return s;
|
14
|
+
return #{allocate str}
|
18
15
|
}
|
19
16
|
end
|
20
17
|
|
21
18
|
def %(data)
|
22
|
-
|
19
|
+
%x{
|
20
|
+
var idx = 0;
|
21
|
+
return #{self}.replace(/%((%)|s)/g, function (match) {
|
22
|
+
return match[2] || data[idx++] || '';
|
23
|
+
});
|
24
|
+
}
|
23
25
|
end
|
24
26
|
|
25
27
|
def *(count)
|
@@ -74,7 +76,7 @@ class String < `String`
|
|
74
76
|
end
|
75
77
|
|
76
78
|
def ==(other)
|
77
|
-
|
79
|
+
`other == String(#{self})`
|
78
80
|
end
|
79
81
|
|
80
82
|
alias === ==
|
@@ -92,20 +94,35 @@ class String < `String`
|
|
92
94
|
# TODO: implement range based accessors
|
93
95
|
def [](index, length)
|
94
96
|
%x{
|
95
|
-
|
96
|
-
if (index < 0) {
|
97
|
-
index += #{self}.length;
|
98
|
-
}
|
97
|
+
var size = #{self}.length;
|
99
98
|
|
100
|
-
|
99
|
+
if (index._isRange) {
|
100
|
+
var exclude = index.exclude,
|
101
|
+
length = index.end,
|
102
|
+
index = index.begin;
|
103
|
+
|
104
|
+
if (index > size) {
|
101
105
|
return nil;
|
102
106
|
}
|
103
107
|
|
104
|
-
|
108
|
+
if (length < 0) {
|
109
|
+
length += size;
|
110
|
+
}
|
111
|
+
|
112
|
+
if (exclude) length -= 1;
|
113
|
+
return #{self}.substr(index, length);
|
105
114
|
}
|
106
115
|
|
107
116
|
if (index < 0) {
|
108
|
-
index += #{self}.length
|
117
|
+
index += #{self}.length;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (length == null) {
|
121
|
+
if (index >= #{self}.length || index < 0) {
|
122
|
+
return nil;
|
123
|
+
}
|
124
|
+
|
125
|
+
return #{self}.substr(index, 1);
|
109
126
|
}
|
110
127
|
|
111
128
|
if (index > #{self}.length || index < 0) {
|
@@ -163,6 +180,10 @@ class String < `String`
|
|
163
180
|
`#{self}.charAt(0)`
|
164
181
|
end
|
165
182
|
|
183
|
+
def count(str)
|
184
|
+
`(#{self}.length - #{self}.replace(new RegExp(str,"g"), '').length) / str.length`
|
185
|
+
end
|
186
|
+
|
166
187
|
def downcase
|
167
188
|
`#{self}.toLowerCase()`
|
168
189
|
end
|
@@ -384,8 +405,9 @@ class String < `String`
|
|
384
405
|
return #{self}.replace(pattern, replace);
|
385
406
|
}
|
386
407
|
if (block !== nil) {
|
387
|
-
return #{self}.replace(pattern, function(str) {
|
388
|
-
|
408
|
+
return #{self}.replace(pattern, function(str, a) {
|
409
|
+
#{ $1 = `a` };
|
410
|
+
return block.call(__context, str);
|
389
411
|
});
|
390
412
|
}
|
391
413
|
else if (replace != null) {
|
@@ -432,7 +454,7 @@ class String < `String`
|
|
432
454
|
return $1 ? $0.toUpperCase() : $0.toLowerCase();
|
433
455
|
});
|
434
456
|
|
435
|
-
if (#{self}
|
457
|
+
if (#{self}._klass === String) {
|
436
458
|
return str;
|
437
459
|
}
|
438
460
|
|
@@ -474,9 +496,9 @@ class String < `String`
|
|
474
496
|
|
475
497
|
def to_proc
|
476
498
|
%x{
|
477
|
-
var name = #{self};
|
499
|
+
var name = '$' + #{self};
|
478
500
|
|
479
|
-
return function(
|
501
|
+
return function(arg) { return arg[name](arg); };
|
480
502
|
}
|
481
503
|
end
|
482
504
|
|
data/core/strscan.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
class StringScanner
|
2
|
+
attr_reader :pos
|
3
|
+
attr_reader :matched
|
4
|
+
|
5
|
+
def initialize(string)
|
6
|
+
@string = string
|
7
|
+
@pos = 0
|
8
|
+
@matched = ''
|
9
|
+
@working = string
|
10
|
+
end
|
11
|
+
|
12
|
+
def scan(regex)
|
13
|
+
%x{
|
14
|
+
var regex = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1)),
|
15
|
+
result = regex.exec(#@working);
|
16
|
+
|
17
|
+
if (result == null) {
|
18
|
+
#@matched = '';
|
19
|
+
|
20
|
+
return nil;
|
21
|
+
}
|
22
|
+
else if (typeof(result) === 'object') {
|
23
|
+
#@pos += result[0].length;
|
24
|
+
#@working = #@working.substring(result[0].length);
|
25
|
+
#@matched = result[0];
|
26
|
+
|
27
|
+
return result[0];
|
28
|
+
}
|
29
|
+
else if (typeof(result) === 'string') {
|
30
|
+
#@pos += result.length;
|
31
|
+
#@working = #@working.substring(result.length);
|
32
|
+
|
33
|
+
return result;
|
34
|
+
}
|
35
|
+
else {
|
36
|
+
return nil;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def check(regex)
|
42
|
+
%x{
|
43
|
+
var regexp = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1)),
|
44
|
+
result = regexp.exec(#@working);
|
45
|
+
|
46
|
+
if (result == null) {
|
47
|
+
return this.matched = nil;
|
48
|
+
}
|
49
|
+
|
50
|
+
return this.matched = result[0];
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def peek(length)
|
55
|
+
`#@working.substring(0, length)`
|
56
|
+
end
|
57
|
+
|
58
|
+
def eos?
|
59
|
+
`#@working.length === 0`
|
60
|
+
end
|
61
|
+
end
|
data/core/time.rb
CHANGED
@@ -1,17 +1,13 @@
|
|
1
1
|
class Time < `Date`
|
2
2
|
include Comparable
|
3
3
|
|
4
|
-
def self.allocate(t)
|
5
|
-
`new Date(t)`
|
6
|
-
end
|
7
|
-
|
8
4
|
def self.at(seconds, frac = 0)
|
9
5
|
allocate `seconds * 1000 + frac`
|
10
6
|
end
|
11
7
|
|
12
8
|
def self.new(year, month, day, hour, minute, second, millisecond)
|
13
9
|
%x{
|
14
|
-
switch (arguments.length
|
10
|
+
switch (arguments.length) {
|
15
11
|
case 1:
|
16
12
|
return new Date(year);
|
17
13
|
case 2:
|
data/docs/index.md
ADDED
@@ -0,0 +1,616 @@
|
|
1
|
+
<div class="hero-unit">
|
2
|
+
<h1 class="main-title">Opal</h1>
|
3
|
+
<p><strong>Opal is a ruby to javascript compiler</strong>.
|
4
|
+
Opal aims to take ruby files
|
5
|
+
and generate efficient javascript that maintains rubys features. Opal
|
6
|
+
will, by default, generate fast and efficient code in preference to
|
7
|
+
keeping all ruby features.
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<p>
|
11
|
+
Opal comes with an implementation of the ruby corelib, written in ruby,
|
12
|
+
that uses a bundled runtime (written in javascript) that tie all the
|
13
|
+
features together. Whenever possible Opal bridges to native javascript
|
14
|
+
features under the hood. The Opal gem includes the compiler used to
|
15
|
+
convert ruby sources into javascript.
|
16
|
+
</p>
|
17
|
+
|
18
|
+
<p>
|
19
|
+
Opal is <a href="http://github.com/adambeynon/opal">hosted on github</a>,
|
20
|
+
and there is a Freenode IRC channel at <code>#opal</code>.
|
21
|
+
</div>
|
22
|
+
|
23
|
+
## Downloads
|
24
|
+
|
25
|
+
The Opal runtime and corelib are distributed here, and are required to
|
26
|
+
run any code generated by opal.
|
27
|
+
|
28
|
+
[Opal version 0.3.21](http://opalrb.org/opal.js) _(13.1kb Minified And Gzipped)_
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
Opal should be added to your Gemfile:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
gem "opal"
|
36
|
+
```
|
37
|
+
|
38
|
+
## Usage
|
39
|
+
|
40
|
+
The easiest way to use opal is to create a rake task using the
|
41
|
+
`RakeTask` helper class. Assuming you have a single ruby file in
|
42
|
+
your Opal app called `app.rb`:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# app.rb
|
46
|
+
puts "Hello world"
|
47
|
+
```
|
48
|
+
|
49
|
+
Then create a rake task similar to:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
# Rakefile
|
53
|
+
require 'opal/rake_task'
|
54
|
+
|
55
|
+
Opal::RakeTask.new do |t|
|
56
|
+
t.files = ['app.rb']
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
### Building the app
|
61
|
+
|
62
|
+
Building the app is as simple as running:
|
63
|
+
|
64
|
+
```
|
65
|
+
rake opal:build
|
66
|
+
```
|
67
|
+
|
68
|
+
This will build all your listed files into `build/app_name.js`. The
|
69
|
+
output name is based on the directory name. This can be overriden by
|
70
|
+
setting the `.name` property in the task:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
Opal::RakeTask.new do |t|
|
74
|
+
t.files = ['app.rb']
|
75
|
+
t.name = 'my_awesome_app'
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
### Building opal runtime
|
80
|
+
|
81
|
+
To run the app in the browser, the opal runtime is required. This can
|
82
|
+
be built using:
|
83
|
+
|
84
|
+
```
|
85
|
+
rake opal:dependencies
|
86
|
+
```
|
87
|
+
|
88
|
+
Which will build `opal.js` into `./build`.
|
89
|
+
|
90
|
+
The output directory can also be overriden inside the rake task:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Opal::RakeTask.new do |t|
|
94
|
+
t.files = ['app.rb']
|
95
|
+
t.build_dir = 'out_dir'
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
The output directory will be created if it doesn't exist.
|
100
|
+
|
101
|
+
### Running the app
|
102
|
+
|
103
|
+
The two compiled files need to be added to a html page so that they
|
104
|
+
can run in the browser:
|
105
|
+
|
106
|
+
```html
|
107
|
+
<!doctype html>
|
108
|
+
<html>
|
109
|
+
<head>
|
110
|
+
<title>My awesome Opal app</title>
|
111
|
+
|
112
|
+
<script src="build/opal.js"></script>
|
113
|
+
<script src="build/my_awesome_app.js"></script>
|
114
|
+
|
115
|
+
<script>
|
116
|
+
// Run opal app
|
117
|
+
Opal.require('app')
|
118
|
+
</script>
|
119
|
+
</head>
|
120
|
+
<body>
|
121
|
+
</body>
|
122
|
+
</html>
|
123
|
+
```
|
124
|
+
|
125
|
+
If you open the html file, observe the console and you should see
|
126
|
+
`"Hello World"` printed to the console.
|
127
|
+
|
128
|
+
It is necessary to run `Opal.require('app')` as all files built for
|
129
|
+
opal are registered so that they can be required inside the ruby
|
130
|
+
code.
|
131
|
+
|
132
|
+
### Adding dependencies
|
133
|
+
|
134
|
+
The `opal:dependencies` rake task above can be used to build gems which
|
135
|
+
are designed to run in the browser. `opal-dom` is a gem that given opal
|
136
|
+
access to the DOM in the browser.
|
137
|
+
|
138
|
+
`opal-dom` first needs to be installed as a gem (currently it is only
|
139
|
+
available from git):
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
# Gemfile
|
143
|
+
gem "opal"
|
144
|
+
gem "opal-dom", :git => 'git://github.com/adambeynon/opal-dom.git'
|
145
|
+
```
|
146
|
+
|
147
|
+
Then add it to the dependencies to build:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
Opal::RakeTask.new do |t|
|
151
|
+
t.files = ['app.rb']
|
152
|
+
t.dependencies = ['opal-dom']
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
156
|
+
Running `rake opal:dependencies` now will also build
|
157
|
+
`build/opal-dom.js`.
|
158
|
+
|
159
|
+
We can now update our application code:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
# app.rb
|
163
|
+
require 'opal-dom'
|
164
|
+
|
165
|
+
alert "Hello!"
|
166
|
+
```
|
167
|
+
|
168
|
+
And rebuild:
|
169
|
+
|
170
|
+
```
|
171
|
+
rake opal:build
|
172
|
+
```
|
173
|
+
|
174
|
+
And add `opal-dom` to the html page:
|
175
|
+
|
176
|
+
```html
|
177
|
+
<script src="build/opal.js"></script>
|
178
|
+
<script src="build/opal-dom.js"></script>
|
179
|
+
<script src="build/app.js"></script>
|
180
|
+
```
|
181
|
+
|
182
|
+
Now running the app should cause an alert box to display.
|
183
|
+
|
184
|
+
## Features And Implementation
|
185
|
+
|
186
|
+
Opal is a source-to-source compiler, so there is no VM as such and the
|
187
|
+
compiled code aims to be as fast and efficient as possible, mapping
|
188
|
+
directly to underlying javascript features and objects where possible.
|
189
|
+
|
190
|
+
### Literals
|
191
|
+
|
192
|
+
**self** is always compiled to `self`. Any context inside the generated
|
193
|
+
code is usually a function body; whether it be a method body, a block,
|
194
|
+
a class/module body or the file itself.
|
195
|
+
|
196
|
+
**true** and **false** are compiled directly into their native boolean
|
197
|
+
equivalents. This makes interaction a lot easier as there is no need
|
198
|
+
to convert values to opal specific values. It does mean that there is
|
199
|
+
only a `Boolean` ruby class available, not seperate `TrueClass` and
|
200
|
+
`FalseClass` classes.
|
201
|
+
|
202
|
+
**nil** is compiled into a `nil` reference, which inside all generated
|
203
|
+
files points to a special object which is just an instance of the ruby
|
204
|
+
`NilClass` class. This object is available externally to javascript as
|
205
|
+
`Opal.nil`.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
nil # => nil
|
209
|
+
true # => true
|
210
|
+
false # => false
|
211
|
+
self # => self
|
212
|
+
```
|
213
|
+
|
214
|
+
#### Strings
|
215
|
+
|
216
|
+
Ruby strings are compiled directly into javascript strings for
|
217
|
+
performance as well as readability. This has the side effect that Opal
|
218
|
+
does not support mutable strings - i.e. all strings are immutable.
|
219
|
+
|
220
|
+
#### Symbols
|
221
|
+
|
222
|
+
For performance reasons, symbols compile directly into strings. Opal
|
223
|
+
supports all the symbol syntaxes, but does not have a real `Symbol`
|
224
|
+
class. Symbols and Strings can therefore be used interchangeably.
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
"hello world!" # => "hello world!"
|
228
|
+
:foo # => "foo"
|
229
|
+
<<-EOS # => "\nHello there.\n"
|
230
|
+
Hello there.
|
231
|
+
EOS
|
232
|
+
```
|
233
|
+
|
234
|
+
#### Numbers
|
235
|
+
|
236
|
+
In Opal there is a single class for numbers; `Numeric`. To keep opal
|
237
|
+
as performant as possible, ruby numbers are mapped to native numbers.
|
238
|
+
This has the side effect that all numbers must be of the same class.
|
239
|
+
Most relevant methods from `Integer`, `Float` and `Numeric` are
|
240
|
+
implemented on this class.
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
42 # => 42
|
244
|
+
3.142 # => 3.142
|
245
|
+
```
|
246
|
+
|
247
|
+
#### Arrays
|
248
|
+
|
249
|
+
Ruby arrays are compiled directly into javascript arrays. Special
|
250
|
+
ruby syntaxes for word arrays etc are also supported.
|
251
|
+
|
252
|
+
```ruby
|
253
|
+
[1, 2, 3, 4] # => [1, 2, 3, 4]
|
254
|
+
%w[foo bar baz] # => ["foo", "bar", "baz"]
|
255
|
+
```
|
256
|
+
|
257
|
+
#### Hash
|
258
|
+
|
259
|
+
Inside a generated ruby script, a function `__hash` is available which
|
260
|
+
creates a new hash. This is also available in javascript as `Opal.hash`
|
261
|
+
and simply returns a new instance of the `Hash` class.
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
{ :foo => 100, :baz => 700 } # => __hash("foo", 100, "baz", 700)
|
265
|
+
{ foo: 42, bar: [1, 2, 3] } # => __hash("foo", 42, "bar", [1, 2, 3])
|
266
|
+
```
|
267
|
+
|
268
|
+
#### Range
|
269
|
+
|
270
|
+
Similar to hash, there is a function `__range` available to create
|
271
|
+
range instances.
|
272
|
+
|
273
|
+
```ruby
|
274
|
+
1..4 # => __range(1, 4, true)
|
275
|
+
3...7 # => __range(3, 7, false)
|
276
|
+
```
|
277
|
+
|
278
|
+
#### Optimized Math Operators
|
279
|
+
|
280
|
+
In ruby, all math operators are method calls, but compiling this into
|
281
|
+
javascript would end up being too slow. For this reason, math
|
282
|
+
operators are optimized to test first if the receiver is a number, and
|
283
|
+
if so then to just carry out the math call.
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
3 + 4
|
287
|
+
```
|
288
|
+
|
289
|
+
This ruby code will then be compiled into the following javascript:
|
290
|
+
|
291
|
+
```javascript
|
292
|
+
(a = 3, b = 4, typeof(a) === "number" ? a + b : /* method call */)
|
293
|
+
```
|
294
|
+
|
295
|
+
This ternary statement falls back on sending a method to the receiver
|
296
|
+
so all non-numeric receivers will still have the normal method call
|
297
|
+
being sent. This optimization makes math operators a **lot faster**.
|
298
|
+
Currently, the optimized method calls are `+`, `-`, `*` and `/`.
|
299
|
+
|
300
|
+
### method_missing
|
301
|
+
|
302
|
+
Method missing is fully supported in Opal. It is implemented as
|
303
|
+
efficiently as possible.
|
304
|
+
|
305
|
+
### Logic and conditionals
|
306
|
+
|
307
|
+
As per ruby, Opal treats only `false` and `nil` as falsy, everything
|
308
|
+
else is a truthy value including `""`, `0` and `[]`. This differs from
|
309
|
+
javascript as these values are also treated as false.
|
310
|
+
|
311
|
+
For this reason, most truthy tests must check if values are `false` or
|
312
|
+
`nil`.
|
313
|
+
|
314
|
+
Taking the following test:
|
315
|
+
|
316
|
+
```javascript
|
317
|
+
val = 42
|
318
|
+
|
319
|
+
if val
|
320
|
+
return 3.142;
|
321
|
+
end
|
322
|
+
```
|
323
|
+
|
324
|
+
This would be compiled into:
|
325
|
+
|
326
|
+
```ruby
|
327
|
+
val = 42;
|
328
|
+
|
329
|
+
if (val !== false && val !== nil) {
|
330
|
+
return 3.142;
|
331
|
+
}
|
332
|
+
```
|
333
|
+
|
334
|
+
This makes the generated truthy tests (`if` statements, `and` checks and
|
335
|
+
`or` statements) a litle more verbose in the generated code.
|
336
|
+
|
337
|
+
### Instance variables
|
338
|
+
|
339
|
+
Instance variables in Opal work just as expected. When ivars are set or
|
340
|
+
retrieved on an object, they are set natively without the `@` prefix.
|
341
|
+
This allows real javascript identifiers to be used which is more
|
342
|
+
efficient then accessing variables by string name.
|
343
|
+
|
344
|
+
```ruby
|
345
|
+
@foo = 200
|
346
|
+
@foo # => 200
|
347
|
+
|
348
|
+
@bar # => nil
|
349
|
+
```
|
350
|
+
|
351
|
+
This gets compiled into:
|
352
|
+
|
353
|
+
```javascript
|
354
|
+
this.foo = 200;
|
355
|
+
this.foo; // => 200
|
356
|
+
|
357
|
+
this.bar; // => nil
|
358
|
+
```
|
359
|
+
|
360
|
+
The only point of warning is that when variables are used for the
|
361
|
+
first time in ruby, they default to `nil`. In javascript, they default
|
362
|
+
to `undefined`/`null`.
|
363
|
+
|
364
|
+
To keep things working in opal, ivars must be preset to `nil` before
|
365
|
+
they can be used. In the top scope and other corner cases, this needs
|
366
|
+
to be done on a per scope basis, which can add overhead.
|
367
|
+
|
368
|
+
To improve performance, once a class body is compiled, all ivars used
|
369
|
+
within methods in that class are preset on the prototype of the class
|
370
|
+
to be `nil`. This means that all known ivars are already set to nil,
|
371
|
+
and this is done just once during the lifespan of the app.
|
372
|
+
|
373
|
+
```ruby
|
374
|
+
class Foo
|
375
|
+
def bar
|
376
|
+
@lol
|
377
|
+
end
|
378
|
+
|
379
|
+
def woosh
|
380
|
+
@kapow
|
381
|
+
end
|
382
|
+
end
|
383
|
+
```
|
384
|
+
|
385
|
+
This example gets compiled into something similar to:
|
386
|
+
|
387
|
+
```javascript
|
388
|
+
(function() {
|
389
|
+
function Foo(){}
|
390
|
+
// ...
|
391
|
+
|
392
|
+
Foo.prototype.lol = Foo.prototype.woosh = nil;
|
393
|
+
|
394
|
+
Foo.prototype.$bar = function() {
|
395
|
+
return this.lol;
|
396
|
+
};
|
397
|
+
|
398
|
+
// etc ...
|
399
|
+
})()
|
400
|
+
```
|
401
|
+
|
402
|
+
### Interacting with javascript
|
403
|
+
|
404
|
+
Opal tries to interact as cleanly with javascript and its api as much
|
405
|
+
as possible. Ruby arrays, strings, numbers, regexps, blocks and booleans
|
406
|
+
are just javascript native equivalents. The only boxed core features are
|
407
|
+
hashes and nil.
|
408
|
+
|
409
|
+
As most of the corelib deals with these low level details, opal provides
|
410
|
+
a special syntax for inlining javascript code. This is done with
|
411
|
+
x-strings or "backticks", as their ruby use has no useful translation
|
412
|
+
in the browser.
|
413
|
+
|
414
|
+
```ruby
|
415
|
+
`window.title`
|
416
|
+
# => "Opal: ruby to javascript compiler"
|
417
|
+
|
418
|
+
%x{
|
419
|
+
console.log("ruby version is:");
|
420
|
+
console.log(#{ OPAL_VERSION });
|
421
|
+
}
|
422
|
+
|
423
|
+
# => ruby version is:
|
424
|
+
# => 0.3.19
|
425
|
+
```
|
426
|
+
|
427
|
+
Even interpolations are supported, as seen here.
|
428
|
+
|
429
|
+
This feature of inlining code is used extensively, for example in
|
430
|
+
Array#length:
|
431
|
+
|
432
|
+
```ruby
|
433
|
+
class Array
|
434
|
+
def length
|
435
|
+
`this.length`
|
436
|
+
end
|
437
|
+
end
|
438
|
+
```
|
439
|
+
|
440
|
+
X-Strings also have the ability to automatically return their value,
|
441
|
+
as used by this example.
|
442
|
+
|
443
|
+
### Compiled Files
|
444
|
+
|
445
|
+
As described above, a compiled ruby source gets generated into a string
|
446
|
+
of javascript code that is wrapped inside an anonymous function. This
|
447
|
+
looks similar to the following:
|
448
|
+
|
449
|
+
```javascript
|
450
|
+
(function() {
|
451
|
+
var nil = Opal.nil, self = Opal.top;
|
452
|
+
// generated code
|
453
|
+
})();
|
454
|
+
```
|
455
|
+
|
456
|
+
Inside the function, `nil` is assigned to ensure a local copy is
|
457
|
+
available, as well as all the helper methods used within the
|
458
|
+
generated file. There is no return value from these functions as they
|
459
|
+
are not used anywhere.
|
460
|
+
|
461
|
+
As a complete example, assuming the following code:
|
462
|
+
|
463
|
+
```ruby
|
464
|
+
puts "foo"
|
465
|
+
```
|
466
|
+
|
467
|
+
This would compile directly into:
|
468
|
+
|
469
|
+
```javascript
|
470
|
+
(function() {
|
471
|
+
var nil = Opal.nil, self = Opal.top;
|
472
|
+
self.$puts("foo");
|
473
|
+
})();
|
474
|
+
```
|
475
|
+
|
476
|
+
Most of the helpers are no longer present as they are not used in this
|
477
|
+
example.
|
478
|
+
|
479
|
+
### Using compiled sources
|
480
|
+
|
481
|
+
If you write the generated code as above into a file `app.js` and add
|
482
|
+
that to your HTML page, then it is obvious that `"foo"` would be
|
483
|
+
written to the browser's console.
|
484
|
+
|
485
|
+
### JSON
|
486
|
+
|
487
|
+
The opal corelib includes JSON support instead of treating it as an
|
488
|
+
external lib. The `JSON` module provides the usual parsing methods.
|
489
|
+
|
490
|
+
```ruby
|
491
|
+
JSON.parse '{"a": 10, "b": [1, 2, 3], "c": null}'
|
492
|
+
# => { "a" => 10, "b" => [1, 2, 3], "c" => nil }
|
493
|
+
```
|
494
|
+
|
495
|
+
Opal expects `JSON` to be present in the browser, so older browsers
|
496
|
+
may require a shim (json2.js) to work with opal. Most mobile browsers
|
497
|
+
and modern desktop browsers include json support natively.
|
498
|
+
|
499
|
+
## Debugging and finding errors
|
500
|
+
|
501
|
+
Because Opal does not aim to be fully compatible with ruby, there are
|
502
|
+
some instances where things can break and it may not be entirely
|
503
|
+
obvious what went wrong.
|
504
|
+
|
505
|
+
### Undefined methods
|
506
|
+
|
507
|
+
By default, opal aims to be as fast as possible, so `method_missing` is
|
508
|
+
not turned on by default. Instead, when calling a method that doesn't
|
509
|
+
exist, a native error will be raised.
|
510
|
+
|
511
|
+
```ruby
|
512
|
+
self.do_something()
|
513
|
+
```
|
514
|
+
|
515
|
+
Might raise an error similar to:
|
516
|
+
|
517
|
+
```
|
518
|
+
Error: 'undefined' is not a function (evaluating 'this.$do_something()')
|
519
|
+
```
|
520
|
+
|
521
|
+
As described above, all ruby methods will have a `$` prefix which gives
|
522
|
+
a good indication that it is a opal method that doesnt exist, and most
|
523
|
+
js engines output the missing function name.
|
524
|
+
|
525
|
+
### Undefined constants
|
526
|
+
|
527
|
+
If trying to access a constant that doesn't exist, there is no runtime
|
528
|
+
error. Instead, the value of that expression is just `undefined` as
|
529
|
+
constants are retrieved from objects that hold all constants in the
|
530
|
+
scope. Trying to send a method to an undefined constant will therefore
|
531
|
+
just raise an ugly javascript `TypeError`.
|
532
|
+
|
533
|
+
If you are using the constant as a reference, it may not be until much
|
534
|
+
later that the error occurs.
|
535
|
+
|
536
|
+
### Using javascript debuggers
|
537
|
+
|
538
|
+
As opal just generates javascript, it is useful to use a native
|
539
|
+
debugger to work through javascript code. To use a debugger, simply
|
540
|
+
add an x-string similar to the following at the place you wish to
|
541
|
+
debug:
|
542
|
+
|
543
|
+
```ruby
|
544
|
+
# .. code
|
545
|
+
`debugger`
|
546
|
+
# .. more code
|
547
|
+
```
|
548
|
+
The x-strings just pass the debugger statement straight through to the
|
549
|
+
javascript output.
|
550
|
+
|
551
|
+
Inside methods and blocks, the current `self` value is always the
|
552
|
+
native `this` value. You will not see `self` inside debuggers as it is
|
553
|
+
never used to refer to the actual ruby self value.
|
554
|
+
|
555
|
+
All local variables and method/block arguments also keep their ruby
|
556
|
+
names except in the rare cases when the name is reserved in javascript.
|
557
|
+
In these cases, a `$` suffix is added to the name (e.g. `try` =>
|
558
|
+
`try$`).
|
559
|
+
|
560
|
+
## License
|
561
|
+
|
562
|
+
Opal is released under the MIT license.
|
563
|
+
|
564
|
+
## Change Log
|
565
|
+
|
566
|
+
**0.3.21** _(16 July 2012)_
|
567
|
+
|
568
|
+
* Add `method_missing` support to all objects and classes
|
569
|
+
* Add `Opal.build_gem()` method to quickly build installed gem
|
570
|
+
* Add `Opal.build_files()` method to build directories of files
|
571
|
+
|
572
|
+
**0.3.20** _(23 June 2012)_
|
573
|
+
|
574
|
+
* Merge JSON into core. JSON module and various #to_json methods are
|
575
|
+
now included as part of corelib
|
576
|
+
* Make `Time` class bridge to native `Date` constructor
|
577
|
+
* Use named functions as class constuctors to make debugging easier
|
578
|
+
* Classes are now real functions with prototypes. Bridged classes are
|
579
|
+
now directly corresponding to the ruby class (e.g. Array === Opal.Array)
|
580
|
+
* Set ivars used inside methods in class to `nil` inside class definition
|
581
|
+
to avoid doing it everytime method is called
|
582
|
+
* Add debug comments to output for def, class and module stating the file
|
583
|
+
and line number the given code was generated from
|
584
|
+
|
585
|
+
**0.3.19** _(30 May 2012)_
|
586
|
+
|
587
|
+
* Add BasicObject as the root class
|
588
|
+
* Add `Opal.define` and `Opal.require` for requiring files
|
589
|
+
* Builder uses a `main` option to dictate which file to require on load
|
590
|
+
* Completely revamp runtime to reduce helper methods
|
591
|
+
* Allow native bridges (Array, String, etc) to be subclassed
|
592
|
+
* Make sure `.js` files can be built with `Opal::Builder`
|
593
|
+
* Include the current file name when raising parse errors
|
594
|
+
|
595
|
+
**0.3.18** _(20 May 2012)_
|
596
|
+
|
597
|
+
* Fix various core lib bugs
|
598
|
+
* Completely remove `require` from corelib
|
599
|
+
* Improve Builder to detect dependencies in files
|
600
|
+
|
601
|
+
**0.3.17** _(19 May 2012)_
|
602
|
+
|
603
|
+
* Revamp of Builder and Parser tools
|
604
|
+
* Remove opal-repl
|
605
|
+
* Added a lot of specs for core lib
|
606
|
+
|
607
|
+
**0.3.16** _(15 January 2012)_
|
608
|
+
|
609
|
+
* Added HEREDOCS support in parser
|
610
|
+
* Parser now handles masgn (mass/multi assignments)
|
611
|
+
* More useful DependencyBuilder class to build gems dependencies
|
612
|
+
* Blocks no longer passed as an argument in method calls
|
613
|
+
|
614
|
+
**0.3.15**
|
615
|
+
|
616
|
+
* Initial Release.
|