rubyjs 0.7.0

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.
Files changed (144) hide show
  1. data/README +128 -0
  2. data/Rakefile +9 -0
  3. data/bin/rubyjs +140 -0
  4. data/examples/ex1/Rakefile +7 -0
  5. data/examples/ex1/ex1.js +771 -0
  6. data/examples/ex1/ex1.rb +42 -0
  7. data/examples/ex1/index.html +7 -0
  8. data/examples/hw/Rakefile +9 -0
  9. data/examples/hw/hw.js +635 -0
  10. data/examples/hw/hw.rb +7 -0
  11. data/examples/hw/index.html +7 -0
  12. data/patches/parse_tree.rb.diff +34 -0
  13. data/rubyjs.gemspec +24 -0
  14. data/src/rubyjs.rb +4 -0
  15. data/src/rubyjs/code_generator.rb +474 -0
  16. data/src/rubyjs/compiler.rb +2007 -0
  17. data/src/rubyjs/debug_name_generator.rb +75 -0
  18. data/src/rubyjs/encoder.rb +171 -0
  19. data/src/rubyjs/eval_into.rb +59 -0
  20. data/src/rubyjs/lib/core.rb +1008 -0
  21. data/src/rubyjs/lib/json.rb +101 -0
  22. data/src/rubyjs/model.rb +287 -0
  23. data/src/rubyjs/name_generator.rb +71 -0
  24. data/src/rwt/AbsolutePanel.rb +161 -0
  25. data/src/rwt/DOM.Konqueror.rb +89 -0
  26. data/src/rwt/DOM.Opera.rb +65 -0
  27. data/src/rwt/DOM.rb +1044 -0
  28. data/src/rwt/Event.Opera.rb +35 -0
  29. data/src/rwt/Event.rb +429 -0
  30. data/src/rwt/HTTPRequest.IE6.rb +5 -0
  31. data/src/rwt/HTTPRequest.rb +74 -0
  32. data/src/rwt/Label.rb +164 -0
  33. data/src/rwt/Panel.rb +90 -0
  34. data/src/rwt/RootPanel.rb +16 -0
  35. data/src/rwt/UIObject.rb +495 -0
  36. data/src/rwt/Widget.rb +193 -0
  37. data/src/rwt/ported-from/AbsolutePanel.java +158 -0
  38. data/src/rwt/ported-from/DOM.java +571 -0
  39. data/src/rwt/ported-from/DOMImpl.java +426 -0
  40. data/src/rwt/ported-from/DOMImplOpera.java +82 -0
  41. data/src/rwt/ported-from/DOMImplStandard.java +234 -0
  42. data/src/rwt/ported-from/HTTPRequest.java +81 -0
  43. data/src/rwt/ported-from/HTTPRequestImpl.java +103 -0
  44. data/src/rwt/ported-from/Label.java +163 -0
  45. data/src/rwt/ported-from/Panel.java +99 -0
  46. data/src/rwt/ported-from/UIObject.java +614 -0
  47. data/src/rwt/ported-from/Widget.java +221 -0
  48. data/test/benchmark/bm_call_conv1.js +16 -0
  49. data/test/benchmark/bm_call_conv2.js +14 -0
  50. data/test/benchmark/bm_var_acc1.js +13 -0
  51. data/test/benchmark/bm_var_acc2.js +11 -0
  52. data/test/benchmark/bm_vm1_block.js +15 -0
  53. data/test/benchmark/bm_vm1_block.rb +15 -0
  54. data/test/benchmark/bm_vm1_const.js +13 -0
  55. data/test/benchmark/bm_vm1_const.rb +13 -0
  56. data/test/benchmark/bm_vm1_ensure.js +17 -0
  57. data/test/benchmark/bm_vm1_ensure.rb +15 -0
  58. data/test/benchmark/common.js +4 -0
  59. data/test/benchmark/common.rb +5 -0
  60. data/test/benchmark/params.yaml +7 -0
  61. data/test/browser.test.html +4059 -0
  62. data/test/browser.test.js +3225 -0
  63. data/test/common.Browser.rb +13 -0
  64. data/test/common.rb +8 -0
  65. data/test/gen_browser_test_suite.rb +129 -0
  66. data/test/gen_test_suite.rb +41 -0
  67. data/test/run_benchs.rb +58 -0
  68. data/test/run_tests.rb +22 -0
  69. data/test/test_args.rb +24 -0
  70. data/test/test_array.rb +26 -0
  71. data/test/test_case.rb +35 -0
  72. data/test/test_class.rb +55 -0
  73. data/test/test_eql.rb +9 -0
  74. data/test/test_exception.rb +61 -0
  75. data/test/test_expr.rb +12 -0
  76. data/test/test_hash.rb +29 -0
  77. data/test/test_if.rb +28 -0
  78. data/test/test_inspect.rb +10 -0
  79. data/test/test_lebewesen.rb +39 -0
  80. data/test/test_massign.rb +66 -0
  81. data/test/test_new.rb +12 -0
  82. data/test/test_range.rb +53 -0
  83. data/test/test_regexp.rb +22 -0
  84. data/test/test_send.rb +65 -0
  85. data/test/test_simple_output.rb +5 -0
  86. data/test/test_splat.rb +21 -0
  87. data/test/test_string.rb +51 -0
  88. data/test/test_yield.rb +152 -0
  89. data/utils/js/Makefile +9 -0
  90. data/utils/js/RunScript.class +0 -0
  91. data/utils/js/RunScript.java +73 -0
  92. data/utils/js/js.jar +0 -0
  93. data/utils/js/run.sh +3 -0
  94. data/utils/jsc/Makefile +7 -0
  95. data/utils/jsc/README +3 -0
  96. data/utils/jsc/RunScript.c +93 -0
  97. data/utils/jsc/run.sh +15 -0
  98. data/utils/yuicompressor/README +1 -0
  99. data/utils/yuicompressor/yuicompressor-2.2.5.jar +0 -0
  100. data/vendor/ParseTree-1.7.1-patched/History.txt +217 -0
  101. data/vendor/ParseTree-1.7.1-patched/Manifest.txt +22 -0
  102. data/vendor/ParseTree-1.7.1-patched/README.txt +110 -0
  103. data/vendor/ParseTree-1.7.1-patched/Rakefile +41 -0
  104. data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_abc +89 -0
  105. data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_audit +28 -0
  106. data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_deps +62 -0
  107. data/vendor/ParseTree-1.7.1-patched/bin/parse_tree_show +49 -0
  108. data/vendor/ParseTree-1.7.1-patched/demo/printer.rb +20 -0
  109. data/vendor/ParseTree-1.7.1-patched/lib/composite_sexp_processor.rb +49 -0
  110. data/vendor/ParseTree-1.7.1-patched/lib/parse_tree.rb +1013 -0
  111. data/vendor/ParseTree-1.7.1-patched/lib/sexp.rb +235 -0
  112. data/vendor/ParseTree-1.7.1-patched/lib/sexp_processor.rb +330 -0
  113. data/vendor/ParseTree-1.7.1-patched/lib/unique.rb +15 -0
  114. data/vendor/ParseTree-1.7.1-patched/test/pt_testcase.rb +1221 -0
  115. data/vendor/ParseTree-1.7.1-patched/test/something.rb +53 -0
  116. data/vendor/ParseTree-1.7.1-patched/test/test_all.rb +13 -0
  117. data/vendor/ParseTree-1.7.1-patched/test/test_composite_sexp_processor.rb +69 -0
  118. data/vendor/ParseTree-1.7.1-patched/test/test_parse_tree.rb +216 -0
  119. data/vendor/ParseTree-1.7.1-patched/test/test_sexp.rb +291 -0
  120. data/vendor/ParseTree-1.7.1-patched/test/test_sexp_processor.rb +244 -0
  121. data/vendor/ParseTree-1.7.1-patched/validate.sh +31 -0
  122. data/vendor/ParseTree-1.7.1/History.txt +217 -0
  123. data/vendor/ParseTree-1.7.1/Manifest.txt +22 -0
  124. data/vendor/ParseTree-1.7.1/README.txt +110 -0
  125. data/vendor/ParseTree-1.7.1/Rakefile +41 -0
  126. data/vendor/ParseTree-1.7.1/bin/parse_tree_abc +89 -0
  127. data/vendor/ParseTree-1.7.1/bin/parse_tree_audit +28 -0
  128. data/vendor/ParseTree-1.7.1/bin/parse_tree_deps +62 -0
  129. data/vendor/ParseTree-1.7.1/bin/parse_tree_show +49 -0
  130. data/vendor/ParseTree-1.7.1/demo/printer.rb +20 -0
  131. data/vendor/ParseTree-1.7.1/lib/composite_sexp_processor.rb +49 -0
  132. data/vendor/ParseTree-1.7.1/lib/parse_tree.rb +1004 -0
  133. data/vendor/ParseTree-1.7.1/lib/sexp.rb +235 -0
  134. data/vendor/ParseTree-1.7.1/lib/sexp_processor.rb +330 -0
  135. data/vendor/ParseTree-1.7.1/lib/unique.rb +15 -0
  136. data/vendor/ParseTree-1.7.1/test/pt_testcase.rb +1221 -0
  137. data/vendor/ParseTree-1.7.1/test/something.rb +53 -0
  138. data/vendor/ParseTree-1.7.1/test/test_all.rb +13 -0
  139. data/vendor/ParseTree-1.7.1/test/test_composite_sexp_processor.rb +69 -0
  140. data/vendor/ParseTree-1.7.1/test/test_parse_tree.rb +216 -0
  141. data/vendor/ParseTree-1.7.1/test/test_sexp.rb +291 -0
  142. data/vendor/ParseTree-1.7.1/test/test_sexp_processor.rb +244 -0
  143. data/vendor/ParseTree-1.7.1/validate.sh +31 -0
  144. metadata +230 -0
