jbarnette-johnson 1.0.0.200806240111

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 (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