diff --git a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java index ac578dcc..49be7448 100644 --- a/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java +++ b/jetlinks-components/script-component/src/main/java/org/jetlinks/community/script/jsr223/JavaScriptFactory.java @@ -30,8 +30,8 @@ public abstract class JavaScriptFactory extends Jsr223ScriptFactory { "this.eval = function(e){};" + "function readFully(){};" + "function readLine(){};" + - "var print = console.log;" + - "var echo = console.log;"); + "const print = function(e){console.log(e)};" + + "const echo = print;"); wrap.add("/* script start */"); diff --git a/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/JavaScriptFactoryTest.java b/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/JavaScriptFactoryTest.java new file mode 100644 index 00000000..00f51687 --- /dev/null +++ b/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/JavaScriptFactoryTest.java @@ -0,0 +1,281 @@ +package org.jetlinks.community.script; + +import jdk.nashorn.internal.objects.Global; +import lombok.SneakyThrows; +import lombok.extern.java.Log; +import org.jetlinks.community.script.jsr223.JavaScriptFactory; +import org.junit.jupiter.api.Test; + +import java.util.*; +import java.util.function.Function; +import java.util.function.Supplier; + +import static org.junit.jupiter.api.Assertions.*; + +public abstract class JavaScriptFactoryTest { + + protected abstract JavaScriptFactory getFactory(); + + @Test + void testBadAccess() { + JavaScriptFactory factory = getFactory(); + + { + CompiledScript script = factory.compile(Script.of("test", "return this.engine")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return global")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return context")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "delete this.engine;return this.engine")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "delete quit;return quit()")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return exit()")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return exit(0)")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "delete this.eval; return eval('1')")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + { + CompiledScript script = factory.compile(Script.of("test", "return eval('1')")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return eval('1')")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return Function('return 1')()")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return this.eval('1')")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "const func = function() { return eval(1); }; return func();")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + { + CompiledScript script = factory.compile(Script.of("test", "return (function(){ return eval('return 1') })()")); + Object resul = script.call(Collections.emptyMap()); + assertNull(resul); + } + + + } + + + @Test + void testArray() { + JavaScriptFactory factory = getFactory(); + Object val = factory.compile(Script.of("test", "var arr = []; arr.push({a:1,b:2}); return arr;")) + .call(Collections.emptyMap()); + System.out.println(val); + assertNotNull(val); + assertTrue(val instanceof List); + } + + @Test + void testPrint() { + JavaScriptFactory factory = getFactory(); + factory.compile(Script + .of("test", "print(123);console.log('test 123');")) + .call(Collections.emptyMap()); + + } + + @Test + void testTernary() { + JavaScriptFactory factory = getFactory(); + Object val = factory.compile(Script.of("test", "return 1 + (1>0?2:1);")) + .call(Collections.emptyMap()); + System.out.println(val); + assertEquals(3, val); + } + + @Test + void testNullSafe() { + JavaScriptFactory factory = getFactory(); + Object val = factory.compile(Script.of("test", "return temp1==null? 10 :0")) + .call(Collections.emptyMap()); + assertEquals(10, val); + } + + @Test + void testBenchmark() { + JavaScriptFactory factory = getFactory(); + CompiledScript script = factory.compile(Script.of("test", "if(temp1==null) {return temp} else {return temp+1}")); + script.call(Collections.singletonMap("temp", 10)); + + long time = System.currentTimeMillis(); + for (long i = 0; i < 10_0000; i++) { + script.call(Collections.singletonMap("temp", 10)); + } + System.out.println(System.currentTimeMillis() - time); + } + + @Test + void testAnonymous() { + JavaScriptFactory factory = getFactory(); + factory.compile(Script.of("test", "parser.fixed(4)\n" + + " .handler(function(buffer){\n" + + " var len = buffer.getShort(2);\n" + + " parser.fixed(len).result(buffer);\n" + + " })\n" + + " .handler(function(buffer){\n" + + " parser.result(buffer)\n" + + " .complete();\n" + + " });")); + + } + + @Test + void testVarNest() { + JavaScriptFactory factory = getFactory(); + TestNest nest = new TestNest(); + + factory.compile(Script.of("test", "const test = this.test; test.setup(function(e){ return e+test.data() })")) + .call(Collections.singletonMap("test", nest)); + + assertNotNull(nest.func); + + System.out.println(nest.func.apply(10)); + } + + public static class TestNest { + Function func; + + public Object data() { + return 2; + } + + public TestNest setup(Function func) { + this.func = func; + return this; + } + } + + @Test + @SneakyThrows + void testUtils() { + { + JavaScriptFactory factory = getFactory(); + MyClazz utils = new MyClazz(); + + ExposedScript script = factory.compileExpose(Script.of("test", "return $recent($recent(),$recent(temp))"), TestExtend.class); + + assertEquals(utils.$recent(utils.$recent(), utils.$recent(2)), script.call(utils, Collections.singletonMap("temp", 2))); + } + } + + @Test + void testNestFunction() { + JavaScriptFactory factory = getFactory(); + + Map ctx = new HashMap<>(); + ctx.put("val", 1); + + ExposedScript script = factory.compileExpose( + Script.of("test", "var $val = val; function decode(){ return $recent()+$val }; return call(decode);"), + TestExtend.class); + + TestExtend extend = new TestExtend(); + script.call(extend, ctx); + + + assertNotNull(extend.call); + assertEquals(2.0, extend.call.get()); + + } + + public static class MyClazz extends TestExtend { + + } + + public static class TestExtend { + Supplier call; + + public int max(int i, int j) { + return Math.max(i, j); + } + + public int $recent() { + return 1; + } + + public int $recent(int i) { + return i; + } + + public int $recent(int i, int j) { + return i + j; + } + + public Object call(Supplier call) { + this.call = call; + return 0; + } + + } + + @Test + void testMake() { + + Api api = getFactory().bind(Script.of(Api.class.getName(), "function add(a,b){return a+b};"), Api.class); + + assertEquals(3, api.add(1, 2)); + + assertNull(api.reduce(1, 2)); + + assertNull(api.reduce(1, 2)); + + } + + public interface Api { + int add(int a, int b); + + Object reduce(int a, int b); + } +} diff --git a/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/nashorn/NashornScriptFactoryTest.java b/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/nashorn/NashornScriptFactoryTest.java new file mode 100644 index 00000000..0a99cc38 --- /dev/null +++ b/jetlinks-components/script-component/src/test/java/org/jetlinks/community/script/nashorn/NashornScriptFactoryTest.java @@ -0,0 +1,15 @@ +package org.jetlinks.community.script.nashorn; + +import org.jetlinks.community.script.JavaScriptFactoryTest; +import org.jetlinks.community.script.jsr223.JavaScriptFactory; + +import static org.junit.jupiter.api.Assertions.assertNull; + +class NashornScriptFactoryTest extends JavaScriptFactoryTest { + NashornScriptFactory factory = new NashornScriptFactory(); + + @Override + protected JavaScriptFactory getFactory() { + return factory; + } +} \ No newline at end of file diff --git a/jetlinks-components/script-component/src/test/resources/javascript-utils.html b/jetlinks-components/script-component/src/test/resources/javascript-utils.html new file mode 100644 index 00000000..c4b96375 --- /dev/null +++ b/jetlinks-components/script-component/src/test/resources/javascript-utils.html @@ -0,0 +1,92 @@ + + + + + Title + + + + +
+ +
+ + + + + \ No newline at end of file diff --git a/jetlinks-components/script-component/src/test/resources/javascript-utils.js b/jetlinks-components/script-component/src/test/resources/javascript-utils.js new file mode 100644 index 00000000..28cc4da2 --- /dev/null +++ b/jetlinks-components/script-component/src/test/resources/javascript-utils.js @@ -0,0 +1,9 @@ + + + + +function parse(json){ + + var jsonObject = JSON.parse(json); + +} \ No newline at end of file