2011-09-13 11:00:30 -04:00
|
|
|
# -*- coding: utf-8 -*-
|
2014-05-19 09:46:58 -04:00
|
|
|
require "minitest/autorun"
|
2011-09-13 11:00:30 -04:00
|
|
|
require "execjs/module"
|
2014-12-11 01:16:36 -05:00
|
|
|
require "json"
|
2011-02-06 20:10:05 -05:00
|
|
|
|
2011-09-13 11:00:30 -04:00
|
|
|
begin
|
|
|
|
require "execjs"
|
|
|
|
rescue ExecJS::RuntimeUnavailable => e
|
|
|
|
warn e
|
|
|
|
exit 2
|
|
|
|
end
|
2011-02-06 21:35:37 -05:00
|
|
|
|
2014-05-19 09:46:58 -04:00
|
|
|
if defined? Minitest::Test
|
|
|
|
Test = Minitest::Test
|
|
|
|
elsif defined? MiniTest::Unit::TestCase
|
|
|
|
Test = MiniTest::Unit::TestCase
|
|
|
|
end
|
|
|
|
|
|
|
|
class TestExecJS < Test
|
2011-02-06 21:35:37 -05:00
|
|
|
def test_runtime_available
|
2014-05-19 18:03:58 -04:00
|
|
|
runtime = ExecJS::ExternalRuntime.new(command: "nonexistent")
|
2011-02-06 23:52:13 -05:00
|
|
|
assert !runtime.available?
|
2011-02-06 21:35:37 -05:00
|
|
|
|
2014-05-19 18:03:58 -04:00
|
|
|
runtime = ExecJS::ExternalRuntime.new(command: "ruby")
|
2011-02-06 23:52:13 -05:00
|
|
|
assert runtime.available?
|
2011-02-06 21:35:37 -05:00
|
|
|
end
|
2011-02-11 12:39:06 -05:00
|
|
|
|
2011-05-17 11:08:41 -04:00
|
|
|
def test_runtime_assignment
|
|
|
|
original_runtime = ExecJS.runtime
|
2014-05-19 18:03:58 -04:00
|
|
|
runtime = ExecJS::ExternalRuntime.new(command: "nonexistent")
|
2011-05-17 11:08:41 -04:00
|
|
|
assert_raises(ExecJS::RuntimeUnavailable) { ExecJS.runtime = runtime }
|
|
|
|
assert_equal original_runtime, ExecJS.runtime
|
|
|
|
|
2014-05-19 18:03:58 -04:00
|
|
|
runtime = ExecJS::ExternalRuntime.new(command: "ruby")
|
2011-05-17 11:08:41 -04:00
|
|
|
ExecJS.runtime = runtime
|
|
|
|
assert_equal runtime, ExecJS.runtime
|
2011-09-13 11:00:30 -04:00
|
|
|
ensure
|
|
|
|
ExecJS.runtime = original_runtime
|
2011-02-11 12:39:06 -05:00
|
|
|
end
|
2011-02-11 12:51:59 -05:00
|
|
|
|
2011-02-12 13:27:08 -05:00
|
|
|
def test_context_call
|
|
|
|
context = ExecJS.compile("id = function(v) { return v; }")
|
|
|
|
assert_equal "bar", context.call("id", "bar")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_nested_context_call
|
|
|
|
context = ExecJS.compile("a = {}; a.b = {}; a.b.id = function(v) { return v; }")
|
|
|
|
assert_equal "bar", context.call("a.b.id", "bar")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_context_call_missing_function
|
|
|
|
context = ExecJS.compile("")
|
|
|
|
assert_raises ExecJS::ProgramError do
|
|
|
|
context.call("missing")
|
|
|
|
end
|
|
|
|
end
|
2011-09-13 11:00:30 -04:00
|
|
|
|
2014-12-11 15:22:01 -05:00
|
|
|
{
|
|
|
|
"function() {}" => nil,
|
|
|
|
"0" => 0,
|
|
|
|
"null" => nil,
|
|
|
|
"undefined" => nil,
|
|
|
|
"true" => true,
|
|
|
|
"false" => false,
|
|
|
|
"[1, 2]" => [1, 2],
|
|
|
|
"[1, function() {}]" => [1, nil],
|
|
|
|
"'hello'" => "hello",
|
|
|
|
"'red yellow blue'.split(' ')" => ["red", "yellow", "blue"],
|
|
|
|
"{a:1,b:2}" => {"a"=>1,"b"=>2},
|
|
|
|
"{a:true,b:function (){}}" => {"a"=>true},
|
|
|
|
"'café'" => "café",
|
|
|
|
'"☃"' => "☃",
|
|
|
|
'"\u2603"' => "☃",
|
2014-12-11 15:25:35 -05:00
|
|
|
"'\u{1f604}'".encode("UTF-8") => "\u{1f604}".encode("UTF-8"), # Smiling emoji
|
|
|
|
"'\u{1f1fa}\u{1f1f8}'".encode("UTF-8") => "\u{1f1fa}\u{1f1f8}".encode("UTF-8"), # US flag
|
2014-12-11 15:22:01 -05:00
|
|
|
'"\\\\"' => "\\"
|
|
|
|
}.each_with_index do |(input, output), index|
|
|
|
|
define_method("test_exec_string_#{index}") do
|
|
|
|
assert_equal output, ExecJS.exec("return #{input}")
|
|
|
|
end
|
2011-09-13 11:00:30 -04:00
|
|
|
|
2014-12-11 15:22:01 -05:00
|
|
|
define_method("test_eval_string_#{index}") do
|
|
|
|
assert_equal output, ExecJS.eval(input)
|
|
|
|
end
|
|
|
|
|
|
|
|
define_method("test_compile_return_string_#{index}") do
|
|
|
|
context = ExecJS.compile("var a = #{input};")
|
|
|
|
assert_equal output, context.eval("a")
|
|
|
|
end
|
|
|
|
|
|
|
|
define_method("test_compile_call_string_#{index}") do
|
|
|
|
context = ExecJS.compile("function a() { return #{input}; }")
|
|
|
|
assert_equal output, context.call("a")
|
|
|
|
end
|
2011-09-13 11:00:30 -04:00
|
|
|
end
|
|
|
|
|
2014-12-11 15:22:01 -05:00
|
|
|
[
|
|
|
|
nil,
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
1,
|
|
|
|
3.14,
|
|
|
|
"hello",
|
|
|
|
"\\",
|
|
|
|
"café",
|
|
|
|
"☃",
|
|
|
|
"\u{1f604}".encode("UTF-8"), # Smiling emoji
|
|
|
|
"\u{1f1fa}\u{1f1f8}".encode("UTF-8"), # US flag
|
|
|
|
[1, 2, 3],
|
|
|
|
[1, [2, 3]],
|
|
|
|
[1, [2, [3]]],
|
|
|
|
["red", "yellow", "blue"],
|
|
|
|
{ "a" => 1, "b" => 2},
|
|
|
|
{ "a" => 1, "b" => [2, 3]},
|
|
|
|
{ "a" => true }
|
|
|
|
].each_with_index do |value, index|
|
|
|
|
json_value = JSON.generate(value, quirks_mode: true)
|
|
|
|
|
|
|
|
define_method("test_json_value_#{index}") do
|
2014-12-11 01:14:01 -05:00
|
|
|
assert_equal value, JSON.parse(json_value, quirks_mode: true)
|
2014-12-11 15:22:01 -05:00
|
|
|
end
|
2014-12-11 01:14:01 -05:00
|
|
|
|
2014-12-11 15:22:01 -05:00
|
|
|
define_method("test_exec_value_#{index}") do
|
2014-12-11 01:14:01 -05:00
|
|
|
assert_equal value, ExecJS.exec("return #{json_value}")
|
2014-12-11 15:22:01 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
define_method("test_eval_value_#{index}") do
|
2014-12-11 01:14:01 -05:00
|
|
|
assert_equal value, ExecJS.eval("#{json_value}")
|
2014-12-11 15:22:01 -05:00
|
|
|
end
|
2014-12-11 01:14:01 -05:00
|
|
|
|
2014-12-11 15:22:01 -05:00
|
|
|
define_method("test_strinigfy_value_#{index}") do
|
2014-12-11 01:14:01 -05:00
|
|
|
context = ExecJS.compile("function json(obj) { return JSON.stringify(obj); }")
|
|
|
|
assert_equal json_value, context.call("json", value)
|
2014-12-11 15:22:01 -05:00
|
|
|
end
|
2014-12-11 01:14:01 -05:00
|
|
|
|
2014-12-11 15:22:01 -05:00
|
|
|
define_method("test_call_value_#{index}") do
|
2014-12-11 01:14:01 -05:00
|
|
|
context = ExecJS.compile("function id(obj) { return obj; }")
|
|
|
|
assert_equal value, context.call("id", value)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-12-11 15:22:01 -05:00
|
|
|
def test_eval_blank
|
|
|
|
assert_nil ExecJS.eval("")
|
|
|
|
assert_nil ExecJS.eval(" ")
|
|
|
|
assert_nil ExecJS.eval(" ")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_exec_return
|
|
|
|
assert_nil ExecJS.exec("return")
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_exec_no_return
|
|
|
|
assert_nil ExecJS.exec("1")
|
|
|
|
end
|
|
|
|
|
2014-05-19 09:45:03 -04:00
|
|
|
def test_encoding
|
|
|
|
utf8 = Encoding.find('UTF-8')
|
|
|
|
|
|
|
|
assert_equal utf8, ExecJS.exec("return 'hello'").encoding
|
|
|
|
assert_equal utf8, ExecJS.eval("'☃'").encoding
|
|
|
|
|
|
|
|
ascii = "'hello'".encode('US-ASCII')
|
|
|
|
result = ExecJS.eval(ascii)
|
|
|
|
assert_equal "hello", result
|
|
|
|
assert_equal utf8, result.encoding
|
|
|
|
|
2014-05-19 09:46:58 -04:00
|
|
|
assert_raises Encoding::UndefinedConversionError do
|
2014-05-19 09:45:03 -04:00
|
|
|
binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
|
|
|
|
ExecJS.eval(binary)
|
2011-09-13 11:00:30 -04:00
|
|
|
end
|
2014-05-19 09:45:03 -04:00
|
|
|
end
|
2011-09-13 11:00:30 -04:00
|
|
|
|
2014-05-19 09:45:03 -04:00
|
|
|
def test_encoding_compile
|
|
|
|
utf8 = Encoding.find('UTF-8')
|
2011-09-13 11:00:30 -04:00
|
|
|
|
2014-05-19 09:45:03 -04:00
|
|
|
context = ExecJS.compile("foo = function(v) { return '¶' + v; }".encode("ISO8859-15"))
|
2011-09-13 11:00:30 -04:00
|
|
|
|
2014-05-19 09:45:03 -04:00
|
|
|
assert_equal utf8, context.exec("return foo('hello')").encoding
|
|
|
|
assert_equal utf8, context.eval("foo('☃')").encoding
|
2011-09-13 11:00:30 -04:00
|
|
|
|
2014-05-19 09:45:03 -04:00
|
|
|
ascii = "foo('hello')".encode('US-ASCII')
|
|
|
|
result = context.eval(ascii)
|
|
|
|
assert_equal "¶hello", result
|
|
|
|
assert_equal utf8, result.encoding
|
2011-09-13 11:00:30 -04:00
|
|
|
|
2014-05-19 09:46:58 -04:00
|
|
|
assert_raises Encoding::UndefinedConversionError do
|
2014-05-19 09:45:03 -04:00
|
|
|
binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
|
|
|
|
context.eval(binary)
|
2011-09-13 11:00:30 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-12-11 13:53:11 -05:00
|
|
|
def test_surrogate_pairs
|
|
|
|
# Smiling emoji
|
2014-12-11 14:40:41 -05:00
|
|
|
str = "\u{1f604}".encode("UTF-8")
|
2014-12-11 13:53:11 -05:00
|
|
|
assert_equal 2, ExecJS.eval("'#{str}'.length")
|
|
|
|
assert_equal str, ExecJS.eval("'#{str}'")
|
|
|
|
|
|
|
|
# US flag emoji
|
2014-12-11 15:03:10 -05:00
|
|
|
str = "\u{1f1fa}\u{1f1f8}".encode("UTF-8")
|
2014-12-11 13:53:11 -05:00
|
|
|
assert_equal 4, ExecJS.eval("'#{str}'.length")
|
|
|
|
assert_equal str, ExecJS.eval("'#{str}'")
|
|
|
|
end
|
|
|
|
|
2014-12-11 13:29:12 -05:00
|
|
|
def test_compile_anonymous_function
|
2011-09-13 11:00:30 -04:00
|
|
|
context = ExecJS.compile("foo = function() { return \"bar\"; }")
|
|
|
|
assert_equal "bar", context.exec("return foo()")
|
|
|
|
assert_equal "bar", context.eval("foo()")
|
|
|
|
assert_equal "bar", context.call("foo")
|
|
|
|
end
|
|
|
|
|
2014-12-11 13:29:12 -05:00
|
|
|
def test_compile_named_function
|
|
|
|
context = ExecJS.compile("function foo() { return \"bar\"; }")
|
|
|
|
assert_equal "bar", context.exec("return foo()")
|
|
|
|
assert_equal "bar", context.eval("foo()")
|
|
|
|
assert_equal "bar", context.call("foo")
|
|
|
|
end
|
|
|
|
|
2011-09-13 11:00:30 -04:00
|
|
|
def test_this_is_global_scope
|
|
|
|
assert_equal true, ExecJS.eval("this === (function() {return this})()")
|
|
|
|
assert_equal true, ExecJS.exec("return this === (function() {return this})()")
|
|
|
|
end
|
|
|
|
|
2015-02-03 16:49:13 -05:00
|
|
|
def test_browser_self_is_undefined
|
|
|
|
assert ExecJS.eval("typeof self == 'undefined'")
|
|
|
|
end
|
|
|
|
|
2015-02-03 16:43:41 -05:00
|
|
|
def test_node_global_is_undefined
|
2015-02-03 16:37:58 -05:00
|
|
|
assert ExecJS.eval("typeof global == 'undefined'")
|
2015-02-03 16:43:41 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_commonjs_vars_are_undefined
|
2011-09-13 11:00:30 -04:00
|
|
|
assert ExecJS.eval("typeof module == 'undefined'")
|
|
|
|
assert ExecJS.eval("typeof exports == 'undefined'")
|
|
|
|
assert ExecJS.eval("typeof require == 'undefined'")
|
|
|
|
end
|
|
|
|
|
2012-05-20 13:26:19 -04:00
|
|
|
def test_console_is_undefined
|
|
|
|
assert ExecJS.eval("typeof console == 'undefined'")
|
|
|
|
end
|
|
|
|
|
2014-12-22 21:34:44 -05:00
|
|
|
def test_timers_are_undefined
|
|
|
|
assert ExecJS.eval("typeof setTimeout == 'undefined'")
|
|
|
|
assert ExecJS.eval("typeof setInterval == 'undefined'")
|
|
|
|
assert ExecJS.eval("typeof clearTimeout == 'undefined'")
|
|
|
|
assert ExecJS.eval("typeof clearInterval == 'undefined'")
|
|
|
|
assert ExecJS.eval("typeof setImmediate == 'undefined'")
|
|
|
|
assert ExecJS.eval("typeof clearImmediate == 'undefined'")
|
|
|
|
end
|
|
|
|
|
2011-09-13 11:00:30 -04:00
|
|
|
def test_compile_large_scripts
|
|
|
|
body = "var foo = 'bar';\n" * 100_000
|
|
|
|
assert ExecJS.exec("function foo() {\n#{body}\n};\nreturn true")
|
|
|
|
end
|
|
|
|
|
2014-12-06 15:26:08 -05:00
|
|
|
def test_exec_syntax_error
|
2014-05-19 09:46:58 -04:00
|
|
|
assert_raises ExecJS::RuntimeError do
|
2011-09-13 11:00:30 -04:00
|
|
|
ExecJS.exec(")")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-12-06 15:26:08 -05:00
|
|
|
def test_eval_syntax_error
|
|
|
|
assert_raises ExecJS::RuntimeError do
|
|
|
|
ExecJS.eval(")")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-12-11 13:57:49 -05:00
|
|
|
def test_compile_syntax_error
|
|
|
|
assert_raises ExecJS::RuntimeError do
|
|
|
|
ExecJS.compile(")")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_exec_thrown_exception
|
|
|
|
assert_raises ExecJS::ProgramError do
|
|
|
|
ExecJS.exec("throw 'hello'")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_eval_thrown_exception
|
|
|
|
assert_raises ExecJS::ProgramError do
|
|
|
|
ExecJS.exec("throw 'hello'")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_compile_thrown_exception
|
2014-05-19 09:46:58 -04:00
|
|
|
assert_raises ExecJS::ProgramError do
|
2011-09-13 11:00:30 -04:00
|
|
|
ExecJS.exec("throw 'hello'")
|
|
|
|
end
|
|
|
|
end
|
2012-05-20 13:35:12 -04:00
|
|
|
|
2015-02-25 15:46:41 -05:00
|
|
|
def test_babel
|
|
|
|
assert source = File.read(File.expand_path("../fixtures/babel.js", __FILE__))
|
|
|
|
source = <<-JS
|
|
|
|
var self = this;
|
|
|
|
#{source}
|
|
|
|
babel.eval = function(code) {
|
|
|
|
return eval(babel.transform(code)["code"]);
|
|
|
|
}
|
|
|
|
JS
|
|
|
|
context = ExecJS.compile(source)
|
|
|
|
assert_equal 64, context.call("babel.eval", "((x) => x * x)(8)")
|
|
|
|
end
|
|
|
|
|
2012-05-20 13:35:12 -04:00
|
|
|
def test_coffeescript
|
2014-10-14 16:31:25 -04:00
|
|
|
assert source = File.read(File.expand_path("../fixtures/coffee-script.js", __FILE__))
|
2012-05-20 13:35:12 -04:00
|
|
|
context = ExecJS.compile(source)
|
|
|
|
assert_equal 64, context.call("CoffeeScript.eval", "((x) -> x * x)(8)")
|
|
|
|
end
|
2015-02-25 15:46:41 -05:00
|
|
|
|
|
|
|
def test_uglify
|
|
|
|
assert source = File.read(File.expand_path("../fixtures/uglify.js", __FILE__))
|
|
|
|
source = <<-JS
|
|
|
|
#{source}
|
|
|
|
|
|
|
|
function uglify(source) {
|
|
|
|
var ast = UglifyJS.parse(source);
|
|
|
|
var stream = UglifyJS.OutputStream();
|
|
|
|
ast.print(stream);
|
|
|
|
return stream.toString();
|
|
|
|
}
|
|
|
|
JS
|
|
|
|
context = ExecJS.compile(source)
|
|
|
|
assert_equal "function foo(bar){return bar}",
|
|
|
|
context.call("uglify", "function foo(bar) {\n return bar;\n}")
|
|
|
|
end
|
2011-02-06 20:10:05 -05:00
|
|
|
end
|