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,16 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class ReturnTest < Johnson::NodeTestCase
4
+ def test_return
5
+ assert_sexp([[:func_expr, "foo", [], [[:return, nil]]]],
6
+ @parser.parse('function foo() { return; }'))
7
+ assert_ecma("function foo() {\n return;\n}",
8
+ @parser.parse('function foo() { return; }'))
9
+
10
+
11
+ assert_sexp([[:func_expr, "foo", [], [[:return, [:lit, 10]]]]],
12
+ @parser.parse('function foo() { return 10; }'))
13
+ assert_ecma("function foo() {\n return 10;\n}",
14
+ @parser.parse('function foo() { return 10; }'))
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class SemiTest < Johnson::NodeTestCase
4
+ def test_null_semi
5
+ assert_sexp([], @parser.parse(';'))
6
+ assert_ecma('', @parser.parse(';'))
7
+ end
8
+ end
@@ -0,0 +1,55 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class SwitchTest < Johnson::NodeTestCase
4
+ def test_empty_switch
5
+ assert_sexp([[:switch, [:name, "o"], []]],
6
+ @parser.parse('switch(o) { }')
7
+ )
8
+ assert_ecma('switch(o) { }',
9
+ @parser.parse('switch(o) { }')
10
+ )
11
+ end
12
+
13
+ def test_switch_with_body
14
+ assert_sexp([[:switch, [:name, "o"],
15
+ [
16
+ [:case, [:name, "j"], [[:name, "foo"]]]
17
+ ]
18
+ ]], @parser.parse('switch(o) { case j: foo; }')
19
+ )
20
+ assert_ecma("switch(o) {\n case j: {\n foo;\n}\n}",
21
+ @parser.parse('switch(o) { case j: foo; }')
22
+ )
23
+ end
24
+
25
+ def test_switch_empty_case
26
+ assert_ecma("switch(o) {\n case j: { }\n}",
27
+ @parser.parse('switch(o) { case j: }')
28
+ )
29
+ end
30
+
31
+ def test_switch_with_body_2_case
32
+ assert_sexp([[:switch, [:name, "o"],
33
+ [
34
+ [:case, [:name, "j"], [[:name, "foo"]]],
35
+ [:case, [:name, "k"], [[:name, "bar"]]]
36
+ ]
37
+ ]], @parser.parse('switch(o) { case j: foo; case k: bar; }')
38
+ )
39
+ end
40
+
41
+ def test_switch_with_default
42
+ assert_sexp([[:switch, [:name, "o"], [[:default, nil, [[:name, "bar"]]]]]],
43
+ @parser.parse('switch(o) { default: bar; }')
44
+ )
45
+ assert_ecma("switch(o) {\n default: {\n bar;\n}\n}",
46
+ @parser.parse('switch(o) { default: bar; }')
47
+ )
48
+ assert_sexp([[:switch, [:name, "o"], [[:default, nil, []]]]],
49
+ @parser.parse('switch(o) { default: }')
50
+ )
51
+ assert_ecma("switch(o) {\n default: { }\n}",
52
+ @parser.parse('switch(o) { default: }')
53
+ )
54
+ end
55
+ end
@@ -0,0 +1,25 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class TernaryNodeTest < Johnson::NodeTestCase
4
+ def test_ternary
5
+ assert_sexp([
6
+ [:var, [[:assign,
7
+ [:name, "x"],
8
+ [:ternary,
9
+ [:lt, [:name, "y"], [:lit, 10]],
10
+ [:lit, 20],
11
+ [:lit, 30]
12
+ ]
13
+ ]]]],
14
+ @parser.parse('var x = y < 10 ? 20 : 30')
15
+ )
16
+ assert_ecma('var x = y < 10 ? 20 : 30;',
17
+ @parser.parse('var x = y < 10 ? 20 : 30')
18
+ )
19
+ end
20
+
21
+ def test_weird_rounding
22
+ ecma = @parser.parse('(value < 0.00001) ? 0 : value;').to_ecma
23
+ assert_match(/\(value < 1.0e-[0]*5\) \? 0 : value;/, ecma)
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class ThrowTest < Johnson::NodeTestCase
4
+ def test_to_sexp
5
+ assert_sexp([[:throw, [:lit, 10]]], @parser.parse('throw 10;'))
6
+ assert_sexp([[:throw, [:lit, 10]]], @parser.parse('throw 10'))
7
+ assert_ecma("throw 10;", @parser.parse('throw 10;'))
8
+ end
9
+ end
@@ -0,0 +1,59 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class TryTest < Johnson::NodeTestCase
4
+ def test_try_finally
5
+ assert_sexp([[:try,
6
+ [[:var, [[:assign, [:name, "x"], [:lit, 10]]]]],
7
+ nil,
8
+ [[:var, [[:assign, [:name, "x"], [:lit, 20]]]]]
9
+ ]],
10
+ @parser.parse('try { var x = 10; } finally { var x = 20; }'))
11
+ assert_ecma(
12
+ "try {\n var x = 10;\n} finally {\n var x = 20;\n}",
13
+ @parser.parse('try { var x = 10; } finally { var x = 20; }'))
14
+ end
15
+
16
+ def test_try_catch
17
+ assert_sexp([
18
+ [:try,
19
+ [[:var, [[:assign, [:name, "x"], [:lit, 10]]]]],
20
+ [[:catch, [:name, "a"], nil,
21
+ [
22
+ [:var, [[:assign, [:name, "x"], [:lit, 20]]]],
23
+ [:postfix_inc, [:name, "x"]]
24
+ ]
25
+ ]],
26
+ nil]],
27
+ @parser.parse('try { var x = 10; } catch(a) { var x = 20; x++; }'))
28
+ assert_ecma("try {\n var x = 10;\n} catch(a) {\n var x = 20;\n x++;\n}",
29
+ @parser.parse('try { var x = 10; } catch(a) { var x = 20; x++; }'))
30
+ end
31
+
32
+ def test_try_multi_catch
33
+ assert_sexp([
34
+ [:try,
35
+ [[:var, [[:assign, [:name, "x"], [:lit, 10]]]]],
36
+ [
37
+ [:catch, [:name, "a"], [:true],
38
+ [
39
+ [:var, [[:assign, [:name, "x"], [:lit, 20]]]],
40
+ [:postfix_inc, [:name, "x"]]
41
+ ]],
42
+ [:catch, [:name, "b"], [:true],
43
+ [
44
+ [:var, [[:assign, [:name, "x"], [:lit, 20]]]],
45
+ [:postfix_inc, [:name, "x"]]
46
+ ]]
47
+ ],
48
+ nil]],
49
+ @parser.parse(' try { var x = 10; }
50
+ catch(a if true) { var x = 20; x++; }
51
+ catch(b if true) { var x = 20; x++; }
52
+ '))
53
+ assert_ecma("try {\n var x = 10;\n} catch(a) {\n var x = 20;\n x++;\n} catch(b) {\n var x = 20;\n x++;\n}",
54
+ @parser.parse(' try { var x = 10; }
55
+ catch(a if true) { var x = 20; x++; }
56
+ catch(b if true) { var x = 20; x++; }
57
+ '))
58
+ end
59
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class TypeofNodeTest < Johnson::NodeTestCase
4
+ def test_typeof_sexp
5
+ assert_sexp(
6
+ [[:typeof, [:name, 'foo']]],
7
+ @parser.parse('typeof foo;')
8
+ )
9
+ assert_ecma('typeof foo;', @parser.parse('typeof foo;'))
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class UnaryNodeTest < Johnson::NodeTestCase
4
+ def test_u_positive_sexp
5
+ assert_sexp([[:u_pos, [:name, 'foo']]], @parser.parse('+foo;'))
6
+ assert_ecma('+foo;', @parser.parse('+foo'))
7
+ end
8
+
9
+ def test_u_negative_sexp
10
+ assert_sexp([[:u_neg, [:name, 'foo']]], @parser.parse('-foo;'))
11
+ assert_ecma('-foo;', @parser.parse('-foo'))
12
+ end
13
+
14
+ def test_u_bit_not_sexp
15
+ assert_sexp([[:bitwise_not, [:name, 'foo']]], @parser.parse('~foo;'))
16
+ assert_ecma('~foo;', @parser.parse('~foo'))
17
+ end
18
+
19
+ def test_u_not_sexp
20
+ assert_sexp([[:not, [:name, 'foo']]], @parser.parse('!foo;'))
21
+ assert_ecma('!foo;', @parser.parse('!foo'))
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class VoidNodeTest < Johnson::NodeTestCase
4
+ def test_delete_sexp
5
+ assert_sexp(
6
+ [[:void, [:name, 'foo']]],
7
+ @parser.parse('void foo;')
8
+ )
9
+ assert_ecma('void foo;', @parser.parse('void foo;'))
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class WhileTest < Johnson::NodeTestCase
4
+ def test_while
5
+ assert_sexp([[:while, [:true], [:var, [[:assign, [:name, "x"], [:lit, 10]]]]]],
6
+ @parser.parse('while(true) var x = 10;'))
7
+ assert_ecma('while(true) var x = 10;',
8
+ @parser.parse('while(true) var x = 10;'))
9
+ end
10
+
11
+ def test_break
12
+ assert_sexp([[:while, [:true], [:break]]],
13
+ @parser.parse('while(true) break;'))
14
+ assert_ecma('while(true) break;',
15
+ @parser.parse('while(true) break;'))
16
+ end
17
+
18
+ def test_continue
19
+ assert_sexp([[:while, [:true], [:continue]]],
20
+ @parser.parse('while(true) continue;'))
21
+ assert_ecma('while(true) continue;',
22
+ @parser.parse('while(true) continue;'))
23
+ assert_ecma("while(true) {\n continue;\n}",
24
+ @parser.parse('while(true) { continue; }'))
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ class WithTest < Johnson::NodeTestCase
4
+ def test_with
5
+ assert_sexp([[:with, [:name, "o"], [:name, "x"]]],
6
+ @parser.parse('with (o) x;')
7
+ )
8
+ assert_ecma("with(o) x;", @parser.parse('with (o) x;'))
9
+ end
10
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../helper"))
2
+
3
+ module Johnson
4
+ class PreludeTest < Johnson::TestCase
5
+ def test_symbols_are_interned
6
+ assert(@runtime.evaluate("Johnson.symbolize('foo') === Johnson.symbolize('foo')"))
7
+ end
8
+
9
+ def test_strings_had_a_to_symbol_method
10
+ assert_js_equal(:monkeys, "'monkeys'.toSymbol()")
11
+ end
12
+
13
+ def test_string_to_symbol_is_not_enumerable
14
+ assert(!@runtime.evaluate(<<-END))
15
+ var flag = false;
16
+ for (x in "foo") { if (x == 'toSymbol') flag = true }
17
+ flag
18
+ END
19
+ end
20
+
21
+ def test_symbol_to_string
22
+ assert_equal("monkey", @runtime.evaluate("Johnson.symbolize('monkey').toString()"))
23
+ end
24
+
25
+ def test_symbol_inspect
26
+ assert_equal(":monkey", @runtime.evaluate("Johnson.symbolize('monkey').inspect()"))
27
+ end
28
+
29
+ def test_all_of_ruby_is_available
30
+ assert_raise(Johnson::Error) { @runtime.evaluate("Ruby.Set.new()") }
31
+
32
+ @runtime.evaluate("Ruby.require('set')")
33
+ assert_kind_of(Set, @runtime.evaluate("Ruby.Set.new()"))
34
+ end
35
+
36
+ def test_require_an_existing_js_file_without_extension
37
+ assert_js("Johnson.require('johnson/template')")
38
+ end
39
+
40
+ def test_require_returns_false_the_second_time_around
41
+ assert_js("Johnson.require('johnson/template')")
42
+ assert(!@runtime.evaluate("Johnson.require('johnson/template')"))
43
+ end
44
+
45
+ def test_missing_requires_throw_LoadError
46
+ assert_js(<<-END)
47
+ var flag = false;
48
+
49
+ try { Johnson.require("johnson/__nonexistent"); }
50
+ catch(ex) { flag = true; }
51
+
52
+ flag;
53
+ END
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,46 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../helper"))
2
+
3
+ module Johnson
4
+ class RuntimeTest < Johnson::TestCase
5
+ def test_default_delegate_is_spidermonkey
6
+ assert_equal(Johnson::SpiderMonkey::Runtime, @runtime.delegate.class)
7
+ end
8
+
9
+ def test_evaluate_returns_nil_for_nil_expression
10
+ assert_nil(@runtime.evaluate(nil))
11
+ end
12
+
13
+ def test_js_eval
14
+ assert_equal(1, @runtime.evaluate('eval("1");'))
15
+ end
16
+
17
+ def test_js_throws_compile_errors
18
+ assert_raises(Johnson::Error) {
19
+ @runtime.evaluate("var js_lambda = function(x) { return x ** 2; }")
20
+ }
21
+ assert_raises(Johnson::Error) {
22
+ @runtime.compile("var js_lambda = function(x) { return x ** 2; }")
23
+ }
24
+ end
25
+
26
+ def test_breakpoint_gets_called
27
+ break_times = 0
28
+ @runtime['some_number'] = 0
29
+ script = @runtime.compile("some_number++;
30
+ var x = 0;
31
+ for(var i = 0; i < 10; i++) {
32
+ x++;
33
+ }
34
+ some_number++;
35
+ ", 'awesome_script')
36
+ @runtime.break('awesome_script', 4) do
37
+ break_times += 1
38
+ assert_equal(@runtime['i'], @runtime['x'])
39
+ assert_equal(1, @runtime['some_number'])
40
+ end
41
+ @runtime.evaluate_compiled_script(script)
42
+ assert_equal(10, break_times)
43
+ assert_equal(2, @runtime['some_number'])
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module SpiderMonkey
5
+ class ContextTest < Johnson::TestCase
6
+ def setup
7
+ @runtime = Johnson::Runtime.new(Johnson::SpiderMonkey::Runtime)
8
+ end
9
+
10
+ def test_wraps_global_unfuckedly
11
+ assert_same(@runtime.global, @runtime.evaluate("this"))
12
+ end
13
+
14
+ def test_provides_basic_runtime_interface
15
+ assert(@runtime.respond_to?(:evaluate))
16
+ assert(@runtime.respond_to?(:[]))
17
+ assert(@runtime.respond_to?(:[]=))
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ require 'stringio'
4
+
5
+ module Johnson
6
+ module SpiderMonkey
7
+ class ImmutableNodeTest < Johnson::TestCase
8
+ include Johnson::SpiderMonkey
9
+
10
+ def test_initialize
11
+ node = nil
12
+ assert_nothing_raised {
13
+ node = ImmutableNode.new
14
+ }
15
+ end
16
+
17
+ def test_parse_some_shit
18
+ assert_nothing_raised {
19
+ node = ImmutableNode.parse_io(StringIO.new('var x = 10;'))
20
+ }
21
+ end
22
+
23
+ def test_index
24
+ node = ImmutableNode.parse_io(StringIO.new('var x = 10;'))
25
+ assert_equal(0, node.index)
26
+ end
27
+
28
+ def test_line
29
+ node = ImmutableNode.parse_io(StringIO.new('var x = 10;'))
30
+ assert_equal(0, node.line)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,236 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module SpiderMonkey
5
+ class JSLandProxyTest < Johnson::TestCase
6
+ module AModule
7
+ end
8
+
9
+ class AClass
10
+ attr_reader :args
11
+
12
+ def initialize(*args)
13
+ @args = args
14
+ end
15
+ end
16
+
17
+ class Foo
18
+ class Inner
19
+ end
20
+
21
+ def self.bar; 10; end
22
+
23
+ attr_accessor :bar
24
+
25
+ def initialize
26
+ @bar = 10
27
+ end
28
+
29
+ def x2(x)
30
+ x * 2
31
+ end
32
+
33
+ def add(*args)
34
+ args.inject { |m,n| m += n }
35
+ end
36
+
37
+ def xform(arg)
38
+ yield(arg)
39
+ end
40
+ end
41
+
42
+ class Indexable
43
+ def initialize
44
+ @store = {}
45
+ end
46
+
47
+ def [](key)
48
+ @store[key]
49
+ end
50
+
51
+ def []=(key, value)
52
+ @store[key] = value
53
+ end
54
+
55
+ def key?(key)
56
+ @store.key?(key)
57
+ end
58
+ end
59
+
60
+ def setup
61
+ @runtime = Johnson::Runtime.new(Johnson::SpiderMonkey::Runtime)
62
+ end
63
+
64
+ def test_find_constants
65
+ assert_js_equal($LOAD_PATH, "Ruby['$LOAD_PATH']")
66
+ end
67
+
68
+ def test_proxies_get_reused
69
+ @runtime["foo"] = @runtime["bar"] = Foo.new
70
+ assert_js_equal(true, "foo === bar")
71
+ end
72
+
73
+ def test_attributes_get_added_to_ruby
74
+ foo = @runtime["foo"] = Foo.new
75
+ assert !foo.respond_to?(:johnson)
76
+ @runtime.evaluate("foo.johnson = 'explode';")
77
+ assert foo.respond_to?(:johnson)
78
+ assert_equal('explode', foo.johnson)
79
+ assert_js_equal('explode', 'foo.johnson')
80
+ assert !Foo.new.respond_to?(:johnson)
81
+ end
82
+
83
+ def test_assign_function_as_attribute
84
+ foo = @runtime["foo"] = Foo.new
85
+ assert !foo.respond_to?(:johnson)
86
+ f = @runtime.evaluate("foo.johnson = function() { return 'explode'; }")
87
+ assert foo.respond_to?(:johnson)
88
+ assert_equal('explode', foo.johnson)
89
+ assert_js_equal('explode', 'foo.johnson()')
90
+ assert_js_equal(f, 'foo.johnson')
91
+ assert !Foo.new.respond_to?(:johnson)
92
+ end
93
+
94
+ def test_assign_function_as_attribute_with_this
95
+ foo = @runtime["foo"] = Foo.new
96
+ @runtime.evaluate("foo.ex_squared = function(x) { return this.x2(x); }")
97
+ assert_equal(4, foo.ex_squared(2))
98
+ @runtime.evaluate("foo.ex_squared = 20;")
99
+ assert_equal(20, foo.ex_squared)
100
+ end
101
+
102
+ def test_use_ruby_global_object
103
+ func = @runtime.evaluate("function(x) { return this.x2(x); }")
104
+ foo = Foo.new
105
+ assert_equal(4, func.call_using(foo, 2))
106
+ end
107
+
108
+ def test_proxies_roundtrip
109
+ @runtime["foo"] = foo = Foo.new
110
+ assert_same(foo, @runtime.evaluate("foo"))
111
+ end
112
+
113
+ def test_proxies_classes
114
+ @runtime["Foo"] = Foo
115
+ assert_same(Foo, @runtime.evaluate("Foo"))
116
+ end
117
+
118
+ def test_proxies_modules
119
+ @runtime["AModule"] = AModule
120
+ assert_same(AModule, @runtime.evaluate("AModule"))
121
+ end
122
+
123
+ def test_proxies_hashes
124
+ @runtime["beatles"] = { "george" => "guitar" }
125
+ assert_equal("guitar", @runtime.evaluate("beatles['george']"))
126
+ end
127
+
128
+ def test_getter_calls_0_arity_method
129
+ @runtime["foo"] = Foo.new
130
+ assert_js_equal(10, "foo.bar")
131
+ end
132
+
133
+ def test_getter_calls_indexer
134
+ @runtime["foo"] = indexable = Indexable.new
135
+ indexable["bar"] = 10
136
+
137
+ assert_js_equal(10, "foo.bar")
138
+ end
139
+
140
+ def test_getter_returns_nil_for_unknown_properties
141
+ @runtime["foo"] = Foo.new
142
+ assert_js_equal(nil, "foo.quux")
143
+ end
144
+
145
+ def test_setter_calls_key=
146
+ @runtime["foo"] = foo = Foo.new
147
+ assert_js_equal(42, "foo.bar = 42")
148
+ assert_equal(42, foo.bar)
149
+ end
150
+
151
+ def test_setter_calls_indexer
152
+ @runtime["foo"] = indexable = Indexable.new
153
+ assert_js_equal(42, "foo.monkey = 42")
154
+ assert_equal(42, indexable["monkey"])
155
+ end
156
+
157
+ def test_calls_attr_reader
158
+ @runtime["foo"] = Foo.new
159
+ assert_js_equal(10, "foo.bar")
160
+ end
161
+
162
+ def test_calls_1_arity_method
163
+ @runtime["foo"] = Foo.new
164
+ assert_js_equal(10, "foo.x2(5)")
165
+ end
166
+
167
+ def test_calls_n_arity_method
168
+ @runtime["foo"] = Foo.new
169
+ assert_js_equal(10, "foo.add(4, 2, 2, 1, 1)")
170
+ end
171
+
172
+ def test_calls_class_method
173
+ @runtime["Foo"] = Foo
174
+ assert_js_equal(Foo.bar, "Foo.bar()")
175
+ end
176
+
177
+ def test_accesses_consts
178
+ @runtime["Foo"] = Foo
179
+ assert_same(Foo::Inner, @runtime.evaluate("Foo.Inner"))
180
+ end
181
+
182
+ def test_can_create_new_instances_in_js
183
+ @runtime["AClass"] = AClass
184
+ foo = @runtime.evaluate("AClass.new()")
185
+ assert_kind_of(AClass, foo)
186
+ end
187
+
188
+ def test_class_proxies_provide_a_ctor
189
+ @runtime["AClass"] = AClass
190
+ foo = @runtime.evaluate("new AClass()")
191
+ assert_kind_of(AClass, foo)
192
+
193
+ bar = @runtime.evaluate("new AClass(1, 2, 3)")
194
+ assert_equal([1, 2, 3], bar.args)
195
+ end
196
+
197
+ def test_dwims_blocks
198
+ @runtime["foo"] = Foo.new
199
+ assert_js_equal(4, "foo.xform(2, function(x) { return x * 2 })")
200
+ end
201
+
202
+ def test_dwims_blocks_for_0_arity_methods
203
+ @runtime[:arr] = [1, 2, 3]
204
+ assert_js_equal([2, 4, 6], "arr.collect(function(x) { return x * 2 })")
205
+ end
206
+
207
+ def test_scope_for_with
208
+ assert_js_equal(84, "with (rb) { b + b }", :b => 1, :rb => { "b" => 42 })
209
+ end
210
+
211
+ def test_lambdas_for_with
212
+ assert_js_equal(84, "with (rb) { b(42) }", :rb => { "b" => lambda { |x| x * 2 } })
213
+ end
214
+
215
+ class MethodForWith
216
+ def b(x); x * 2; end
217
+ end
218
+
219
+ def test_method_for_with
220
+ assert_js_equal(84, "with (rb) { b(42) }", :rb => MethodForWith.new)
221
+ end
222
+
223
+ def test_raises_string_to_ruby
224
+ assert_raise(Johnson::Error) { @runtime.evaluate("throw 'my string';") }
225
+ end
226
+
227
+ def test_raises_object_to_ruby
228
+ assert_raise(Johnson::Error) { @runtime.evaluate("throw { bad: true };") }
229
+ end
230
+
231
+ def test_raises_exception_to_ruby
232
+ assert_raise(Johnson::Error) { @runtime.evaluate("undefinedValue();") }
233
+ end
234
+ end
235
+ end
236
+ end