package org.dynjs.runtime; import static org.fest.assertions.Assertions.*; import static org.junit.Assert.*; import org.junit.Ignore; import org.junit.Test; public class FunctionDeclarationTest extends AbstractDynJSTestSupport { @Test public void testFunctionDeclaration() { eval("function foo() { return 42.0 };"); Reference foo = getContext().resolve("foo"); assertThat(foo).isNotNull(); assertThat(foo.isUnresolvableReference()).isFalse(); JSFunction fn = (JSFunction) foo.getValue(getContext()); assertThat(fn).isNotNull(); Object result = fn.call(getContext()); assertThat(result).isEqualTo(42L); } @Test public void testInvalidFunction() { try { eval("function (){};"); fail("Invalid functions should be invalid, dammit."); } catch (Exception e) { } } @Test public void testValidFunctionExpr() { eval("(function (){});"); } @Test public void testFunctionPropertyNamedPrint() { eval("var o = new Object();"); eval("o.print = function() { return 'printed' }"); assertThat(eval("o.print()")).isEqualTo("printed"); } @Test public void testFunctionPropertyNamedFoo() { eval("var o = new Object();"); eval("o.foo = function() { return 'foo' }"); assertThat(eval("o.foo()")).isEqualTo("foo"); } @Test public void testFunctionDeclInParameter() { Object result = eval( "function foo(arg) { return arg(); };", "foo( function bar() { return bar; } );" ); assertThat( result ).isNotNull(); assertThat( result ).isInstanceOf( JSFunction.class ); } @Test public void testNamedFunction() { eval("var handlers = {}"); eval("var registerHandler = function(name, f) {", "handlers[name] = f;", "}"); eval("var unregisterHandler = function(name, f) {", "if (handlers[name] === f) {", " handlers[name] = null;", "}" + "}"); eval("registerHandler('myhandler', function MyHandler() {", "unregisterHandler('myhandler', MyHandler);", "return 'foobar';", "});"); assertThat(eval("handlers['myhandler']()")).isEqualTo("foobar"); assertThat(eval("handlers['myhandler'] == null")).isEqualTo(true); } @Test public void testFunctionDeclarationMutability() { String program = new StringBuilder() .append("'use strict';") .append("function f() {") .append(" f = function(amount) {") .append(" return amount*2;") .append(" };") .append(" return f.apply(this, arguments);") .append("};") .append("f(11);") .toString(); Object result = eval(program); assertThat(result).isEqualTo(22L); } }