summaryrefslogtreecommitdiff
path: root/tests/test_closure.js
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_closure.js')
-rw-r--r--tests/test_closure.js221
1 files changed, 221 insertions, 0 deletions
diff --git a/tests/test_closure.js b/tests/test_closure.js
new file mode 100644
index 0000000..aa1d17e
--- /dev/null
+++ b/tests/test_closure.js
@@ -0,0 +1,221 @@
+function assert(actual, expected, message) {
+ if (arguments.length == 1)
+ expected = true;
+
+ if (actual === expected)
+ return;
+
+ if (actual !== null && expected !== null
+ && typeof actual == 'object' && typeof expected == 'object'
+ && actual.toString() === expected.toString())
+ return;
+
+ throw Error("assertion failed: got |" + actual + "|" +
+ ", expected |" + expected + "|" +
+ (message ? " (" + message + ")" : ""));
+}
+
+// load more elaborate version of assert if available
+try { __loadScript("test_assert.js"); } catch(e) {}
+
+/*----------------*/
+
+var log_str = "";
+
+function log(str)
+{
+ log_str += str + ",";
+}
+
+function f(a, b, c)
+{
+ var x = 10;
+ log("a="+a);
+ function g(d) {
+ function h() {
+ log("d=" + d);
+ log("x=" + x);
+ }
+ log("b=" + b);
+ log("c=" + c);
+ h();
+ }
+ g(4);
+ return g;
+}
+
+var g1 = f(1, 2, 3);
+g1(5);
+
+assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1");
+
+function test_closure1()
+{
+ function f2()
+ {
+ var val = 1;
+
+ function set(a) {
+ val = a;
+ }
+ function get(a) {
+ return val;
+ }
+ return { "set": set, "get": get };
+ }
+
+ var obj = f2();
+ obj.set(10);
+ var r;
+ r = obj.get();
+ assert(r, 10, "closure2");
+}
+
+function test_closure2()
+{
+ var expr_func = function myfunc1(n) {
+ function myfunc2(n) {
+ return myfunc1(n - 1);
+ }
+ if (n == 0)
+ return 0;
+ else
+ return myfunc2(n);
+ };
+ var r;
+ r = expr_func(1);
+ assert(r, 0, "expr_func");
+}
+
+function test_closure3()
+{
+ function fib(n)
+ {
+ if (n <= 0)
+ return 0;
+ else if (n == 1)
+ return 1;
+ else
+ return fib(n - 1) + fib(n - 2);
+ }
+
+ var fib_func = function fib1(n)
+ {
+ if (n <= 0)
+ return 0;
+ else if (n == 1)
+ return 1;
+ else
+ return fib1(n - 1) + fib1(n - 2);
+ };
+
+ assert(fib(6), 8, "fib");
+ assert(fib_func(6), 8, "fib_func");
+}
+
+function test_arrow_function()
+{
+ "use strict";
+
+ function f1() {
+ return (() => arguments)();
+ }
+ function f2() {
+ return (() => this)();
+ }
+ function f3() {
+ return (() => eval("this"))();
+ }
+ function f4() {
+ return (() => eval("new.target"))();
+ }
+ var a;
+
+ a = f1(1, 2);
+ assert(a.length, 2);
+ assert(a[0] === 1 && a[1] === 2);
+
+ assert(f2.call("this_val") === "this_val");
+ assert(f3.call("this_val") === "this_val");
+ assert(new f4() === f4);
+
+ var o1 = { f() { return this; } };
+ var o2 = { f() {
+ return (() => eval("super.f()"))();
+ } };
+ o2.__proto__ = o1;
+
+ assert(o2.f() === o2);
+}
+
+function test_with()
+{
+ var o1 = { x: "o1", y: "o1" };
+ var x = "local";
+ eval('var z="var_obj";');
+ assert(z === "var_obj");
+ with (o1) {
+ assert(x === "o1");
+ assert(eval("x") === "o1");
+ var f = function () {
+ o2 = { x: "o2" };
+ with (o2) {
+ assert(x === "o2");
+ assert(y === "o1");
+ assert(z === "var_obj");
+ assert(eval("x") === "o2");
+ assert(eval("y") === "o1");
+ assert(eval("z") === "var_obj");
+ assert(eval('eval("x")') === "o2");
+ }
+ };
+ f();
+ }
+}
+
+function test_eval_closure()
+{
+ var tab;
+
+ tab = [];
+ for(let i = 0; i < 3; i++) {
+ eval("tab.push(function g1() { return i; })");
+ }
+ for(let i = 0; i < 3; i++) {
+ assert(tab[i]() === i);
+ }
+
+ tab = [];
+ for(let i = 0; i < 3; i++) {
+ let f = function f() {
+ eval("tab.push(function g2() { return i; })");
+ };
+ f();
+ }
+ for(let i = 0; i < 3; i++) {
+ assert(tab[i]() === i);
+ }
+}
+
+function test_eval_const()
+{
+ const a = 1;
+ var success = false;
+ var f = function () {
+ eval("a = 1");
+ };
+ try {
+ f();
+ } catch(e) {
+ success = (e instanceof TypeError);
+ }
+ assert(success);
+}
+
+test_closure1();
+test_closure2();
+test_closure3();
+test_arrow_function();
+test_with();
+test_eval_closure();
+test_eval_const();