jbarnette-johnson 1.0.0.200806240111

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. data/CHANGELOG +5 -0
  2. data/MANIFEST +385 -0
  3. data/MINGW32.mk +124 -0
  4. data/README.rdoc +51 -0
  5. data/Rakefile +166 -0
  6. data/bin/johnson +107 -0
  7. data/cross-compile.txt +38 -0
  8. data/ext/spidermonkey/context.c +122 -0
  9. data/ext/spidermonkey/context.h +19 -0
  10. data/ext/spidermonkey/conversions.c +286 -0
  11. data/ext/spidermonkey/conversions.h +18 -0
  12. data/ext/spidermonkey/debugger.c +208 -0
  13. data/ext/spidermonkey/debugger.h +9 -0
  14. data/ext/spidermonkey/extconf.rb +25 -0
  15. data/ext/spidermonkey/extensions.c +37 -0
  16. data/ext/spidermonkey/extensions.h +12 -0
  17. data/ext/spidermonkey/global.c +40 -0
  18. data/ext/spidermonkey/global.h +11 -0
  19. data/ext/spidermonkey/idhash.c +16 -0
  20. data/ext/spidermonkey/idhash.h +8 -0
  21. data/ext/spidermonkey/immutable_node.c.erb +522 -0
  22. data/ext/spidermonkey/immutable_node.h +22 -0
  23. data/ext/spidermonkey/jroot.h +187 -0
  24. data/ext/spidermonkey/js_land_proxy.c +609 -0
  25. data/ext/spidermonkey/js_land_proxy.h +20 -0
  26. data/ext/spidermonkey/ruby_land_proxy.c +537 -0
  27. data/ext/spidermonkey/ruby_land_proxy.h +17 -0
  28. data/ext/spidermonkey/runtime.c +304 -0
  29. data/ext/spidermonkey/runtime.h +25 -0
  30. data/ext/spidermonkey/spidermonkey.c +20 -0
  31. data/ext/spidermonkey/spidermonkey.h +29 -0
  32. data/js/johnson/browser.js +9 -0
  33. data/js/johnson/browser/env.js +687 -0
  34. data/js/johnson/browser/jquery.js +3444 -0
  35. data/js/johnson/browser/xmlsax.js +1564 -0
  36. data/js/johnson/browser/xmlw3cdom.js +4189 -0
  37. data/js/johnson/cli.js +30 -0
  38. data/js/johnson/prelude.js +80 -0
  39. data/js/johnson/template.js +29 -0
  40. data/lib/hoe.rb +748 -0
  41. data/lib/johnson.rb +46 -0
  42. data/lib/johnson/cli.rb +7 -0
  43. data/lib/johnson/cli/options.rb +56 -0
  44. data/lib/johnson/error.rb +4 -0
  45. data/lib/johnson/nodes.rb +7 -0
  46. data/lib/johnson/nodes/binary_node.rb +64 -0
  47. data/lib/johnson/nodes/for.rb +14 -0
  48. data/lib/johnson/nodes/for_in.rb +12 -0
  49. data/lib/johnson/nodes/function.rb +13 -0
  50. data/lib/johnson/nodes/list.rb +27 -0
  51. data/lib/johnson/nodes/node.rb +68 -0
  52. data/lib/johnson/nodes/ternary_node.rb +20 -0
  53. data/lib/johnson/parser.rb +21 -0
  54. data/lib/johnson/parser/syntax_error.rb +13 -0
  55. data/lib/johnson/runtime.rb +55 -0
  56. data/lib/johnson/spidermonkey/context.rb +10 -0
  57. data/lib/johnson/spidermonkey/debugger.rb +67 -0
  58. data/lib/johnson/spidermonkey/immutable_node.rb +280 -0
  59. data/lib/johnson/spidermonkey/js_land_proxy.rb +62 -0
  60. data/lib/johnson/spidermonkey/mutable_tree_visitor.rb +233 -0
  61. data/lib/johnson/spidermonkey/ruby_land_proxy.rb +52 -0
  62. data/lib/johnson/spidermonkey/runtime.rb +94 -0
  63. data/lib/johnson/version.rb +4 -0
  64. data/lib/johnson/visitable.rb +16 -0
  65. data/lib/johnson/visitors.rb +4 -0
  66. data/lib/johnson/visitors/dot_visitor.rb +167 -0
  67. data/lib/johnson/visitors/ecma_visitor.rb +315 -0
  68. data/lib/johnson/visitors/enumerating_visitor.rb +115 -0
  69. data/lib/johnson/visitors/sexp_visitor.rb +172 -0
  70. data/lib/rails/init.rb +37 -0
  71. data/test/assets/index.html +38 -0
  72. data/test/assets/jquery_test.html +186 -0
  73. data/test/helper.rb +58 -0
  74. data/test/johnson/browser_test.rb +38 -0
  75. data/test/johnson/conversions/array_test.rb +32 -0
  76. data/test/johnson/conversions/boolean_test.rb +17 -0
  77. data/test/johnson/conversions/callable_test.rb +34 -0
  78. data/test/johnson/conversions/file_test.rb +15 -0
  79. data/test/johnson/conversions/nil_test.rb +20 -0
  80. data/test/johnson/conversions/number_test.rb +34 -0
  81. data/test/johnson/conversions/regexp_test.rb +24 -0
  82. data/test/johnson/conversions/string_test.rb +26 -0
  83. data/test/johnson/conversions/struct_test.rb +15 -0
  84. data/test/johnson/conversions/symbol_test.rb +19 -0
  85. data/test/johnson/conversions/thread_test.rb +24 -0
  86. data/test/johnson/error_test.rb +9 -0
  87. data/test/johnson/extensions_test.rb +56 -0
  88. data/test/johnson/nodes/array_literal_test.rb +57 -0
  89. data/test/johnson/nodes/array_node_test.rb +26 -0
  90. data/test/johnson/nodes/binary_node_test.rb +61 -0
  91. data/test/johnson/nodes/bracket_access_test.rb +16 -0
  92. data/test/johnson/nodes/delete_test.rb +11 -0
  93. data/test/johnson/nodes/do_while_test.rb +12 -0
  94. data/test/johnson/nodes/dot_accessor_test.rb +15 -0
  95. data/test/johnson/nodes/export_test.rb +9 -0
  96. data/test/johnson/nodes/for_test.rb +54 -0
  97. data/test/johnson/nodes/function_test.rb +71 -0
  98. data/test/johnson/nodes/if_test.rb +41 -0
  99. data/test/johnson/nodes/import_test.rb +13 -0
  100. data/test/johnson/nodes/label_test.rb +19 -0
  101. data/test/johnson/nodes/object_literal_test.rb +110 -0
  102. data/test/johnson/nodes/return_test.rb +16 -0
  103. data/test/johnson/nodes/semi_test.rb +8 -0
  104. data/test/johnson/nodes/switch_test.rb +55 -0
  105. data/test/johnson/nodes/ternary_test.rb +25 -0
  106. data/test/johnson/nodes/throw_test.rb +9 -0
  107. data/test/johnson/nodes/try_node_test.rb +59 -0
  108. data/test/johnson/nodes/typeof_test.rb +11 -0
  109. data/test/johnson/nodes/unary_node_test.rb +23 -0
  110. data/test/johnson/nodes/void_test.rb +11 -0
  111. data/test/johnson/nodes/while_test.rb +26 -0
  112. data/test/johnson/nodes/with_test.rb +10 -0
  113. data/test/johnson/prelude_test.rb +56 -0
  114. data/test/johnson/runtime_test.rb +46 -0
  115. data/test/johnson/spidermonkey/context_test.rb +21 -0
  116. data/test/johnson/spidermonkey/immutable_node_test.rb +34 -0
  117. data/test/johnson/spidermonkey/js_land_proxy_test.rb +236 -0
  118. data/test/johnson/spidermonkey/ruby_land_proxy_test.rb +225 -0
  119. data/test/johnson/spidermonkey/runtime_test.rb +17 -0
  120. data/test/johnson/version_test.rb +13 -0
  121. data/test/johnson/visitors/dot_visitor_test.rb +39 -0
  122. data/test/johnson/visitors/enumerating_visitor_test.rb +12 -0
  123. data/test/johnson_test.rb +16 -0
  124. data/test/jquery_units/test.js +27 -0
  125. data/test/jquery_units/test_helper.js +197 -0
  126. data/test/jquery_units/units/ajax.js +795 -0
  127. data/test/jquery_units/units/core.js +1563 -0
  128. data/test/jquery_units/units/event.js +299 -0
  129. data/test/jquery_units/units/fx.js +427 -0
  130. data/test/jquery_units/units/offset.js +112 -0
  131. data/test/jquery_units/units/selector.js +224 -0
  132. data/test/jspec/helper.js +7 -0
  133. data/test/jspec/jspec.js +192 -0
  134. data/test/jspec/simple_spec.js +68 -0
  135. data/test/parser_test.rb +276 -0
  136. data/todo/.keep +0 -0
  137. metadata +501 -0