@@ -0,0 +1,101 @@
1
+ #
2
+ # JSON loading/dumping
3
+ #
4
+ # Parser code taken from http://www.json.org/json.js
5
+ #
6
+
7
+ class JSON
8
+ class SyntaxError < RuntimeError; end
9
+
10
+ #
11
+ # Parsing happens in three stages. In the first stage, we run the text against
12
+ # a regular expression which looks for non-JSON characters. We are especially
13
+ # concerned with '()' and 'new' because they can cause invocation, and '='
14
+ # because it can cause mutation. But just to be safe, we will reject all
15
+ # unexpected characters.
16
+ #
17
+ # We split the first stage into 4 regexp operations in order to work around
18
+ # crippling deficiencies in IE's and Safari's regexp engines. First we replace
19
+ # all backslash pairs with '@' (a non-JSON character). Second, we replace all
20
+ # simple value tokens with ']' characters. Third, we delete all open brackets
21
+ # that follow a colon or comma or that begin the text. Finally, we look to see
22
+ # that the remaining characters are only whitespace or ']' or ',' or ':' or '{'
23
+ # or '}'. If that is so, then the text is safe for eval.
24
+ #
25
+ # In the second stage we use the eval function to compile the text into a
26
+ # JavaScript structure. The '{' operator is subject to a syntactic ambiguity
27
+ # in JavaScript: it can begin a block or an object literal. We wrap the text
28
+ # in parens to eliminate the ambiguity.
29
+ #
30
+ def self._parse(str)
31
+ RubyJS::inline <<-'endjs'
32
+ if (/^[\],:{}\s]*$/.test(#<str>.replace(/\\./g, '@').
33
+ replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(:?[eE][+\-]?\d+)?/g, ']').
34
+ replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
35
+ return eval('(' + #<str> + ')');
36
+ }
37
+ endjs
38
+
39
+ raise SyntaxError, str
40
+ end
41
+
42
+ def self.load(str)
43
+ obj = _parse(str)
44
+ `
45
+ var conv = function(obj) {
46
+ if (obj==null) return #<nil>;
47
+ else if (obj instanceof Array) {
48
+ for (var i=0; i<obj.length; i++) obj[i] = conv(obj[i]);
49
+ }
50
+ else if (typeof(obj) == 'object') {
51
+ var nobj = #<Hash>.#<m:new>();
52
+ for (var i in obj) {
53
+ nobj.#<m:[]=>(#<nil>, conv(i), conv(obj[i]));
54
+ }
55
+ return nobj;
56
+ }
57
+ return obj;
58
+ };
59
+ return conv(#<obj>);
60
+ `
61
+ end
62
+
63
+ def self.dump(obj)
64
+ obj.to_json
65
+ end
66
+ end
67
+
68
+ class Object
69
+ def to_json; raise end
70
+ end
71
+
72
+ class Boolean
73
+ alias to_json to_s
74
+ end
75
+
76
+ class NilClass
77
+ def to_json; "null" end
78
+ end
79
+
80
+ class String
81
+ alias to_json inspect # FIXME?
82
+ end
83
+
84
+ class Number
85
+ alias to_json to_s
86
+ end
87
+
88
+ class Array
89
+ def to_json
90
+ map {|a| a.to_json}.join(",")
91
+ end
92
+ end
93
+
94
+ class Hash
95
+ def to_json
96
+ str = "{"
97
+ str += map {|k, v| (k.to_json + ":" + v.to_json) }.join(",")
98
+ str += "}"
99
+ str
100
+ end
101
+ end
@@ -0,0 +1,287 @@
1
+ #
2
+ # Extract the class/module hierarchy and the methods.
3
+ #
4
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de).
5
+ # All rights reserved.
6
+ #
7
+
8
+ require 'parse_tree'
9
+ require 'sexp_processor'
10
+ require 'enumerator'
11
+ require 'rubyjs/encoder'
12
+ require 'set'
13
+
14
+ class MethodExtractor < SexpProcessor
15
+ attr_accessor :instance_methods, :methods
16
+
17
+ def initialize
18
+ super()
19
+
20
+ self.strict = false
21
+ self.auto_shift_type = false
22
+ self.require_empty = false
23
+
24
+ @instance_methods = {}
25
+ @methods = {}
26
+ end
27
+
28
+ def process_defn(exp)
29
+ defn, name, code = *exp
30
+ name = name.to_s
31
+ if name =~ /^self\.(.*)$/
32
+ @methods[$1] = exp
33
+ else
34
+ @instance_methods[name] = exp
35
+ end
36
+ return s()
37
+ end
38
+ end
39
+
40
+ class Model < Encoder
41
+ SCOPE_R = /^RubyJS::Environment::(.*)$/
42
+
43
+ attr_accessor :models
44
+ attr_accessor :current_model
45
+
46
+ attr_reader :method_calls
47
+
48
+ def initialize
49
+ super()
50
+
51
+ #
52
+ # record all (potential) names of all method calls
53
+ #
54
+ @method_calls = Set.new
55
+
56
+
57
+ @models = {}
58
+
59
+ # all modules and classes (a Class is_a Module)
60
+ ObjectSpace.each_object {|o|
61
+ @models[o] = model_for(o) if o.is_a?(::Module) && o.name =~ SCOPE_R
62
+ }
63
+ end
64
+
65
+ def add_method_call(name)
66
+ @method_calls.add(name)
67
+ end
68
+
69
+ def iterate_all(seen, &block)
70
+ @models.each_value do |v|
71
+ iterate_rec(v, seen, &block)
72
+ end
73
+ end
74
+
75
+ def iterate_rec(model, seen, &block)
76
+ return if seen.include?(model[:for])
77
+ iterate_rec(@models[model[:superclass]], seen, &block) if model[:superclass]
78
+
79
+ model[:modules].each do |m|
80
+ iterate_rec(@models[m], seen, &block)
81
+ end
82
+
83
+ with_current_model(model) do
84
+ block.call(model)
85
+ end
86
+ seen.add(model[:for])
87
+ end
88
+
89
+ alias old_encode_constant encode_constant
90
+
91
+ def encode_constant(name)
92
+ if @current_model
93
+ lookup_constant(name)
94
+ else
95
+ old_encode_constant(name)
96
+ end
97
+ end
98
+
99
+ #
100
+ # Compile time constant lookup.
101
+ #
102
+ # Lookup rules (like Ruby 1.9+):
103
+ #
104
+ # 1. Current class
105
+ # 2. Super classes except object
106
+ # 3. lexically enclosing modules/classes
107
+ # 4. Object
108
+ #
109
+ def lookup_constant(name)
110
+ model = @current_model
111
+ prefix, *path = name.split("::")
112
+
113
+ start_lookup_at = nil
114
+ done = false
115
+
116
+ if prefix.empty?
117
+ # e.g. "::A"
118
+ start_lookup_at = RubyJS::Environment
119
+ done = true
120
+ else
121
+
122
+ # 1. Current class
123
+ if model[:for].constants.include?(prefix)
124
+ start_lookup_at = model[:for].const_get(prefix)
125
+ done = true
126
+ end
127
+
128
+ # 2. Super classes except object
129
+ unless done
130
+ m = model
131
+ loop do
132
+ if m[:superclass] and m[:superclass] != RubyJS::Environment::Object
133
+ if m[:superclass].constants.include?(prefix)
134
+ start_lookup_at = m[:superclass].const_get(prefix)
135
+ done = true
136
+ break
137
+ else
138
+ m = @models[m[:superclass]]
139
+ end
140
+ else
141
+ break
142
+ end
143
+ end
144
+ end
145
+
146
+ # 3. lexically enclosing modules/classes
147
+ # FIXME
148
+ unless done
149
+ arr = model[:name].split("::")
150
+ loop do
151
+ arr.pop
152
+
153
+ begin
154
+ start_lookup_at = eval((["RubyJS", "Environment"] + arr + [prefix]).join("::"))
155
+ done = true
156
+ break
157
+ rescue NameError
158
+ end
159
+
160
+ break if arr.empty?
161
+ end
162
+ end
163
+
164
+ # 4. Object
165
+ unless done
166
+ begin
167
+ start_lookup_at = RubyJS::Environment::Object.const_get(prefix)
168
+ done = true
169
+ rescue NameError
170
+ end
171
+ end
172
+
173
+ end
174
+
175
+ unless done
176
+ raise "failed to lookup constant prefix #{prefix}"
177
+ end
178
+
179
+ #
180
+ # follow the whole path, e.g. A::B::C
181
+ #
182
+ value = start_lookup_at
183
+ path.each do |piece|
184
+ value = value.const_get(piece)
185
+ end
186
+
187
+ if value.is_a?(::Class) or value.is_a?(::Module)
188
+ # A class or module
189
+
190
+ if model = @models[value]
191
+ return old_encode_constant(model[:name])
192
+ else
193
+ raise("unrecognized class/module referenced by constant")
194
+ end
195
+ else
196
+ # A value
197
+ if value.is_a?(Fixnum)
198
+ # If it is the receiver of a method call, we have to surround it
199
+ # with parens, e.g. (1).
200
+ # As we can't easily decide whether it's a receiver of a method
201
+ # call, we simply surround every constant Fixnum with parens.
202
+ return "(" + value.inspect + ")"
203
+ elsif value.is_a?(String)
204
+ # FIXME: Generate a reference instead?
205
+ return value.inspect
206
+ else
207
+ raise
208
+ end
209
+ end
210
+ end
211
+
212
+ def namify(klass)
213
+ name = klass.name
214
+ if name =~ SCOPE_R
215
+ name = $1
216
+ else
217
+ raise "must be scoped inside RubyJS module"
218
+ end
219
+ return name
220
+ end
221
+
222
+ def with_current_model(model)
223
+ old_current_model = @current_model
224
+ @current_model = model
225
+ begin
226
+ yield
227
+ ensure
228
+ @current_model = old_current_model
229
+ end
230
+ end
231
+
232
+ def model_for(klass)
233
+ name = namify(klass)
234
+
235
+ me = MethodExtractor.new
236
+ me.process(ParseTree.new.parse_tree(klass))
237
+
238
+ if klass.is_a?(::Class)
239
+ a = klass.ancestors
240
+ a = a[0...(a.index(::Object))]
241
+
242
+ s = klass.superclass
243
+ s = nil if s == ::Object
244
+
245
+ # remove klass from the ancestor chain
246
+ a = a[1..-1] if a[0] == klass
247
+
248
+ # a now contains the included modules
249
+ a = a[0...(a.index(s))] if s
250
+
251
+ if klass == RubyJS::Environment::Object
252
+ raise unless s.nil?
253
+ s = nil
254
+ else
255
+ if s.nil?
256
+ s = RubyJS::Environment::Object
257
+ end
258
+ end
259
+
260
+ return {
261
+ :for => klass,
262
+ :modules => a,
263
+ :superclass => s,
264
+ :is_a => :class,
265
+ :name => name,
266
+ :instance_methods => me.instance_methods,
267
+ :methods => me.methods
268
+ }
269
+ elsif klass.is_a?(::Module)
270
+ a = klass.ancestors
271
+
272
+ # remove klass from the ancestor chain
273
+ a = a[1..-1] if a[0] == klass
274
+
275
+ return {
276
+ :for => klass,
277
+ :modules => a,
278
+ :is_a => :module,
279
+ :name => name,
280
+ :instance_methods => me.instance_methods,
281
+ :methods => me.methods
282
+ }
283
+ else
284
+ raise
285
+ end
286
+ end
287
+ end
@@ -0,0 +1,71 @@
1
+ #
2
+ # Generate unique names from a (custom) alphabet.
3
+ #
4
+ # Copyright (c) 2007 by Michael Neumann (mneumann@ntecs.de).
5
+ # All rights reserved.
6
+ #
7
+
8
+ class NameGenerator
9
+
10
+ DEFAULT_ALPHABET = ('a' .. 'z').to_a + ('A' .. 'Z').to_a + ('0' .. '9').to_a + ['_', '$']
11
+ RESERVED_WORDS = %w(this self new break continue if then else while true false null undefined function document window)
12
+
13
+ def initialize(alphabet=DEFAULT_ALPHABET, reserved_words=RESERVED_WORDS)
14
+ @alphabet = alphabet
15
+ @reserved_words = reserved_words
16
+ @digits = [0]
17
+ @cache = {}
18
+ end
19
+
20
+ #
21
+ # We generate names using a g-adic development (where g=alphabet.size)
22
+ #
23
+ # The least significant digit is the first. If you think of it as a
24
+ # bit-string, then bit 0 would be @digits[0].
25
+ #
26
+ # In each call to next we try to increase the least significant digit.
27
+ # If it overflows, then we reset it to zero and increase the next digit.
28
+ # This continues up to the most significant digit. If this overflows,
29
+ # we introduce a new most significant digit and set this to "zero".
30
+ #
31
+
32
+ def fresh
33
+ loop do
34
+ value = @digits.reverse.map {|d| @alphabet[d] }.join("")
35
+ sz = @alphabet.size
36
+
37
+ i = 0
38
+ loop do
39
+ # increase or initialize with 0
40
+ @digits[i] = @digits[i] ? @digits[i]+1 : 0
41
+
42
+ if @digits[i] >= sz
43
+ @digits[i] = 0
44
+ i += 1
45
+ else
46
+ break
47
+ end
48
+ end
49
+
50
+ return value unless @reserved_words.include?(value)
51
+ end
52
+ end
53
+
54
+ #
55
+ # Generate a name for +name+. Return the same name for the same
56
+ # +name+.
57
+ #
58
+
59
+ def get(name)
60
+ raise unless name.is_a?(String)
61
+ @cache[name] ||= self.fresh
62
+ end
63
+
64
+ def reverse_lookup(encoded_name)
65
+ @cache.index(encoded_name)
66
+ end
67
+
68
+ def cache
69
+ @cache
70
+ end
71
+ end