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
data/test/helper.rb ADDED
@@ -0,0 +1,58 @@
1
+ require "rubygems"
2
+ require "test/unit"
3
+
4
+ %w(../lib ../ext/spidermonkey).each do |path|
5
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), path)))
6
+ end
7
+
8
+ # If the test isn't running from Rake, make sure the extension's current.
9
+ Rake rescue Dir.chdir(File.dirname(__FILE__) + "/..") { %x(rake extensions) }
10
+
11
+ require "johnson"
12
+
13
+ module Johnson
14
+ class TestCase < Test::Unit::TestCase
15
+ class TestLogger
16
+ def debug(string)
17
+ puts string
18
+ end
19
+ end
20
+
21
+ undef :default_test
22
+
23
+ def setup
24
+ @runtime = Johnson::Runtime.new
25
+ #@runtime.delegate.gc_zeal = 2
26
+ #@runtime.delegate.debugger = Johnson::SpiderMonkey::Debugger.new(TestLogger.new)
27
+ end
28
+
29
+ def assert_js(expression, options={})
30
+ runtime = options[:runtime] || @runtime
31
+ assert(runtime.evaluate(expression), "Expected JS expression [#{expression}] to be true.")
32
+ end
33
+
34
+ def assert_js_equal(expected, expression, options={})
35
+ runtime = options.delete(:runtime) || @runtime
36
+ options.each { |k, v| runtime[k.to_s] = v }
37
+ assert_equal(expected, runtime.evaluate(expression))
38
+ end
39
+ end
40
+
41
+ class NodeTestCase < Test::Unit::TestCase
42
+ include Johnson::Nodes
43
+
44
+ undef :default_test
45
+
46
+ def setup
47
+ @parser = Johnson::Parser
48
+ end
49
+
50
+ def assert_sexp(expected, actual)
51
+ assert_equal(expected, actual.to_sexp)
52
+ end
53
+
54
+ def assert_ecma(expected, actual)
55
+ assert_equal(expected, actual.to_ecma)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../helper"))
2
+
3
+ require 'net/http'
4
+
5
+ module Johnson
6
+ class BrowserTest < Johnson::TestCase
7
+ def setup
8
+ super
9
+ @runtime.evaluate('Johnson.require("johnson/browser");')
10
+ end
11
+
12
+ def test_set_location_returns_location
13
+ filename = "file://#{File.expand_path(__FILE__)}"
14
+
15
+ may_thread {
16
+ @runtime.evaluate("window.location = '#{filename}'")
17
+ }
18
+
19
+ uri = URI.parse(filename)
20
+ assert_equal(uri.to_s, @runtime.evaluate('window.location').to_s)
21
+ end
22
+
23
+ def test_set_location_with_url
24
+ file = File.expand_path(__FILE__) + "/../../assets/index.html"
25
+ filename = "file://#{File.expand_path(file)}"
26
+ may_thread {
27
+ @runtime.evaluate("window.location = '#{filename}'")
28
+ }
29
+ doc = @runtime.evaluate('window.document')
30
+ assert_not_nil(doc)
31
+ end
32
+
33
+ def may_thread(&block)
34
+ block.call
35
+ (Thread.list - [Thread.main]).each { |t| t.join }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class ArrayTest < Johnson::TestCase
6
+ def test_array_index_get
7
+ @runtime[:list] = [1, 2, 3, 4]
8
+ assert_equal(1, @runtime.evaluate("list[0]"))
9
+ end
10
+
11
+ def test_array_index_set
12
+ @runtime[:list] = []
13
+ @runtime.evaluate("list[0] = 42")
14
+ assert_equal(42, @runtime[:list][0])
15
+ end
16
+
17
+ def test_array_works_with_for_in
18
+ list = [1, 2, 3, 4]
19
+
20
+ @runtime['alert'] = lambda { |x| p x }
21
+ @runtime['list'] = list
22
+ @runtime.evaluate("
23
+ var new_list = [];
24
+ for(x in list) {
25
+ new_list.push(x + 1);
26
+ }
27
+ ")
28
+ assert_equal(list.map { |x| x + 1}, @runtime['new_list'].to_a)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class BooleanTest < Johnson::TestCase
6
+ def test_truthiness
7
+ @runtime[:v] = true
8
+ assert_same(true, @runtime.evaluate("v === true"))
9
+ end
10
+
11
+ def test_dirty_lies
12
+ @runtime[:v] = false
13
+ assert_same(false, @runtime.evaluate("v === true"))
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class CallableTest < Johnson::TestCase
6
+ def test_proc_works_in_jsland
7
+ @runtime[:squared] = Proc.new { |x| x * x }
8
+ assert_js_equal(4, "squared(2)")
9
+ end
10
+
11
+ def test_procs_roundtrip
12
+ @runtime[:k] = k = lambda { |x| x }
13
+ assert_same(k, @runtime.evaluate("k"))
14
+ end
15
+
16
+ def test_proc_js_function_proxy_gets_reused
17
+ @runtime[:k] = k = lambda { |x| x }
18
+ @runtime[:kk] = k
19
+ assert_js("k === kk")
20
+ end
21
+
22
+ class CallableThing
23
+ def call
24
+ "foo"
25
+ end
26
+ end
27
+
28
+ def test_anything_with_a_call_method_can_be_called_as_a_method
29
+ @runtime[:c] = CallableThing.new
30
+ assert_js_equal("foo", "c()")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class FileTest < Johnson::TestCase
6
+ def test_read_file
7
+ File.open(__FILE__, 'rb') { |f|
8
+ @runtime[:foo] = f
9
+ assert_equal(f, @runtime.evaluate("foo"))
10
+ assert_equal(File.read(__FILE__), @runtime.evaluate("foo.read()"))
11
+ }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class NilTest < Johnson::TestCase
6
+ def test_ruby_nil_is_js_null
7
+ @runtime[:v] = nil
8
+ assert_equal(true, @runtime.evaluate("v == null"))
9
+ end
10
+
11
+ def test_js_null_is_ruby_nil
12
+ assert_nil(@runtime.evaluate("null"))
13
+ end
14
+
15
+ def test_js_undefined_is_ruby_nil
16
+ assert_nil(@runtime.evaluate("undefined"))
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class NumberTest < Johnson::TestCase
6
+ def test_ruby_fixnum_in_js
7
+ @runtime[:v] = 42
8
+
9
+ assert_js("v == 42")
10
+ assert_js_equal(42, "v")
11
+ assert_equal(42, @runtime[:v])
12
+ end
13
+
14
+ def test_js_fixnum_in_ruby
15
+ fix = @runtime.evaluate("42")
16
+ assert_equal(42, fix)
17
+ assert_kind_of(Fixnum, fix)
18
+ end
19
+
20
+ def test_ruby_float_in_js
21
+ @runtime[:pi] = pi = 3.141592654
22
+ assert_js_equal(pi, "pi")
23
+ assert_in_delta(pi, @runtime.evaluate("pi"), 2 ** -20)
24
+ end
25
+
26
+ def test_ruby_bignum_in_js
27
+ @runtime[:big] = big = 2 ** 200
28
+
29
+ assert_js_equal(big, "big")
30
+ assert_kind_of(Float, @runtime.evaluate("big"))
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class RegexpTest < Johnson::TestCase
6
+ def test_regex_converts
7
+ @runtime[:x] = /aaron/
8
+ @runtime[:y] = /john/i
9
+ assert @runtime.evaluate('"aaron".match(x)')
10
+ assert !@runtime.evaluate('"Aaron".match(x)')
11
+ assert @runtime.evaluate('"john".match(y)')
12
+ assert @runtime.evaluate('"John".match(y)')
13
+ end
14
+
15
+ def test_regex_roundtrips
16
+ @runtime[:x] = /aaron/
17
+ assert_equal(/aaron/, @runtime.evaluate('x'))
18
+
19
+ @runtime[:x] = /aaron/m
20
+ assert_equal(/aaron/m, @runtime.evaluate('x'))
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class StringTest < Johnson::TestCase
6
+ def test_ruby_string_in_js
7
+ @runtime[:v] = "foo"
8
+ assert_js("'foo' == v")
9
+ end
10
+
11
+ def test_js_string_in_ruby
12
+ assert_equal("foo", @runtime.evaluate("'foo'"))
13
+ end
14
+
15
+ def test_roundtrip
16
+ @runtime[:v] = v = "hola"
17
+ assert_equal(v, @runtime.evaluate("v"))
18
+ end
19
+
20
+ def test_strings_are_copies
21
+ @runtime[:v] = v = "hola"
22
+ assert_not_same(v, @runtime.evaluate("v"))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class StructTest < Johnson::TestCase
6
+ def test_use_struct
7
+ f = Struct.new(:phil_collins).new
8
+ f.phil_collins = 'awesome'
9
+ @runtime[:foo] = f
10
+ assert_equal(f, @runtime.evaluate('foo'))
11
+ assert_equal('awesome', @runtime.evaluate('foo.phil_collins'))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class SymbolTest < Johnson::TestCase
6
+ def test_symbols_are_interned
7
+ @runtime[:v] = :symbol
8
+ @runtime[:x] = :symbol
9
+
10
+ assert(@runtime.evaluate("v !== null && v === x"))
11
+ end
12
+
13
+ def test_ruby_symbol_roundtrips
14
+ @runtime[:v] = :foo
15
+ assert_equal(:foo, @runtime.evaluate("v"))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../../helper"))
2
+
3
+ module Johnson
4
+ module Conversions
5
+ class ThreadTest < Johnson::TestCase
6
+ def test_manipulate_thread
7
+ thread = Thread.new { }
8
+ @runtime['thread'] = thread
9
+ assert_js_equal(false, "thread.send('alive?')")
10
+ end
11
+
12
+ def test_new_js_thread
13
+ @runtime.evaluate('function testing() { Ruby.sleep(10); }')
14
+ @runtime.evaluate('new Ruby.Thread(function() { testing(); })')
15
+ end
16
+
17
+ def test_js_thread_read_file
18
+ @runtime['filename'] = File.expand_path(__FILE__)
19
+ @runtime.evaluate('function testing() { Ruby.File.read(filename); }')
20
+ @runtime.evaluate('new Ruby.Thread(function() { testing(); })')
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../helper"))
2
+
3
+ module Johnson
4
+ class ErrorTest < Johnson::TestCase
5
+ def test_inherits_from_standard_error
6
+ assert(Johnson::Error < StandardError)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/../helper"))
2
+
3
+ module Johnson
4
+ module Extensions
5
+ class DefinePropertyTest < Johnson::TestCase
6
+ def setup
7
+ super
8
+ @runtime.evaluate("x = {}")
9
+ end
10
+
11
+ def test_object_can_define_property
12
+ @runtime.evaluate("Object.defineProperty(x, 'answer', 42)")
13
+ assert_js_equal(42, "x.answer")
14
+ end
15
+
16
+ def test_object_can_define_unenumerable_property
17
+ @runtime.evaluate("Object.defineProperty(x, 'answer', 42)")
18
+ @runtime.evaluate <<-JS
19
+ y = [];
20
+ for(prop in x) if(prop == "answer") y.push(prop)
21
+ JS
22
+ assert_js("y.length == 0")
23
+ end
24
+
25
+ def test_object_can_define_enumerable_property
26
+ @runtime.evaluate("Object.defineProperty(x, 'answer', 42, Object.ITERABLE)")
27
+ @runtime.evaluate <<-JS
28
+ y = [];
29
+ for(prop in x) if(prop == "answer") y.push(prop)
30
+ JS
31
+ assert_js("y.length == 1")
32
+ end
33
+
34
+ def test_object_can_define_read_only_property
35
+ @runtime.evaluate("Object.defineProperty(x, 'answer', 42, Object.READ_ONLY)")
36
+ @runtime.evaluate("x.answer = 47")
37
+ assert_js_equal(42, "x.answer")
38
+ end
39
+
40
+ def test_object_can_define_non_deletable_property
41
+ @runtime.evaluate("Object.defineProperty(x, 'answer', 42, Object.NON_DELETABLE)")
42
+ @runtime.evaluate("r = (delete x.answer)")
43
+ assert_js_equal(false, "r")
44
+ assert_js_equal(42, "x.answer")
45
+ end
46
+
47
+ def test_object_can_define_mixed_property
48
+ @runtime.evaluate("Object.defineProperty(x, 'answer', 42, Object.NON_DELETABLE | Object.READ_ONLY)")
49
+ @runtime.evaluate("r = (delete x.answer)")
50
+ @runtime.evaluate("x.answer = 47")
51
+ assert_js_equal(false, "r")
52
+ assert_js_equal(42, "x.answer")
53
+ end
54
+ end
55
+ end
56
+ end