@@ -0,0 +1,10 @@
1
+ module Johnson #:nodoc:
2
+ module SpiderMonkey #:nodoc:
3
+ class Context # native
4
+ def initialize(runtime, options={})
5
+ @runtime = runtime
6
+ initialize_native(runtime, options)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,67 @@
1
+ module Johnson #:nodoc:
2
+ module SpiderMonkey #:nodoc:
3
+ class Debugger # native
4
+ JSTRAP_ERROR = 0
5
+ JSTRAP_CONTINUE = 1
6
+ JSTRAP_RETURN = 2
7
+ JSTRAP_THROW = 3
8
+ JSTRAP_LIMIT = 4
9
+ attr_accessor :logger
10
+ def initialize(logger)
11
+ @logger = logger
12
+ end
13
+
14
+ def interrupt_handler(context, script, bytecode)
15
+ line_num = line_number(context, script, bytecode)
16
+ f_name = file_name(context, script)
17
+ logger.debug("interrupt_handler #{f_name} #{line_num}")
18
+ JSTRAP_CONTINUE
19
+ end
20
+
21
+ def new_script_hook(filename, linenum)
22
+ logger.debug("new_script_hook: #{filename} #{linenum}")
23
+ end
24
+
25
+ def destroy_script_hook
26
+ logger.debug("destroy_script_hook")
27
+ end
28
+
29
+ def debugger_handler(context, script, bytecode)
30
+ line_num = line_number(context, script, bytecode)
31
+ f_name = file_name(context, script)
32
+ logger.debug("debugger_handler: #{bytecode}")
33
+ JSTRAP_CONTINUE
34
+ end
35
+
36
+ def source_handler(filename, line_number, str)
37
+ logger.debug("source_handler: #{filename}(#{line_number}): #{str}")
38
+ end
39
+
40
+ # +call_hook+ is called before and after script execution. +before+
41
+ # is +true+ if before, +false+ otherwise.
42
+ def execute_hook(context, stack_frame, before, ok)
43
+ logger.debug("execute_hook: #{before} #{ok}")
44
+ end
45
+
46
+ # +call_hook+ is called before and after a function call. +before+
47
+ # is +true+ if before, +false+ otherwise.
48
+ def call_hook(before, ok)
49
+ logger.debug("call_hook: #{before} #{ok}")
50
+ end
51
+
52
+ def object_hook(is_new)
53
+ logger.debug("object_hook: #{is_new}")
54
+ end
55
+
56
+ # This hook can change the control
57
+ def throw_hook(bytecode)
58
+ logger.debug("throw_hook: #{bytecode}")
59
+ JSTRAP_CONTINUE
60
+ end
61
+
62
+ def debug_error_hook(message)
63
+ logger.debug("debug_error_hook: #{message}")
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,280 @@
1
+ module Johnson #:nodoc:
2
+ module SpiderMonkey #:nodoc:
3
+ class ImmutableNode
4
+ def accept(visitor)
5
+ case pn_arity
6
+ when :pn_list
7
+ handle_list(visitor)
8
+ when :pn_name
9
+ if pn_expr
10
+ m = {
11
+ :tok_colon => :visit_Label,
12
+ :tok_name => :visit_AssignExpr,
13
+ :tok_dot => :visit_DotAccessor,
14
+ }[pn_type]
15
+ raise "Unknown type #{pn_type}" unless m
16
+ visitor.send(m, self)
17
+ else
18
+ visitor.visit_Name(self)
19
+ end
20
+ when :pn_binary
21
+ handle_binary(visitor)
22
+ when :pn_unary
23
+ handle_unary(visitor)
24
+ when :pn_nullary
25
+ handle_nullary(visitor)
26
+ when :pn_func
27
+ visitor.visit_Function(self)
28
+ when :pn_ternary
29
+ m = {
30
+ :tok_hook => :visit_Ternary,
31
+ :tok_if => :visit_If,
32
+ :tok_try => :visit_Try,
33
+ :tok_catch => :visit_Catch,
34
+ }[pn_type]
35
+ raise "Unknown ternary #{pn_type}" unless m
36
+ visitor.send(m, self)
37
+ else
38
+ raise "unkown arity: #{pn_arity}"
39
+ end
40
+ end
41
+
42
+ def to_mutable_tree
43
+ MutableTreeVisitor.new.accept(self)
44
+ end
45
+
46
+ def to_sexp
47
+ to_mutable_tree.to_sexp
48
+ end
49
+
50
+ private
51
+ def handle_unary(visitor)
52
+ case pn_type
53
+ when :tok_throw
54
+ visitor.visit_Throw(self)
55
+ when :tok_delete
56
+ visitor.visit_Delete(self)
57
+ when :tok_return
58
+ visitor.visit_Return(self)
59
+ when :tok_unaryop
60
+ m = {
61
+ :jsop_void => :visit_Void,
62
+ :jsop_typeof => :visit_Typeof,
63
+ :jsop_pos => :visit_UnaryPositive,
64
+ :jsop_neg => :visit_UnaryNegative,
65
+ :jsop_bitnot => :visit_BitwiseNot,
66
+ :jsop_not => :visit_Not,
67
+ }[pn_op]
68
+ raise "Unknown tok_unaryop type: #{pn_op}" unless m
69
+ visitor.send(m, self)
70
+ when :tok_rp
71
+ visitor.visit_Parenthesis(self)
72
+ when :tok_inc
73
+ m = {
74
+ :jsop_nameinc => :visit_PostfixIncrement,
75
+ :jsop_propinc => :visit_PostfixIncrement,
76
+ :jsop_eleminc => :visit_PostfixIncrement,
77
+ :jsop_incname => :visit_PrefixIncrement,
78
+ :jsop_incprop => :visit_PrefixIncrement,
79
+ :jsop_incelem => :visit_PrefixIncrement,
80
+ }[pn_op]
81
+ raise "Unknown increment type: #{pn_op}" unless m
82
+ visitor.send(m, self)
83
+ when :tok_dec
84
+ m = {
85
+ :jsop_namedec => :visit_PostfixDecrement,
86
+ :jsop_propdec => :visit_PostfixDecrement,
87
+ :jsop_elemdec => :visit_PostfixDecrement,
88
+ :jsop_decname => :visit_PrefixDecrement,
89
+ :jsop_decprop => :visit_PrefixDecrement,
90
+ :jsop_decelem => :visit_PrefixDecrement,
91
+ }[pn_op]
92
+ raise "Unknown decrement type: #{pn_op}" unless m
93
+ visitor.send(m, self)
94
+ when :tok_semi
95
+ pn_kid.accept(visitor) if pn_kid
96
+ else
97
+ raise "unknown unary: #{pn_type}"
98
+ end
99
+ end
100
+
101
+ def handle_list(visitor)
102
+ case pn_type
103
+ when :tok_shop
104
+ handle_shiftop(visitor)
105
+ when :tok_divop
106
+ handle_divop(visitor)
107
+ when :tok_eqop
108
+ handle_eqop(visitor)
109
+ when :tok_relop
110
+ handle_relop(visitor)
111
+ else
112
+ m = {
113
+ :tok_lc => :visit_SourceElements,
114
+ :tok_var => :visit_VarStatement,
115
+ :tok_comma => :visit_Comma,
116
+ :tok_rc => :visit_ObjectLiteral,
117
+ :tok_rb => :visit_ArrayLiteral,
118
+ :tok_new => :visit_New,
119
+ :tok_lp => :visit_FunctionCall,
120
+ :tok_import => :visit_Import,
121
+ :tok_export => :visit_Export,
122
+ :tok_plus => :visit_OpAdd,
123
+ :tok_or => :visit_Or,
124
+ :tok_minus => :visit_OpSubtract,
125
+ :tok_and => :visit_And,
126
+ :tok_bitand => :visit_OpBitAnd,
127
+ :tok_bitor => :visit_OpBitOr,
128
+ :tok_bitxor => :visit_OpBitXor,
129
+ :tok_star => :visit_OpMultiply,
130
+ :tok_instanceof => :visit_InstanceOf,
131
+ }[pn_type]
132
+ raise "Unknown type: #{pn_type} at (#{line}, #{index})" unless m
133
+ visitor.send(m, self)
134
+ end
135
+ end
136
+
137
+ OP_TO_METHOD = {
138
+ :jsop_null => :visit_Null,
139
+ :jsop_true => :visit_True,
140
+ :jsop_false => :visit_False,
141
+ :jsop_this => :visit_This,
142
+ }
143
+ def handle_nullary(visitor)
144
+ case pn_type
145
+ when :tok_number
146
+ visitor.visit_Number(self)
147
+ when :tok_string
148
+ visitor.visit_String(self)
149
+ when :tok_regexp
150
+ visitor.visit_Regexp(self)
151
+ when :tok_name
152
+ visitor.visit_Name(self)
153
+ when :tok_comma
154
+ visitor.visit_Null(self)
155
+ when :tok_continue
156
+ visitor.visit_Continue(self)
157
+ when :tok_break
158
+ visitor.visit_Break(self)
159
+ when :tok_primary
160
+ sym = OP_TO_METHOD[pn_op]
161
+ raise "Unknown op #{pn_op}" unless sym
162
+ visitor.send(sym, self)
163
+ else
164
+ raise "Unknown nullary type: #{pn_type}"
165
+ end
166
+ end
167
+
168
+ def handle_binary(visitor)
169
+ case pn_type
170
+ when :tok_assign
171
+ m = {
172
+ :jsop_add => :visit_OpAddEqual,
173
+ :jsop_sub => :visit_OpSubtractEqual,
174
+ :jsop_nop => :visit_OpEqual,
175
+ :jsop_mul => :visit_OpMultiplyEqual,
176
+ :jsop_div => :visit_OpDivideEqual,
177
+ :jsop_lsh => :visit_OpLShiftEqual,
178
+ :jsop_rsh => :visit_OpRShiftEqual,
179
+ :jsop_ursh => :visit_OpURShiftEqual,
180
+ :jsop_bitand => :visit_OpBitAndEqual,
181
+ :jsop_bitxor => :visit_OpBitXorEqual,
182
+ :jsop_bitor => :visit_OpBitOrEqual,
183
+ :jsop_mod => :visit_OpModEqual,
184
+ }[pn_op]
185
+ raise "Unknown assign op #{pn_op}" unless m
186
+ visitor.send(m, self)
187
+ when :tok_divop
188
+ handle_divop(visitor)
189
+ when :tok_shop
190
+ handle_shiftop(visitor)
191
+ when :tok_eqop
192
+ handle_eqop(visitor)
193
+ when :tok_colon
194
+ m = {
195
+ :jsop_getter => :visit_GetterProperty,
196
+ :jsop_setter => :visit_SetterProperty,
197
+ :jsop_nop => :visit_Property
198
+ }[pn_op]
199
+ raise "Unknown assign op #{pn_op}" unless m
200
+ visitor.send(m, self)
201
+ when :tok_relop
202
+ handle_relop(visitor)
203
+ when :tok_for
204
+ if pn_left.pn_type == :tok_in
205
+ visitor.visit_ForIn(self)
206
+ else
207
+ visitor.visit_For(self)
208
+ end
209
+ else
210
+ m = {
211
+ :tok_while => :visit_While,
212
+ :tok_with => :visit_With,
213
+ :tok_default => :visit_Default,
214
+ :tok_case => :visit_Case,
215
+ :tok_switch => :visit_Switch,
216
+ :tok_do => :visit_DoWhile,
217
+ :tok_instanceof => :visit_InstanceOf,
218
+ :tok_in => :visit_In,
219
+ :tok_and => :visit_And,
220
+ :tok_or => :visit_Or,
221
+ :tok_star => :visit_OpMultiply,
222
+ :tok_lb => :visit_BracketAccess,
223
+ :tok_minus => :visit_OpSubtract,
224
+ :tok_plus => :visit_OpAdd,
225
+ :tok_bitor => :visit_OpBitOr,
226
+ :tok_bitxor => :visit_OpBitXor,
227
+ :tok_bitand => :visit_OpBitAnd,
228
+ }[pn_type]
229
+ raise "Unknown binary type: #{pn_type}" unless m
230
+ visitor.send(m, self)
231
+ end
232
+ end
233
+
234
+ def handle_shiftop(visitor)
235
+ m = {
236
+ :jsop_ursh => :visit_OpURShift,
237
+ :jsop_rsh => :visit_OpRShift,
238
+ :jsop_lsh => :visit_OpLShift,
239
+ }[pn_op]
240
+ raise "Unknown shift op #{pn_op} at (#{line}, #{index})" unless m
241
+ visitor.send(m, self)
242
+ end
243
+
244
+ def handle_divop(visitor)
245
+ m = {
246
+ :jsop_div => :visit_OpDivide,
247
+ :jsop_mod => :visit_OpMod,
248
+ }[pn_op]
249
+ raise "Unknown assign op #{pn_op} at (#{line}, #{index})" unless m
250
+ visitor.send(m, self)
251
+ end
252
+
253
+ def handle_eqop(visitor)
254
+ m = {
255
+ :jsop_strictne => :visit_StrictNotEqual,
256
+ :jsop_stricteq => :visit_StrictEqual,
257
+ :jsop_ne => :visit_NotEqual,
258
+ :jsop_eq => :visit_Equal,
259
+ }[pn_op]
260
+ raise "Unknown equal op #{pn_op} at (#{line}, #{index})" unless m
261
+ visitor.send(m, self)
262
+ end
263
+
264
+ def handle_relop(visitor)
265
+ m = {
266
+ :jsop_ge => :visit_GreaterThanOrEqual,
267
+ :jsop_le => :visit_LessThanOrEqual,
268
+ :jsop_gt => :visit_GreaterThan,
269
+ :jsop_lt => :visit_LessThan,
270
+ }[pn_op]
271
+ raise "Unknown relop #{pn_op} at (#{line}, #{index})" unless m
272
+ visitor.send(m, self)
273
+ end
274
+
275
+ def raise_parse_error(message, file_name, line_number)
276
+ raise Johnson::Parser::SyntaxError.new(message, file_name, line_number)
277
+ end
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,62 @@
1
+ module Johnson
2
+ module SpiderMonkey
3
+ module JSLandProxy #:nodoc:
4
+ def self.send_with_possible_block(target, symbol, args)
5
+ block = args.pop if args.last.is_a?(RubyLandProxy) && args.last.function?
6
+ target.__send__(symbol, *args, &block)
7
+ end
8
+
9
+ def self.treat_all_properties_as_methods(target)
10
+ def target.js_property?(name); true; end
11
+ end
12
+
13
+ def self.js_property?(target, name)
14
+ # FIXME: that rescue is gross; handles, e.g., "name?"
15
+ (target.send(:instance_variable_defined?, "@#{name}") rescue false) ||
16
+ (target.respond_to?(:js_property?) && target.__send__(:js_property?, name))
17
+ end
18
+
19
+ def self.call_proc_by_oid(oid, *args)
20
+ id2ref(oid).call(*args)
21
+ end
22
+
23
+ def self.id2ref(oid)
24
+ ObjectSpace._id2ref(oid)
25
+ end
26
+
27
+ def self.autovivified(target, attribute)
28
+ target.send(:__johnson_js_properties)[attribute]
29
+ end
30
+
31
+ def self.autovivified?(target, attribute)
32
+ target.respond_to?(:__johnson_js_properties) &&
33
+ target.send(:__johnson_js_properties).key?(attribute)
34
+ end
35
+
36
+ def self.autovivify(target, attribute, value)
37
+ (class << target; self; end).instance_eval do
38
+ unless target.respond_to?(:__johnson_js_properties)
39
+ define_method(:__johnson_js_properties) do
40
+ @__johnson_js_properties ||= {}
41
+ end
42
+ end
43
+
44
+ define_method(:"#{attribute}=") do |arg|
45
+ send(:__johnson_js_properties)[attribute] = arg
46
+ end
47
+
48
+ define_method(:"#{attribute}") do |*args|
49
+ js_prop = send(:__johnson_js_properties)[attribute]
50
+ if js_prop.is_a?(RubyLandProxy) && js_prop.function?
51
+ js_prop.call_using(self, *args)
52
+ else
53
+ js_prop
54
+ end
55
+ end
56
+ end
57
+
58
+ target.send(:"#{attribute}=", value)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,233 @@
1
+ module Johnson
2
+ module SpiderMonkey
3
+ class MutableTreeVisitor
4
+ include Johnson::Nodes
5
+
6
+ def visit_For(ro_node)
7
+ For.new( ro_node.line,
8
+ ro_node.index,
9
+ ro_node.pn_left.pn_kid1 && ro_node.pn_left.pn_kid1.accept(self),
10
+ ro_node.pn_left.pn_kid2 && ro_node.pn_left.pn_kid2.accept(self),
11
+ ro_node.pn_left.pn_kid3 && ro_node.pn_left.pn_kid3.accept(self),
12
+ ro_node.pn_right.accept(self)
13
+ )
14
+ end
15
+
16
+ def visit_Name(ro_node)
17
+ Name.new(ro_node.line, ro_node.index, ro_node.name)
18
+ end
19
+
20
+ def visit_Number(ro_node)
21
+ Number.new(ro_node.line, ro_node.index, ro_node.pn_dval)
22
+ end
23
+
24
+ def visit_String(ro_node)
25
+ Nodes::String.new( ro_node.line,
26
+ ro_node.index,
27
+ ro_node.name )
28
+ end
29
+
30
+ def visit_Regexp(ro_node)
31
+ Regexp.new( ro_node.line,
32
+ ro_node.index,
33
+ ro_node.regexp )
34
+ end
35
+
36
+ def visit_Function(ro_node)
37
+ Function.new( ro_node.line,
38
+ ro_node.index,
39
+ ro_node.function_name,
40
+ ro_node.function_args,
41
+ ro_node.function_body.accept(self) )
42
+ end
43
+
44
+ %w{ Label AssignExpr DotAccessor }.each do |type|
45
+ define_method(:"visit_#{type}") do |ro_node|
46
+ Nodes.const_get(type).new(
47
+ ro_node.line,
48
+ ro_node.index,
49
+ Name.new(ro_node.line, ro_node.index, ro_node.name),
50
+ ro_node.pn_expr.accept(self)
51
+ )
52
+ end
53
+ end
54
+
55
+ %w{
56
+ SourceElements
57
+ VarStatement
58
+ Comma
59
+ ObjectLiteral
60
+ ArrayLiteral
61
+ New
62
+ FunctionCall
63
+ Import
64
+ Export
65
+ }.each do |list_op|
66
+ define_method(:"visit_#{list_op}") do |ro_node|
67
+ Nodes.const_get(list_op).new( ro_node.line,
68
+ ro_node.index,
69
+ ro_node.children.map { |c|
70
+ c.accept(self)
71
+ }.compact)
72
+ end
73
+ end
74
+
75
+ {
76
+ 'Null' => nil,
77
+ 'True' => true,
78
+ 'False' => false,
79
+ 'This' => 'this',
80
+ 'Continue' => 'continue',
81
+ 'Break' => 'break',
82
+ }.each do |type,val|
83
+ define_method(:"visit_#{type}") do |ro_node|
84
+ Nodes.const_get(type).new(
85
+ ro_node.line,
86
+ ro_node.index,
87
+ val
88
+ )
89
+ end
90
+ end
91
+
92
+ def visit_Try(ro_node)
93
+ Try.new(
94
+ ro_node.line,
95
+ ro_node.index,
96
+ ro_node.pn_kid1 && ro_node.pn_kid1.accept(self),
97
+ if ro_node.pn_kid2
98
+ case ro_node.pn_kid2.pn_type
99
+ when :tok_reserved
100
+ ro_node.pn_kid2.children.map { |x| x.pn_expr.accept(self) }
101
+ else
102
+ raise "HALP some other catch #{ro_node.line}, #{ro_node.index}"
103
+ end
104
+ else
105
+ nil
106
+ end,
107
+ ro_node.pn_kid3 && ro_node.pn_kid3.accept(self)
108
+ )
109
+ end
110
+
111
+ %w{
112
+ Ternary
113
+ If
114
+ Catch
115
+ }.each do |node|
116
+ define_method(:"visit_#{node}") do |ro_node|
117
+ Nodes.const_get(node).new(
118
+ ro_node.line,
119
+ ro_node.index,
120
+ ro_node.pn_kid1 && ro_node.pn_kid1.accept(self),
121
+ ro_node.pn_kid2 && ro_node.pn_kid2.accept(self),
122
+ ro_node.pn_kid3 && ro_node.pn_kid3.accept(self)
123
+ )
124
+ end
125
+ end
126
+
127
+ %w{
128
+ BitwiseNot
129
+ Delete
130
+ Not
131
+ Parenthesis
132
+ PostfixDecrement
133
+ PostfixIncrement
134
+ PrefixDecrement
135
+ PrefixIncrement
136
+ Return
137
+ Throw
138
+ Typeof
139
+ UnaryNegative
140
+ UnaryPositive
141
+ Void
142
+ }.each do |node|
143
+ define_method(:"visit_#{node}") do |ro_node|
144
+ Nodes.const_get(node).new(ro_node.line,
145
+ ro_node.index,
146
+ ro_node.pn_kid && ro_node.pn_kid.accept(self))
147
+ end
148
+ end
149
+
150
+ %w{
151
+ And
152
+ BracketAccess
153
+ DoWhile
154
+ Case
155
+ Default
156
+ While
157
+ With
158
+ Equal
159
+ Switch
160
+ In
161
+ InstanceOf
162
+ GetterProperty
163
+ ForIn
164
+ GreaterThan
165
+ LessThan
166
+ GreaterThanOrEqual
167
+ LessThanOrEqual
168
+ NotEqual
169
+ OpAdd
170
+ OpAddEqual
171
+ OpBitAnd
172
+ OpBitAndEqual
173
+ OpBitOr
174
+ OpBitOrEqual
175
+ OpBitXor
176
+ OpBitXorEqual
177
+ OpDivide
178
+ OpDivideEqual
179
+ OpEqual
180
+ OpLShift
181
+ OpLShiftEqual
182
+ OpMod
183
+ OpModEqual
184
+ OpMultiply
185
+ OpMultiplyEqual
186
+ OpRShift
187
+ OpRShiftEqual
188
+ OpSubtract
189
+ OpSubtractEqual
190
+ OpURShift
191
+ OpURShiftEqual
192
+ Or
193
+ Property
194
+ SetterProperty
195
+ StrictEqual
196
+ StrictNotEqual
197
+ }.each do |bin_op|
198
+ define_method(:"visit_#{bin_op}") do |ro_node|
199
+ if ro_node.children.length > 1
200
+ kids = ro_node.children.reverse
201
+ tree = self.class.const_get(bin_op).new(
202
+ ro_node.line,
203
+ ro_node.index,
204
+ kids[1].accept(self),
205
+ kids[0].accept(self)
206
+ )
207
+ 2.times { kids.shift }
208
+ kids.each do |kid|
209
+ tree = self.class.const_get(bin_op).new(
210
+ ro_node.line,
211
+ ro_node.index,
212
+ kid.accept(self),
213
+ tree
214
+ )
215
+ end
216
+ tree
217
+ else
218
+ self.class.const_get(bin_op).new(
219
+ ro_node.line,
220
+ ro_node.index,
221
+ ro_node.pn_left && ro_node.pn_left.accept(self),
222
+ ro_node.pn_right && ro_node.pn_right.accept(self)
223
+ )
224
+ end
225
+ end
226
+ end
227
+
228
+ def accept(target)
229
+ target.accept(self)
230
+ end
231
+ end
232
+ end
233
+ end